1var bidspiritApi; 2 3// Suppress PayTrace env_includes errors 4(function() { 5 var originalOnError = window.onerror; 6 window.onerror = function(message, source, lineno, colno, error) { 7 if (source && source.indexOf('env_includes') !== -1 && source.indexOf('paytrace.com') !== -1) { 8 console.warn('[PayTrace] Suppressed broken dependency error:', message); 9 return true; // Suppress error 10 } 11 if (originalOnError) { 12 return originalOnError.apply(this, arguments); 13 } 14 return false; 15 }; 16})(); 17 18(function ($) { 19 var BIDSPIRIT_SERVER = window.bidSpiritServer, 20 BIDSPIRIT_API_BASE = BIDSPIRIT_SERVER + "api/thirdparty/v1/", 21 REST_API_BASE = "/wp-json/bidspirit/v1/", 22 LANG = window.bidSpiritLang, 23 currencySymbol = window.bidSpiritCurrency !== "" ? window.bidSpiritCurrency : "$", 24 bidspiritSessionId, 25 bidspiritAuthToken, 26 bidspiritUser, 27 currentAuctionNumber, 28 currentLotIndex, 29 allIncrementsPrices = null, 30 currentItemInfoResponse = null, 31 currentItemInfo = null, 32 auctionApprovalState = null, 33 countriesList = null, 34 auctionHouseData = { 35 disclaimer: null, 36 email: null, 37 info: null, 38 name: null, 39 noVatByDefault: null, 40 phone: null, 41 noVatOnCommission: null, 42 43 /** 44 * Depricated: 45 * enablePrebidsUnderStartPrice: null, 46 * houseCommissionVatRule: null, 47 * requireIdPhoto: null, 48 * idPhotoUploadRequired: null, 49 * vat: null 50 **/ 51 }, 52 auctionInfo = { 53 approvalRequired: null, 54 paymentMethodRequired: null, 55 absenteeBidsEnabled: null, 56 address: null, 57 automaticAuction: null, 58 commission: null, 59 commissionInfo: null, 60 currency: null, 61 days: null, 62 displayStartPriceInCatalog: null, 63 id: null, 64 info: null, 65 lastCatalogUpdate: null, 66 name: null, 67 number: null, 68 showEstimatedPriceInItemsList: null, 69 state: null, 70 }, 71 auctionItemInfo = {}, 72 paymentMethods = [], 73 auctionSettingsData = { 74 requireUserId: null, 75 requireTaxNumber: null, 76 documentUrlBase: null, 77 stripePublicKey: null, 78 bidspiritPortal: null, 79 creditCardProvider: null, 80 alertsEnabled: null, 81 minimumForUsersCallRequests: null, 82 enableUsersCallRequests: null, 83 proxyDomain: null, 84 houseInfo: null, 85 autoPaymentDays: null, 86 enablePrebidsUnderStartPrice: null, 87 houseCommissionVatRule: null, 88 requireIdPhoto: null, 89 idPhotoUploadRequired: null, 90 vat: null, 91 hideSoldPrice: true, 92 }, 93 imageBlank = (typeof AuctionForgePlugin !== "undefined" && AuctionForgePlugin.imageBlank) ? AuctionForgePlugin.imageBlank : "/wp-content/plugins/uco-auctions/img/not_found.jpg", 94 triggerClass = "is-load-earlier"; 95 bidspiritApi = { 96 lang: LANG, 97 getBidspiritSessionId: function () { 98 return bidspiritSessionId; 99 }, 100 setBidspiritSessionId: function (sessionId) { 101 if (sessionId === undefined) { 102 try { 103 sessionId = localStorage.getItem("bidspiritSessionId") || ""; 104 } catch (e) { 105 console.error("Local storage disabled"); 106 } 107 } 108 109 bidspiritSessionId = sessionId; 110 }, 111 getAuthToken: function (apiAction) { 112 if (apiAction !== undefined && apiAction === "users/initSession" && bpGetQueryParams("authToken") !== null) { 113 return bpGetQueryParams("authToken"); 114 } 115 116 try { 117 bidspiritAuthToken = localStorage.getItem("bidspiritAuthToken"); 118 } catch (e) { 119 console.error("Local storage disabled"); 120 bidspiritAuthToken = ""; 121 } 122 123 return bidspiritAuthToken; 124 }, 125 setAuthToken: function (authToken) { 126 try { 127 localStorage.setItem("bidspiritAuthToken", authToken); 128 } catch (e) { 129 console.error("Local storage disabled"); 130 } 131 132 bidspiritAuthToken = authToken; 133 }, 134 getBidspiritUser: function () { 135 return bidspiritUser; 136 }, 137 setBidspiritUser: function (user) { 138 bidspiritUser = user; 139 let successMessage = ""; 140 141 if (bidspiritUser !== undefined) { 142 if (bidspiritUser.honorific === undefined) { 143 bidspiritUser.honorific = ""; 144 } 145 146 if (bidspiritUser.firstName === undefined) { 147 bidspiritUser.firstName = ""; 148 } 149 150 if (bidspiritUser.lastName === undefined) { 151 bidspiritUser.lastName = ""; 152 } 153 154 successMessage = window.bs_lang.login_success_hello + ", " + bidspiritUser.firstName; 155 156 if (bidspiritUser.honorific !== "") { 157 successMessage = window.bs_lang.login_success_full_hello.replace(/%s1/, bidspiritUser.honorific).replace(/%s2/, bidspiritUser.firstName).replace(/%s3/, bidspiritUser.lastName); 158 } 159 160 if (window.bs_lang.login_success_hello_custom !== "" && bidspiritUser.honorific !== "") { 161 successMessage = window.bs_lang.login_success_hello_custom.replace(/%s1/, bidspiritUser.honorific).replace(/%s2/, bidspiritUser.firstName).replace(/%s3/, bidspiritUser.lastName); 162 } else if (window.bs_lang.login_success_hello_custom_default !== "" && bidspiritUser.honorific === "") { 163 successMessage = window.bs_lang.login_success_hello_custom_default.replace(/%s1/, bidspiritUser.firstName).replace(/%s2/, bidspiritUser.lastName); 164 } 165 166 bidspiritUser.successMessage = successMessage; 167 } 168 }, 169 getAuctionApprovalState: function () { 170 return auctionApprovalState; 171 }, 172 setAuctionApprovalState: function (value) { 173 auctionApprovalState = value; 174 }, 175 getCountriesList: function () { 176 return countriesList; 177 }, 178 setCountriesList: function (value) { 179 countriesList = value; 180 }, 181 getAuctionHouseData: function () { 182 return auctionHouseData; 183 }, 184 setAuctionHouseData: function (value) { 185 auctionHouseData = value; 186 }, 187 getAuctionSettingsData: function () { 188 return auctionSettingsData; 189 }, 190 setAuctionSettingsData: function (value) { 191 auctionSettingsData = value; 192 }, 193 getAuctionInfo: function () { 194 return auctionInfo; 195 }, 196 setAuctionInfo: function (value) { 197 if (value.currency !== undefined) { 198 currencySymbol = value.currency; 199 } 200 auctionInfo = value; 201 }, 202 getAuctionItemInfo: function () { 203 return auctionItemInfo; 204 }, 205 setAuctionItemInfo: function (value) { 206 auctionItemInfo = value; 207 }, 208 setIncrementsPrices: function (callback) { 209 if (allIncrementsPrices === null) { 210 allIncrementsPrices = bidspiritApi.getAuctionInfo().increments; 211 } else { 212 callback(allIncrementsPrices); 213 } 214 }, 215 getIncrementsPrices: function () { 216 return allIncrementsPrices; 217 },
218 stripeLoad: function (callback) { 219 var classTrigger = "stripe-load"; 220 221 if (document.body.classList.contains(classTrigger)) { 222 callback(); 223 } else { 224 $.getScript("https://js.stripe.com/v3/").done(function (script, textStatus) { 225 callback(); 226 console.info(textStatus + " Stripe load"); 227 document.body.classList.add(classTrigger); 228 }).fail(function (jqxhr, settings, exception) { 229 console.error("Error Stripe load", jqxhr, settings, exception); 230 }); 231 } 232 }, 233 getLinkOnLive() { 234 let lat = ""; 235 236 if (bidspiritUser !== undefined && bidspiritUser.liveAuctionToken !== undefined) { 237 lat = "?lat=" + bidspiritUser.liveAuctionToken; 238 } 239 240 return BIDSPIRIT_SERVER + lat; 241 }, 242 auctionSettingsDataInit: function () { 243 if (auctionSettingsData.requireUserId === null) { 244 bidspiritQuery("settings/getSettings", { 245 sessionId: bidspiritSessionId, 246 language: LANG 247 }, function (data) { 248 auctionSettingsData = data.response; 249 bidspiritApi.setAuctionSettingsData(auctionSettingsData); 250 }); 251 } 252 }, 253 bidspiritQuery: bidspiritQuery, 254 bidspiritPostQuery: bidspiritPostQuery, 255 init: init, 256 doLogout: doLogout, 257 checkError: checkError, 258 initIncrementSteps: initIncrementSteps, 259 checkErrorForm: checkErrorForm, 260 auctionInfoInit: auctionInfoInit, 261 hangUpEvent: hangUpEvent, 262 saveFirebaseUser: saveFirebaseUser, 263 updateUserDisplay: updateUserDisplay, 264 updateDisplay: updateDisplay, 265 loginLink: loginLink, 266 submitRegister: submitRegister, 267 getDataForm: getDataForm 268 }; 269 270 function ajaxQuery(params, apiAction, data, callback, errorCallback, alwaysCallback) { 271 $.ajax(params).done(function (response) { 272 if (callback !== undefined) { 273 callback(response); 274 } 275 }).fail(function () { 276 if (errorCallback !== undefined) { 277 errorCallback(); 278 } 279 }).always(function () { 280 if (alwaysCallback !== undefined) { 281 alwaysCallback(); 282 } 283 }); 284 } 285 286 function restQuery(apiCall, method, data, callback) { 287 var xhttp = new XMLHttpRequest(); 288 289 xhttp.onreadystatechange = function () { 290 if (this.readyState == 4 && this.status == 200) { 291 if (callback !== undefined) { 292 callback(this.responseText); 293 } 294 } 295 }; 296 297 apiCall = REST_API_BASE + apiCall + "?" + new URLSearchParams(data).toString(); 298 xhttp.open(method, apiCall, true); 299 xhttp.setRequestHeader("Content-type", "application/json"); 300 xhttp.send(); 301 } 302 303 // A BidSpirit Shop term carries a synthetic auction id (Shop::AUCTION_ID_BASE 304 // on the PHP side) purely because AuctionForge keys every lot on one. No 305 // auction-scoped endpoint can succeed for it: BidSpirit answers 306 // BAD_PARAM_VALUE "Auction <id> not found", and checkError() puts that in 307 // front of the customer as an error modal. Rather than chase every call site 308 // (the catalogue bid loader, the 10s poller, approvals, ...), drop these at 309 // the transport and unwind the caller cleanly. 310 var BS_SHOP_AUCTION_ID_BASE = 990000000; 311 312 function bsShopIsSyntheticAuctionId(value) { 313 var n = parseInt(value, 10); 314 return !isNaN(n) && n >= BS_SHOP_AUCTION_ID_BASE; 315 } 316 317 function bsShopSkipAuctionCall(data, callback, alwaysCallback) { 318 if (!data || (!bsShopIsSyntheticAuctionId(data.auctionId) 319 && !bsShopIsSyntheticAuctionId(data.auctionNumber))) { 320 return false; 321 } 322 323 // Hand back an empty but well-formed response so callers that walk 324 // itemsInfo/notFoundLots do not throw, and run the always handler so no 325 // poller is left stuck marked busy. 326 if (callback !== undefined) { 327 callback({ 328 response: { 329 success: true, 330 itemsInfo: {}, 331 notFoundLots: [], 332 auctionIsLive: false 333 } 334 }); 335 } 336 337 if (alwaysCallback !== undefined) { 338 alwaysCallback(); 339 } 340 341 return true; 342 } 343 344 function bidspiritQuery(apiAction, data, callback, errorCallback, alwaysCallback) { 345 if (bsShopSkipAuctionCall(data, callback, alwaysCallback)) { 346 return; 347 } 348 349 if (bpGetQueryParams("sessionId") !== null) { 350 data.sessionId = bpGetQueryParams("sessionId"); 351 } 352 353 ajaxQuery({ 354 url: BIDSPIRIT_API_BASE + apiAction + ".api", 355 data: data, 356 timeout: 0, 357 beforeSend: function (request) { 358 request.setRequestHeader("BIDSPIRIT-AUTH-TOKEN", bidspiritApi.getAuthToken(apiAction)); 359 }, 360 xhrFields: { 361 withCredentials: true 362 } 363 }, apiAction, data, callback, errorCallback, alwaysCallback); 364 } 365 366 function bidspiritPostQuery(apiAction, data, callback, errorCallback, alwaysCallback) { 367 if (bsShopSkipAuctionCall(data, callback, alwaysCallback)) { 368 return; 369 } 370 371 if (bpGetQueryParams("sessionId") !== null) { 372 data.sessionId = bpGetQueryParams("sessionId"); 373 } 374 375 ajaxQuery({ 376 url: BIDSPIRIT_API_BASE + apiAction + ".api", 377 data: data, 378 type: "POST", 379 timeout: 0, 380 beforeSend: function (request) { 381 request.setRequestHeader("BIDSPIRIT-AUTH-TOKEN", bidspiritApi.getAuthToken(apiAction)); 382 }, 383 xhrFields: { 384 withCredentials: true 385 } 386 }, apiAction, data, callback, errorCallback, alwaysCallback); 387 } 388 389 function hangUpEvent(name, data, target) { 390 var event = jQuery.Event(name); 391 event.response = data; 392 393 if (target === undefined) { 394 $("body").trigger(event); 395 } else { 396 target.trigger(event); 397 } 398 } 399 400 function compareItemIndex(itemIndex, firstLotIndex, lastLotIndex) { 401 return parseInt(itemIndex) >= parseInt(firstLotIndex) && itemIndex <= parseInt(lastLotIndex); 402 } 403 404 function initialPostAuctionSaleOpenedUntil(auctionData, lotIndex) { 405 let currentAuctionDayIndex = 0, 406 postAuctionSaleOpenedUntil = 0; 407 if (auctionData.days !== undefined && auctionData.days.length > 1) { 408 let indexDetect = false;
409 auctionData.days.forEach((elem, index) => { 410 if (compareItemIndex(lotIndex, elem.firstLotIndex, elem.lastLotIndex) && !indexDetect) { 411 currentAuctionDayIndex = elem.index - 1; 412 indexDetect = true; 413 } 414 }); 415 416 if (auctionData.days[currentAuctionDayIndex] !== undefined && auctionData.days[currentAuctionDayIndex].postAuctionSaleOpenedUntil !== undefined) { 417 postAuctionSaleOpenedUntil = auctionData.days[currentAuctionDayIndex].postAuctionSaleOpenedUntil; 418 //console.log("testX2.0"); 419 } else { 420 postAuctionSaleOpenedUntil = 0; 421 //console.log("testX2.1"); 422 } 423 } else { 424 if (auctionData.days[0] !== undefined && auctionData.days[0].postAuctionSaleOpenedUntil !== undefined) { 425 postAuctionSaleOpenedUntil = auctionData.days[0].postAuctionSaleOpenedUntil; 426 //console.log("testX3.0"); 427 } else { 428 postAuctionSaleOpenedUntil = 0; 429 //console.log("testX3.1"); 430 } 431 } 432 433 return [currentAuctionDayIndex, postAuctionSaleOpenedUntil]; 434 } 435 436 function urldecode(url) { 437 return decodeURIComponent(url.replace(/\+/g, " ")); 438 } 439 440 function passwordShowAction() { 441 let profilePasswordIcons = $(".bp_show_password-action"); 442 443 if (profilePasswordIcons.length > 0) { 444 profilePasswordIcons.each(function (index, elem) { 445 $(elem).off("click", ".bp_show_password").on("click", ".bp_show_password", function (event) { 446 let profilePasswordIcon = event.target, 447 fieldPassword = $(elem).find(".bp-form-control_eye"); 448 449 if (fieldPassword[0].type === "password") { 450 fieldPassword[0].type = "text"; 451 profilePasswordIcon.classList.remove("svg-eye"); 452 profilePasswordIcon.classList.add("svg-eye-slash"); 453 } else { 454 fieldPassword[0].type = "password"; 455 profilePasswordIcon.classList.remove("svg-eye-slash"); 456 profilePasswordIcon.classList.add("svg-eye"); 457 } 458 }); 459 }); 460 } 461 } 462 463 function checkPoint(name, clear) { 464 if (clear !== undefined) { 465 document.body.classList.remove(name); 466 setCookie(name, false, -1); 467 } else { 468 document.body.classList.add(name); 469 setCookie(name, true, 1); 470 } 471 } 472 473 function setCookie(cname, cvalue, exdays) { 474 var d = new Date(); 475 476 if (exdays === -1) { 477 d.setTime(d.getTime() + exdays); 478 } else { 479 d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000); 480 } 481 482 var expires = "expires=" + d.toUTCString(); 483 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;SameSite=Lax"; 484 } 485 486 function getCookie(cname) { 487 var name = cname + "=", 488 data = document.cookie.split(";"); 489 490 for (var i = 0; i < data.length; i++) { 491 var item = data[i]; 492 493 while (item.charAt(0) === " ") { 494 item = item.substring(1); 495 } 496 497 if (item.indexOf(name) === 0) { 498 return item.substring(name.length, item.length); 499 } 500 } 501 502 return ""; 503 } 504 505 function addBodyClass(className) { 506 // $("body").addClass(className); 507 document.body.classList.add(className); 508 } 509 510 function searchGetParam(param) { 511 var name = param.replace(/[\[\]]/g, "\\$&"), 512 regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), 513 results = regex.exec(window.location.href); 514 515 if (!results) { 516 return null; 517 } 518 519 if (!results[2]) { 520 return ""; 521 } 522 523 return decodeURIComponent(results[2].replace(/\+/g, " ")); 524 } 525 526 function fireSwall(message, confirmCallback, deniedCallback) { 527 Swal.fire({ 528 html: message, 529 showDenyButton: true, 530 showCancelButton: true, 531 confirmButtonText: "Ok", 532 denyButtonText: "Cancel" 533 }).then(result => { 534 if (result.isConfirmed) { 535 if (confirmCallback !== undefined) { 536 confirmCallback(); 537 } 538 } else if (result.isDenied) { 539 if (deniedCallback !== undefined) { 540 deniedCallback(); 541 } 542 } 543 }); 544 } 545 546 function loadTemplate(elem, idTemplate, data, visible, callback, append, prepend) { 547 var jElem = $(elem); 548 549 if (typeof elem === "string" && elem.match(/\#/)) { 550 elem = elem.replace(/\#/, ""); 551 jElem = $(document.getElementById(elem)); 552 } 553 554 var html = _.template(document.getElementById(idTemplate).innerHTML), 555 hiddenClass = window.bs_data.hidden_class; 556 557 if (visible) { 558 jElem.removeClass(hiddenClass); 559 } 560 561 if (append !== undefined) { 562 if (prepend !== undefined) { 563 jElem.prepend(html(data)); 564 } else { 565 jElem.append(html(data)); 566 } 567 } else { 568 jElem.html(html(data)); 569 } 570 571 if (callback !== undefined) { 572 callback(); 573 } 574 } 575 576 function loadTemplateInsert(elem, idTemplate, data, append, prepend, callback) { 577 var jElem = $(elem), 578 html = _.template(document.getElementById(idTemplate).innerHTML); 579 580 if (append !== undefined) { 581 if (prepend !== undefined) { 582 jElem.prepend(html(data)); 583 } else { 584 jElem.append(html(data)); 585 } 586 } else { 587 jElem.html(html(data)); 588 } 589 590 if (callback !== undefined) { 591 callback(); 592 } 593 } 594 595 function bPcheckError(responseData) { 596 if (!responseData || responseData.response == null) { 597 noticeSwall(modal, window.bs_lang.error, window.bs_lang.empty_response); 598 return true; 599 } 600 601 if (responseData.response.errorCode) { 602 noticeSwall(window.bs_lang.error, responseData.response.errorCode, responseData.response.errorMessage); 603 604 if (responseData.response.errorCode == "SESSION_ENDED") { 605 bidspiritUser = null; 606 updateDisplay(); 607 } 608 609 return true; 610 } 611 612 return false;
613 } 614 615 function checkError(responseData, modal) { 616 if (!responseData || responseData.response.success) { 617 return false; 618 } 619 620 if (!responseData) { 621 noticeSwall(modal, "error", "empty response"); 622 return true; 623 } 624 625 hangUpEvent("bp:check-error", responseData.response); 626 627 if (responseData.response.errorCode) { 628 noticeSwall("error", "error", responseData.response.errorMessage); 629 630 if (responseData.response.errorCode === "SESSION_ENDED") { 631 bidspiritUser = null; 632 } 633 634 console.error(responseData.response.errorMessage); 635 return true; 636 } 637 638 return false; 639 } 640 641 function checkErrorForm(form, responseData) { 642 var groupContainerSelector = ".errors-group", 643 submitButton = $(form).find("[type=submit]"), 644 status = false; 645 $(form).find(groupContainerSelector).addClass(window.bs_data.hidden_class); 646 647 if (!!submitButton) { 648 submitButton[0].disabled = true; 649 } 650 651 function printError(form, message) { 652 var groupContainer = $(form).find(groupContainerSelector); 653 654 if (groupContainer.hasClass(window.bs_data.hidden_class)) { 655 groupContainer.removeClass(window.bs_data.hidden_class); 656 } 657 658 groupContainer.empty().append("<p>" + bp_t(message) + "</p>"); 659 660 if (!!submitButton) { 661 submitButton[0].disabled = false; 662 } 663 } 664 665 if (!responseData || responseData.response == null) { 666 printError(form, "empty response"); 667 status = true; 668 } 669 670 if (responseData.response.errorCode == "USER_EXIST" && window.bs_lang.user_exist !== undefined) { 671 printError(form, window.bs_lang.user_exist); 672 status = true; 673 } else if (responseData.response.errorCode) { 674 printError(form, responseData.response.errorMessage); 675 status = true; 676 } 677 678 hangUpEvent("bp:checkErrorForm", responseData); 679 return status; 680 } 681 682 /** 683 * @param price 684 * @param auctionCommission 685 * @param isFull 686 * @returns {string} 687 * @deprecated Depricated. Used getFullPriceInfo 688 */ 689 function calculateCommission(price, auctionCommission, isFull) { 690 var secondPercent = auctionSettingsData.vat, 691 pricePercent = parseFloat(price) * parseFloat(auctionCommission / 100), 692 varPercent = 0, 693 vatRule = auctionSettingsData.houseCommissionVatRule; 694 695 switch (vatRule) { 696 case "EXEMPTED_FROM_VAT": 697 varPercent = pricePercent; 698 break; 699 case "VAT_INCLUDED": 700 varPercent = pricePercent + ((parseFloat(price) + pricePercent) * (secondPercent / 100)); 701 break; 702 case "SHOULD_ADD_VAT": 703 varPercent = pricePercent; 704 //varPercent = pricePercent + (secondPercent / 100); 705 // varPercent = pricePercent + (pricePercent * (secondPercent / 100)); 706 break; 707 default: 708 varPercent = pricePercent + (pricePercent * (secondPercent / 100)); 709 } 710 711 if (isFull) { 712 price = parseFloat(price) + (price * (secondPercent / 100)); 713 return (parseFloat(price) + varPercent).toFixed(2); 714 } else { 715 return (parseFloat(price) + varPercent).toFixed(2); 716 } 717 } 718 719 function roundToCents(sum){ 720 return Math.round(sum*100)/100; 721 } 722 723 function getCommissonInfoForPrice(lot, auction, price) { 724 var commission = price * (auction.commission) / 100; 725 var commissionLabel = auction.commission+"%"; 726 if (auction.minimumItemCommission) { 727 commissionLabel+=". Minimum commission: " + auction.currency+auction.minimumItemCommission; 728 if (auction.itemPriceForMinimumCommission) { 729 commissionLabel+=". Item price for minimum commission:"+auction.itemPriceForMinimumCommission; 730 if (price <= auction.itemPriceForMinimumCommission) { 731 commission = auction.minimumItemCommission; 732 } 733 } else if (commission < auction.minimumItemCommission) { 734 commission = auction.minimumItemCommission; 735 } 736 } 737 return { 738 commission:roundToCents(commission), 739 commissionLabel:commissionLabel 740 } 741 } 742 743 /** 744 * currentItemInfo, auctionInfo, price 745 * @param lot 746 * @param auction 747 * @param price 748 * @returns {{hammerPrice, commissionInfo: {commission: *, commissionLabel: string}, vatInfo: {vat: *, vatLabel: string}, totalPriceInfo: {price: *, label: string}}} 749 */ 750 function getFullPriceInfo(lot, auction, price) { 751 let settings = bidspiritApi.getAuctionSettingsData(), 752 vatPercent = settings.vat, 753 shouldAddVat = vatPercent && (!bidspiritUser || !bidspiritUser.exemptedFromTax), 754 commissionInfo = getCommissonInfoForPrice(lot, auction, price), 755 priceWithCommission = roundToCents(price * 1+ commissionInfo.commission), 756 totalPriceLabel, 757 fullPriceVat = lot.fullPriceVat, 758 vatLabel, 759 vat; 760 761 if (shouldAddVat) { 762 vatLabel = vatPercent + "% " + bp_t("vat"); 763 if (commissionInfo.commission) { 764 totalPriceLabel = bp_t("price_including_buyers_premium_and_vat"); 765 if (fullPriceVat) { 766 vatLabel += " " + bp_t("on_the_full_lots_price_and_commission"); 767 if (settings.houseCommissionVatRule == 'SHOULD_ADD_VAT') { 768 vat = vatPercent * priceWithCommission / 100; 769 } else { 770 vat = vatPercent * price / 100; 771 } 772 } else { 773 vatLabel += " " + bp_t("on commission only"); 774 vat = vatPercent * commissionInfo.commission / 100; 775 } 776 } else { 777 if (fullPriceVat) { 778 vatLabel = bp_t("on_item_price"); 779 totalPriceLabel = bp_t("price_including_vat"); 780 vat = vatPercent * price / 100; 781 } else { 782 vatLabel = bp_t("exempted"); 783 totalPriceLabel = bp_t("full_price_no_vat_or_buyers_permium"); 784 vat = 0; 785 } 786 } 787 } else { 788 vatLabel = bp_t("exempted"); 789 totalPriceLabel = bp_t("total_with_commission"); 790 vat = 0; 791 } 792 vat = roundToCents(vat); 793 return { 794 hammerPrice: parseFloat(price), 795 commissionInfo: commissionInfo, 796 vatInfo:{ 797 vat:vat, 798 vatLabel:vatLabel 799 }, 800 totalPriceInfo:{ 801 price:roundToCents(priceWithCommission + vat), 802 label:totalPriceLabel 803 } 804 805 } 806 } 807 808 function getCommissionPrice(price, fullPriceVat, auctionCommission) { 809 if (fullPriceVat === undefined) { 810 var singleLot = $("#single-lot"); 811 } 812 813 if (fullPriceVat === undefined) { 814 fullPriceVat = Boolean(parseInt(singleLot.attr("data-full-price-vat"))); 815 } 816 817 if (auctionCommission === undefined) { 818 auctionCommission = bidspiritApi.getAuctionInfo().commission; 819 } 820 821 return calculateCommission(price, auctionCommission, fullPriceVat); 822 } 823 824 function renderCommissionPrice(price) { 825 let fullPriceInfo = getFullPriceInfo(currentItemInfo, auctionInfo, price), 826 auctionHouseData = bidspiritApi.getAuctionSettingsData(), 827 fullVatPrice = Boolean(parseInt($("#single-lot").attr("data-full-price-vat"))), 828 secondaryFullPrice = 0, 829 text = ""; 830 831 console.log(fullPriceInfo); 832 833 if (auctionInfo.secondCurrencyRate !== undefined) { 834 secondaryFullPrice = (fullPriceInfo.totalPriceInfo.price * (auctionInfo.secondCurrencyRate).toFixed(4)).toFixed(2); 835 text = " (" + formattedPrice(secondaryFullPrice,auctionInfo.secondCurrency) + ")"; 836 } 837 838 loadTemplate("#bp-fullPrice", "full-price-template", { 839 text: text, 840 fullPriceVat: fullVatPrice, 841 fullPriceInfo: getFullPriceInfo(currentItemInfo, auctionInfo, price), 842 auctionHouseData: auctionHouseData, 843 currencySymbol: currencySymbol 844 }); 845 } 846 847 function galleryInitial() { 848 function featureGallery(galleryMainSlider, galleryThumbs) { 849 var bidspiritUser = bidspiritApi.getBidspiritUser(), 850 galleryInfo = $("#gallery-info"); 851 852 if (window.bs_data.only_for_user_auth && bidspiritUser !== undefined) { 853 var imageWrapper = $("#wrpLotImages"); 854 galleryInfo.remove(); 855 856 if (imageWrapper.length) { 857 var imageList = imageWrapper.attr("data-image-list"), 858 imageTemplate = imageWrapper.attr("data-image-template"), 859 imgTemplate = "", 860 isCloned = Boolean(parseInt(imageWrapper.attr("data-image-cloned"))); 861 862 try { 863 imageTemplate = JSON.parse(imageTemplate); 864 imageList = imageList.split(/\,/); 865 imgTemplate = imageTemplate.uncloned.custom; 866 867 if (Array.isArray(imageList)) { 868 imageList.splice(0, 1); 869 } 870 871 if (isCloned) { 872 imgTemplate = imageTemplate.cloned.custom; 873 } 874 875 var mainSlide = [], 876 thumbSlide = []; 877 imageList.forEach(function (elem, index) { 878 var imgSrc = ""; 879 imgSrc = imgTemplate.replace(/\$1/g, elem); 880 imgSrc = imgSrc.replace(/\$2/g, elem.replace(/\D+/, ""));
881 var thumbsTemplate = `<div data-slide="${index + 1}" class='grid-slide swiper-slide' style='background-image:url("${imgSrc}")'></div>`, 882 slideTemplate = `<a href="${imgSrc}" data-fancybox-bp="gallery" class="swiper-slide" style="background-image:url('${imgSrc}')"></a>`; 883 mainSlide.push(slideTemplate); 884 thumbSlide.push(thumbsTemplate); 885 }); 886 887 if (mainSlide.length > 0) { 888 galleryMainSlider.appendSlide(mainSlide); 889 890 if (typeof galleryThumbs.appendSlide === "function") { 891 galleryThumbs.appendSlide(thumbSlide); 892 } else { 893 galleryThumbs.append(thumbSlide); 894 } 895 } 896 } catch (e) { 897 console.error(e); 898 } 899 } 900 } else { 901 galleryInfo.removeClass(window.bs_data.hidden_class); 902 } 903 } 904 905 var gallerySelector = ".bp-gallery-thumbs", 906 topGallerySelector = ".bp-gallery-top", 907 topGalleryConfig = { 908 spaceBetween: 10, 909 navigation: { 910 nextEl: ".swiper-button-next", 911 prevEl: ".swiper-button-prev" 912 } 913 }, 914 gridGalleryThumbs = ".bp-gallery-thumbs-grid", 915 galleryMainSlider = null, 916 galleryThumbs = null; 917 918 if ($(gallerySelector).length) { 919 galleryThumbs = new SwiperBP(".bp-gallery-thumbs", { 920 spaceBetween: 10, 921 slidesPerView: 4, 922 freeMode: true, 923 centeredSlidesBounds: true, 924 slideToClickedSlide: true, 925 watchSlidesVisibility: true, 926 watchSlidesProgress: true 927 }); 928 929 if ($(topGallerySelector).length) { 930 topGalleryConfig.thumbs = { 931 swiper: galleryThumbs 932 }; 933 galleryMainSlider = new SwiperBP(topGallerySelector, topGalleryConfig); 934 } 935 } else { 936 if ($(topGallerySelector).length) { 937 galleryMainSlider = new SwiperBP(topGallerySelector, topGalleryConfig), galleryThumbs = $(".bp-gallery-thumbs-grid .swiper-wrapper"); 938 939 if (gridGalleryThumbs.length) { 940 $(gridGalleryThumbs).on("click", ".swiper-slide", function (item) { 941 var slide = $(this).attr("data-slide"); 942 galleryMainSlider.slideTo(slide); 943 }); 944 } 945 } 946 } 947 948 $(window).on("bp:after-init", function (data) { 949 featureGallery(galleryMainSlider, galleryThumbs); 950 }); 951 $(window).on("bp:after-login", function (data) { 952 featureGallery(galleryMainSlider, galleryThumbs); 953 }); 954 } 955 956 function initIncrementSteps(incrementsStepPrices, minPrice, enablePrebidsUnderStartPrice) { 957 if (minPrice === undefined) { 958 return; 959 } 960 961 allIncrementsPrices = []; 962 var startStep = null, 963 price = 0, 964 bidLength = 200, 965 bidCount = 0; 966 967 if (enablePrebidsUnderStartPrice !== undefined && enablePrebidsUnderStartPrice === true) { 968 allIncrementsPrices.push(1); 969 } 970 971 for (var j = 0; j < incrementsStepPrices.length; j++) { 972 if (incrementsStepPrices[j][0] >= price) { 973 if (incrementsStepPrices[j - 1] !== undefined) { 974 startStep = incrementsStepPrices[j - 1][0]; 975 break; 976 } else { 977 startStep = incrementsStepPrices[j][0]; 978 break; 979 } 980 } 981 } 982 983 for (var i = 0; i < incrementsStepPrices.length; i++) { 984 var increment = incrementsStepPrices[i], 985 step = increment[1], 986 nextPart = null; 987 988 if (incrementsStepPrices[i + 1] !== undefined) { 989 nextPart = incrementsStepPrices[i + 1][0]; 990 991 while (nextPart > price) { 992 price += step; 993 994 if (price > minPrice) { 995 allIncrementsPrices.push(price); 996 bidCount++; 997 } 998 999 if (bidLength === bidCount) { 1000 return; 1001 } 1002 } 1003 } else { 1004 while (bidLength >= bidCount) { 1005 price += step; 1006 1007 if (price > minPrice) { 1008 allIncrementsPrices.push(price); 1009 bidCount++; 1010 } 1011 } 1012 } 1013 } 1014 } 1015 1016 /*function listIncrementSteps(incrementsStepPrices, minPrice) { 1017 if (incrementsStepPrices === null) { 1018 return []; 1019 } 1020 1021 let incrementsPrices = [], 1022 price = 0, 1023 bidCount = 0; 1024 1025 for (var i = 0; i < incrementsStepPrices.length; i++) { 1026 var increment = incrementsStepPrices[i], 1027 step = increment[1], 1028 nextPart = null; 1029 1030 if (incrementsStepPrices[i + 1] !== undefined) { 1031 nextPart = incrementsStepPrices[i + 1][0]; 1032 1033 while (nextPart > price) { 1034 price += step; 1035 incrementsPrices.push(price); 1036 bidCount++; 1037 } 1038 } 1039 } 1040 1041 return incrementsPrices; 1042 }*/ 1043 1044 function select2ToolsInit() { 1045 function toolsInit(formTools) { 1046 var formSearch = $("#bp-from-tools .bp-btn-search"), 1047 inputSearch = formTools.find("[name=phrase_by]"), 1048 inputPerPage = formTools.find("[name=per_page]"), 1049 inputFilter = $(".bp-form_category"), 1050 soldFilter = $(".bp-form_sold-unsold"), 1051 btnClear = formTools.find(".bp-btn-close"); 1052 var settingsSelect2 = { 1053 width: "resolve", 1054 theme: "default bp-custom-select", 1055 minimumResultsForSearch: -1, 1056 dropdownParent: $(".bp-form_sorter .bp-form-group__inner") 1057 }; 1058 var settingsSelect2PerPage = { 1059 width: "resolve", 1060 theme: "default bp-custom-select", 1061 minimumResultsForSearch: -1, 1062 dropdownParent: $(".bp-form_per_page .bp-form-group__inner") 1063 }; 1064 var settingsSelect2Category = { 1065 width: "resolve", 1066 theme: "default bp-custom-select", 1067 // minimumResultsForSearch: -1, 1068 dropdownParent: $(".bp-form_category .bp-form-group__inner"), 1069 placeholder: window.bs_lang.select_value, 1070 allowClear: true 1071 }; 1072 1073 if (formTools.length) { 1074 formSearch.on("click", ".bp-btn-search", function (event) { 1075 event.preventDefault(); 1076 formTools.submit(); 1077 }); 1078 inputSearch.on("input, change", function (event) { 1079 btnClear.removeClass(window.bs_data.hidden_class); 1080 }); 1081 btnClear.on("click", function (event) { 1082 event.preventDefault(); 1083 inputSearch.val(""); 1084 $(this).addClass(window.bs_data.hidden_class); 1085 formTools.submit(); 1086 }); 1087 formSearch.on("submit", function (event) { 1088 event.preventDefault(); 1089 }); 1090 var currentValue = inputSearch.val(); 1091 1092 if (currentValue !== "") { 1093 inputSearch.trigger("change"); 1094 } 1095 } 1096 1097 var selectField = $(".bp-form_sorter .bp-filter-select2"); 1098 1099 if (formTools.length && selectField.length) { 1100 selectField.select2(settingsSelect2); 1101 selectField.on("select2:select", function (event) { 1102 formTools.submit(); 1103 }); 1104 } 1105 1106 if (inputFilter.length) { 1107 var selectFieldCategory = $(".bp-form_category .bp-filter-select2"); 1108 selectFieldCategory.select2(settingsSelect2Category); 1109 selectFieldCategory.on("select2:clear", function (event) { 1110 formTools.submit(); 1111 }); 1112 selectFieldCategory.on("select2:select", function (event) { 1113 formTools.submit(); 1114 }); 1115 } 1116 1117 if (formTools.length && inputPerPage.length) { 1118 var selectFieldPerPage = $(".bp-form_per_page .bp-per-page-select2"); 1119 selectFieldPerPage.select2(settingsSelect2PerPage); 1120 selectFieldPerPage.on("select2:select", function (event) { 1121 // Changing items-per-page returns to page 1. Done client-side because the 1122 // server can't rely on the PHP session for this on cached/CDN auction pages. 1123 try { 1124 formTools.attr("action", window.location.pathname.replace(/\/page\/\d+\/?/, "/")); 1125 } catch (e) {} 1126 formTools.submit(); 1127 }); 1128 } 1129 1130 if ($(".bp-day-switcher").length) { 1131 var daysSwitcher = $(".bp-day-switcher"); 1132 daysSwitcher.select2({ 1133 width: "resolve", 1134 theme: "default bp-custom-select", 1135 minimumResultsForSearch: -1 1136 }); 1137 daysSwitcher.on("select2:select", function (event) { 1138 let data = event.params.data, 1139 value = data.element.getAttribute("value"); 1140 1141 if (value !== undefined) { 1142 window.location = value; 1143 } 1144 }); 1145 } 1146 1147 if (soldFilter.length) { 1148 soldFilter.find('.bp-select2').select2(settingsSelect2); 1149 soldFilter.on("select2:select", function (event) { 1150 formTools.submit(); 1151 }); 1152 } 1153 } 1154 1155 function toolsInitOutdated() { 1156 var formFilter = $("#bp-from-filter"), 1157 formSearch = $("#bp-from-search"), 1158 inputSearch = formSearch.find("[name=bp_auction_search]"), 1159 inputSearchHidden = $("#bp_auction_search"), 1160 inputFilter = $(".bp-form_category"), 1161 btnClear = formSearch.find(".bp-btn-close"), 1162 soldFilter = $(".bp-form_sold-unsold"), 1163 inputSorter = $(".bp-form_sorter"); 1164 var settingsSelect2 = { 1165 width: "resolve", 1166 theme: "default bp-custom-select", 1167 minimumResultsForSearch: -1, 1168 dropdownParent: $(".bp-form_sorter .bp-form-group__inner") 1169 }; 1170 var settingsSelect2Category = { 1171 width: "resolve", 1172 theme: "default bp-custom-select", 1173 minimumResultsForSearch: -1, 1174 dropdownParent: $(".bp-form_category .bp-form-group__inner"), 1175 placeholder: window.bs_lang.select_value, 1176 allowClear: true 1177 }; 1178 1179 if (formSearch.length) { 1180 formSearch.on("click", ".bp-btn-search", function (event) { 1181 event.preventDefault(); 1182 formFilter.submit(); 1183 }); 1184 inputSearch.on("input, change", function (event) { 1185 btnClear.removeClass(window.bs_data.hidden_class); 1186 }); 1187 btnClear.on("click", function (event) { 1188 event.preventDefault(); 1189 inputSearch.val(""); 1190 inputSearchHidden.val(""); 1191 $(this).addClass(window.bs_data.hidden_class); 1192 formFilter.submit(); 1193 }); 1194 formSearch.on("submit", function (event) { 1195 event.preventDefault(); 1196 }); 1197 inputSearch.on("keypress", function (event) { 1198 if (event.keyCode === 13) { 1199 inputSearchHidden.val(inputSearch.val()); 1200 } 1201 }); 1202 var currentValue = inputSearch.val(); 1203 1204 if (currentValue !== "") { 1205 inputSearch.trigger("change"); 1206 } 1207 } 1208 1209 if (inputSorter.length) { 1210 var selectField = $(".bp-form_sorter .bp-filter-select2"), 1211 filterParam = searchGetParam("sort_by"); 1212 selectField.select2(settingsSelect2); 1213 1214 if (filterParam !== null) { 1215 var select = selectField.find('option[value="' + filterParam + '"]'); 1216 1217 if (select.length) { 1218 selectField.val(filterParam); 1219 selectField.trigger("change"); 1220 } 1221 } 1222 1223 selectField.on("select2:select", function (event) { 1224 formFilter.submit(); 1225 }); 1226 } 1227 1228 if (inputSearch.length) { 1229 inputSearch.on("input, change", function (event) { 1230 inputSearchHidden.val($(this).val()); 1231 }); 1232 } 1233 1234 if (inputFilter.length) { 1235 var selectFieldCategory = $(".bp-form_category .bp-filter-select2"), 1236 filterParamCategory = searchGetParam("category_by"); 1237 selectFieldCategory.select2(settingsSelect2Category); 1238 1239 if (filterParamCategory !== null) { 1240 var selectCategory = selectFieldCategory.find('option[value="' + filterParamCategory + '"]'); 1241 1242 if (selectCategory.length) { 1243 selectFieldCategory.val(filterParamCategory); 1244 selectFieldCategory.trigger("change"); 1245 } 1246 } 1247 1248 selectFieldCategory.on("select2:clear", function (event) { 1249 formFilter.submit(); 1250 }); 1251 selectFieldCategory.on("select2:select", function (event) { 1252 formFilter.submit(); 1253 }); 1254 } 1255 } 1256 1257 var formTools = $("#bp-from-tools"); 1258 1259 if (formTools.length > 0) { 1260 toolsInit(formTools); 1261 } else { 1262 toolsInitOutdated(); 1263 } 1264 } 1265 1266 function select2init() { 1267 function loadStepSelect() { 1268 (function (auctionInfo) { 1269 var select = $("#bidFormPrice"), 1270 minBidPrice = 1, 1271 enablePrebidsUnderStartPrice = false;
1272 1273 if (auctionInfo.increments !== undefined) { 1274 hangUpEvent("bp:get-increment-steps", auctionInfo.increments); 1275 } 1276 1277 if (currentItemInfo !== null) { 1278 var itemInfo = currentItemInfo, 1279 settings = bidspiritApi.getAuctionSettingsData(); 1280 select.empty(); 1281 1282 1283 if (itemInfo.leadingBid !== undefined && itemInfo.leadingBid.isSelf && itemInfo.selfAbsenteeBid !== undefined && !isNaN(itemInfo.selfAbsenteeBid.price) && itemInfo.selfAbsenteeBid.price > 0) { 1284 minBidPrice = itemInfo.selfAbsenteeBid.price - 1; 1285 } else if (itemInfo.leadingBid !== undefined) { 1286 minBidPrice = itemInfo.leadingBid.price; 1287 } else if (settings.enablePrebidsUnderStartPrice !== undefined && settings.enablePrebidsUnderStartPrice === true) { 1288 enablePrebidsUnderStartPrice = true; 1289 1290 if (auctionInfo.increments[0][0] !== undefined && auctionInfo.increments[0][0] > 0) { 1291 minBidPrice = auctionInfo.increments[0][0] - 1; 1292 } else { 1293 minBidPrice = 0; 1294 } 1295 } else if (itemInfo.startPrice !== undefined) { 1296 minBidPrice = itemInfo.startPrice; 1297 select.append('<option value="' + minBidPrice + '">' + formattedPrice(minBidPrice, currencySymbol) + "</option>"); 1298 } else { 1299 select.append('<option value="0">' + formattedPrice(0, currencySymbol) + "</option>"); 1300 } 1301 1302 if (isNaN(minBidPrice) || minBidPrice === undefined || minBidPrice === null) { 1303 if (itemInfo.leadingBid !== undefined && !isNaN(itemInfo.leadingBid.price)) { 1304 minBidPrice = itemInfo.leadingBid.price; 1305 } else if (itemInfo.startPrice !== undefined && !isNaN(itemInfo.startPrice)) { 1306 minBidPrice = itemInfo.startPrice; 1307 } else { 1308 minBidPrice = 0; 1309 } 1310 } 1311 1312 initIncrementSteps(bidspiritApi.getAuctionInfo().increments, minBidPrice); 1313 1314 for (var i = 0; i < allIncrementsPrices.length; i++) { 1315 var stepPrice = allIncrementsPrices[i]; 1316 1317 if (stepPrice !== undefined) { 1318 select.append('<option value="' + stepPrice + '">' + formattedPrice(stepPrice, currencySymbol) + "</option>"); 1319 } 1320 } 1321 } 1322 })(bidspiritApi.getAuctionInfo()); 1323 } 1324 1325 loadStepSelect(); 1326 var settingsSelect2 = { 1327 width: "resolve", 1328 theme: "default bp-custom-select", 1329 minimumResultsForSearch: -1, 1330 templateSelection: function (data, container) { 1331 renderCommissionPrice(data.id); 1332 return data.text; 1333 } 1334 }; 1335 $(".bp-select2").each(function (index, elem) { 1336 $(elem).select2(settingsSelect2).trigger("change"); 1337 }); 1338 } 1339 1340 function select2build(elemId, items) { 1341 return $(elemId).select2({ 1342 data: items, 1343 minimumResultsForSearch: -1, 1344 width: "resolve" 1345 }); 1346 } 1347 1348 function setInvitationsEnabled(value) { 1349 bidspiritQuery("users/setInvitationsEnabled", { 1350 sessionId: bidspiritSessionId, 1351 isEnabled: value 1352 }); 1353 } 1354 1355 // Consolidated notification preferences (users/updateAlertsPreferences) — saves 1356 // invitations + bid/overbid email prefs together in one call, replacing the separate 1357 // setInvitationsEnabled call. leadingBidAlertsEnabled is passed through unchanged 1358 // (it is auto-managed via Firebase push in saveFirebaseUser, so it has no UI toggle). 1359 function saveAlertsPreferences() { 1360 var user = bidspiritApi.getBidspiritUser() || {}; 1361 var allowInvitations = $("#invitationsEnabled input").prop("checked"); 1362 var sendBidEmails = $("#af-pref-bid-emails").length ? $("#af-pref-bid-emails").prop("checked") : !!user.sendBidEmails; 1363 var sendOverBidEmails = $("#af-pref-overbid-emails").length ? $("#af-pref-overbid-emails").prop("checked") : !!user.sendOverBidEmails; 1364 1365 bidspiritQuery("users/updateAlertsPreferences", { 1366 sessionId: bidspiritSessionId, 1367 allowInvitations: allowInvitations, 1368 leadingBidAlertsEnabled: !!user.leadingBidAlertsEnabled, 1369 sendBidEmails: sendBidEmails, 1370 sendOverBidEmails: sendOverBidEmails 1371 }, function (data) { 1372 if (!checkError(data)) { 1373 user.allowInvitations = allowInvitations; 1374 user.sendBidEmails = sendBidEmails; 1375 user.sendOverBidEmails = sendOverBidEmails; 1376 bidspiritApi.setBidspiritUser(user); 1377 } 1378 }); 1379 } 1380 1381 // === Live bid auto-refresh for the profile Wish List / My Bids "Future" sections === 1382 // Polls items/getItemsInfo every 10s and patches current bid amounts in place (no reload), 1383 // flashing any price that changed. Only touches non-ended lots in a visible "*-future" section. 1384 var afBidWatch = { intervalId: null, busy: false }; 1385 var AF_BIDWATCH_MS = 10000; 1386 var AF_BIDWATCH_KEY = "af_bidwatch_enabled"; 1387 var AF_FUTURE_SEL = "[id^='bp-paginated-'][id$='-future']:visible"; 1388 1389 function afBidWatchEnabled() { 1390 try { return localStorage.getItem(AF_BIDWATCH_KEY) === "1"; } catch (e) { return false; } 1391 } 1392 1393 function afSetBidWatchEnabled(on) { 1394 try { localStorage.setItem(AF_BIDWATCH_KEY, on ? "1" : "0"); } catch (e) {} 1395 $(".af-bidwatch-checkbox").prop("checked", !!on); 1396 } 1397 1398 function afStopBidWatch() { 1399 if (afBidWatch.intervalId) { 1400 clearInterval(afBidWatch.intervalId); 1401 afBidWatch.intervalId = null; 1402 } 1403 afBidWatch.busy = false;
1404 } 1405 1406 function afStartBidWatch() { 1407 afStopBidWatch(); 1408 if (!afBidWatchEnabled()) { 1409 return; 1410 } 1411 afBidWatchTick(); 1412 afBidWatch.intervalId = setInterval(afBidWatchTick, AF_BIDWATCH_MS); 1413 } 1414 1415 function afFlashPrice($node) { 1416 if (!$node || !$node.length) { 1417 return; 1418 } 1419 $node.removeClass("af-bid-flash"); 1420 void $node[0].offsetWidth; // restart the CSS animation 1421 $node.addClass("af-bid-flash"); 1422 setTimeout(function () { $node.removeClass("af-bid-flash"); }, 1500); 1423 } 1424 1425 function afBidWatchTick() { 1426 if (!afBidWatchEnabled()) { afStopBidWatch(); return; } 1427 if (document.hidden || afBidWatch.busy) { 1428 return; 1429 } 1430 1431 var $lots = $(AF_FUTURE_SEL + " .bp-lot").filter(function () { 1432 return $(this).attr("data-ended") !== "1" && 1433 $(this).attr("data-lot-index") !== undefined && 1434 !!$(this).attr("data-auction-number"); 1435 }); 1436 if (!$lots.length) { 1437 return; 1438 } 1439 1440 var groups = {}; 1441 $lots.each(function () { 1442 var a = $(this).attr("data-auction-number"); 1443 var li = $(this).attr("data-lot-index"); 1444 if (!a || li === undefined) { return; } 1445 (groups[a] = groups[a] || []).push(li); 1446 }); 1447 1448 var auctionIds = Object.keys(groups); 1449 if (!auctionIds.length) { 1450 return; 1451 } 1452 1453 afBidWatch.busy = true; 1454 var pending = auctionIds.length; 1455 function done() { pending--; if (pending <= 0) { afBidWatch.busy = false; } } 1456 1457 auctionIds.forEach(function (auctionId) { 1458 bidspiritQuery("items/getItemsInfo", { 1459 sessionId: bidspiritSessionId, 1460 auctionId: auctionId, 1461 lotIndexes: groups[auctionId].join(",") 1462 }, function (data) { 1463 if (!data || !data.response || !data.response.itemsInfo) { return; } 1464 var resp = data.response; 1465 var live = resp.auctionIsLive === true; 1466 groups[auctionId].forEach(function (li) { 1467 var info = resp.itemsInfo[li]; 1468 if (!info) { return; } 1469 var $lot = $(AF_FUTURE_SEL + " .bp-lot[data-auction-number='" + auctionId + "'][data-lot-index='" + li + "']"); 1470 if ($lot.length) { afPatchWatchedLot($lot.first(), info, live); } 1471 }); 1472 }, function () {}, done); 1473 }); 1474 } 1475 1476 // Is this rendered lot part of a shop? Profile rows carry the auction id in 1477 // data-auction-number, and bs_data.shop_auction_ids lists every shop on the 1478 // site (legacy "Auctions as shop" plus any BidSpirit Shop). 1479 function afIsShopLot($lot) { 1480 var ids = (window.bs_data && bs_data.shop_auction_ids) ? bs_data.shop_auction_ids : []; 1481 if (!ids.length) { 1482 return false; 1483 } 1484 return ids.indexOf(String($lot.attr("data-auction-number"))) !== -1; 1485 } 1486 1487 function afPatchWatchedLot($lot, info, auctionIsLive) { 1488 var L = window.afBidWatchLang || {}; 1489 var current = (auctionIsLive && info.liveBid && info.liveBid.price !== undefined && info.liveBid.price !== null) 1490 ? info.liveBid : info.leadingBid; 1491 var hasSelfAbsentee = info.selfAbsenteeBid && info.selfAbsenteeBid.price !== undefined && info.selfAbsenteeBid.price !== null; 1492 var sold = (info.soldBid && info.soldBid.isSold === true) || (current && current.isSold === true); 1493 1494 var $tool = $lot.find(".bp-lot__tool").first(); 1495 var $price = $tool.find(".bp-price").first(); 1496 var $subtitle = $tool.find(".bp-subtitle").first(); 1497 var $message = $lot.find(".bp-lot__message").first(); 1498 if (!$tool.length || !$price.length) { 1499 return; 1500 } 1501 1502 var oldPriceText = $.trim($price.text()); 1503 var newPriceVal, subtitle, bgClass = "", withLead = false, messageHtml = ""; 1504 1505 if (sold) { 1506 var sb = (info.soldBid && info.soldBid.price !== undefined) ? info.soldBid : current; 1507 newPriceVal = sb.price; 1508 subtitle = sb.isSelf ? (L.sold_to_you_for || "Sold to you for") : (L.sold_for || "Sold for"); 1509 bgClass = sb.isSelf ? "bp-bg-green" : "bp-bg-blue"; 1510 withLead = true; 1511 $lot.attr("data-ended", "1"); // ended during watch — drop from future ticks 1512 } else if (current && current.price !== undefined && current.price !== null) { 1513 newPriceVal = current.price; 1514 subtitle = current.isSelf ? (L.your_leading_bid || "Your leading bid") : (L.leading_bid || "Leading bid"); 1515 withLead = true; 1516 if (current.isSelf) { 1517 bgClass = "bp-bg-green"; 1518 } else if (hasSelfAbsentee) { 1519 bgClass = "bp-bg-red"; 1520 } 1521 1522 if (!current.isSelf && hasSelfAbsentee) { 1523 messageHtml = '<p class="bp-lot__message-inner bp-text-red bp-lot__message-you_bid">' + 1524 (L.your_bid_of || "Your bid of") + " " + formattedPrice(info.selfAbsenteeBid.price, currencySymbol) + " " + 1525 (L.outbid_by_higher || "has been outbid by a higher bid") + "</p>"; 1526 } else if (current.isSelf && hasSelfAbsentee) { 1527 messageHtml = '<p class="bp-lot__message-inner bp-text-green bp-lot__message-you_bid">' + 1528 (L.your_max_absentee_bid || "Your max absentee bid") + ": " + formattedPrice(info.selfAbsenteeBid.price, currencySymbol) + "</p>"; 1529 } 1530 } else if (afIsShopLot($lot)) { 1531 // A shop item is bought at a fixed price and has no start price 1532 // (the API reports 0). Without this branch every 10s tick overwrote 1533 // the rendered "Purchase price" with "Start price: $0". 1534 var buyout = (info.buyoutPrice !== undefined && info.buyoutPrice !== null) ? info.buyoutPrice : 0; 1535 if (buyout <= 0) { 1536 // Nothing meaningful to patch — leave what was rendered rather 1537 // than replacing a correct price with a wrong one. 1538 return; 1539 } 1540 newPriceVal = buyout; 1541 subtitle = L.purchase_price || "Purchase Price"; 1542 } else { 1543 newPriceVal = info.startPrice;
1544 subtitle = L.start_price || "Start price"; 1545 } 1546 1547 if ($subtitle.length) { 1548 $subtitle.text(subtitle + ":"); 1549 } 1550 $tool.removeClass("bp-bg-green bp-bg-red bp-bg-blue"); 1551 if (bgClass) { 1552 $tool.addClass(bgClass); 1553 } 1554 if (withLead) { 1555 $tool.addClass("bp-lead"); 1556 } else { 1557 $tool.removeClass("bp-lead"); 1558 } 1559 if ($message.length) { 1560 $message.html(messageHtml); 1561 } 1562 1563 var newPriceText = formattedPrice(newPriceVal, currencySymbol); 1564 if (newPriceText !== oldPriceText) { 1565 $price.text(newPriceText); 1566 afFlashPrice($price); 1567 } 1568 } 1569 1570 // Instant refresh when the user returns to the tab (registered once). 1571 if (!window.afBidWatchVisBound) { 1572 window.afBidWatchVisBound = true; 1573 document.addEventListener("visibilitychange", function () { 1574 if (!document.hidden && afBidWatchEnabled()) { 1575 if (!afBidWatch.intervalId) { afStartBidWatch(); } else { afBidWatchTick(); } 1576 } 1577 }); 1578 } 1579 1580 function updateUserDisplay() { 1581 (function () { 1582 var userFront = $("#userFront"); 1583 1584 if (bidspiritUser && userFront.length) { 1585 loadTemplate("#modal-profile-content", "user-profile-form", bidspiritUser); 1586 } 1587 })(); 1588 } 1589 1590 function someCode() { 1591 var singleLogin = $(".bp-single-login-btn"); 1592 1593 if (singleLogin.length && bidspiritUser !== undefined) { 1594 singleLogin.addClass(window.bs_data.hidden_class); 1595 } 1596 1597 if (bidspiritUser !== undefined) { 1598 $(".bp-register-api, .bp-login-api").each(function (index, elem) { 1599 if (elem.name === "bp_short_login_form" || elem.name === "bp_short_register_form") { 1600 elem.innerHTML = '<div class="bs-loader-small"></div>'; 1601 window.location = window.bs_data.link_profile; 1602 } else { 1603 elem.innerHTML = "<p class='bp-notice'>" + window.bs_lang.login_success_hello + ", " + bidspiritUser.firstName + "!</p>"; 1604 } 1605 }); 1606 } 1607 } 1608 1609 function noticeUser(bidspiritUser) { 1610 var mainContentContainer = $(".bp-main-container"); 1611 1612 if (bidspiritUser !== undefined && bidspiritUser.approvalState !== null && bidspiritUser.approvalState !== "APPROVED" && mainContentContainer.length) { 1613 mainContentContainer.empty(); 1614 loadTemplateInsert(mainContentContainer, "main-notice-template", { 1615 type: bidspiritUser.approvalState, 1616 emailConfirmed: bidspiritUser.emailConfirmed 1617 }, true, true, function () { 1618 resendEmailAction(); 1619 changeEmailAction(); 1620 }); 1621 } 1622 } 1623 1624 function renderVatField(auctionHouseData) { 1625 var fullVatPrice = Boolean(parseInt($("#single-lot").attr("data-full-price-vat"))); 1626 1627 if (auctionHouseData.noVatOnCommission && !fullVatPrice) { 1628 $(".vat-field").remove(); 1629 } else if (auctionHouseData.noVatOnCommission && fullVatPrice) { 1630 $(".vat-field span").html(window.bs_lang.vat_lot_price_commission); 1631 } 1632 } 1633 1634 /** 1635 * Checks for unpaid invoices and shows a site-wide banner. 1636 * Uses server-side WordPress transients to avoid API calls on every page load. 1637 * Called once from initCore() when a user is logged in. 1638 * 1639 * Session logic: 1640 * - First page load of a browser session (or after login): always fetches fresh from BidSpirit API. 1641 * - Subsequent page loads in the same session: uses the server-side cache. 1642 * - If the user clicked "Pay Now" (banner or individual bill): banner is suppressed for this session. 1643 */ 1644 function checkUnpaidBillsBanner() { 1645 // Site has the My Invoices tab disabled — the banner's "Pay Now" would 1646 // link to a profile tab that doesn't exist, so skip the check entirely. 1647 if (window.afBillingTabEnabled === false) return; 1648 if (!bidspiritUser || !bidspiritUser.email) return; 1649 var userKey = bidspiritUser.email; 1650 1651 try { 1652 // First page load of a session (or right after login): bypass cache, fetch fresh 1653 if (!sessionStorage.getItem("af_bills_session_checked")) { 1654 fetchAndCacheUnpaidBills(userKey); 1655 return; 1656 } 1657 } catch(e) {} 1658
1659 // Subsequent page loads: check server-side cache first 1660 $.ajax({ 1661 type: "post", 1662 dataType: "json", 1663 url: window.wp_data.ajax_url, 1664 data: { 1665 action: "af_get_unpaid_status", 1666 security: window.wp_nonce, 1667 user_key: userKey 1668 } 1669 }).done(function(res) { 1670 if (res.success && res.data.cached) { 1671 // Cache hit — use stored status, no BidSpirit API call 1672 if (res.data.has_unpaid) { 1673 renderUnpaidBanner(res.data.count); 1674 } 1675 return; 1676 } 1677 // Cache miss — fetch from BidSpirit API 1678 fetchAndCacheUnpaidBills(userKey); 1679 }).fail(function() { 1680 // WP AJAX failed — try BidSpirit directly as fallback 1681 fetchAndCacheUnpaidBills(userKey); 1682 }); 1683 } 1684 1685 /** 1686 * Fetches unpaid bills from BidSpirit and stores result in server-side cache. 1687 * Sets a sessionStorage flag so subsequent page loads in the same session use the cache. 1688 */ 1689 function fetchAndCacheUnpaidBills(userKey) { 1690 bidspiritQuery("bills/getUnpaidBills", { 1691 sessionId: bidspiritSessionId, 1692 language: LANG 1693 }, function (data) { 1694 var bills = data && data.response ? data.response : []; 1695 if (!Array.isArray(bills)) bills = []; 1696 var count = bills.length; 1697 1698 // Mark this session as checked so subsequent page loads use the cache 1699 try { sessionStorage.setItem("af_bills_session_checked", "1"); } catch(e) {} 1700 1701 // Store in server-side cache 1702 $.ajax({ 1703 type: "post", 1704 url: window.wp_data.ajax_url, 1705 data: { 1706 action: "af_set_unpaid_status", 1707 security: window.wp_nonce, 1708 user_key: userKey, 1709 count: count 1710 } 1711 }); 1712 1713 if (count > 0) { 1714 renderUnpaidBanner(count); 1715 } 1716 }, function () { 1717 // BidSpirit API failed — don't show banner 1718 }); 1719 } 1720 1721 /** 1722 * Clears the server-side unpaid bills cache for the current user. 1723 */ 1724 function clearUnpaidBillsCache() { 1725 if (!bidspiritUser || !bidspiritUser.email) return; 1726 $.ajax({ 1727 type: "post", 1728 url: window.wp_data.ajax_url, 1729 data: { 1730 action: "af_set_unpaid_status", 1731 security: window.wp_nonce, 1732 user_key: bidspiritUser.email, 1733 clear: "1" 1734 } 1735 }); 1736 } 1737 1738 /** 1739 * Renders (or removes) the unpaid invoice alert banner. 1740 */ 1741 function renderUnpaidBanner(count) { 1742 // Remove any existing banner first 1743 $(".bp-unpaid-invoice-banner").remove(); 1744 1745 if (!count || count <= 0) return; 1746 1747 var profileUrl = (window.bs_data && window.bs_data.link_profile) 1748 ? window.bs_data.link_profile + "#bp-bills" 1749 : "#bp-bills"; 1750 1751 var bannerHtml = '<div class="bp-unpaid-invoice-banner" style="' + 1752 'width: 100%; z-index: 999; ' + 1753 'background: #cc0000; ' + 1754 'color: #fff; text-align: center; padding: 10px 20px; ' + 1755 'font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; ' + 1756 'display: flex; align-items: center; justify-content: center; gap: 15px;">' + 1757 '<span style="font-weight: 700;">⚠This account has open invoices</span>' + 1758 '<a href="' + profileUrl + '" class="bp-unpaid-pay-btn" style="' + 1759 'display: inline-block; background: #fff; color: #000; ' + 1760 'padding: 5px 20px; border-radius: 50px; text-decoration: none; ' + 1761 'font-weight: 700; font-size: 13px; ' + 1762 'transition: background 0.2s ease; border: none; cursor: pointer;"' + 1763 ' onmouseover="this.style.background=\'#e6e6e6\'" onmouseout="this.style.background=\'#fff\'"' + 1764 '>Pay Now</a>' + 1765 '</div>'; 1766 1767 // Insert after the site header 1768 var $header = $("header.elementor-location-header, #masthead, header").first(); 1769 if ($header.length) { 1770 $header.after(bannerHtml); 1771 } else { 1772 $("body").prepend(bannerHtml); 1773 } 1774 1775 // Clear cache and remove banner; next page load will do a fresh check 1776 $(".bp-unpaid-pay-btn").on("click", function(e) { 1777 clearUnpaidBillsCache(); 1778 try { sessionStorage.removeItem("af_bills_session_checked"); } catch(e2) {} 1779 1780 // If we're already on the profile page, activate the tab directly 1781 var billsTab = $('.bp-tabs-block a[href="#bp-bills"]'); 1782 if (billsTab.length) { 1783 e.preventDefault(); 1784 // Set hash — the hashchange listener will handle the tab switch + scroll 1785 window.location.hash = "#bp-bills"; 1786 // Remove the banner 1787 $(".bp-unpaid-invoice-banner").remove(); 1788 } 1789 }); 1790 } 1791 1792 /** 1793 * Watches for clicks on individual invoice "Pay Now" / "Resume" buttons 1794 * in the My Invoices tab. Clears the server-side unpaid cache so the 1795 * banner re-evaluates on the next page load. 1796 */ 1797 $(document).on("click", "#profile-bills-section a.bp-btn", function() { 1798 var href = $(this).attr("href") || ""; 1799 // Only act on payment links (Pay Now / Resume), not View or Download PDF 1800 if (href.indexOf("standaloneScene=payment") !== -1 || href.indexOf("paymentUrl") !== -1) { 1801 clearUnpaidBillsCache(); 1802 try { sessionStorage.removeItem("af_bills_session_checked"); } catch(e) {} 1803 // Remove the banner immediately since user is taking action 1804 $(".bp-unpaid-invoice-banner").remove(); 1805 } 1806 }); 1807 1808 function initApp() { 1809 var firebaseTokenFCM = getCookie("FCM_TOKEN"); 1810 1811 if (firebaseTokenFCM !== "") { 1812 try { 1813 localStorage.setItem("token_firebase_push_id", firebaseTokenFCM); 1814 } catch (e) { 1815 console.error("Local storage disabled"); 1816 } 1817 } 1818 } 1819
1820 function init() { 1821 $("#bsLoader").removeClass(window.bs_data.hidden_class); 1822 bidspiritApi.setBidspiritSessionId(); 1823 bidspiritQuery("users/initSession", { 1824 sessionId: bidspiritApi.getBidspiritSessionId(), 1825 language: LANG 1826 }, function (data) { 1827 let coreData = data; 1828 if (data.response !== undefined) { 1829 function initCore(data) { 1830 updateUserDisplay(); 1831 updateDisplay(); 1832 loginLink(); 1833 someCode(); 1834 1835 galleryInitial(); 1836 updateLotsWidget(); 1837 updateWidgetLots(); 1838 widgetSliders(); 1839 1840 hangUpEvent("bp:after-init", data.response); 1841 checkPoint("bp-init"); 1842 1843 if (bidspiritUser !== undefined) { 1844 checkPoint("bp-login"); 1845 1846 if (bidspiritUser.approvalState !== undefined && bidspiritUser.approvalState === "APPROVED") { 1847 checkPoint("bp-approved-user"); 1848 } 1849 1850 // Check for unpaid invoices (uses server-side cache) 1851 checkUnpaidBillsBanner(); 1852 } 1853 } 1854 1855 if (data.response.user !== undefined) { 1856 bidspiritApi.setAuthToken(data.response.user.authToken); 1857 } 1858 1859 try { 1860 bidspiritSessionId = localStorage.bidspiritSessionId = data.response.sessionId; 1861 } catch (e) { 1862 console.error("Local storage disabled"); 1863 bidspiritSessionId = ""; 1864 } 1865 1866 bidspiritQuery("settings/getHouseInfo", { 1867 sessionId: bidspiritSessionId, 1868 language: LANG 1869 }, function (data) { 1870 auctionHouseData = data.response; 1871 bidspiritApi.setAuctionHouseData(auctionHouseData); 1872 }); 1873 1874 bidspiritApi.setBidspiritUser(data.response.user); 1875 1876 bidspiritQuery("settings/getSettings", { 1877 sessionId: bidspiritSessionId, 1878 language: LANG 1879 }, function (data) { 1880 auctionSettingsData = data.response; 1881 bidspiritApi.setAuctionSettingsData(auctionSettingsData); 1882 1883 initCore(coreData); 1884 }); 1885 } 1886 1887 bidspiritQuery("settings/getCountriesList", { 1888 sessionId: bidspiritSessionId, 1889 language: LANG 1890 }, function (data) { 1891 countriesList = data.response; 1892 bidspiritApi.setCountriesList(countriesList); 1893 1894 (function () { 1895 let codeSelect = jQuery('.countryCodeField'), 1896 countriesList = bidspiritApi.getCountriesList(), 1897 codeItems = jQuery.map(countriesList, function (obj) { 1898 if (obj.phoneCode !== undefined) { 1899 return { 1900 id: obj.phoneCode, 1901 text: obj.phoneCode + " (" + obj.name + ")" 1902 }; 1903 } 1904 }); 1905 codeSelect.each(function (index, elem) { 1906 if (elem.classList.contains(window.bs_data.hidden_class)) { 1907 elem.classList.remove(window.bs_data.hidden_class); 1908 } 1909 1910 if (!!jQuery(elem).select2) { 1911 jQuery(elem).select2({ 1912 theme: "default bp-custom-select", 1913 width: "resolve", 1914 data: codeItems, 1915 placeholder: window.bs_lang.country_code 1916 }); 1917 } 1918 }) 1919 })(); 1920 }); 1921 1922 passwordShowAction(); 1923 }, function (data) { 1924 disableLoader(); 1925 }); 1926 } 1927 1928 function loadBid(lotIndex, currentAuctionNumber) { 1929 // A BidSpirit Shop lot belongs to no auction, so items/getAuctionItem 1930 // and items/getItemsInfo have nothing to return for it — calling them 1931 // would just log the lot as not found. Drive the buy-now UI from the 1932 // server-rendered price instead. 1933 if (bsShopIsActive()) { 1934 bsShopRenderBuy(lotIndex, currentAuctionNumber); 1935 return; 1936 } 1937 1938 function vatAndCommission() { 1939 if (!!document.getElementById('vat-and-commission')) { 1940 let itemInfo = bidspiritApi.getAuctionItemInfo(), 1941 auctionInfo = bidspiritApi.getAuctionInfo(); 1942 if (itemInfo.item !== undefined) { 1943 loadTemplate('#vat-and-commission', 'vat-and-commission-template', { 1944 itemInfo: itemInfo, 1945 fullPriceInfo: getFullPriceInfo(itemInfo, auctionInfo, 1), 1946 auctionHouseData: bidspiritApi.getAuctionSettingsData(),//bidspiritApi.getAuctionHouseData() - some fields depricated 1947 settings: bidspiritApi.getAuctionSettingsData(), 1948 bidspiritUser: bidspiritUser, 1949 }) 1950 } 1951 } 1952 } 1953 1954 if (currentAuctionNumber === "") { 1955 return; 1956 } 1957 1958 bidspiritQuery("items/getAuctionItem", { 1959 sessionId: bidspiritSessionId, 1960 auctionId: currentAuctionNumber, 1961 itemIndex: lotIndex, 1962 language: LANG 1963 }, function (data) { 1964 String.prototype.allReplace = function (obj) { 1965 var retStr = this; 1966 1967 for (var x in obj) { 1968 retStr = retStr.replace(new RegExp("\\" + x, "g"), obj[x]); 1969 } 1970 1971 return retStr; 1972 }; //oversea 1973 1974 bidspiritApi.setAuctionItemInfo(data.response); 1975 1976 if (data.response !== undefined) { 1977 hangUpEvent("bp:get-auction-item", data.response); 1978 } 1979 1980 vatAndCommission(); 1981 1982 if ($('#startPriceSingleLot').length > 0) { 1983 if (data.response.item.startPrice !== undefined && data.response.item.currency !== undefined) { 1984 $('#startPriceSingleLot').html(formattedPrice(data.response.item.startPrice, data.response.item.currency, true)); 1985 } 1986 } 1987 1988 bidspiritQuery("items/getItemsInfo", { 1989 sessionId: bidspiritSessionId, 1990 auctionId: currentAuctionNumber, 1991 lotIndexes: lotIndex 1992 }, function (data) { 1993 if (!checkError(data)) { 1994 if (data.response !== undefined) { 1995 hangUpEvent("bp:get-items-info", data.response); 1996 } 1997 1998 // Live auction: pop the "Auction is live" modal on single-lot pages 1999 // (catalogue pages get this via updateBidsInfoDisplay) 2000 if (data.response !== undefined && data.response.auctionIsLive === true) {
2001 loadTemplate("#modal-islive-content", "modal-islive-template", { 2002 bidsInfoData: data.response, 2003 linkLive: bidspiritApi.getLinkOnLive() 2004 }); 2005 MicroModal.init(microModalInitConfig()); 2006 MicroModal.show("modal-islive", microModalInitConfig()); 2007 } 2008 2009 if (data.response.notFoundLots[0] === lotIndex) { 2010 console.error("error", "Lot " + lotIndex, window.bs_lang.not_found); 2011 disableLoader(); 2012 } else { 2013 currentItemInfoResponse = data.response; 2014 currentItemInfo = data.response.itemsInfo[lotIndex]; 2015 2016 if (bpIsset(currentItemInfo)) { 2017 if (bpIsset(currentItemInfo.isFavorite) && currentItemInfo.isFavorite) { 2018 $("#single-lot").find(".bp__wishlist").addClass("bp__wishlist-active"); 2019 } 2020 2021 displayBidFormData(currentItemInfo); 2022 buyoutAction(currentItemInfoResponse, lotIndex, currentAuctionNumber); 2023 postSaleAction(currentItemInfoResponse, lotIndex, currentAuctionNumber); 2024 renderVatField(auctionHouseData); 2025 hangUpEvent("bp:after-getItemsInfo-content-item", currentItemInfo, $("#single-lot")); 2026 } else { 2027 noticeSwall("info", window.bs_lang.not_found); 2028 disableLoader(); 2029 } 2030 } 2031 } else { 2032 disableLoader(); 2033 } 2034 }); 2035 }); 2036 } 2037 2038 // ── BidSpirit Shop ──────────────────────────────────────────────────── 2039 // A Shop lot is a fixed-price item that lives outside the auction system: 2040 // shop/getShopItems reports auctionId 0 and no itemIndex, so none of the 2041 // auction endpoints can describe it. AuctionForge imports it as an ordinary 2042 // lot (inc/import/ShopList.php) and the template stamps its price onto 2043 // #preSale-section, which is all the buy flow actually needs. 2044 2045 function bsShopSection() { 2046 return $("#preSale-section[data-bs-shop='1']"); 2047 } 2048 2049 // True on any shop surface — the lot page (#preSale-section) and the shop 2050 // catalogue page (the lots container), which both stamp data-bs-shop. 2051 function bsShopIsActive() { 2052 return $("[data-bs-shop='1']").length > 0; 2053 } 2054 2055 // Minimal auctionInfo for a shop. There is no auction to fetch, so anything 2056 // reading bidspiritApi.getAuctionInfo() gets a sane object rather than 2057 // undefined. Commission is 0 deliberately: shop/purchaseShopItem requires 2058 // price to equal shopPrice exactly, so a premium must not be displayed. 2059 function bsShopAuctionInfo() { 2060 return { 2061 id: 0, 2062 state: "READY", 2063 commission: 0, 2064 approvalRequired: false, 2065 paymentMethodRequired: false, 2066 auctionIsLive: false, 2067 days: [], 2068 increments: [] 2069 }; 2070 } 2071 2072 // Rebuild the shape items/getItemsInfo would have returned, from what the 2073 // server already rendered. Keeps the whole downstream buy flow unchanged. 2074 function bsShopItemInfoResponse(lotIndex) { 2075 var $section = bsShopSection(), 2076 price = parseInt($section.attr("data-shop-price"), 10) || 0, 2077 sold = parseInt($section.attr("data-shop-sold"), 10) || 0, 2078 itemInfo = { 2079 lotIndex: lotIndex, 2080 lotId: parseInt($section.attr("data-shop-lot-id"), 10) || parseInt(lotIndex, 10), 2081 startPrice: 0, 2082 buyoutPrice: price 2083 }; 2084 2085 // A sold shop item keeps its page but must not offer a buy button — 2086 // buyoutAction() already bails when soldBid carries a price. 2087 if (sold > 0) { 2088 itemInfo.soldBid = {price: sold, isSold: true, isSelf: false}; 2089 } 2090 2091 var itemsInfo = {}; 2092 itemsInfo[lotIndex] = itemInfo; 2093 2094 return { 2095 state: "READY", 2096 auctionIsLive: false, 2097 notFoundLots: [], 2098 itemsInfo: itemsInfo 2099 }; 2100 } 2101 2102 function bsShopRenderBuy(lotIndex, auctionNumber) { 2103 var response = bsShopItemInfoResponse(lotIndex); 2104 2105 currentItemInfoResponse = response; 2106 currentItemInfo = response.itemsInfo[lotIndex]; 2107
2108 buyoutAction(response, lotIndex, auctionNumber); 2109 hangUpEvent("bp:after-getItemsInfo-content-item", currentItemInfo, $("#single-lot")); 2110 2111 // #bsLoader ships visible and is only ever hidden by disableLoader() in 2112 // the getAuctionItem/getItemsInfo callbacks — which this path skips. Without 2113 // this the page renders correctly but sits behind a full-screen 90%-white 2114 // overlay at z-index 999 that also swallows every click. 2115 disableLoader(); 2116 } 2117 2118 function buyoutAction(currentItemInfoResponse, lotIndex, auctionNumber) { 2119 var currentItemInfo = currentItemInfoResponse.itemsInfo[lotIndex], 2120 preSaleSectionSelector = "#preSale-section", 2121 auctionInfo = bidspiritApi.getAuctionInfo(), 2122 // Shop lots have no auction behind them, so these two lookups come 2123 // back empty. Defaulting keeps the shared path working for both. 2124 auctionCommission = (auctionInfo && auctionInfo.commission) ? auctionInfo.commission : 0, 2125 modalPreSaleForm = "#modal-pre-sale-content", 2126 auctionItemInfo = bidspiritApi.getAuctionItemInfo(), 2127 fullPriceVat = (auctionItemInfo && auctionItemInfo.item) ? auctionItemInfo.item.fullPriceVat : false, 2128 isShop = Boolean(parseInt($(preSaleSectionSelector).attr("data-is-shop"))), 2129 isBsShop = $(preSaleSectionSelector).attr("data-bs-shop") === "1"; 2130 2131 if (currentItemInfoResponse.state === "ENDED" || currentItemInfoResponse.state === "ARCHIVED") { 2132 return; 2133 } 2134 2135 if (currentItemInfoResponse.auctionIsLive === true || currentItemInfo.buyoutPrice === undefined) { 2136 return; 2137 } 2138 2139 if (currentItemInfo.leadingBid !== undefined && currentItemInfo.leadingBid.price !== undefined && currentItemInfo.leadingBid.price >= currentItemInfo.buyoutPrice) { 2140 return; 2141 } 2142 2143 if (currentItemInfo.soldBid !== undefined && currentItemInfo.soldBid.price !== undefined) { 2144 return; 2145 } 2146 2147 $(modalPreSaleForm).off("click", "#agreeSaleBid").on("click", "#agreeSaleBid", function (event) { 2148 event.preventDefault(); 2149 let $this = $(this); 2150 $this.prop("disabled", true); 2151 $this.addClass("bp-disabled"); 2152 // A BidSpirit Shop item is bought through the shop endpoint, which 2153 // is keyed on the item's own lotId rather than an auction + index, 2154 // and requires price to equal shopPrice exactly. 2155 var purchaseAction = isBsShop ? "shop/purchaseShopItem" : "items/buyout", 2156 purchaseData = isBsShop 2157 ? { 2158 sessionId: bidspiritSessionId, 2159 lotId: currentItemInfo.lotId, 2160 price: currentItemInfo.buyoutPrice 2161 } 2162 : { 2163 sessionId: bidspiritSessionId, 2164 auctionId: auctionNumber, 2165 lotIndex: lotIndex, 2166 price: currentItemInfo.buyoutPrice 2167 }; 2168 2169 bidspiritPostQuery(purchaseAction, purchaseData, function (data) { 2170 if (!checkError(data)) { 2171 if (data.response.success === true) { 2172 MicroModal.close("modal-pre-sale"); 2173 $(modalPreSaleForm).empty(); 2174 $(preSaleSectionSelector).empty(); 2175 loadTemplate(modalPreSaleForm, "modal-presale-confirm-template", { 2176 data: auctionHouseData 2177 }, false, function () { 2178 MicroModal.show("modal-pre-sale", microModalInitConfig()); 2179 }); 2180 // The shop's sold state is rendered server-side, so mark 2181 // it here too — otherwise the loadBid() refresh below 2182 // reads the stale attribute and re-offers a sold item. 2183 if (isBsShop) { 2184 $(preSaleSectionSelector).attr("data-shop-sold", currentItemInfo.buyoutPrice); 2185 } 2186 loadBid(lotIndex, auctionNumber); 2187 } 2188 } else { 2189 MicroModal.close("modal-pre-sale"); 2190 noticeSwall("info", data.response.errorMessage); 2191 $(preSaleSectionSelector).empty(); 2192 } 2193 }, function () { 2194 }, function () { 2195 $this.prop("disabled", false); 2196 $this.removeClass("bp-disabled"); 2197 }); 2198 }); 2199 2200 if (currentItemInfo.buyoutPrice > 0 && currentItemInfo.buyoutPrice >= currentItemInfo.startPrice) { 2201 var commissionPrice = calculateCommission(currentItemInfo.buyoutPrice, auctionCommission, fullPriceVat); 2202 loadTemplate(preSaleSectionSelector, "pre-sale-template", { 2203 currentItemInfo: currentItemInfo, 2204 currentCurrency: currencySymbol, 2205 price: currentItemInfo.buyoutPrice, 2206 commissionPrice: commissionPrice, 2207 isShop: isShop 2208 }, true, function () { 2209 $(preSaleSectionSelector).on("click", "#pre-sale-action", function (event) { 2210 event.preventDefault(); 2211 2212 if (!bidspiritUser) { 2213 try { 2214 MicroModal.show("modal-login", microModalInitConfig()); 2215 } catch (e) { 2216 console.error(e); 2217 } 2218 2219 return; 2220 } 2221 2222 var lotName = $(modalPreSaleForm).attr("data-name"), 2223 lotLinkTerm = window.bs_data.page_terms; 2224 MicroModal.show("modal-pre-sale", microModalInitConfig()); 2225 loadTemplate(modalPreSaleForm, "modal-presale-template", { 2226 index: currentItemInfo.lotIndex, 2227 name: lotName, 2228 currentCurrency: currencySymbol, 2229 price: currentItemInfo.buyoutPrice, 2230 linkTerms: lotLinkTerm, 2231 commissionPrice: commissionPrice,
2232 buyoutAction: true, 2233 auctionCommission: auctionCommission, 2234 auctionHouseData: auctionHouseData, 2235 fullPriceVat: fullPriceVat, 2236 settings: auctionSettingsData, 2237 user: bidspiritUser, 2238 isShop: isShop 2239 }, false, function () { 2240 $(modalPreSaleForm).on("click", "#dontAgreeSaleBid", function (event) { 2241 event.preventDefault(); 2242 MicroModal.close("modal-pre-sale"); 2243 }); 2244 }); 2245 }); 2246 }); 2247 } else { 2248 console.info("not for pre sold"); 2249 } 2250 } 2251 2252 function postSaleAction(currentItemInfoResponse, lotIndex, currentAuctionNumber) { 2253 var currentItemInfo = currentItemInfoResponse.itemsInfo[lotIndex], 2254 postSaleSectionSelector = "#postSaleBid", 2255 auctionInfo = bidspiritApi.getAuctionInfo(), 2256 //houseInfo = bidspiritApi.getAuctionHouseData(), 2257 auctionCommission = auctionInfo.commission, 2258 auctionItemInfo = bidspiritApi.getAuctionItemInfo(), 2259 fullPriceVat = auctionItemInfo.item.fullPriceVat, 2260 //postAuctionSaleOpenedUntil = Boolean(parseInt($(postSaleSectionSelector).attr("data-post-auction-sale-opened-until"))), 2261 wrpNotice = $(postSaleSectionSelector).parents(".bp-control__notice"), 2262 modalPostSaleForm = "#modal-post-sale-content", 2263 commissionPrice = calculateCommission(currentItemInfo.postSalePrice, auctionCommission, fullPriceVat), 2264 timestamp = new Date().getTime(); 2265 2266 let [currentAuctionDayIndex, postAuctionSaleOpenedUntil] = initialPostAuctionSaleOpenedUntil(auctionInfo, lotIndex); 2267 2268 // Available and for first day with post sale enabled 2269 /*if (currentItemInfoResponse.state !== "ENDED" && currentItemInfoResponse.state !== "ARCHIVED") { 2270 return; 2271 }*/ 2272 2273 if (!postAuctionSaleOpenedUntil) { 2274 //console.log("testX2", auctionInfo, !postAuctionSaleOpenedUntil, postAuctionSaleOpenedUntil); 2275 return; 2276 } 2277 2278 if (currentItemInfo.soldBid !== undefined && currentItemInfo.soldBid.price !== undefined) { 2279 //console.log("testX33", auctionInfo, currentItemInfo, (currentItemInfo.soldBid !== undefined && currentItemInfo.soldBid.price !== undefined)); 2280 return; 2281 } 2282 2283 addBodyClass("bp_sale_action"); 2284 $(modalPostSaleForm).off("click", "#agreeSaleBid").on("click", "#agreeSaleBid", function (event) { 2285 event.preventDefault(); 2286 let $this = $(this); 2287 $this.prop("disabled", true); 2288 $this.addClass("bp-disabled"); 2289 bidspiritPostQuery("items/postSalePurchase", { 2290 sessionId: bidspiritSessionId, 2291 auctionId: currentAuctionNumber, 2292 lotIndex: lotIndex, 2293 price: currentItemInfo.postSalePrice 2294 }, function (data) { 2295 if (!checkError(data)) { 2296 if (data.response.success === true) { 2297 MicroModal.close("modal-pre-sale"); 2298 $(postSaleSectionSelector).empty(); 2299 $(modalPostSaleForm).empty(); 2300 loadTemplate(modalPostSaleForm, "modal-post-sale-confirm-template", { 2301 data: auctionHouseData 2302 }, false, function () { 2303 MicroModal.show("modal-post-sale", microModalInitConfig()); 2304 }); 2305 loadBid(lotIndex, currentAuctionNumber); 2306 } 2307 } else { 2308 MicroModal.close("modal-post-sale"); 2309 noticeSwall("info", data.response.errorMessage); 2310 $(modalPostSaleForm).empty(); 2311 } 2312 }, function () { 2313 }, function () { 2314 $this.prop("disabled", false); 2315 $this.removeClass("bp-disabled"); 2316 }); 2317 }); 2318 2319 //currentItemInfo.wasInLiveAuction 2320 //console.log("testX5", currentItemInfo, postAuctionSaleOpenedUntil > timestamp); 2321 if ((currentItemInfo.wasInLiveAuction === true) && postAuctionSaleOpenedUntil > timestamp) { 2322 wrpNotice.addClass("bp-control__notice-mod"); 2323 loadTemplate(postSaleSectionSelector, "post-sale-template", { 2324 currentItemInfo: currentItemInfo, 2325 currentCurrency: currencySymbol, 2326 price: currentItemInfo.postSalePrice 2327 }, true, function () { 2328 $(postSaleSectionSelector).on("click", "#post-sale-action", function (event) { 2329 var lotName = $(modalPostSaleForm).attr("data-name"), 2330 lotLinkTerm = window.bs_data.page_terms; 2331 2332 if (!bidspiritUser) { 2333 try { 2334 MicroModal.show("modal-login", microModalInitConfig()); 2335 } catch (e) { 2336 console.error(e); 2337 } 2338 2339 return; 2340 } 2341 2342 MicroModal.show("modal-post-sale", microModalInitConfig()); 2343 loadTemplate(modalPostSaleForm, "modal-post-sale-template", { 2344 index: currentItemInfo.lotIndex, 2345 name: lotName, 2346 currentCurrency: currencySymbol, 2347 price: currentItemInfo.postSalePrice, 2348 linkTerms: lotLinkTerm, 2349 commissionPrice: commissionPrice,
2350 buyoutAction: false, 2351 auctionHouseData: auctionHouseData, 2352 auctionCommission: auctionCommission, 2353 fullPriceVat: fullPriceVat 2354 }, false, function () { 2355 $(modalPostSaleForm).on("click", "#dontAgreeSaleBid", function (event) { 2356 event.preventDefault(); 2357 MicroModal.close("modal-post-sale"); 2358 }); 2359 }); 2360 }); 2361 }); 2362 } 2363 2364 hangUpEvent("bp:auction-sales", { 2365 currentItemInfoResponse, 2366 lotIndex, 2367 currentAuctionNumber 2368 }); 2369 } 2370 2371 function displayBidFormData(itemInfo) { 2372 currentItemInfo = itemInfo; 2373 let houseInfo = bidspiritApi.getAuctionHouseData(), 2374 settings = bidspiritApi.getAuctionSettingsData(), 2375 auctionItemInfo = currentItemInfoResponse["itemsInfo"][currentLotIndex], 2376 timestamp = new Date().getTime(); 2377 2378 let auctionInfo = bidspiritApi.getAuctionInfo(), 2379 lotIndex = auctionItemInfo.lotIndex; 2380 2381 let [currentAuctionDayIndex, postAuctionSaleOpenedUntil] = initialPostAuctionSaleOpenedUntil(auctionInfo, lotIndex); 2382 2383 function price(itemInfo) { 2384 var obj = { 2385 price: itemInfo.startPrice, 2386 leader: false 2387 }; 2388 2389 if (itemInfo["selfAbsenteeBid"] !== undefined && itemInfo["leadingBid"] !== undefined) { 2390 if (itemInfo["selfAbsenteeBid"].price && itemInfo["leadingBid"].isSelf) { 2391 obj.price = itemInfo["selfAbsenteeBid"].price; 2392 obj.leader = true; 2393 } else if (itemInfo["selfAbsenteeBid"].price) { 2394 obj.price = itemInfo["selfAbsenteeBid"].price; 2395 } else { 2396 obj.price = itemInfo["leadingBid"].price; 2397 } 2398 } else if (itemInfo["leadingBid"] !== undefined) { 2399 obj.price = itemInfo["leadingBid"].price; 2400 } 2401 2402 return obj; 2403 } 2404 2405 var visible = false, 2406 priceData = price(itemInfo); 2407 2408 if (currentItemInfoResponse.state === "ENDED" || currentItemInfoResponse.state === "ARCHIVED" || currentItemInfoResponse.state === "READY") { 2409 visible = true; 2410 } 2411 2412 if (auctionItemInfo.leadingBid !== undefined || auctionItemInfo.soldBid !== undefined) { 2413 visible = true; 2414 } 2415 2416 if (auctionItemInfo.selfAbsenteeBid !== undefined && auctionItemInfo.selfAbsenteeBid.price !== undefined) { 2417 visible = true; 2418 } 2419 2420 var singleLotSection = $("#single-lot"), 2421 hiddenPrice = false; 2422 2423 if (singleLotSection !== undefined) { 2424 hiddenPrice = Boolean(parseInt(singleLotSection.attr("data-hidden-price"))); 2425 } 2426 console.log("testX4", auctionInfo, currentAuctionDayIndex, auctionInfo.days[currentAuctionDayIndex], visible, postAuctionSaleOpenedUntil); 2427 loadTemplate("#leadingBid", "leadingBid-template", { 2428 currencySymbol: currencySymbol, 2429 item: auctionItemInfo, 2430 itemInfo: currentItemInfoResponse, 2431 postAuctionSaleOpenedUntil: postAuctionSaleOpenedUntil, 2432 postAuctionSaleOpened: (postAuctionSaleOpenedUntil > timestamp), 2433 obj: priceData, 2434 hiddenPrice: hiddenPrice, 2435 settings: settings, 2436 hideleadingBidSection: (auctionInfo.days[currentAuctionDayIndex] !== undefined && auctionInfo.days[currentAuctionDayIndex].auctionEnded === undefined) 2437 }, visible); 2438 loadTemplate("#houseInfo-section", "house-info-template", { 2439 auctionHouseData: bidspiritApi.getAuctionHouseData() 2440 }, visible); 2441 2442 if ( 2443 auctionItemInfo.wasInLiveAuction !== undefined && 2444 auctionItemInfo.wasInLiveAuction === false && 2445 auctionItemInfo.soldBid === undefined && 2446 auctionInfo.absenteeBidsEnabled !== undefined && 2447 auctionInfo.absenteeBidsEnabled === true 2448 ) {
2449 auctionIsLive(currentItemInfoResponse, auctionItemInfo); 2450 } else if ( 2451 auctionItemInfo.startPrice === 0 && 2452 settings.enablePrebidsUnderStartPrice !== undefined && 2453 settings.enablePrebidsUnderStartPrice === false && 2454 // Shop lots legitimately have startPrice 0 — they are bought at a 2455 // fixed price, never bid on — so this "wait for the catalog to be 2456 // published, then place absentee bids" notice is meaningless for 2457 // them. It was firing over the purchase confirmation modal on 2458 // buy-now sites. Covers both shop mechanisms, since data-is-shop is 2459 // set for an "Auctions as shop" auction and a BidSpirit Shop alike. 2460 // #preSale-section only exists on single-lot pages; elsewhere the 2461 // attribute is undefined, so this term is true and nothing changes. 2462 !Boolean(parseInt($("#preSale-section").attr("data-is-shop"))) 2463 ) { 2464 if (!getCookie("bs_read_notice") && !isDisabledReadNotice()) { 2465 noticeSwall("warning", window.bs_lang.auction_preview_title, window.bs_lang.auction_preview_notice, {}, function () { 2466 setCookie("bs_read_notice", true, 7); 2467 }); 2468 } 2469 } else { 2470 console.info("auctionIsLive", auctionInfo, auctionItemInfo); 2471 } 2472 2473 // Bid count fallback: adjust displayed count based on BidSpirit leading bid vs start price 2474 (function() { 2475 var $bidEl = $("#af-bid-count-display"); 2476 if (!$bidEl.length) return; 2477 var startPrice = parseFloat(auctionItemInfo.startPrice) || 0; 2478 var leadingBidPrice = 0; 2479 if (auctionItemInfo.leadingBid !== undefined && auctionItemInfo.leadingBid.price !== undefined) { 2480 leadingBidPrice = parseFloat(auctionItemInfo.leadingBid.price) || 0; 2481 } else if (auctionItemInfo.selfAbsenteeBid !== undefined && auctionItemInfo.selfAbsenteeBid.price !== undefined) { 2482 leadingBidPrice = parseFloat(auctionItemInfo.selfAbsenteeBid.price) || 0; 2483 } 2484 if (leadingBidPrice > 0) { 2485 var svg = $bidEl.find("svg").prop("outerHTML") || ""; 2486 var currentText = $bidEl.text().trim(); 2487 var currentCount = parseInt(currentText) || 0; 2488 var minCount = 1; 2489 if (leadingBidPrice > startPrice && startPrice > 0) { 2490 minCount = 2; 2491 } 2492 if (currentCount < minCount) { 2493 $bidEl.html(svg + minCount + " " + (minCount === 1 ? "bid" : "bids")); 2494 } 2495 } 2496 })(); 2497 2498 disableLoader(); 2499 } 2500 2501 function auctionIsLive(dataResponse, item) { 2502 loadTemplate("#auctionIsLive-section", "auctionIsLive-template", { 2503 isLive: dataResponse.auctionIsLive, 2504 auctionInfo: bidspiritApi.getAuctionInfo(), 2505 linkLive: bidspiritApi.getLinkOnLive(), 2506 state: dataResponse.state, 2507 fullPriceInfo: getFullPriceInfo(currentItemInfo, auctionInfo, 1), 2508 auctionHouseData: bidspiritApi.getAuctionHouseData(), 2509 item: item 2510 }); 2511 2512 function checkShowcaseEnable(showcaseEnable) { 2513 if ($("#dateTimeField").length) { 2514 let dateTimeField = $("#dateTimeField"), 2515 timeBegin = dateTimeField.attr("data-time"), 2516 dateStart = timeShift(new Date(Date.parse(timeBegin))), 2517 dateNow = new Date(), 2518 timeToStart = (dateStart - dateNow) / 1000 / 3600; 2519 showcaseEnable = Boolean(parseInt(dateTimeField.attr("data-showcase-enable"))); 2520 2521 if (parseInt(timeToStart) < parseInt(window.bs_data.auto_close_showcase)) { 2522 showcaseEnable = false; 2523 } 2524 } 2525 2526 return showcaseEnable; 2527 } 2528 2529 let showcaseEnable = window.bs_data.is_showcase_enable; 2530 2531 if (checkShowcaseEnable(showcaseEnable)) { 2532 let showcase = $("#showcase-section"); 2533 showcase.removeClass(window.bs_data.hidden_class); 2534 } 2535 2536 if (dataResponse.state === "PRE_AUCTION") { 2537 disableLoader(); 2538 } 2539 2540 select2init(); 2541 2542 if (dataResponse !== undefined) { 2543 hangUpEvent("bp:auction-is-live", dataResponse); 2544 } 2545 2546 $("#bp-showcase").on("click", function (event) { 2547 event.preventDefault(); 2548 2549 if (!checkShowcaseEnable(showcaseEnable)) { 2550 return; 2551 } 2552
2553 let $this = $(this), 2554 title = $("#single-lot h1").text(), 2555 skuCode = $("#single-lot").attr("data-lot-index"); 2556 $this.addClass(window.bs_data.loader_class); 2557 $.ajax({ 2558 url: window.wp_data.ajax_url, 2559 type: "POST", 2560 dataType: "json", 2561 data: { 2562 action: "do_showcase", 2563 security: window.wp_nonce, 2564 skuCode: skuCode 2565 } 2566 }).done(function (response) { 2567 if (response.success) { 2568 noticeSwall("success", window.bs_lang.showcase_success_title.replace(/#title#/, title), window.bs_lang.showcase_success_notice, {}, function () { 2569 if (response.data !== undefined && response.data.cart_url !== undefined) { 2570 window.location = response.data.cart_url; 2571 } 2572 }); 2573 } else { 2574 noticeSwall("error", "", response.data.notice); 2575 } 2576 }).fail(function () { 2577 noticeSwall("error", window.bs_lang.error); 2578 }).always(function () { 2579 $this.prop("disabled", true); 2580 $this.removeClass(window.bs_data.loader_class); 2581 }); 2582 }); 2583 } 2584 2585 function getDataForm(id) { 2586 var dataForm = {}, 2587 form = document.forms[id]; 2588 2589 if (document.forms[id] !== undefined) { 2590 Array.prototype.forEach.call(form.elements, function (elem, index) { 2591 if (!elem.disabled) { 2592 if (elem.type === "checkbox" || elem.type === "radio") { 2593 dataForm[elem.name] = elem.checked.toString(); 2594 } else { 2595 dataForm[elem.name] = elem.value; 2596 } 2597 } 2598 }); 2599 } 2600 2601 return dataForm; 2602 } 2603 2604 2605 // AuctionForge User Tracking - Device ID + Browser Fingerprint (Tier 1) 2606 function afGetDeviceId() { 2607 var key = 'af_device_id'; 2608 var id = null; 2609 try { id = localStorage.getItem(key); } catch(e) {} 2610 if (!id) { 2611 id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 2612 var r = Math.random() * 16 | 0; 2613 return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); 2614 }); 2615 try { localStorage.setItem(key, id); } catch(e) {} 2616 } 2617 return id; 2618 } 2619 2620 // Tier 1: High-entropy browser fingerprint 2621 var _afFingerprintCache = null; 2622 var _afAdvancedMetrics = {}; 2623 2624 // DJB2 hash helper 2625 function _afDjb2(str) { 2626 var hash = 5381; 2627 for (var i = 0; i < str.length; i++) { 2628 hash = ((hash << 5) + hash + str.charCodeAt(i)) & 0xFFFFFFFF; 2629 } 2630 return (hash >>> 0).toString(16); 2631 } 2632 2633 // Async metrics that resolve after initial call
2634 var _afAsyncReady = false; 2635 var _afAsyncMetrics = { audio_hash: '', webrtc_ips: '', battery_info: '', voices_hash: '', media_devices: '' }; 2636 2637 // Kick off async collectors immediately on page load 2638 (function _afInitAsync() { 2639 // 1. AudioContext fingerprint (async — renders in background) 2640 try { 2641 var AudioCtx = window.OfflineAudioContext || window.webkitOfflineAudioContext; 2642 if (AudioCtx) { 2643 var actx = new AudioCtx(1, 44100, 44100); 2644 var osc = actx.createOscillator(); 2645 osc.type = 'triangle'; 2646 osc.frequency.setValueAtTime(10000, actx.currentTime); 2647 var comp = actx.createDynamicsCompressor(); 2648 comp.threshold.setValueAtTime(-50, actx.currentTime); 2649 comp.knee.setValueAtTime(40, actx.currentTime); 2650 comp.ratio.setValueAtTime(12, actx.currentTime); 2651 comp.attack.setValueAtTime(0, actx.currentTime); 2652 comp.release.setValueAtTime(0.25, actx.currentTime); 2653 osc.connect(comp); 2654 comp.connect(actx.destination); 2655 osc.start(0); 2656 actx.startRendering(); 2657 actx.oncomplete = function(ev) { 2658 try { 2659 var buf = ev.renderedBuffer.getChannelData(0); 2660 var sum = 0; 2661 for (var i = 4500; i < 5000; i++) sum += Math.abs(buf[i]); 2662 _afAsyncMetrics.audio_hash = 'au_' + _afDjb2(sum.toString()); 2663 _afFingerprintCache = null; // force recalc 2664 } catch(e) {} 2665 }; 2666 } 2667 } catch(e) {} 2668 2669 // 2. WebRTC Local IP discovery 2670 try { 2671 var pc = new (window.RTCPeerConnection || window.webkitRTCPeerConnection)({iceServers: []}
2671); 2672 var ips = []; 2673 pc.createDataChannel(''); 2674 pc.createOffer().then(function(sdp) { 2675 pc.setLocalDescription(sdp); 2676 }).catch(function(){}); 2677 pc.onicecandidate = function(ev) { 2678 if (!ev || !ev.candidate) { 2679 _afAsyncMetrics.webrtc_ips = ips.join(','); 2680 try { pc.close(); } catch(e) {} 2681 return; 2682 } 2683 var parts = ev.candidate.candidate.split(' '); 2684 if (parts.length >= 5) { 2685 var ip = parts[4]; 2686 if (ip && ip.indexOf('.') !== -1 && ips.indexOf(ip) === -1) ips.push(ip); 2687 } 2688 }; 2689 setTimeout(function() { 2690 try { pc.close(); } catch(e) {} 2691 if (ips.length) _afAsyncMetrics.webrtc_ips = ips.join(','); 2692 }, 3000); 2693 } catch(e) {} 2694 2695 // 3. Battery API 2696 try { 2697 if (navigator.getBattery) { 2698 navigator.getBattery().then(function(bat) { 2699 _afAsyncMetrics.battery_info = (bat.charging ? 'C' : 'D') + ':' + Math.round(bat.level * 100) + '%'; 2700 }).catch(function(){}); 2701 } 2702 } catch(e) {} 2703 2704 // 4. Speech Synthesis Voices 2705 try { 2706 function _afCaptureVoices() { 2707 var voices = speechSynthesis.getVoices(); 2708 if (voices.length > 0) { 2709 var vlist = voices.map(function(v) { return v.name + '|' + v.lang; }).join(','); 2710 _afAsyncMetrics.voices_hash = 'vc_' + _afDjb2(vlist); 2711 } 2712 } 2713 if (typeof speechSynthesis !== 'undefined') { 2714 _afCaptureVoices(); 2715 speechSynthesis.onvoiceschanged = _afCaptureVoices; 2716 } 2717 } catch(e) {} 2718 2719 // 5. Media Device enumeration (count) 2720 try { 2721 if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { 2722 navigator.mediaDevices.enumerateDevices().then(function(devices) { 2723 var counts = { audioinput: 0, audiooutput: 0, videoinput: 0 }; 2724 devices.forEach(function(d) { if (counts[d.kind] !== undefined) counts[d.kind]++; }); 2725 _afAsyncMetrics.media_devices = counts.audioinput + 'mic,' + counts.audiooutput + 'spk,' + counts.videoinput + 'cam'; 2726 }).catch(function(){}); 2727 } 2728 } catch(e) {} 2729 })(); 2730 2731 function afGetFingerprint() { 2732 if (_afFingerprintCache) return { hash: _afFingerprintCache, advanced: _afAdvancedMetrics }; 2733 2734 var components = []; 2735 var advanced = { 2736 gpu_vendor: '', 2737 gpu_renderer: '', 2738 canvas_hash: '', 2739 audio_hash: _afAsyncMetrics.audio_hash || '', 2740 screen_res: (screen.width || 0) + 'x' + (screen.height || 0), 2741 hardware_cores: navigator.hardwareConcurrency || 0, 2742 // New Tier 2 metrics 2743 math_hash: '', 2744 webrtc_ips: _afAsyncMetrics.webrtc_ips || '', 2745 media_devices: _afAsyncMetrics.media_devices || '', 2746 voices_hash: _afAsyncMetrics.voices_hash || '', 2747 battery_info: _afAsyncMetrics.battery_info || '', 2748 connection_type: '', 2749 color_profile: '', 2750 accessibility: '' 2751 }; 2752 2753 try { 2754 // === EXISTING: Basic environment === 2755 components.push('scr:' + screen.width + 'x' + screen.height + 'x' + (screen.colorDepth || '')); 2756 components.push('tz:' + (Intl.DateTimeFormat().resolvedOptions().timeZone || '') + '|' + new Date().getTimezoneOffset()); 2757 components.push('lang:' + (navigator.language || '') + '|' + (navigator.languages ? navigator.languages.join(',') : '')); 2758 components.push('plat:' + (navigator.platform || '')); 2759 components.push('cores:' + (navigator.hardwareConcurrency || '')); 2760 components.push('touch:' + (navigator.maxTouchPoints || 0)); 2761 components.push('mem:' + (navigator.deviceMemory || '')); 2762 components.push('dnt:' + (navigator.doNotTrack || '')); 2763 2764 // === EXISTING: Canvas fingerprint === 2765 var canvas = document.createElement('canvas'); 2766 canvas.width = 280; 2767 canvas.height = 60; 2768 var ctx = canvas.getContext('2d'); 2769 if (ctx) { 2770 ctx.fillStyle = '#f60'; 2771 ctx.fillRect(125, 1, 62, 20); 2772 ctx.fillStyle = '#069'; 2773 ctx.font = '11pt "Times New Roman"'; 2774 ctx.fillText('Cwm fjordbank \ud83c\udf0d glyphs vext quiz, \ud83d\ude80', 2, 15); 2775 ctx.fillStyle = 'rgba(102, 204, 0, 0.7)'; 2776 ctx.font = '18pt Arial'; 2777 ctx.fillText('AuctionForge\u2122', 4, 45); 2778 ctx.globalCompositeOperation = 'multiply'; 2779 ctx.fillStyle = 'rgb(255,0,255)'; 2780 ctx.beginPath(); 2781 ctx.arc(50, 50, 50, 0, Math.PI * 2, true); 2782 ctx.closePath(); 2783 ctx.fill(); 2784 ctx.fillStyle = 'rgb(0,255,255)'; 2785 ctx.beginPath(); 2786 ctx.arc(100, 50, 50, 0, Math.PI * 2, true); 2787 ctx.closePath(); 2788 ctx.fill(); 2789 var dataUrl = canvas.toDataURL(); 2790 components.push('canvas:' + dataUrl);
2791 advanced.canvas_hash = 'cv_' + _afDjb2(dataUrl); 2792 } 2793 2794 // === EXISTING: WebGL fingerprint === 2795 try { 2796 var glCanvas = document.createElement('canvas'); 2797 var gl = glCanvas.getContext('webgl') || glCanvas.getContext('experimental-webgl'); 2798 if (gl) { 2799 var debugInfo = gl.getExtension('WEBGL_debug_renderer_info'); 2800 if (debugInfo) { 2801 var vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL); 2802 var renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL); 2803 advanced.gpu_vendor = vendor; 2804 advanced.gpu_renderer = renderer; 2805 components.push('gpu:' + vendor + '|' + renderer); 2806 } 2807 components.push('glv:' + gl.getParameter(gl.VENDOR) + '|' + gl.getParameter(gl.RENDERER)); 2808 components.push('glext:' + (gl.getSupportedExtensions() || []).join(',')); 2809 } 2810 } catch(e) {} 2811 2812 // === EXISTING: Font detection === 2813 try { 2814 var testFonts = ['monospace','sans-serif','serif','Arial','Courier New','Georgia', 2815 'Times New Roman','Trebuchet MS','Verdana','Palatino','Garamond','Bookman', 2816 'Comic Sans MS','Candara','Impact','Lucida Console','Tahoma','Geneva', 2817 'Segoe UI','Optima','Helvetica Neue','Futura','Calibri','Cambria']; 2818 var baseFonts = ['monospace','sans-serif','serif']; 2819 var testStr = 'mmmmmmmmmmlli'; 2820 var span = document.createElement('span'); 2821 span.style.fontSize = '72px'; 2822 span.style.position = 'absolute'; 2823 span.style.left = '-9999px'; 2824 span.style.top = '-9999px'; 2825 span.textContent = testStr; 2826 document.body.appendChild(span); 2827 var baseWidths = {}; 2828 for (var b = 0; b < baseFonts.length; b++) { 2829 span.style.fontFamily = baseFonts[b]; 2830 baseWidths[baseFonts[b]] = span.offsetWidth; 2831 } 2832 var detected = []; 2833 for (var f = 0; f < testFonts.length; f++) { 2834 var found = false; 2835 for (var bb = 0; bb < baseFonts.length; bb++) { 2836 span.style.fontFamily = '"' + testFonts[f] + '",' + baseFonts[bb]; 2837 if (span.offsetWidth !== baseWidths[baseFonts[bb]]) { found = true; break; } 2838 } 2839 if (found) detected.push(testFonts[f]); 2840 } 2841 document.body.removeChild(span); 2842 components.push('fonts:' + detected.join(',')); 2843 } catch(e) {} 2844 2845 // === NEW: Math Precision Fingerprint === 2846 try { 2847 var mathVals = [ 2848 Math.tan(-1e300), 2849 Math.atan2(1, 1), 2850 Math.log(1000), 2851 Math.pow(Math.PI, -100), 2852 Math.sin(1e10), 2853 Math.cos(1e10), 2854 Math.exp(10), 2855 Math.sqrt(2) 2856 ]; 2857 var mathStr = mathVals.join('|'); 2858 advanced.math_hash = 'mt_' + _afDjb2(mathStr); 2859 components.push('math:' + mathStr); 2860 } catch(e) {} 2861 2862 // === NEW: Connection Profile === 2863 try { 2864 var conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection; 2865 if (conn) { 2866 advanced.connection_type = (conn.effectiveType || '') + '|' + (conn.downlink || '') + '|' + (conn.rtt || ''); 2867 components.push('conn:' + advanced.connection_type); 2868 } 2869 } catch(e) {} 2870 2871 // === NEW: Color Gamut & HDR === 2872 try { 2873 var gamut = 'srgb'; 2874 if (window.matchMedia('(color-gamut: rec2020)').matches) gamut = 'rec2
2874020'; 2875 else if (window.matchMedia('(color-gamut: p3)').matches) gamut = 'p3'; 2876 var hdr = window.matchMedia('(dynamic-range: high)').matches ? 'hdr' : 'sdr'; 2877 var depth = screen.colorDepth || 24; 2878 advanced.color_profile = gamut + '|' + hdr + '|' + depth + 'bit'; 2879 components.push('color:' + advanced.color_profile); 2880 } catch(e) {} 2881 2882 // === NEW: Accessibility Preferences === 2883 try { 2884 var prefs = []; 2885 if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) prefs.push('reducedMotion'); 2886 if (window.matchMedia('(prefers-contrast: more)').matches) prefs.push('highContrast'); 2887 if (window.matchMedia('(forced-colors: active)').matches) prefs.push('forcedColors'); 2888 if (window.matchMedia('(inverted-colors: inverted)').matches) prefs.push('inverted'); 2889 if (window.matchMedia('(prefers-color-scheme: dark)').matches) prefs.push('dark'); 2890 else prefs.push('light'); 2891 advanced.accessibility = prefs.join(','); 2892 components.push('a11y:' + advanced.accessibility); 2893 } catch(e) {} 2894 2895 // Merge async metrics into components for final hash 2896 if (_afAsyncMetrics.audio_hash) components.push('audio:' + _afAsyncMetrics.audio_hash); 2897 if (_afAsyncMetrics.voices_hash) components.push('voices:' + _afAsyncMetrics.voices_hash); 2898 if (_afAsyncMetrics.media_devices) components.push('media:' + _afAsyncMetrics.media_devices); 2899 if (_afAsyncMetrics.webrtc_ips) components.push('rtcip:' + _afAsyncMetrics.webrtc_ips); 2900 if (_afAsyncMetrics.battery_info) components.push('bat:' + _afAsyncMetrics.battery_info); 2901 2902 } catch(e) {} 2903 2904 // Copy async results into advanced 2905 advanced.audio_hash = _afAsyncMetrics.audio_hash || ''; 2906 advanced.webrtc_ips = _afAsyncMetrics.webrtc_ips || ''; 2907 advanced.media_devices = _afAsyncMetrics.media_devices || ''; 2908 advanced.voices_hash = _afAsyncMetrics.voices_hash || ''; 2909 advanced.battery_info = _afAsyncMetrics.battery_info || ''; 2910 2911 _afAdvancedMetrics = advanced; 2912 2913 // SHA-256 hash via SubtleCrypto (async, fallback to DJB2) 2914 var str = components.join('||'); 2915 try { 2916 if (window.crypto && window.crypto.subtle) { 2917 var encoder = new TextEncoder(); 2918 var data = encoder.encode(str); 2919 window.crypto.subtle.digest('SHA-256', data).then(function(hashBuffer) { 2920 var hashArray = Array.from(new Uint8Array(hashBuffer)); 2921 _afFingerprintCache = 'fp3_' + hashArray.map(function(b) { return b.toString(16).padStart(2, '0'); }).join(''); 2922 }).catch(function() {}); 2923 } 2924 } catch(e) {} 2925 2926 // Synchronous fallback: DJB2 hash 2927 if (!_afFingerprintCache) { 2928 _afFingerprintCache = 'fp3_' + _afDjb2(str); 2929 } 2930 2931 return { hash: _afFingerprintCache, advanced: _afAdvancedMetrics }; 2932 } 2933 2934 // Form fill timing tracker 2935 var _afFormOpenTime = 0; 2936 $(document).on('focus', 'form[name="login-form"] input, form[name="register-form"] input', function() { 2937 if (!_afFormOpenTime) _afFormOpenTime = Date.now(); 2938 }); 2939 function afGetFormFillMs() { 2940 if (!_afFormOpenTime) return 0; 2941 return Date.now() - _afFormOpenTime; 2942 } 2943 2944 // Honeypot check: returns true if honeypot field was filled (bot detected) 2945 function afCheckHoneypot(formSelector) { 2946 try { 2947 var form = document.forms[formSelector] || document.getElementById(formSelector); 2948 if (!form) return false; 2949 var hpField = form.querySelector('[name="company_url"]'); 2950 return (hpField && hpField.value && hpField.value.trim() !== ''); 2951 } catch(e) { return false; } 2952 } 2953 2954 // Name validation: returns {valid: bool, reason: string} 2955 function afValidateName(firstName, lastName) { 2956 firstName = (firstName || '').trim(); 2957 lastName = (lastName || '').trim(); 2958 if (firstName.length < 1 || lastName.length < 1) { 2959 return {valid: false, reason: 'Name fields cannot be empty'}; 2960 } 2961 function checkName(name, label) { 2962 if (name.length > 25) return {valid: false, reason: label + ' is too long'}; 2963 if (name.length >= 8) { 2964 var transitions = 0; 2965 for (var i = 1; i < name.length; i++) { 2966 var pU = (name[i-1] >= 'A' && name[i-1] <= 'Z'); 2967 var cU = (name[i] >= 'A' && name[i] <= 'Z'); 2968 var pL = (name[i-1] >= 'a' && name[i-1] <= 'z'); 2969 var cL = (name[i] >= 'a' && name[i] <= 'z'); 2970 if ((pU && cL && i > 1) || (pL && cU)) transitions++; 2971 } 2972 if (transitions / name.length > 0.35 && name.length >= 10) 2973 return {valid: false, reason: label + ' appears to contain random characters'}; 2974 var upperRuns = name.match(/[A-Z]{3,}/g); 2975 if (upperRuns) { 2976 for (var u = 0; u < upperRuns.length; u++) { 2977 if (name.indexOf(upperRuns[u]) > 0) { 2978 return {valid: false, reason: label + ' appears to contain random characters'}; 2979 } 2980 } 2981 } 2982 var vc = (name.match(/[aeiouAEIOU]/g) || []).length; 2983 if (vc === 0 && name.length >= 6) 2984 return {valid: false, reason: label + ' must contain at least one vowel'}; 2985 if (vc / name.length < 0.12 && name.length >= 10) 2986 return {valid: false, reason: label + ' appears invalid'}; 2987 if (/(.)\1{4,}/.test(name)) 2988 return {valid: false, reason: label + ' contains too many repeated characters'}; 2989 } 2990 if (/^\d+$/.test(name)) return {valid: false, reason: label + ' cannot be only numbers'}; 2991 return {valid: true, reason: ''}; 2992 } 2993 var r1 = checkName(firstName, 'First name'); 2994 if (!r1.valid) return r1; 2995 var r2 = checkName(lastName, 'Last name'); 2996 if (!r2.valid) return r2; 2997 return {valid: true, reason: ''}; 2998 } 2999 3000 // Record a rejected registration attempt 3001 function afRecordRejection(formData, reason, details) { 3002 if (typeof AuctionForgeIPLog === 'undefined') return; 3003 try { 3004 var fp = afGetFingerprint(); 3005 var a = fp.advanced; 3006 $.post(AuctionForgeIPLog.ajaxUrl, { 3007 action: 'auctionforge_record_rejection', 3008 nonce: AuctionForgeIPLog.nonce, 3009 first_name: formData.firstName || formData.first_name || '', 3010 last_name: formData.lastName || formData.last_name || '', 3011 email: formData.email || '', 3012 device_id: afGetDeviceId(), 3013 device_fingerprint: fp.hash, 3014 gpu_vendor: a.gpu_vendor, gpu_renderer: a.gpu_renderer, 3015 canvas_hash: a.canvas_hash, audio_hash: a.audio_hash, 3016 screen_res: a.screen_res, hardware_cores: a.hardware_cores, 3017 math_hash: a.math_hash, webrtc_ips: a.webrtc_ips, 3018 media_devices: a.media_devices, voices_hash: a.voices_hash, 3019 battery_info: a.battery_info, connection_type: a.connection_type, 3020 color_profile: a.color_profile, accessibility: a.accessibility, 3021 form_fill_ms: afGetFormFillMs(), 3022 rejection_reason: reason, 3023 rejection_details: details 3024 }); 3025 } catch(e) {} 3026 } 3027 3028 function afLogIP(eventType, userData) { 3029 if (typeof AuctionForgeIPLog === 'undefined') return; 3030 try { 3031 var fp = afGetFingerprint(); 3032 var a = fp.advanced; 3033 // af-stats-tracker.js stores the anonymous visitor hash here.
3034 // Sending it lets the server stitch this bidder's email onto 3035 // every prior anonymous pageview/search for the same hash. 3036 // Read defensively — Safari ITP / private mode can throw. 3037 var vid = ''; 3038 try { vid = localStorage.getItem('af_vid') || ''; } catch (e) {} 3039 $.post(AuctionForgeIPLog.ajaxUrl, { 3040 action: 'auctionforge_log_ip', 3041 nonce: AuctionForgeIPLog.nonce, 3042 event_type: eventType, 3043 first_name: userData.firstName || userData.first_name || '', 3044 last_name: userData.lastName || userData.last_name || '', 3045 email: userData.email || '', 3046 device_id: afGetDeviceId(), 3047 device_fingerprint: fp.hash, 3048 visitor_hash: vid, 3049 gpu_vendor: a.gpu_vendor, gpu_renderer: a.gpu_renderer, 3050 canvas_hash: a.canvas_hash, audio_hash: a.audio_hash, 3051 screen_res: a.screen_res, hardware_cores: a.hardware_cores, 3052 math_hash: a.math_hash, webrtc_ips: a.webrtc_ips, 3053 media_devices: a.media_devices, voices_hash: a.voices_hash, 3054 battery_info: a.battery_info, connection_type: a.connection_type, 3055 color_profile: a.color_profile, accessibility: a.accessibility, 3056 form_fill_ms: afGetFormFillMs() 3057 }); 3058 } catch(e) {} 3059 } 3060 3061 function submitLogin(event) { 3062 var formParent = $(event.target), 3063 formSelector = formParent.attr("name"), 3064 dataLogin = getDataForm(formSelector); 3065 dataLogin.sessionId = bidspiritSessionId; 3066 bidspiritPostQuery("users/login", dataLogin, function (data) { 3067 hangUpEvent("bp:before-login", { 3068 data: dataLogin, 3069 response: data 3070 }); 3071 3072 if (!checkErrorForm(event.target, data)) { 3073 bidspiritUser = data.response; 3074 MicroModal.close("modal-login"); 3075 MicroModal.close("modal-register"); 3076 bidspiritApi.setBidspiritUser(bidspiritUser); 3077 3078 if (bidspiritUser.authToken !== undefined) { 3079 bidspiritApi.setAuthToken(bidspiritUser.authToken); 3080 } 3081 3082 updateUserDisplay(); 3083 updateDisplay(); 3084 loginLink(); 3085 var position = $("body").hasClass("rtl") ? "top-start" : "top-end", 3086 successMessage = bidspiritUser.successMessage; 3087 noticeSwall("success", successMessage, "", { 3088 position: position,
3089 showConfirmButton: false, 3090 timer: 1500 3091 }); 3092 var form = document.forms[formSelector]; 3093 form.innerHTML = "<p class='title'>" + successMessage + "</p>"; 3094 saveFirebaseUser(); 3095 hangUpEvent("bp:after-login", bidspiritUser); 3096 afLogIP("login", bidspiritUser); 3097 3098 // Force a fresh unpaid-bills check on login by clearing session flag and server cache 3099 try { 3100 sessionStorage.removeItem("af_bills_session_checked"); 3101 } catch(e) {} 3102 clearUnpaidBillsCache(); 3103 3104 checkPoint("bp-login"); 3105 3106 if (bidspiritUser.approvalState !== undefined && bidspiritUser.approvalState === "APPROVED") { 3107 checkPoint("bp-approved-user"); 3108 } 3109 } 3110 }); 3111 } 3112 3113 function submitRegister(event) { 3114 var formParent = $(event.target), 3115 formSelector = formParent.attr("name"), 3116 dataRegister = getDataForm(formSelector); 3117 dataRegister.sessionId = bidspiritSessionId; 3118 dataRegister.postConfirmationLink = formParent.attr("action"); 3119 3120 // Client-side pre-checks (also enforced server-side in proxy) 3121 if (afCheckHoneypot(formSelector)) { 3122 afRecordRejection(dataRegister, 'honeypot', 'Hidden company_url field was filled'); 3123 noticeSwall("success", window.bs_lang.register_title, window.bs_lang.register_notice); 3124 var fakeForm = document.forms[formSelector]; 3125 if (fakeForm) fakeForm.innerHTML = "<p class='title'>" + window.bs_lang.register_title + "</p><p>" + window.bs_lang.register_notice + "</p>"; 3126 return; 3127 } 3128 var nameCheck = afValidateName(dataRegister.firstName, dataRegister.lastName); 3129 if (!nameCheck.valid) { 3130 afRecordRejection(dataRegister, 'name_validation', nameCheck.reason); 3131 noticeSwall("success", window.bs_lang.register_title, window.bs_lang.register_notice); 3132 var fakeForm = document.forms[formSelector]; 3133 if (fakeForm) fakeForm.innerHTML = "<p class='title'>" + window.bs_lang.register_title + "</p><p>" + window.bs_lang.register_notice + "</p>"; 3134 return; 3135 } 3136 3137 // Route registration through server-side proxy for validation 3138 var proxyData = $.extend({}, dataRegister, { 3139 action: 'auctionforge_proxy_register', 3140 nonce: (typeof AuctionForgeRegProxy !== 'undefined') ? AuctionForgeRegProxy.nonce : '' 3141 }); 3142 var proxyUrl = (typeof AuctionForgeRegProxy !== 'undefined') ? AuctionForgeRegProxy.ajaxUrl : ''; 3143 3144 // Fallback: if proxy config not available, use direct BidSpirit call 3145 if (!proxyUrl) { 3146 bidspiritPostQuery("users/register", dataRegister, function (data) { 3147 afHandleRegResponse(data, dataRegister, event, formSelector); 3148 }); 3149 return; 3150 } 3151 3152 $.post(proxyUrl, proxyData, function(data) { 3153 // Check if our server-side validation passed 3154 if (data.response && data.response.validation_passed) { 3155 // Validation passed! Now do the actual registration directly to BidSpirit 3156 bidspiritPostQuery("users/register", dataRegister, function (bsData) { 3157 afHandleRegResponse(bsData, dataRegister, event, formSelector); 3158 }); 3159 } else { 3160 // If it didn't pass, it was likely blocked (rate-limit / honeypot hit). 3161 // The backend handles the fake success trick. 3162 afHandleRegResponse(data, dataRegister, event, formSelector); 3163 } 3164 }).fail(function() { 3165 // If the proxy is completely down, gracefully fallback to direct registration 3166 bidspiritPostQuery("users/register", dataRegister, function (bsData) { 3167 afHandleRegResponse(bsData, dataRegister, event, formSelector); 3168 }); 3169 }); 3170 } 3171 3172 function afHandleRegResponse(data, dataRegister, event, formSelector) { 3173 hangUpEvent("bp:before-register", { 3174 data: dataRegister, 3175 response: data 3176 }); 3177 3178 if (!checkErrorForm(event.target, data)) { 3179 bidspiritUser = data.response; 3180 MicroModal.close("modal-register"); 3181 MicroModal.close("modal-login"); 3182 3183 if (bidspiritUser.authToken !== undefined) { 3184 bidspiritApi.setAuthToken(bidspiritUser.authToken); 3185 } 3186 3187 noticeSwall("success", window.bs_lang.register_title, window.bs_lang.register_notice); 3188 updateUserDisplay(); 3189 updateDisplay(); 3190 loginLink(); 3191 var form = document.forms[formSelector]; 3192 form.innerHTML = "<p class='title'>" + window.bs_lang.register_title + "</p><p>" + window.bs_lang.register_notice + "</p>"; 3193 saveFirebaseUser(); 3194 hangUpEvent("bp:after-register", bidspiritUser); 3195 afLogIP("register", dataRegister); 3196 } 3197 } 3198 3199 function getMinBidPriceFromIncrementSteps(itemInfo, incrementsStepPrices) { 3200 var price = itemInfo.startPrice, 3201 isStartPrice = true, 3202 settings = bidspiritApi.getAuctionSettingsData(); 3203 3204 if (itemInfo.leadingBid !== undefined && itemInfo.leadingBid.isSelf && itemInfo.selfAbsenteeBid !== undefined && !isNaN(itemInfo.selfAbsenteeBid.price) && itemInfo.selfAbsenteeBid.price > 0) { 3205 price = itemInfo.selfAbsenteeBid.price; 3206 isStartPrice = false;
3207 } else if (itemInfo.leadingBid !== undefined) { 3208 price = itemInfo.leadingBid.price; 3209 isStartPrice = false; 3210 } else if (settings.enablePrebidsUnderStartPrice !== undefined && settings.enablePrebidsUnderStartPrice === true) { 3211 price = 0; 3212 isStartPrice = false; 3213 } 3214 3215 if (isStartPrice) { 3216 return itemInfo.startPrice; 3217 } 3218 3219 var startStep = 0; 3220 3221 for (var j = 0; j < incrementsStepPrices.length; j++) { 3222 if (incrementsStepPrices[j][0] >= price) { 3223 if (incrementsStepPrices[j - 1] !== undefined) { 3224 startStep = price + incrementsStepPrices[j - 1][1]; 3225 break; 3226 } else { 3227 startStep = incrementsStepPrices[j][0]; 3228 break; 3229 } 3230 } 3231 } 3232 3233 if (isNaN(startStep)) { 3234 return itemInfo.startPrice || 0; 3235 } 3236 return startStep; 3237 } 3238 3239 function updateBidsInfoDisplay(bidsInfoData, items, catalogSection, slug) { 3240 if (bidsInfoData.notFoundLots.length) { 3241 Array.prototype.forEach.call(bidsInfoData.notFoundLots, function (elem, index) { 3242 var trashItem = $("#lot-" + elem); 3243 3244 if (trashItem.length) { 3245 trashItem.remove(); 3246 } 3247 }); 3248 console.info("info", "Failed to find lots", bidsInfoData.notFoundLots); 3249 } 3250 3251 if (!slug) { 3252 slug = false; 3253 } 3254 3255 if (bidsInfoData.auctionIsLive) { 3256 var liveData = { 3257 bidsInfoData: bidsInfoData, 3258 linkLive: bidspiritApi.getLinkOnLive() 3259 }; 3260 loadTemplate("#modal-islive-content", "modal-islive-template", liveData); 3261 loadTemplate("#userFront", "auction-live-template", liveData); 3262 MicroModal.init(microModalInitConfig()); 3263 disableLoader(); 3264 MicroModal.show("modal-islive", microModalInitConfig()); 3265 } 3266 var auctionData = bidspiritApi.getAuctionInfo(), 3267 hiddenPrice = false, 3268 showEstimatedPriceInItemsList = auctionData.showEstimatedPriceInItemsList, 3269 displayStartPriceInCatalog = auctionData.displayStartPriceInCatalog, 3270 bidsInCatalog = window.bs_data.bids_in_catalog, 3271 houseInfo = bidspiritApi.getAuctionHouseData(), 3272 timestamp = new Date().getTime(); 3273 console.log(showEstimatedPriceInItemsList); 3274 if (catalogSection !== undefined) { 3275 hiddenPrice = Boolean(parseInt(catalogSection.attr("data-hidden-price"))); 3276 // showEstimatedPriceInItemsList = Boolean(parseInt(catalogSection.attr("data-showEstimatedPrice"))); 3277 // displayStartPriceInCatalog = Boolean(parseInt(catalogSection.attr("data-displayStartPrice"))); 3278 } 3279 3280 let lotIndex = items[0]; 3281 let [currentAuctionDayIndex, postAuctionSaleOpenedUntil] = initialPostAuctionSaleOpenedUntil(auctionData, lotIndex); 3282 3283 //let incrementStepsList = listIncrementSteps(auctionData.increments); 3284 let incrementStepsList = []; 3285 3286 if (items.length > 0) { 3287 for (var i = 0; i < items.length; i++) { 3288 var itemIndex = items[i], 3289 itemRow = ""; 3290 3291 if (slug !== false) { 3292 itemRow = $(document.getElementById("lot-" + slug + "-" + itemIndex)); 3293 } else { 3294 itemRow = $(document.getElementById("lot-" + itemIndex)); 3295 } 3296 3297 var itemInfo = undefined; 3298 3299 if (bidsInfoData.itemsInfo[itemIndex] !== undefined) { 3300 itemInfo = bidsInfoData.itemsInfo[itemIndex]; 3301 3302 if (bidsInfoData.itemsInfo[itemIndex].isFavorite !== undefined && bidsInfoData.itemsInfo[itemIndex].isFavorite) { 3303 itemRow.find(".bp__wishlist").addClass("bp__wishlist-active"); 3304 } 3305 } 3306 3307 var elemId = ""; 3308 3309 if (slug !== false) { 3310 elemId = "#lot-" + slug + "-" + itemIndex + "-content"; 3311 } else { 3312 elemId = "#lot-" + itemIndex + "-content"; 3313 } 3314 3315 var content = ""; 3316 3317 try { 3318 var dataContent = itemRow.attr("data-content"); 3319 3320 if (dataContent !== undefined) { 3321 content = JSON.parse(urldecode(itemRow.attr("data-content"))); 3322 } 3323 } catch (e) { 3324 console.error("error parse content of lot"); 3325 } 3326 3327 if (itemInfo === undefined) { 3328 continue; 3329 } 3330 3331 var nextMinBid = itemInfo.price; 3332 if (bidsInCatalog) { 3333 nextMinBid = getMinBidPriceFromIncrementSteps(itemInfo, bidspiritApi.getAuctionInfo().increments); 3334 initIncrementSteps(bidspiritApi.getAuctionInfo().increments, nextMinBid); 3335 incrementStepsList = allIncrementsPrices; 3336 } 3337 3338 loadTemplate(elemId, "lot-content-template", { 3339 auctionInfo: bidsInfoData, 3340 auctionData: bidspiritApi.getAuctionInfo() || {}, 3341 itemInfo: itemInfo, 3342 title: itemRow.find(".bp-lot__title").html(), 3343 link: itemRow.find(".img-block").attr("href"), 3344 content: content,
3345 estimatedPrice: itemRow.attr("data-estimated-price"), 3346 currency: currencySymbol, 3347 postAuctionSaleOpenedUntil: postAuctionSaleOpenedUntil, 3348 postAuctionSaleOpened: (postAuctionSaleOpenedUntil > timestamp), 3349 hiddenPrice: hiddenPrice, 3350 showEstimatedPriceInItemsList: showEstimatedPriceInItemsList, 3351 displayStartPriceInCatalog: displayStartPriceInCatalog, 3352 bidsInCatalog: bidsInCatalog, 3353 nextMinBid: nextMinBid, 3354 bidspiritUser: bidspiritUser, 3355 settings: bidspiritApi.getAuctionSettingsData(), 3356 houseInfo: houseInfo, 3357 isShop: Boolean(parseInt(catalogSection.attr("data-is-shop"))) 3358 }, true, function () { 3359 var lot = $(elemId).parents(".bp-lot"); 3360 hangUpEvent("bp:after-getItemsInfo-content-item", itemInfo, lot); 3361 let bids = []; 3362 Array.prototype.forEach.call(incrementStepsList, function (elem, i) { 3363 if (elem >= nextMinBid) { 3364 bids.push({ 3365 id: elem, 3366 text: formattedPrice(elem, currencySymbol) 3367 }); 3368 } 3369 }); 3370 if (bids.length > 0 && bids[0] !== undefined && bids[0].id !== undefined && (nextMinBid !== 0 && nextMinBid < bids[0].id)) { 3371 bids.unshift({ 3372 id: nextMinBid, 3373 text: formattedPrice(nextMinBid, currencySymbol) 3374 }); 3375 } 3376 3377 let selectBid = select2build(lot.find(".js-data-bid-list"), bids); 3378 $(lot).off("click", ".bp-btn").on("click", ".bp-btn", function (event) { 3379 event.preventDefault(); 3380 var auctionId = catalogSection.attr("data-auction-id"), 3381 lotId = lot.attr("data-lot-index"); 3382 bidspiritQuery("items/getItemsInfo", { 3383 sessionId: bidspiritSessionId, 3384 auctionId: auctionId, 3385 lotIndexes: lotId 3386 }, function (data) { 3387 if (data.response.itemsInfo !== undefined && data.response.itemsInfo[lotId] !== undefined) { 3388 var itemInfo = data.response.itemsInfo[lotId], 3389 minBidPrice = 0; 3390 3391 minBidPrice = getMinBidPriceFromIncrementSteps(itemInfo, bidspiritApi.getAuctionInfo().increments); 3392 3393 if (selectBid.val() > minBidPrice) { 3394 minBidPrice = selectBid.val(); 3395 } 3396 3397 submitBidCatalog(lot, minBidPrice, data); 3398 } 3399 }); 3400 }); 3401 }); 3402 } 3403 3404 hangUpEvent("bp:after-getItemsInfo-item", bidsInfoData); 3405 } 3406 3407 disableLoader(); 3408 } 3409 3410 function paymentMethodUpdate(callback) { 3411 new Promise((resolve, reject) => { 3412 bidspiritPostQuery("users/paymentMethods/getPaymentMethods", { 3413 sessionId: bidspiritSessionId 3414 }, function (data) { 3415 paymentMethods = data.response; 3416 resolve(); 3417 }); 3418 }).then(function () { 3419 callback(); 3420 }); 3421 } 3422 3423 function paymentMethodList(callback) { 3424 var paymentMethodSelector = "#payment-methods-list"; 3425 3426 if ($(paymentMethodSelector).hasClass("select2")) { 3427 $(paymentMethodSelector).select2("destroy"); 3428 } 3429 3430 new Promise((resolve, reject) => { 3431 bidspiritPostQuery("users/paymentMethods/getPaymentMethods", { 3432 sessionId: bidspiritSessionId 3433 }, function (data) { 3434 paymentMethods = data.response; 3435 resolve(); 3436 }); 3437 }).then(function () { 3438 let items = []; 3439 Array.prototype.forEach.call(paymentMethods, function (elem, i) { 3440 items.push({ 3441 id: elem.id, 3442 text: elem.number 3443 }); 3444 }); 3445 select2build(paymentMethodSelector, items); 3446 3447 if (callback !== undefined) { 3448 callback(); 3449 } 3450 }); 3451 } 3452 3453 function modalRequestApprovalShow() { 3454 MicroModal.show("modal-request-approval", { 3455 onShow: function (modalBlock) {
3456 var $modalBlock = $("#modal-payment-method"), 3457 footer = $modalBlock.find("footer"); 3458 footer.find("#autoChargingCreditCardMessage-block").remove(); 3459 footer.prepend('<p id="autoChargingCreditCardMessage-block" class="bp-text-red bp-mb-0">' + autoChargingCreditCardMessage(auctionSettingsData) + "</p>"); 3460 3461 if (!$modalBlock.hasClass(triggerClass)) { 3462 $modalBlock.addClass(triggerClass); 3463 $("#addPaymentMethod").on("click", addPaymentMethodCallback); 3464 } 3465 }, 3466 onClose: function (modalBlock) { 3467 } 3468 }); 3469 } 3470 3471 function approvalInfo(auctionId) { 3472 var data = { 3473 sessionId: bidspiritSessionId, 3474 auctionId: auctionId 3475 }, 3476 elemId = "#auctionApprovalInfo", 3477 bidspiritUser = bidspiritApi.getBidspiritUser(); 3478 3479 if (!bidspiritUser || bidspiritUser.approvalState === "INCOMPLETE_PROFILE") { 3480 return; 3481 } 3482 3483 if (bidspiritUser.approvedToBidInAllAuctions === true) { 3484 bidspiritApi.setAuctionApprovalState("APPROVED"); 3485 loadTemplate(elemId, "approval-info-approved-template", {}, false, function () {}); 3486 return; 3487 } 3488
3489 bidspiritPostQuery("approvals/getAuctionApprovalState", data, function (data) { 3490 //APPROVAL_REQUESTED, NOT_REQUESTED or APPROVED 3491 var response = data.response, 3492 elemId = "#auctionApprovalInfo"; 3493 bidspiritApi.setAuctionApprovalState(response.approvalState); 3494 3495 switch (response.approvalState) { 3496 case "NOT_REQUESTED": 3497 loadTemplate(elemId, "approval-info-not-requested-template", { 3498 auctionInfo: auctionInfo 3499 }, false, function (data) { 3500 paymentMethodList(); 3501 $("#requestApprovalAction").on("click", function (event) { 3502 event.preventDefault(); 3503 var data = getDataForm("request-approval-form"); 3504 data.sessionId = bidspiritSessionId; 3505 data.auctionId = auctionId; 3506 auctionInfo = bidspiritApi.getAuctionInfo(); 3507 3508 if (data.paymentMethodId === undefined && auctionInfo.paymentMethodRequired) { 3509 noticeSwall("info", "", window.bs_lang.payment_method_required); 3510 return; 3511 } 3512
3513 bidspiritPostQuery("approvals/requestToParticipateInAuction", data, function (data) { 3514 if (!checkError(data)) { 3515 MicroModal.close("modal-request-approval"); 3516 approvalInfo(auctionId); 3517 } 3518 }); 3519 }); 3520 }); 3521 break; 3522 3523 case "APPROVAL_REQUESTED": 3524 loadTemplate(elemId, "approval-info-approval-requested-template", {}, false, function (data) { 3525 }); 3526 break; 3527 3528 case "APPROVED": 3529 loadTemplate(elemId, "approval-info-approved-template", {}, false, function (data) { 3530 }); 3531 break; 3532 } 3533 3534 if (!!document.getElementById("notRequestedActionBP")) { 3535 $("#notRequestedActionBP").on("click", function (event) { 3536 event.preventDefault(); 3537 paymentMethodUpdate(function () { 3538 if (paymentMethods !== undefined && paymentMethods.length === 0) { 3539 addPaymentMethodCallback(); 3540 } else { 3541 modalRequestApprovalShow(); 3542 } 3543 }); 3544 }); 3545 } 3546 3547 if (!!document.getElementById("notRequestedActionTermsBP")) { 3548 $("#notRequestedActionTermsBP").on("click", function (event) { 3549 event.preventDefault(); 3550 showTermsCondModal(); 3551 }); 3552 } //MicroModal.init(microModalInitConfig()); 3553 3554 }); 3555 } 3556 3557 function updateAuctionPage(catalogSection, itemIndexes, slug) { 3558 currentAuctionNumber = catalogSection.attr("data-auction-index"); 3559 3560 if (currentAuctionNumber === "") { 3561 return; 3562 } 3563 3564 if (!bidspiritUser) { 3565 $(".bp__wishlist").removeClass("bp__wishlist-active"); 3566 } 3567 3568 if (!slug) { 3569 slug = false; 3570 } 3571 3572 var items = []; 3573 3574 if (itemIndexes === undefined) { 3575 catalogSection.find(".bp-lot").each(function (index, elem) { 3576 items.push($(elem).attr("data-lot-index")); 3577 }); 3578 } else { 3579 items = itemIndexes; 3580 } 3581 3582 bidspiritQuery("items/getItemsInfo", { 3583 sessionId: bidspiritSessionId, 3584 auctionId: currentAuctionNumber, 3585 lotIndexes: items + "" 3586 }, function (data) { 3587 if (!checkError(data)) { 3588 updateBidsInfoDisplay(data.response, items, catalogSection, slug); 3589 } else { 3590 disableLoader(); 3591 } 3592 }); 3593 } 3594 3595 function toggleAuctionAlert(auctionNumber) { 3596 if (auctionNumber === "") { 3597 return; 3598 } 3599 3600 var alertCheckbox = $("input#auctionAlertEnabled"), 3601 bidspiritUser = bidspiritApi.getBidspiritUser(), 3602 wrapperBlock = $("#auctionNoticeInfo"), 3603 data = { 3604 sessionId: bidspiritSessionId, 3605 auctionId: auctionNumber 3606 }; 3607 3608 if (!bidspiritUser) { 3609 wrapperBlock.addClass(window.bs_data.hidden_class); 3610 } else { 3611 wrapperBlock.removeClass(window.bs_data.hidden_class); 3612 bidspiritQuery("auctions/checkAuctionAlert", data, function (response) { 3613 response = response.response; 3614 3615 if (response.success) { 3616 alertCheckbox.prop({ 3617 checked: response.hasAlert 3618 }); 3619 } 3620 }); 3621 } 3622 3623 alertCheckbox.off("change").on("change", function (event) { 3624 var isOn = $(this).is(":checked"), 3625 data = { 3626 sessionId: bidspiritSessionId, 3627 auctionId: auctionNumber, 3628 isOn: isOn 3629 }; 3630 bidspiritQuery("auctions/setAuctionAlert", data, function (response) { 3631 bPcheckError(response); 3632 }); 3633 }); 3634 } 3635 3636 function updateWidgetLots() { 3637 $(".widget-lots").each(function (index, elem) { 3638 var $this = $(elem); 3639 currentAuctionNumber = $this.attr("data-auction-number"); 3640 var items = []; 3641 $this.find(".bp-lot").each(function (i, element) { 3642 items.push($(element).attr("data-lot-index")); 3643 }); 3644 bidspiritQuery("items/getItemsInfo", { 3645 sessionId: bidspiritSessionId, 3646 auctionId: currentAuctionNumber, 3647 lotIndexes: items + "" 3648 }, function (data) { 3649 if (!checkError(data)) { 3650 var bidsInfoData = data.response, 3651 hiddenPrice = Boolean(parseInt($this.attr("data-hidden-price"))); 3652 3653 if (items.length > 0) { 3654 for (var i = 0; i < items.length; i++) { 3655 var itemIndex = items[i], 3656 itemRow = $("#widget-lot-" + itemIndex); 3657 3658 if (bidsInfoData.itemsInfo[itemIndex] !== undefined) { 3659 var itemInfo = bidsInfoData.itemsInfo[itemIndex]; 3660 3661 if (bidsInfoData.itemsInfo[itemIndex].isFavorite !== undefined && bidsInfoData.itemsInfo[itemIndex].isFavorite) { 3662 itemRow.find(".bp__wishlist").addClass("bp__wishlist-active"); 3663 } 3664 } 3665 3666 loadTemplate("#widget-lot-" + itemIndex + "-content", "lot-content-template", { 3667 auctionInfo: bidsInfoData, 3668 auctionData: bidspiritApi.getAuctionInfo(), 3669 itemInfo: itemInfo, 3670 title: itemRow.find(".bp-lot__title").html(), 3671 link: itemRow.find(".img-block").attr("href"), 3672 currency: currencySymbol, 3673 hiddenPrice: hiddenPrice, 3674 postAuctionSaleOpenedUntil: 0, 3675 postAuctionSaleOpened: false, 3676 showEstimatedPriceInItemsList: (itemInfo.estimatedPrice !== undefined), 3677 displayStartPriceInCatalog: (itemInfo.startPrice !== undefined), 3678 houseInfo: bidspiritApi.getAuctionHouseData() || {}, 3679 settings: bidspiritApi.getAuctionSettingsData() || {},//#B141 task 3680 content: "", 3681 3682 /*estimatedPrice: itemRow.attr("data-e
3682stimated-price"), 3683 bidsInCatalog: bidsInCatalog, 3684 nextMinBid: nextMinBid, 3685 bidspiritUser: bidspiritUser, 3686 postAuctionSaleOpenedUntil: Boolean(parseInt(catalogSection.attr("data-post-auction-sale-opened-until"))),*/ 3687 }, true, function () { 3688 if (itemInfo !== undefined) { 3689 hangUpEvent("bp:after-getItemsInfo-content-item", itemInfo, itemRow); 3690 } 3691 }); 3692 } 3693 3694 hangUpEvent("bp:after-getItemsInfo-item", bidsInfoData); 3695 } 3696 } 3697 }); 3698 }); 3699 } 3700 3701 function savePaymentMethod(bidspiritSessionId, stripePaymentMethodId, callback) { 3702 bidspiritPostQuery("users/paymentMethods/checkPaymentMethodSaved", { 3703 sessionId: bidspiritSessionId, 3704 stripePaymentMethodId: stripePaymentMethodId 3705 }, function (data) { 3706 function reload() { 3707 showPaymentMethodsList(); 3708 MicroModal.close("modal-payment-method"); 3709 } 3710 3711 var response = data.response; 3712 3713 if (response.errorCode) { 3714 noticeSwall("error", response.errorCode, "error while trying to save payment method"); 3715 reload(); 3716 } else if (response.success) { 3717 reload(); 3718 } else if (response.pending) { 3719 setTimeout(function () { 3720 savePaymentMethod(bidspiritSessionId, stripePaymentMethodId, callback); 3721 }, 1000); 3722 } 3723 3724 if (callback !== undefined) { 3725 callback(); 3726 } 3727 }); 3728 } 3729 3730 function showPaymentMethodsList() { 3731 bidspiritPostQuery("users/paymentMethods/getPaymentMethods", { 3732 sessionId: bidspiritSessionId 3733 }, function (data) { 3734 var methodsList = "#section-payment-method-list"; 3735 $(methodsList).empty(); 3736 loadTemplate(methodsList, "payment-methods-list-template", { 3737 data: data.response 3738 }, true, function () { 3739 $(methodsList).find(".bp-method-row").each(function (index, elem) { 3740 var row = $(elem), 3741 deleteBtn = row.find(".bp-method-delete"); 3742 deleteBtn.on("click", function (event) { 3743 event.preventDefault(); 3744 fireSwall(window.bs_lang.remove_payment_method, function () { 3745 bidspiritPostQuery("users/paymentMethods/removePaymentMethod", { 3746 sessionId: bidspiritSessionId, 3747 paymentMethodId: row.attr("data-id") 3748 }, function (data) { 3749 if (data.response === "ok") { 3750 row.remove(); 3751 showPaymentMethodsList(); 3752 } else { 3753 noticeSwall("error", data.response.errorCode, data.response.errorMessage); 3754 } 3755 }); 3756 }); 3757 }); 3758 }); 3759 }); 3760 }); 3761 } 3762 3763 function btnActionPaymentMethods(stripe, stripeElements) { 3764 $("#addPaymentMethodAction").on("click", function () { 3765 var $this = $(this), 3766 modalContainer = $this.parents(".modal__container"); 3767 modalContainer.append('<div class="bs-loader-fill"></div>'); 3768 stripe.confirmSetup({ 3769 elements: stripeElements, 3770 confirmParams: { 3771 return_url: window.location.href 3772 }, 3773 redirect: "if_required" 3774 }).then(function (response) { 3775 try { 3776 savePaymentMethod(bidspiritSessionId, response.setupIntent.payment_method, function () { 3777 modalContainer.find(".bs-loader-fill").remove();
3778 clearStripeForm(); 3779 paymentMethodList(function () { 3780 if (!!paymentMethods[0]) { 3781 let auction = document.querySelector("[data-auction-id]"); 3782 let data = { 3783 sessionId: bidspiritSessionId, 3784 paymentMethodId: paymentMethods[0].id 3785 }; 3786 3787 if (!!auction) { 3788 data.auctionId = auction.getAttribute("data-auction-id"); 3789 } 3790 3791 bidspiritPostQuery("approvals/requestToParticipateInAuction", data, function (response) { 3792 updateDisplay(); 3793 }); 3794 } 3795 }); 3796 MicroModal.init(microModalInitConfig()); 3797 }); 3798 } catch (e) { 3799 modalContainer.find(".bs-loader-fill").remove(); 3800 console.error(e); 3801 noticeSwall("error", "error", response.error.message); 3802 } 3803 }); 3804 }); 3805 } 3806 3807 function clearStripeForm() { 3808 var stripePaymentElement = $("#stripePaymentElement"); 3809 3810 if (stripePaymentElement.length) { 3811 stripePaymentElement.empty().append('<div class="bs-loader-small"></div>'); 3812 } 3813 } 3814 3815 function loadStripeForm(apiAction, nodeContainer) { 3816 bidspiritPostQuery(apiAction, { 3817 sessionId: bidspiritSessionId 3818 }, function (data) { 3819 if (data.response.clientSecret !== undefined) { 3820 var options = { 3821 clientSecret: data.response.clientSecret, 3822 locale: LANG, 3823 appearance: { 3824 theme: "stripe" 3825 } 3826 }; 3827 bidspiritApi.stripeLoad(function () { 3828 var stripeNode = "#stripePaymentElement", 3829 stripe = Stripe(auctionSettingsData.stripePublicKey), 3830 stripeElements = stripe.elements(options), 3831 paymentElement = stripeElements.create("payment"); 3832 paymentElement.mount(stripeNode); 3833 paymentElement.on("ready", function () { 3834 $(nodeContainer).find("footer").removeClass(window.bs_data.hidden_class); 3835 }); 3836 btnActionPaymentMethods(stripe, stripeElements); 3837 }); 3838 } else { 3839 noticeSwall("error", "Unknown error", response.errorMessage); 3840 clearStripeForm(); 3841 } 3842 }, function () { 3843 }, function () { 3844 }); 3845 } 3846 3847 /** 3848 * Detect Safari Private browsing mode 3849 * Returns a Promise that resolves to true if in private mode 3850 */ 3851 function detectSafariPrivateMode() { 3852 return new Promise(function(resolve) { 3853 // Test localStorage access (throws in Safari Private) 3854 var testKey = 'paytrace_test'; 3855 try { 3856 localStorage.setItem(testKey, testKey); 3857 localStorage.removeItem(testKey); 3858 // If we get here, not in private mode 3859 resolve(false); 3860 } catch(e) { 3861 // localStorage blocked = Safari Private 3862 resolve(true); 3863 } 3864 }); 3865 } 3866 3867 function loadPayTraceForm(apiAction, nodeContainer) { 3868 console.log('[PayTrace] === STARTING PAYMENT FORM LOAD ==='); 3869 console.log('[PayTrace] Checking browser compatibility...'); 3870 3871 // Detect Safari Private mode first 3872 detectSafariPrivateMode().then(function(isPrivate) { 3873 if (isPrivate) { 3874 console.error('[PayTrace] Safari Private mode detected - PayTrace not supported'); 3875 $(nodeContainer).find(".bs-loader-small").remove(); 3876 noticeSwall( 3877 "error", 3878 "Browser Compatibility Issue", 3879 "Safari Private browsing mode is not compatible with PayTrace. " + 3880 "Please disable Private browsing mode or use Chrome/Firefox to add a payment method." 3881 ); 3882 return; // Exit early 3883 } 3884 3885 // Not in private mode, proceed normally 3886 console.log('[PayTrace] Browser compatible - proceeding'); 3887 loadPayTraceFormInternal(apiAction, nodeContainer); 3888 }); 3889 } 3890 3891 function loadPayTraceFormInternal(apiAction, nodeContainer) { 3892 // BidSpirit call works directly from browser (has cookies) 3893 console.log('[PayTrace] Step 1: Calling BidSpirit API for clientSecret'); 3894 console.log('[PayTrace] SessionId:', bidspiritSessionId); 3895 console.log('[PayTrace] API Action:', apiAction); 3896 3897 // State tracking to prevent multiple error handlers 3898 var formLoadCompleted = false;
3899 var formLoadFailed = false; 3900 3901 // Timeout fallback in case things hang 3902 var loadTimeout = setTimeout(function() { 3903 if (!formLoadCompleted && !formLoadFailed) { 3904 formLoadFailed = true; 3905 console.error('[PayTrace] TIMEOUT: Form load took too long (30s)'); 3906 $(nodeContainer).find(".bs-loader-small").remove(); 3907 noticeSwall("error", "Timeout", "Payment form failed to load. Please try again."); 3908 } else { 3909 console.log('[PayTrace] 30s timeout ignored - form already completed/failed'); 3910 } 3911 }, 30000); 3912 3913 bidspiritPostQuery(apiAction, { 3914 sessionId: bidspiritSessionId 3915 }, function (data) { 3916 console.log('[PayTrace] Step 2: BidSpirit API SUCCESS'); 3917 console.log('[PayTrace] Response data:', data); 3918 $(nodeContainer).find('#payTracePaymentElement').append("<div id=\"pt_hpf_form\"></div>"); 3919 if (data.response.clientSecret !== undefined) { 3920 console.log('[PayTrace] Step 3: Got clientSecret (length: ' + data.response.clientSecret.length + ')'); 3921 console.log('[PayTrace] Step 4: Loading PayTrace SDK...'); 3922 loadPayTraceSDK(function() { 3923 console.log('[PayTrace] Step 5: SDK loaded successfully'); 3924 console.log('[PayTrace] Step 6: Calling PTPayment.setup (no interception - letting it run naturally)...'); 3925 3926 // Call PTPayment.setup without any interception 3927 PTPayment.setup({ 3928 styles: getPayTraceStyles(), 3929 authorization: { 3930 clientKey: data.response.clientSecret 3931 } 3932 }).then(function(instance) { 3933 if (!formLoadCompleted && !formLoadFailed) { 3934 formLoadCompleted = true; 3935 clearTimeout(loadTimeout); 3936 console.log('[PayTrace] Step 7: PTPayment.setup SUCCESS'); 3937 console.log('[PayTrace] Instance:', instance); 3938 window.payTraceInstance = instance; 3939 $(nodeContainer).find("footer").removeClass(window.bs_data.hidden_class); 3940 $(nodeContainer).find(".bs-loader-small").remove(); 3941 console.log('[PayTrace] === FORM LOAD COMPLETE ==='); 3942 btnActionPayTracePaymentMethods(); 3943 } 3944 }).catch(function(error) { 3945 if (!formLoadCompleted && !formLoadFailed) { 3946 formLoadFailed = true; 3947 clearTimeout(loadTimeout); 3948 console.error('[PayTrace] Step 7 FAILED: PTPayment.setup error'); 3949 console.error('[PayTrace] Error details:', error); 3950 console.error('[PayTrace] Error stack:', error ? error.stack : 'no stack'); 3951 3952 // Restore original fetch/XHR 3953 window.fetch = originalFetch; 3954 XMLHttpRequest.prototype.open = originalOpen; 3955 3956 $(nodeContainer).find(".bs-loader-small").remove(); 3957 3958 // Check if it's a timeout 3959 if (error.message && error.message.indexOf('timed out') !== -1) { 3960 noticeSwall("error", "Timeout", "PayTrace is incompatible with Safari Private browsing mode. Please use normal browsing or a different browser."); 3961 } else { 3962 noticeSwall("error", "Error", "Failed to initialize PayTrace form: " + error.message); 3963 } 3964 } 3965 }); 3966 }); 3967 } else { 3968 if (!formLoadCompleted && !formLoadFailed) { 3969 formLoadFailed = true; 3970 clearTimeout(loadTimeout); 3971 console.error('[PayTrace] Step 3 FAILED: No clientSecret in response'); 3972 console.error('[PayTrace] Response:', data); 3973 $(nodeContainer).find(".bs-loader-small").remove(); 3974 noticeSwall("error", "Unknown error", data.response.errorMessage); 3975 } 3976 } 3977 }, function(error) { 3978 if (!formLoadCompleted && !formLoadFailed) { 3979 formLoadFailed = true; 3980 clearTimeout(loadTimeout); 3981 console.error('[PayTrace] Step 2 FAILED: BidSpirit API error callback'); 3982 console.error('[PayTrace] Error:', error); 3983 $(nodeContainer).find(".bs-loader-small").remove(); 3984 noticeSwall("error", "API Error", "Failed to connect to BidSpirit API"); 3985 } 3986 }); 3987 } 3988 3989 function loadPayTraceSDK(callback) { 3990 var classTrigger = "paytrace-load"; 3991 if (document.body.classList.contains(classTrigger)) { 3992 callback(); 3993 } else { 3994 if (window.wp_data.sandbox === true) { 3995 console.info("We use sandbox envirement"); 3996 } 3997 const sdkUrl = window.wp_data.sandbox === true 3998 ? "https://protect.sandbox.paytrace.com/js/protect.min.js" 3999 : "https://protect.paytrace.com/js/protect.min.js"; 4000 4001 console.log('[PayTrace] Fetching SDK from:', sdkUrl); 4002 $.getScript(sdkUrl) 4003 .done(function(script, textStatus) { 4004 console.log('[PayTrace] SDK fetch done, status:', textStatus); 4005 console.log('[PayTrace] PTPayment available:', typeof PTPayment !== 'undefined'); 4006 callback(); 4007 console.info(textStatus + " PayTrace SDK load"); 4008 document.body.classList.add(classTrigger); 4009 }) 4010 .fail(function(jqxhr, settings, exception) { 4011 console.error('[PayTrace] SDK LOAD FAILED'); 4012 console.error('[PayTrace] jqXHR:', jqxhr); 4013 console.error('[PayTrace] Settings:', settings); 4014 console.error('[PayTrace] Exception:', exception); 4015 console.error('[PayTrace] Response text:', jqxhr.responseText); 4016 $(nodeContainer).find(".bs-loader-small").remove(); 4017 noticeSwall("error", "Error", "Failed to load PayTrace SDK: " + exception); 4018 }); 4019 } 4020 } 4021 4022 function getPayTraceStyles() { 4023 var styles = { 4024 'cc': { 4025 'font_size': '16px', 4026 'input_border_radius': '2px', 4027 'input_border_width': '1px', 4028 'input_margin': '5px 0px 5px 0px', 4029 'input_padding': '3px 5px 3px 5px', 4030 'label_size': '14px', 4031 'label_width': '150px', 4032 'label_font_weight': 'bold', 4033 'label_margin': '5px 0px 0px 0px', 4034 'label_padding': '0px 5px 0px 5px', 4035 'background_color': 'white', 4036 'height': '25px', 4037 'width': '327px', 4038 'padding_bottom': '0px' 4039 }, 4040 'code': { 4041 'border_color': '#333', 4042 'font_size': '13pt', 4043 'input_border_radius': '2px', 4044 'input_border_width': '1px', 4045 'input_margin': '5px 0px 5px 20px', 4046 'input_padding': '3px 5px 3px 5px', 4047 'background_color': 'white', 4048 'label_size': '14px', 4049 'label_width': '150px', 4050 'label_font_weight': 'bold', 4051 'label_margin': '5px 0px 0px 20px', 4052 'label_padding': '2px 5px 2px 5px', 4053 'height': '25px', 4054 'width': '110px', 4055 'padding_bottom': '2px' 4056 }, 4057 'body': { 4058 'background_color': 'white' 4059 } 4060 } 4061 return styles; 4062 } 4063 4064 function clearPayTraceForm() { 4065 var payTraceElement = $("#payTracePaymentElement"); 4066 if (payTraceElement.length) { 4067 payTraceElement.empty().append('<div class="bs-loader-small"></div>'); 4068 } 4069 } 4070 4071 function btnActionPayTracePaymentMethods() {
4072 $("#addPaymentMethodAction").off("click").on("click", function () { 4073 var $this = $(this), 4074 modalContainer = $this.parents(".modal__container"); 4075 modalContainer.append('<div class="bs-loader-fill"></div>'); 4076 4077 if (!window.payTraceInstance) { 4078 modalContainer.find(".bs-loader-fill").remove(); 4079 noticeSwall("error", "Error", "PayTrace form not initialized"); 4080 return; 4081 } 4082 4083 window.payTraceInstance.process() 4084 .then(handlePayTraceCardSubmissionSuccess) 4085 .catch(handlePayTraceCardSubmissionError) 4086 .finally(function() { 4087 modalContainer.find(".bs-loader-fill").remove(); 4088 }); 4089 }); 4090 } 4091 4092 function handlePayTraceCardSubmissionSuccess(encryptedCardInfo) { 4093 clearPayTraceForm(); 4094 bidspiritQuery("users/paymentMethods/saveCardFromPayTrace", { 4095 sessionId: bidspiritSessionId, 4096 hpfToken: encryptedCardInfo.message.hpf_token, 4097 encKey: encryptedCardInfo.message.enc_key 4098 }, function (response) { 4099 clearPayTraceForm(); 4100 if (!checkError(response)) { 4101 if (document.body.classList.contains('bp_profile_page')) { 4102 showPaymentMethodsList(); 4103 } 4104 4105 paymentMethodList(function () { 4106 if (!!paymentMethods[0]) { 4107 let auction = document.querySelector("[data-auction-id]"); 4108 let data = { 4109 sessionId: bidspiritSessionId, 4110 paymentMethodId: paymentMethods[0].id 4111 }; 4112 4113 if (!!auction) { 4114 data.auctionId = auction.getAttribute("data-auction-id"); 4115 } 4116
4117 bidspiritPostQuery("approvals/requestToParticipateInAuction", data, function (response) { 4118 updateDisplay(); 4119 }); 4120 } 4121 }); 4122 4123 MicroModal.close("modal-payment-method"); 4124 MicroModal.close("modal-request-approval"); 4125 } else { 4126 console.log("handlePayTraceCardSubmissionError 1"); 4127 handlePayTraceCardSubmissionError(response.error); 4128 } 4129 }); 4130 } 4131 4132 function handlePayTraceCardSubmissionError(error) { 4133 if (error !== undefined) { 4134 console.error("PayTrace submission error:", error); 4135 } 4136 clearPayTraceForm(); 4137 loadPayTraceForm("users/paymentMethods/getPayTraceSetupSecret", $("#modal-payment-method").find(".modal__container")); 4138 } 4139 4140 function togglePaymentForms(provider) { 4141 const stripForm = $("#stripePaymentElement"); 4142 const payTraceForm = $("#payTracePaymentElement"); 4143 4144 if (provider === "PAY_TRACE") { 4145 stripForm.removeClass("active").addClass(window.bs_data.hidden_class); 4146 payTraceForm.addClass("active").removeClass(window.bs_data.hidden_class); 4147 } else { 4148 stripForm.addClass("active").removeClass(window.bs_data.hidden_class); 4149 payTraceForm.removeClass("active").addClass(window.bs_data.hidden_class); 4150 } 4151 } 4152 4153 function addPaymentMethodCallback() { 4154 MicroModal.show("modal-payment-method", { 4155 onShow: function (modalBlock) { 4156 var $modalBlock = $("#modal-payment-method"), 4157 footer = $modalBlock.find("footer"); 4158 footer.find("#autoChargingCreditCardMessage-block").remove(); 4159 footer.prepend('<p id="autoChargingCreditCardMessage-block" class="bp-text-red bp-mb-0">' + autoChargingCreditCardMessage(auctionSettingsData) + "</p>"); 4160 4161 togglePaymentForms(auctionSettingsData.creditCardProvider); 4162 4163 if (auctionSettingsData.creditCardProvider === "PAY_TRACE") { 4164 loadPayTraceForm("users/paymentMethods/getPayTraceSetupSecret", $modalBlock.find(".modal__container")); 4165 } else { 4166 loadStripeForm("users/paymentMethods/getStripeSetupSecret", $modalBlock.find(".modal__container")); 4167 } 4168 4169 $modalBlock.addClass(triggerClass); 4170 }, 4171 onClose: function (modalBlock) { 4172 var $modalBlock = $(modalBlock); 4173 // $modalBlock.find(".modal__container").append('<div class="bs-loader-small"></div>'); 4174 4175 if (auctionSettingsData.creditCardProvider === "PAY_TRACE") { 4176 clearPayTraceForm(); 4177 } else { 4178 clearStripeForm(); 4179 } 4180 4181 $modalBlock.find("footer").addClass(window.bs_data.hidden_class); 4182 $modalBlock.removeClass(triggerClass); 4183 } 4184 }); 4185 } 4186 4187 function paymentMethodAction(apiAction, container, bidspiritUser) { 4188 if (bidspiritUser !== undefined && bidspiritUser.approvalState === "INCOMPLETE_PROFILE") { 4189 loadTemplate(container, "account-empty-template", { 4190 message: window.bs_lang.access_denied 4191 }); 4192 } else { 4193 loadTemplate(container, "payment-methods-template", {}, true, function () { 4194 $("#addPaymentMethod").on("click", addPaymentMethodCallback); 4195 showPaymentMethodsList(); 4196 }); 4197 } 4198 } 4199 4200 function auctionInfoInit(bidspiritSessionId, currentAuctionNumber, callback) { 4201 // A BidSpirit Shop has no auction behind it, so auctions/getAuctionInfo 4202 // answers "Auction <synthetic id> not found" — and checkError() puts 4203 // that straight in front of the customer as an error modal. Seed a 4204 // minimal auctionInfo instead and skip the call. 4205 if (bsShopIsActive()) { 4206 bidspiritApi.setAuctionInfo(bsShopAuctionInfo()); 4207 if (callback !== undefined) { 4208 callback(); 4209 } 4210 return true; 4211 } 4212 4213 if (currentAuctionNumber === "") { 4214 return false;
4215 } else { 4216 bidspiritQuery("auctions/getAuctionInfo", { 4217 sessionId: bidspiritSessionId, 4218 auctionId: currentAuctionNumber 4219 }, function (data) { 4220 if (!checkError(data)) { 4221 bidspiritApi.setAuctionInfo(data.response); 4222 var response = data.response; 4223 4224 if (response.approvalRequired !== undefined && response.approvalRequired) { 4225 approvalInfo(currentAuctionNumber); 4226 } 4227 4228 if (!!document.getElementById('auction-commission-field')) { 4229 document.getElementById('auction-commission-field').textContent = data.response.commission + "%"; 4230 } 4231 } 4232 4233 if (callback !== undefined) { 4234 callback(); 4235 } 4236 }); 4237 } 4238 } 4239 4240 function autoChargingCreditCardMessage(auctionSettingsData) { 4241 var additionalMessage = ""; 4242 4243 if (auctionSettingsData.autoPaymentDays !== undefined) { 4244 additionalMessage = window.bs_lang.auto_charge_x_days_after.replace(/#days#/, auctionSettingsData.autoPaymentDays); 4245 } 4246 4247 return additionalMessage; 4248 } 4249 4250 (function () { 4251 function loadMoreLots() { 4252 var triggerEvent = true, 4253 totalLots = catalogSection.attr("data-lot-count"); 4254 $(window, ".st-content").scroll(function (event) { 4255 var st = $(this).scrollTop(), 4256 wHeight = $(window).height(), 4257 catalogSection = $("#catalog-section"), 4258 catalogBlockHeight = catalogSection.height(), 4259 catalogOffset = catalogSection.offset(), 4260 endCatalog = catalogBlockHeight + catalogOffset.top, 4261 midTriggerHeight = st + wHeight + 1000, 4262 bgColor = catalogSection.attr("data-bg-color"), 4263 count = catalogSection.find(".bp-lot").length, 4264 part = catalogSection.attr("data-auction-part"), 4265 loaderTemplate = $("#loadMore-template").html(), 4266 lang = window.bs_data.lang; 4267 4268 var sortBy = function () { 4269 return searchGetParam("sort_by"); 4270 }; 4271 4272 var categoryBy = function () { 4273 return searchGetParam("category_by"); 4274 }; 4275 4276 var phraseBy = function () { 4277 return searchGetParam("phrase_by"); 4278 }; 4279 4280 var perPage = function () { 4281 return searchGetParam("per_page"); 4282 }; 4283 4284 if (midTriggerHeight > endCatalog && triggerEvent && count < totalLots) { 4285 catalogSection.append(loaderTemplate); 4286 triggerEvent = false; 4287 let currentAuctionNumber = catalogSection.attr("data-auction-index"); 4288 $.ajax({ 4289 type: "post", 4290 dataType: "json", 4291 url: window.wp_data.ajax_url, 4292 data: { 4293 action: "do_load_more", 4294 security: window.wp_nonce, 4295 auctionId: currentAuctionNumber, 4296 termId: catalogSection.attr("data-term-id"), 4297 count: count, 4298 part: part, 4299 lang: lang, 4300 sort_by: sortBy(), 4301 category_by: categoryBy(), 4302 phrase_by: phraseBy(), 4303 per_page: perPage() 4304 } 4305 }).done(function (response) { 4306 var indexes = []; 4307 $.each(response.data.lots, function (index, elem) { 4308 indexes.push(elem.itemIndex); 4309 }); 4310 loadTemplate(catalogSection, "lotsLoadMore-template", { 4311 lots: response.data.lots, 4312 currency: currencySymbol, 4313 bgColor: bgColor, 4314 showEstimatedPriceInItemsList: Boolean(parseInt(response.data.showEstimatedPriceInItemsList)), 4315 displayStartPriceInCatalog: Boolean(parseInt(response.data.displayStartPriceInCatalog)) 4316 }, false, function () { 4317 }, true); 4318 count = catalogSection.find(".bp-lot").length; 4319 totalLots = response.data.total; 4320 4321 new Promise((resolve, reject) => { 4322 auctionInfoInit(bidspiritSessionId, currentAuctionNumber, resolve); 4323 // resolve(); 4324 }).then(function (response) { 4325 updateAuctionPage(catalogSection, indexes); 4326 }); 4327 4328 triggerEvent = true; 4329 }).fail(function () { 4330 console.error("Fatal error"); 4331 }).always(function () { 4332 $("#bsLoaderCatalog").remove(); 4333 }); 4334 } 4335 }); 4336 } 4337 4338 var catalogSection = $("#catalog-section"), 4339 pagination = window.bs_data.use_pagination; 4340 4341 if (catalogSection.length && pagination === "off") {
4342 loadMoreLots(); 4343 } 4344 })(); 4345 4346 function updateDisplay() { 4347 var singleLot = $("#single-lot"), 4348 catalogSection = $("#catalog-section"), 4349 profile = $("#profile-page"); 4350 4351 (function () { 4352 if (catalogSection.length) { 4353 var currentAuctionNumber = catalogSection.attr("data-auction-id"); 4354 4355 new Promise((resolve, reject) => { 4356 auctionInfoInit(bidspiritSessionId, currentAuctionNumber, resolve); 4357 }).then(function (response) { 4358 updateAuctionPage(catalogSection); 4359 toggleAuctionAlert(currentAuctionNumber); 4360 }); 4361 } 4362 })(); 4363 4364 (function () { 4365 if (singleLot.length) { 4366 var lot = $("#single-lot"), 4367 dateTime = $("#dateTimeField"), 4368 fullPriceNode = $("#bp-fullPrice"); 4369 currentLotIndex = lot.attr("data-lot-index"); 4370 currentAuctionNumber = lot.attr("data-auction-index"); 4371 4372 new Promise((resolve, reject) => { 4373 auctionInfoInit(bidspiritSessionId, currentAuctionNumber, resolve); 4374 }).then(function (response) { 4375 loadBid(currentLotIndex, currentAuctionNumber); 4376 }); 4377 4378 if (dateTime.length) { 4379 getLeftDate(dateTime.attr("data-time")); 4380 } 4381 } 4382 })(); 4383 4384 (function () { 4385 function profileQuery(apiAction, lotList) { 4386 // Use the paginated function with future/past toggle for all profile tabs 4387 if (apiAction === "account/getAbsenteeBids" || 4388 apiAction === "account/getFavorites" || 4389 apiAction === "account/getPurchases") { 4390 profilePaginatedQuery(apiAction, lotList); 4391 return; 4392 } 4393 bidspiritQuery(apiAction, { 4394 sessionId: bidspiritSessionId, 4395 language: LANG 4396 }, function (data) { 4397 if (data.response.count > 0) { 4398 loadTemplate(lotList, "account-items-template", { 4399 items: data.response.items, 4400 currency: currencySymbol, 4401 imageBlank: imageBlank, 4402 bgColor: $("#profile-page").attr("data-bg-color") 4403 }, false, function () { 4404 $(lotList + " .bp-lots .bp-lot").each(function (index, elem) { 4405 var $this = $(elem), 4406 wishBtn = $this.find(".bp__wishlist"); 4407 $this.find("a").on("click", function (event) { 4408 event.preventDefault(); 4409 event.stopPropagation(); 4410 $.ajax({ 4411 type: "post", 4412 dataType: "json", 4413 url: window.wp_data.ajax_url, 4414 data: { 4415 action: "do_link", 4416 security: window.wp_nonce, 4417 bidSpirit: { 4418 lot_id: $this.attr("data-lot-id") 4419 } 4420 } 4421 }).done(function (response) { 4422 if (response.data !== undefined && response.success === true) { 4423 window.location = response.data.link; 4424 } else { 4425 noticeSwall("error", window.bs_lang.not_found); 4426 } 4427 }).fail(function (response) { 4428 noticeSwall("error", window.bs_lang.not_found); 4429 }); 4430 }); 4431 wishBtn.on("click", function (event) { 4432 event.preventDefault(); 4433 event.stopPropagation(); 4434 toggleFavorite($this, wishBtn, $this.attr("data-auction-number"), true); 4435 }); 4436 }); 4437
4438 data.response.items.forEach(function (lot) { 4439 if (lot.item.id !== undefined) { 4440 let elem = $("[data-lot-id=\"" + lot.item.id + "\"]"); 4441 if (elem.length > 0) { 4442 let $this = $(elem); 4443 4444 var nextMinBid = 0; 4445 nextMinBid = getMinBidPriceFromIncrementSteps(lot, lot.auction.increments); 4446 initIncrementSteps(lot.auction.increments, nextMinBid); 4447 let incrementStepsList = allIncrementsPrices; 4448 4449 let bids = []; 4450 Array.prototype.forEach.call(incrementStepsList, function (elem, i) { 4451 if (elem >= nextMinBid) { 4452 bids.push({ 4453 id: elem, 4454 text: formattedPrice(elem, currencySymbol) 4455 }); 4456 } 4457 }); 4458 4459 if (bids.length > 0 && bids[0] !== undefined && bids[0].id !== undefined && (nextMinBid !== 0 && nextMinBid < bids[0].id)) { 4460 bids.unshift({ 4461 id: nextMinBid, 4462 text: formattedPrice(nextMinBid, currencySymbol) 4463 }); 4464 } 4465 4466 console.log($this); 4467 let selectBid = select2build($this.find(".js-data-bid-list"), bids); 4468 } 4469 } 4470 }); 4471 }); 4472 } else { 4473 loadTemplate(lotList, "account-empty-template", { 4474 message: "Lot list empty" 4475 }); 4476 } 4477 }, function (data) { 4478 noticeSwall("error", "The request failed", "Your account may have been logged in earlier."); 4479 }); 4480 } 4481 4482 /** 4483 * Generic paginated profile query with Future / Ended auction toggle. 4484 * Handles BidSpirit's 1000-item API limit by fetching additional pages. 4485 * Works for: getAbsenteeBids, getFavorites, getPurchases 4486 */ 4487 function profilePaginatedQuery(apiAction, lotList) { 4488 var API_PAGE_SIZE = 1000; 4489 var allCollectedItems = []; 4490 var sectionPrefix = "bp-paginated-" + apiAction.replace(/\//g, "-"); 4491 var futureId = sectionPrefix + "-future"; 4492 var endedId = sectionPrefix + "-ended"; 4493 4494 $(lotList).html('<div class="bp-row bp-fix-width-lot"><div class="bp-d-flex bp-f-wrap bp-f-center bp-mb-30"><p>Loading...</p></div></div>'); 4495 4496 function fetchPage(offset) { 4497 var params = { 4498 sessionId: bidspiritSessionId, 4499 language: LANG 4500 }; 4501 if (offset > 0) { 4502 params.offset = offset; 4503 } 4504 4505 console.log("[Profile:" + apiAction + "] Fetching page, offset=" + offset); 4506 4507 bidspiritQuery(apiAction, params, function (data) { 4508 console.log("[Profile:" + apiAction + "] Page response (offset=" + offset + "):", "count=" + data.response.count, "items=" + (data.response.items ? data.response.items.length : 0)); 4509 4510 if (data.response.items && data.response.items.length > 0) { 4511 allCollectedItems = allCollectedItems.concat(data.response.items); 4512 console.log("[Profile:" + apiAction + "] Total collected so far:", allCollectedItems.length); 4513 4514 if (data.response.items.length >= API_PAGE_SIZE) { 4515 $(lotList).html('<div class="bp-row bp-fix-width-lot"><div class="bp-d-flex bp-f-wrap bp-f-center bp-mb-30"><p>Loading... (' + allCollectedItems.length + ' loaded)</p></div></div>'); 4516 fetchPage(offset + API_PAGE_SIZE); 4517 return; 4518 } 4519 } 4520 4521 if (allCollectedItems.length > 0) { 4522 renderAllItems(allCollectedItems); 4523 } else { 4524 loadTemplate(lotList, "account-empty-template", { 4525 message: "Lots not found" 4526 }); 4527 } 4528 }, function (data) { 4529 if (allCollectedItems.length > 0) { 4530 console.warn("[Profile:" + apiAction + "] Page fetch failed at offset=" + offset + ", rendering " + allCollectedItems.length + " items collected so far"); 4531 renderAllItems(allCollectedItems); 4532 } else { 4533 console.error("[Profile:" + apiAction + "] API request failed:", data); 4534 noticeSwall("error", "The request failed", "Your account may have been logged in earlier."); 4535 } 4536 }); 4537 } 4538 4539 function renderAllItems(allItems) { 4540 console.log("[Profile:" + apiAction + "] Rendering all items, total:", allItems.length); 4541 4542 var auctionDates = {};
4543 allItems.forEach(function(lot) { 4544 var key = lot.auction.date || 'unknown'; 4545 if (!auctionDates[key]) auctionDates[key] = 0; 4546 auctionDates[key]++; 4547 }); 4548 console.log("[Profile:" + apiAction + "] Auction dates breakdown:", auctionDates); 4549 4550 var futureItems = []; 4551 var endedItems = []; 4552 4553 allItems.forEach(function(lot) { 4554 var isEnded = false; 4555 if (lot.item.wasInLiveAuction === true) { 4556 isEnded = true; 4557 } else if (lot.soldBid !== undefined && lot.soldBid.isSold === true) { 4558 isEnded = true; 4559 } else if (lot.leadingBid !== undefined && lot.leadingBid.isSold === true) { 4560 isEnded = true; 4561 } 4562 4563 if (isEnded) { 4564 endedItems.push(lot); 4565 } else { 4566 futureItems.push(lot); 4567 } 4568 }); 4569 4570 console.log("[Profile:" + apiAction + "] Future items:", futureItems.length, "Ended items:", endedItems.length); 4571 4572 var toggleHtml = '<div class="bp-bids-toggle-wrapper" style="text-align: center; padding: 15px 0 5px;">'; 4573 toggleHtml += '<button type="button" class="bp-bids-toggle-btn bp-bids-toggle-active" data-target="future">Future Auctions (' + futureItems.length + ')</button>'; 4574 toggleHtml += '<button type="button" class="bp-bids-toggle-btn" data-target="ended">Ended Auctions (' + endedItems.length + ')</button>'; 4575 toggleHtml += '</div>'; 4576 if (futureItems.length > 0) { 4577 // The checkbox stays as the real control — it keeps the 4578 // keyboard/tab behaviour and every existing binding on 4579 // .af-bidwatch-checkbox — and the slider span is purely 4580 // its visual skin. aria-hidden so screen readers announce 4581 // the checkbox once, not twice. 4582 toggleHtml += '<div class="af-bidwatch-wrap"><label class="af-bidwatch-toggle">' + 4583 '<input type="checkbox" class="af-bidwatch-checkbox">' + 4584 '<span class="af-bidwatch-slider" aria-hidden="true"></span>' + 4585 '<span class="af-bidwatch-text">' + 4586 ((window.afBidWatchLang && window.afBidWatchLang.auto_refresh_label) || 'Auto-refresh bids (every 10s)') + 4587 '</span></label></div>'; 4588 } 4589 toggleHtml += '<div id="' + futureId + '"></div>'; 4590 toggleHtml += '<div id="' + endedId + '" style="display:none;"></div>'; 4591 4592 $(lotList).html(toggleHtml); 4593
4594 function renderSectionItems(targetSelector, items) { 4595 if (items.length === 0) { 4596 $(targetSelector).html('<div class="bp-row bp-fix-width-lot"><div class="bp-d-flex bp-f-wrap bp-f-center bp-mb-30"><p>Lots not found</p></div></div>'); 4597 return; 4598 } 4599 loadTemplate(targetSelector, "account-items-template", { 4600 items: items, 4601 currency: currencySymbol, 4602 imageBlank: imageBlank, 4603 bgColor: $("#profile-page").attr("data-bg-color") 4604 }, false, function () { 4605 $(targetSelector + " .bp-lots .bp-lot").each(function (index, elem) { 4606 var $this = $(elem), 4607 wishBtn = $this.find(".bp__wishlist"); 4608 $this.find("a").on("click", function (event) { 4609 event.preventDefault(); 4610 event.stopPropagation(); 4611 $.ajax({ 4612 type: "post", 4613 dataType: "json", 4614 url: window.wp_data.ajax_url, 4615 data: { 4616 action: "do_link", 4617 security: window.wp_nonce, 4618 bidSpirit: { 4619 lot_id: $this.attr("data-lot-id") 4620 } 4621 } 4622 }).done(function (response) { 4623 if (response.data !== undefined && response.success === true) { 4624 window.location = response.data.link; 4625 } else { 4626 noticeSwall("error", window.bs_lang.not_found); 4627 } 4628 }).fail(function (response) { 4629 noticeSwall("error", window.bs_lang.not_found); 4630 }); 4631 }); 4632 wishBtn.on("click", function (event) { 4633 event.preventDefault(); 4634 event.stopPropagation(); 4635 toggleFavorite($this, wishBtn, $this.attr("data-auction-number"), true); 4636 }); 4637 }); 4638 4639 items.forEach(function (lot) { 4640 if (lot.item.id !== undefined) { 4641 var elem = $(targetSelector + " [data-lot-id=\"" + lot.item.id + "\"]"); 4642 if (elem.length > 0) { 4643 var $this = $(elem); 4644 var nextMinBid = 0; 4645 nextMinBid = getMinBidPriceFromIncrementSteps(lot, lot.auction.increments); 4646 initIncrementSteps(lot.auction.increments, nextMinBid); 4647 var incrementStepsList = allIncrementsPrices; 4648 4649 var bids = []; 4650 Array.prototype.forEach.call(incrementStepsList, function (elem, i) { 4651 if (elem >= nextMinBid) { 4652 bids.push({ 4653 id: elem, 4654 text: formattedPrice(elem, currencySymbol) 4655 }); 4656 } 4657 }); 4658 4659 if (bids.length > 0 && bids[0] !== undefined && bids[0].id !== undefined && (nextMinBid !== 0 && nextMinBid < bids[0].id)) { 4660 bids.unshift({ 4661 id: nextMinBid, 4662 text: formattedPrice(nextMinBid, currencySymbol) 4663 }); 4664 } 4665 4666 select2build($this.find(".js-data-bid-l
4666ist"), bids); 4667 } 4668 } 4669 }); 4670 }); 4671 } 4672 4673 renderSectionItems("#" + futureId, futureItems); 4674 renderSectionItems("#" + endedId, endedItems); 4675 4676 // Auto-refresh (live bid watch) toggle — only present when there are future lots. 4677 afStopBidWatch(); 4678 if (futureItems.length > 0) { 4679 var $afBw = $(lotList).find(".af-bidwatch-checkbox"); 4680 $afBw.prop("checked", afBidWatchEnabled()); 4681 $afBw.off("change.afbw").on("change.afbw", function () { 4682 afSetBidWatchEnabled(this.checked); 4683 if (this.checked) { afStartBidWatch(); } else { afStopBidWatch(); } 4684 }); 4685 if (afBidWatchEnabled()) { afStartBidWatch(); } 4686 } 4687 4688 $(lotList).on("click", ".bp-bids-toggle-btn", function () { 4689 var target = $(this).attr("data-target"); 4690 $(lotList).find(".bp-bids-toggle-btn").removeClass("bp-bids-toggle-active"); 4691 $(this).addClass("bp-bids-toggle-active"); 4692 if (target === "future") { 4693 $("#" + futureId).show(); 4694 $("#" + endedId).hide(); 4695 } else { 4696 $("#" + futureId).hide(); 4697 $("#" + endedId).show(); 4698 } 4699 }); 4700 } 4701 4702 // Start fetching from offset 0 4703 fetchPage(0); 4704 } 4705 4706 function buildFields(user) { 4707 function checkField(field) { 4708 return field !== undefined ? field : ""; 4709 } 4710 4711 let settings = bidspiritApi.getAuctionSettingsData(); 4712 4713 var fields = { 4714 honorific: { 4715 value: checkField(user.honorific), 4716 label: "Honorific", 4717 required: false, 4718 type: "text" 4719 }, 4720 firstName: { 4721 value: checkField(user.firstName), 4722 label: "First Name", 4723 required: true, 4724 type: "text" 4725 }, 4726 lastName: { 4727 value: checkField(user.lastName), 4728 label: "Last Name", 4729 required: true, 4730 type: "text" 4731 }, 4732 email: { 4733 value: checkField(user.email), 4734 label: "Email", 4735 required: true, 4736 type: "email" 4737 }, 4738 password: { 4739 value: "", 4740 label: "Password", 4741 required: false, 4742 type: "password" 4743 }, 4744 phone: { 4745 value: checkField(user.phone), 4746 label: "Phone", 4747 required: true, 4748 type: "phone" 4749 }, 4750 secondPhone: { 4751 value: checkField(user.secondPhone), 4752 label: "Second phone", 4753 required: false, 4754 type: "phone" 4755 }, 4756 id: { 4757 value: checkField(user.id), 4758 label: "ID", 4759 required: false, 4760 type: "text", 4761 idPhotoUploadRequired: settings.idPhotoUploadRequired, 4762 requireIdPhoto: settings.requireIdPhoto, 4763 missingIdPhoto: bidspiritUser.missingIdPhoto, 4764 hasIdPhoto: bidspiritUser.hasIdPhoto 4765 }, 4766 taxNumber: { 4767 value: checkField(user.taxNumber), 4768 label: "Tax number", 4769 required: false, 4770 type: "text" 4771 } 4772 }, 4773 fieldsAddress = { 4774 countryCode: { 4775 value: "", 4776 label: "Country", 4777 required: true, 4778 type: "select" 4779 }, 4780 state: { 4781 value: "", 4782 label: "State", 4783 required: false, 4784 type: "select", 4785 hidden: true 4786 }, 4787 province: { 4788 value: "", 4789 label: "State", 4790 required: false, 4791 type: "text", 4792 hidden: true 4793 }, 4794 city: { 4795 value: "", 4796 label: "City", 4797 required: true, 4798 type: "text" 4799 }, 4800 address: { 4801 value: "", 4802 label: "Address", 4803 required: true, 4804 type: "text" 4805 }, 4806 zipCode: { 4807 value: "", 4808 label: "Zip Code", 4809 required: true, 4810 type: "text" 4811 } 4812 }; 4813 4814 if (user.address !== undefined) { 4815 fieldsAddress = { 4816 countryCode: { 4817 value: checkField(user.address.countryCode), 4818 label: "Country", 4819 required: true, 4820 type: "select" 4821 }, 4822 state: { 4823 value: checkField(user.address.state), 4824 label: "State", 4825 required: false, 4826 type: "select", 4827 hidden: true 4828 }, 4829 province: { 4830 value: checkField(user.address.state), 4831 label: "State", 4832 required: false, 4833 type: "text", 4834 hidden: true 4835 }, 4836 city: { 4837 value: checkField(user.address.city), 4838 label: "City", 4839 required: true, 4840 type: "text" 4841 }, 4842 address: { 4843 value: checkField(user.address.address), 4844 label: "Address", 4845 required: true, 4846 type: "text" 4847 }, 4848 zipCode: { 4849 value: checkField(user.address.zipCode), 4850 label: "Zip Code", 4851 required: true, 4852 type: "text" 4853 } 4854 }; 4855 } 4856 4857 return $.extend(fields, fieldsAddress); 4858 } 4859 4860 function buildShippingFields(user) { 4861 function checkField(field) { 4862 return field !== undefined ? field : ""; 4863 } 4864 4865 var shippingFields = { 4866 recipientName: { 4867 value: "", 4868 label: "Recipient name", 4869 required: false, 4870 type: "text" 4871 }, 4872 countryCode: { 4873 value: "", 4874 label: "Country", 4875 required: true, 4876 type: "select" 4877 }, 4878 state: { 4879 value: "", 4880 label: "State", 4881 required: false, 4882 type: "select", 4883 hidden: true 4884 }, 4885 province: { 4886 value: "", 4887 label: "State", 4888 required: false, 4889 type: "text", 4890 hidden: true 4891 }, 4892 city: { 4893 value: "", 4894 label: "City", 4895 required: true, 4896 type: "text" 4897 }, 4898 address: { 4899 value: "", 4900 label: "Address", 4901 required: true, 4902 type: "text" 4903 }, 4904 zipCode: { 4905 value: "", 4906 label: "Zip Code", 4907 required: true, 4908 type: "text" 4909 } 4910 }; 4911 4912 if (user.shipping !== undefined) { 4913 shippingFields = { 4914 recipientName: { 4915 value: checkField(user.shipping.recipientName), 4916 label: "Recipient name", 4917 required: false, 4918 type: "text" 4919 }, 4920 countryCode: { 4921 value: checkField(user.shipping.countryCode), 4922 label: "Country", 4923 required: true, 4924 type: "select" 4925 }, 4926 state: { 4927 value: checkField(user.shipping.state), 4928 label: "State", 4929 required: false, 4930 type: "select", 4931 hidden: true 4932 }, 4933 province: { 4934 value: checkField(user.shipping.state), 4935 label: "State", 4936 required: false, 4937 type: "text", 4938 hidden: true 4939 }, 4940 city: { 4941 value: checkField(user.shipping.city), 4942 label: "City", 4943 required: true, 4944 type: "text" 4945 }, 4946 address: { 4947 value: checkField(user.shipping.address), 4948 label: "Address", 4949 required: true, 4950 type: "text" 4951 }, 4952 zipCode: { 4953 value: checkField(user.shipping.zipCode), 4954 label: "Zip Code", 4955 required: true, 4956 type: "text" 4957 } 4958 }; 4959 } 4960 4961 return shippingFields; 4962 } 4963 4964 function profileFormAction() { 4965 var profileSection = "#profile-account-section"; 4966 4967 function uploadIdPhotoAction() { 4968 $('#uploadPhotoIdAction').off('click').on('click', function (event) { 4969 if (!$("#uploadIdPhotoInput").val()){ 4970 noticeSwall("error", window.bs_lang.select_file_to_upload); 4971 return; 4972 }
4973 let $this = $(this); 4974 $this.prop("disabled", true); 4975 var formData = new FormData(); 4976 formData.append("file", $("#uploadIdPhotoInput")[0].files[0]) 4977 4978 $.ajax({ 4979 url: BIDSPIRIT_API_BASE + "users/idphoto/setUserIdPhoto.api?sessionId="+bidspiritSessionId, 4980 headers: { 4981 'BIDSPIRIT-AUTH-TOKEN': bidspiritApi.getAuthToken('users/idphoto/setUserIdPhoto'), 4982 }, 4983 type: 'POST', 4984 data: formData, 4985 cache: false, 4986 contentType: false, 4987 processData: false, 4988 }) 4989 .done(function(data) { 4990 if (!checkError(data)) { 4991 $("#uploadIdPhotoButton").prop({disabled:false}); 4992 bidspiritUser.hasIdPhoto = true; 4993 noticeSwall("info", window.bs_lang.photo_id_uploaded_successfully); 4994 updateIdPhotoUploadDisplay(); 4995 } 4996 }) 4997 .fail(function() { 4998 console.error("error"); 4999 }) 5000 .always(function() { 5001 $this.prop("disabled", false); 5002 }); 5003 }) 5004 } 5005 5006 function displayIdPhoto(button){ 5007 MicroModal.init(microModalInitConfig()); 5008 $.ajax({ 5009 url: BIDSPIRIT_API_BASE + "users/idphoto/getUserIdPhoto.api?sessionId=" + bidspiritSessionId, 5010 headers: { 5011 'BIDSPIRIT-AUTH-TOKEN': bidspiritApi.getAuthToken('users/idphoto/getUserIdPhoto'), 5012 }, 5013 xhrFields: { 5014 responseType: 'blob' 5015 } 5016 }) 5017 .done(function(data) { 5018 var url = URL.createObjectURL(data); 5019 $('#idPhotoImage').attr('src', url); 5020 MicroModal.show("modal-photoId", microModalInitConfig()); 5021 }) 5022 .fail(function() { 5023 console.error("error displayIdPhoto"); 5024 }) 5025 .always(function() { 5026 $(button).prop("disabled", false); 5027 }); 5028 } 5029 5030 function updateIdPhotoUploadDisplay(){ 5031 if (bidspiritUser && (!bidspiritUser.hasIdPhoto)) { 5032 $("#uploadIdPhotoSection").show(); 5033 $("#deleteIdPhotoSection").hide(); 5034 5035 if (auctionSettingsData.idPhotoUploadRequired) { 5036 $('#uploadIdPhotoInput').prop("required", true); 5037 } 5038 } else { 5039 $("#uploadIdPhotoSection").hide(); 5040 $("#deleteIdPhotoSection").show(); 5041 } 5042 } 5043 5044 function deleteIdPhoto(button){ 5045 Swal.fire({ 5046 title: window.bs_lang.you_want_to_remove_your_id_photo, 5047 showDenyButton: true, 5048 showCancelButton: true, 5049 confirmButtonText: window.bs_lang.yes, 5050 denyButtonText: window.bs_lang.cancel 5051 }).then((result) => { 5052 if (result.isConfirmed) { 5053 bidspiritPostQuery("users/idphoto/removeUserIdPhoto", { 5054 sessionId: bidspiritSessionId 5055 }, (data) => { 5056 if (!checkError(data)) { 5057 bidspiritUser.hasIdPhoto = false; 5058 noticeSwall("info", window.bs_lang.id_photo_deleted); 5059 } 5060 5061 updateIdPhotoUploadDisplay(); 5062 }, () => {}, () => { 5063 $(button).prop("disabled", false); 5064 }); 5065 } else if (result.isDenied) { 5066 5067 } 5068 }); 5069 } 5070 5071 function codeFieldList(bidspiritUser) { 5072 bidspiritQuery("settings/getCountriesList", { 5073 sessionId: bidspiritSessionId, 5074 language: LANG 5075 }, function (data) { 5076 var countrySelect = $("#profilecountryCode"), 5077 countryShippingSelect = $("#shippingcountryCode"), 5078 stateSelect = $("#profilestate"), 5079 stateShippingSelect = $("#shippingFieldstate"), 5080 provinceShippingSelect = $("#shippingFieldprovince"), 5081 codeSelect = $(".phoneCodeSelect"), 5082 codeFirstSelect = $("#detailsphoneCountryCode"), 5083 codeSecondSelect = $("#detailssecondPhoneCountryCode"), 5084 items = [], 5085 codeItems = []; 5086 5087 if (data.response !== undefined) { 5088 items = $.map(data.response, function (obj) { 5089 return { 5090 id: obj.code, 5091 phoneCode: obj.phoneCode, 5092 text: obj.name 5093 }; 5094 }); 5095 codeItems = $.map(data.response, function (obj) { 5096 if (obj.phoneCode !== undefined) { 5097 return { 5098 id: obj.phoneCode, 5099 text: obj.phoneCode + " (" + obj.name + ")" 5100 }; 5101 } 5102 }); 5103 } 5104 5105 countrySelect.select2({ 5106 theme: "default bp-custom-select", 5107 width: "resolve", 5108 data: items 5109 }); 5110 countryShippingSelect.select2({ 5111 theme: "default bp-custom-select", 5112 width: "resolve", 5113 data: items 5114 }); 5115 5116 if (bidspiritUser.address !== undefined && bidspiritUser.address.countryCode !== undefined) { 5117 countrySelect.val(bidspiritUser.address.countryCode).trigger("change.select2"); 5118 5119 if (bidspiritUser.address.countryCode !== "US") { 5120 stateSelect.val("").trigger("change.select2"); 5121 } 5122 } 5123 if (bidspiritUser.shipping !== undefined && bidspiritUser.shipping.countryCode !== undefined) { 5124 countryShippingSelect.val(bidspiritUser.shipping.countryCode).trigger("change.select2"); 5125 5126 if (bidspiritUser.shipping.countryCode !== "US") { 5127 countryShippingSelect.val("").trigger("change.select2"); 5128 } 5129 } 5130 5131 countrySelect.on("select2:select", function (event) { 5132 var data = event.params.data; 5133 fieldState(data.id, ""); 5134 fieldTaxNumber(); 5135 }); 5136 countryShippingSelect.on("select2:select", function (event) { 5137 var data = event.params.data; 5138 fieldShippingFields(data.id, ""); 5139 }); 5140 codeSelect.select2({ 5141 theme: "default bp-custom-select", 5142 width: "resolve", 5143 data: codeItems, 5144 placeholder: window.bs_lang.country_code 5145 }); 5146 5147 if (bidspiritUser.phoneCountryCode !== undefined) { 5148 codeFirstSelect.val(bidspiritUser.phoneCountryCode).trigger("change.select2"); 5149 } 5150 5151 if (bidspiritUser.secondPhoneCountryCode !== undefined) { 5152 codeSecondSelect.val(bidspiritUser.secondPhoneCountryCode).trigger("change.select2"); 5153 } 5154 5155 stateList(bidspiritUser); 5156 5157 if (countrySelect.val() === "US") { 5158 stateSelect.parents(".bp-form-group").removeClass(window.bs_data.hidden_class); 5159 } 5160 if (countryShippingSelect.val() === "US") { 5161 stateShippingSelect.parents(".bp-form-group").removeClass(window.bs_data.hidden_class); 5162 } 5163 if (countryShippingSelect.val() !== "US" && countryShippingSelect.val() !== "IL") { 5164 provinceShippingSelect.removeClass(window.bs_data.hidden_class); 5165 } 5166 }); 5167 } 5168 5169 function fieldState(stateCode, value) { 5170 var stateSelect = $("#profilestate"), 5171 provinceField = $("#profileprovince"), 5172 stateCodeUS = "US", 5173 stateCodeIL = "IL"; 5174 5175 if (stateCode === stateCodeUS) { 5176 provinceField.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5177 provinceField.attr("name", "province"); 5178 stateSelect.parents(".bp-form-group").removeClass(window.bs_data.hidden_class); 5179 5180 if (bidspiritUser.address !== undefined && bidspiritUser.address.stateCode !== undefined && value !== "") { 5181 stateSelect.val(bidspiritUser.address.stateCode).trigger("change.select2"); 5182 } 5183 } else if (stateCode === stateCodeIL) { 5184 stateSelect.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5185 provinceField.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5186 provinceField.attr({ 5187 name: "state", 5188 value: "" 5189 }); 5190 } else { 5191 provinceField.parents(".bp-form-group").removeClass(window.bs_data.hidden_class); 5192 provinceField.attr({ 5193 name: "state", 5194 value: value 5195 }); 5196 stateSelect.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5197 } 5198 } 5199 5200 function fieldShippingFields(stateCode, value) { 5201 var stateSelect = $("#shippingstate"), 5202 countryField = $("#shippingcountryCode"), 5203 provinceField = $("#shippingprovince"), 5204 stateCodeUS = "US", 5205 stateCodeIL = "IL"; 5206 5207 if (bidspiritUser.shipping !== undefined && bidspiritUser.shipping.countryCode !== undefined && stateCode !== "") { 5208 countryField.val(stateCode).trigger("change.select2"); 5209 } 5210 5211 if (stateCode === stateCodeUS) { 5212 provinceField.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5213 provinceField.attr("name", "shipping.province"); 5214 stateSelect.parents(".bp-form-group").removeClass(window.bs_data.hidden_class); 5215 5216 if (bidspiritUser.shipping !== undefined && bidspiritUser.shipping.state !== undefined && value !== "") { 5217 stateSelect.val(bidspiritUser.shipping.state).trigger("change.select2"); 5218 } 5219 } else if (stateCode === stateCodeIL) { 5220 stateSelect.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5221 provinceField.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5222 provinceField.attr({ 5223 name: "shipping.state", 5224 value: "" 5225 }); 5226 } else { 5227 provinceField.parents(".bp-form-group").removeClass(window.bs_data.hidden_class); 5228 provinceField.attr({ 5229 name: "shipping.state", 5230 value: value 5231 }); 5232 stateSelect.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5233 5234 if (bidspiritUser.shipping !== undefined && bidspiritUser.shipping.countryCode !== undefined && value !== "") { 5235 countryField.val(bidspiritUser.shipping.countryCode).trigger("change.select2"); 5236 } 5237 } 5238 } 5239 5240 function fieldTaxNumber() { 5241 var taxNumberField = $("#profiletaxNumber"), 5242 bsOptions = window.bs_data; 5243 5244 if (bsOptions.tax_number_required !== undefined && bsOptions.tax_number_required === "on") { 5245 taxNumberField.parents(".bp-form-group").removeClass(window.bs_data.hidden_class); 5246 taxNumberField.attr("required", "true").attr("placeholder", taxNumberField.attr("placeholder") + " *"); 5247 } else { 5248 taxNumberField.parents(".bp-form-group").addClass(window.bs_data.hidden_class); 5249 taxNumberField.val("").removeAttr("required"); 5250 } 5251 } 5252 5253 function stateList(bidspiritUser) { 5254 var stateCodeUS = "US"; 5255 bidspiritQuery("settings/getCountryStates", { 5256 sessionId: bidspiritSessionId, 5257 countryCode: stateCodeUS 5258 }, function (data) { 5259 var countrySelect = $("#profilecountryCode"), 5260 stateSelect = $("#profilestate"), 5261 stateShippingSelect = $("#shippingstate"), 5262 items = []; 5263 5264 if (data.response !== undefined) { 5265 data.response.unshift({ 5266 code: "", 5267 name: "" 5268 }); 5269 items = $.map(data.response, function (obj) { 5270 return { 5271 id: obj.code, 5272 text: obj.name 5273 }; 5274 }); 5275 } 5276 5277 stateSelect.select2({ 5278 theme: "default bp-custom-select", 5279 width: "resolve", 5280 data: items, 5281 placeholder: "State" 5282 }); 5283 stateShippingSelect.select2({ 5284 theme: "default bp-custom-select", 5285 width: "resolve", 5286 data: items, 5287 placeholder: "State" 5288 }); 5289 5290 var stateVal = ""; 5291 5292 if (bidspiritUser.address !== undefined && (bidspiritUser.address.state !== undefined || bidspiritUser.address.stateCode !== undefined)) { 5293 stateVal = bidspiritUser.address.state; 5294 5295
5295 if (bidspiritUser.address.countryCode === "US") { 5296 stateVal = bpIsset(bidspiritUser.address.stateCode) ? bidspiritUser.address.stateCode : bidspiritUser.address.state; 5297 } 5298 5299 fieldState(countrySelect.val(), stateVal); 5300 } 5301 5302 if (bidspiritUser.shipping !== undefined && (bidspiritUser.shipping.state !== undefined || bidspiritUser.shipping.stateCode !== undefined)) { 5303 stateVal = bidspiritUser.shipping.state; 5304 5305 /*if (bidspiritUser.shipping.countryCode === "US") { 5306 stateVal = bpIsset(bidspiritUser.shipping.stateCode) ? bidspiritUser.shipping.stateCode : bidspiritUser.shipping.state; 5307 }*/ 5308 5309 fieldShippingFields(bidspiritUser.shipping.countryCode, stateVal); 5310 } 5311 5312 fieldTaxNumber(); 5313 }); 5314 } 5315 5316 if (!$(profileSection + " > *").length) { 5317 let profileJsTemplate = "profile-account-template"; 5318 if (!!document.getElementById("profile-account-v2-template")) { 5319 profileJsTemplate = "profile-account-v2-template"; 5320 } 5321 5322 loadTemplate(profileSection, profileJsTemplate, { 5323 user: bidspiritUser, 5324 fields: buildFields(bidspiritUser), 5325 shippingFields: buildShippingFields(bidspiritUser), 5326 stateInfo: getApprovalStateInfo(bidspiritUser) 5327 }, true, function () { 5328 if (bidspiritUser.allowInvitations !== undefined) { 5329 $(subscribeCheckbox).prop("checked", bidspiritUser.allowInvitations); 5330 } 5331 $("#af-pref-bid-emails").prop("checked", !!bidspiritUser.sendBidEmails); 5332 $("#af-pref-overbid-emails").prop("checked", !!bidspiritUser.sendOverBidEmails); 5333 5334 $(subscribeCheckbox + ", #af-pref-bid-emails, #af-pref-overbid-emails").on("change", function () { 5335 saveAlertsPreferences(); 5336 }); 5337 5338 updateIdPhotoUploadDisplay(); 5339 initPhoneVerificationSection(); 5340 5341 if (!!document.getElementById('uploadPhotoIdAction') && !!document.getElementById('uploadIdPhotoInput')) { 5342 uploadIdPhotoAction(); 5343 } 5344 5345 if (!!document.getElementById('showIdPhoto') && !!document.getElementById('deleteIdPhoto')) { 5346 $('#showIdPhoto').off('click').on('click', function (event) { 5347 event.preventDefault(); 5348 $(event.target).prop("disabled", true); 5349 displayIdPhoto(event.target); 5350 }); 5351 $('#deleteIdPhoto').off('click').on('click', function (event) { 5352 event.preventDefault(); 5353 $(event.target).prop("disabled", true); 5354 deleteIdPhoto(event.target); 5355 }); 5356 } 5357 }); 5358 5359 codeFieldList(bidspiritUser); 5360 5361 } 5362 5363 let profileEmailEditSelector = "#profileemail + svg.icon"; 5364 5365 if ($(profileEmailEditSelector).length !== 0) { 5366 $(profileEmailEditSelector).off('click').on("click", function (event) { 5367 document.getElementById("profileemail").disabled = false; 5368 }); 5369 } 5370 5371 passwordShowAction(); 5372 } 5373 5374 if (profile.length) { 5375 var wishList = "#bp-wish-list", 5376 wishListSection = "#profile-wishlist-section", 5377 bidsList = "#bp-my-bids", 5378 bidsListSection = "#profile-bids-section", 5379 winningsList = "#bp-winnings", 5380 winningsListSection = "#profile-winnings-section", 5381 billsList = "#bp-bills", 5382 billsListSection = "#profile-bills-section", 5383 paymentMethods = "#bp-payment-methods", 5384 paymentMethodsSection = "#profile-payment-methods-section", 5385 subscribeCheckbox = "#invitationsEnabled input"; 5386 5387 if (bidspiritUser && bidspiritUser.emailConfirmed === true) { 5388 loadTemplate("#profile-page", "profile-page-template", bidspiritUser, false, function () { 5389 activeTabs(); 5390 5391 switch (window.location.hash) { 5392 case wishList: 5393 profileQuery("account/getFavorites", wishListSection); 5394 break; 5395 5396 case bidsList: 5397 profileQuery("account/getAbsenteeBids", bidsListSection); 5398 break; 5399 5400 case winningsList: 5401 profileQuery("account/getPurchases", winningsListSection); 5402 break; 5403 5404 case billsList: 5405 billsAction(billsListSection); 5406 break; 5407 5408 case paymentMethods: 5409 paymentMethodAction("users/paymentMethods/getStripeSetupSecret", paymentMethodsSection, bidspiritUser); 5410 break; 5411 5412 default: 5413 profileFormAction(); 5414 } 5415 }); 5416 } else if (bidspiritUser && bidspiritUser.emailConfirmed === false) { 5417 loadTemplate("#profile-page", "profile-page-empty-template", bidspiritUser); 5418 } else { 5419 loadTemplate("#profile-page", "profile-page-gate-template", bidspiritUser); 5420 MicroModal.init(microModalInitConfig()); 5421 } 5422 5423 var updateDetailsForm = $("#updateDetailsSection"), 5424 logoutAction = $(".logoutLink"), 5425 shippingAction = $("#profileShippingCheckbox"), 5426 shippingWrapper = $("#wrpShippingField"), 5427 profileLink = $("#bp-profile-link, #bp-account .bp-spoiler-trigger"), 5428 wishListLink = $("#bp-wish-list-link, #bp-wish-list .bp-spoiler-trigger"), 5429 bidsListLink = $("#bp-bids-list-link, #bp-my-bids .bp-spoiler-trigger"), 5430 paymentMethodsLink = $("#bp-payment-methods-link, #bp-payment-methods .bp-spoiler-trigger"), 5431 winningsListLink = $("#bp-winnings-list-link, #bp-winnings .bp-spoiler-trigger"), 5432 billsListLink = $("#bp-bills-link, #bp-bills .bp-spoiler-trigger"); 5433 5434 if (updateDetailsForm.length) { 5435 updateDetailsForm.on("submit", function (event) { 5436 event.preventDefault(); 5437 submitUpdateDetails(); 5438 }); 5439 5440 if (shippingAction.length > 0) { 5441 let shippingFields = updateDetailsForm.find('.bp-shippingField'); 5442 shippingAction.on('change', function (event) {
5443 let $this = $(this), 5444 isChecked = $this.prop('checked'); 5445 5446 if (isChecked) { 5447 shippingWrapper.addClass('hidden'); 5448 shippingFields.each(function (index, field) { 5449 $(field).prop("disabled", true); 5450 }); 5451 } else { 5452 shippingWrapper.removeClass('hidden'); 5453 shippingFields.each(function (index, field) { 5454 $(field).prop("disabled", false); 5455 }); 5456 } 5457 }); 5458 5459 if (bidspiritUser.shipping !== undefined && bidspiritUser.shipping.countryCode !== "") { 5460 shippingAction.prop("checked", false); 5461 shippingAction.trigger("change"); 5462 } 5463 } 5464 } 5465 5466 resendEmailAction(); 5467 changeEmailAction(); 5468 5469 if (profileLink.length) { 5470 profileLink.on("click", function (event) { 5471 event.preventDefault(); 5472 profileFormAction(); 5473 }); 5474 } 5475 5476 if (wishListLink.length) { 5477 wishListLink.on("click", function (event) { 5478 event.preventDefault(); 5479 5480 if ($(wishListSection).is(":empty")) { 5481 profileQuery("account/getFavorites", wishListSection); 5482 } 5483 }); 5484 } 5485 5486 if (bidsListLink.length) { 5487 bidsListLink.on("click", function (event) { 5488 event.preventDefault(); 5489 5490 if ($(bidsListSection).is(":empty")) { 5491 profileQuery("account/getAbsenteeBids", bidsListSection); 5492 } 5493 }); 5494 } 5495 5496 if (paymentMethodsLink.length) { 5497 paymentMethodsLink.on("click", function (event) { 5498 event.preventDefault(); 5499 5500 if ($(paymentMethodsSection).is(":empty")) { 5501 paymentMethodAction("users/paymentMethods/getStripeSetupSecret", paymentMethodsSection, bidspiritUser); 5502 } 5503 }); 5504 } 5505 5506 if (winningsListLink.length) { 5507 winningsListLink.on("click", function (event) { 5508 event.preventDefault(); 5509 5510 if ($(winningsListSection).is(":empty")) { 5511 profileQuery("account/getPurchases", winningsListSection); 5512 } 5513 }); 5514 } 5515 5516 if (billsListLink.length) { 5517 billsListLink.on("click", function (event) { 5518 event.preventDefault(); 5519 5520 if ($(billsListSection).is(":empty")) { 5521 billsAction(billsListSection); 5522 } 5523 }); 5524 } 5525 5526 function billsAction(container) { 5527 // Clear the cached unpaid bills so the banner re-checks on next page load 5528 clearUnpaidBillsCache(); 5529 $(container).html('<div class="bp-loading-bills bp-text-center"><p>'+ (window.bs_lang.loading || 'Loading...') +'</p></div>'); 5530 var unpaidReq = $.Deferred(); 5531 bidspiritQuery("bills/getUnpaidBills", { 5532 sessionId: bidspiritSessionId, 5533 language: LANG 5534 }, function (data) { 5535 var bills = data && data.response ? data.response : []; 5536 if (!Array.isArray(bills)) bills = []; 5537 unpaidReq.resolve(bills); 5538 }, function () { 5539 unpaidReq.resolve([]); 5540 }); 5541 5542 var paidReq = $.Deferred(); 5543 bidspiritQuery("bills/getPaidBills", { 5544 sessionId: bidspiritSessionId, 5545 language: LANG 5546 }, function (data) { 5547 var bills = data && data.response ? data.response : []; 5548 if (!Array.isArray(bills)) bills = []; 5549 paidReq.resolve(bills); 5550 }, function () { 5551 paidReq.resolve([]); 5552 }); 5553 5554 $.when(unpaidReq, paidReq).done(function(unpaidBills, paidBills) { 5555 unpaidBills = unpaidBills || []; 5556 paidBills = paidBills || []; 5557 var allBills = unpaidBills.concat(paidBills); 5558 5559 // Extract codes and dates for mapping
5560 allBills.forEach(function(b) { 5561 if (b.description) { 5562 // Only match "for auction [code]" to avoid false positives like "Auction House" 5563 var m = b.description.match(/for auction\s+#?([a-zA-Z0-9-]+)/i); 5564 if (m) { 5565 b.auctionCode = m[1]; 5566 } 5567 // Extract date from end of description (e.g., "Mar 29, 2026") 5568 var mDate = b.description.match(/,\s*([A-Z][a-z]{2}\s+\d{1,2},\s*\d{4})\s*$/i); 5569 if (mDate) b.auctionDateStr = mDate[1].trim(); 5570 } 5571 // Also try billTime epoch for date 5572 if (!b.auctionDateStr && b.billTime) { 5573 var d = new Date(b.billTime); 5574 var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; 5575 b.auctionDateStr = months[d.getMonth()] + ' ' + d.getDate() + ', ' + d.getFullYear(); 5576 } 5577 b.isPaid = (b.status && b.status.toUpperCase() === "PAID") || b.isPaid === true; 5578 }); 5579 5580 // Build lookups for ALL bills — pass code if available, otherwise pass date for server-side auction matching 5581 var lookups = {}; 5582 var hasLookups = false; 5583 allBills.forEach(function(b, idx) { 5584 var entry = {}; 5585 if (b.auctionCode) { 5586 entry.code = b.auctionCode; 5587 } 5588 if (b.auctionDateStr) { 5589 entry.date = b.auctionDateStr; 5590 } 5591 if (entry.code || entry.date) { 5592 lookups["bill_" + idx] = entry; 5593 hasLookups = true; 5594 } 5595 }); 5596 5597 if (hasLookups) { 5598 $.ajax({ 5599 type: "post", 5600 url: window.wp_data.ajax_url, 5601 data: { 5602 action: "af_resolve_bill_titles", 5603 security: window.wp_nonce, 5604 lookups: lookups 5605 } 5606 }).done(function(res) { 5607 var mapping = res.success ? res.data : {}; 5608 allBills.forEach(function(b, idx) { 5609 var resolvedName = mapping["bill_" + idx]; 5610 if (b.description) { 5611 if (resolvedName) { 5612 var datePart = b.auctionDateStr ? " - " + b.auctionDateStr : ""; 5613 b.description = "Auction: " + resolvedName + datePart; 5614 } else { 5615 // Fallback cleaning 5616 b.description = b.description.replace(/^Bill for auction\s+#?[a-zA-Z0-9-]+\s+/i, "Auction: "); 5617 b.description = b.description.replace(/\sthat took place on\s+/i, " - "); 5618 b.description = b.description.replace(/\s+-\s+[a-zA-Z0-9-]+\s+-\s+/i, " - "); 5619 b.description = b.description.replace(/\s*-\s*-\s*/, " - "); 5620 } 5621 b.invoiceNumber = b.description; 5622 } 5623 }); 5624 renderInvoices(); 5625 }).fail(function() { 5626 renderInvoices(); 5627 }); 5628 } else { 5629 renderInvoices(); 5630 } 5631 5632 function renderInvoices() { 5633 loadTemplate(container, "account-bills-template", { 5634 items: allBills, 5635 currency: currencySymbol, 5636 isPaidTab: false, 5637 formattedPrice: formattedPrice, 5638 bidspiritServer: BIDSPIRIT_SERVER, 5639 ajaxUrl: window.wp_data.ajax_url, 5640 nonce: window.wp_nonce 5641 }, false); 5642 } 5643 }); 5644 } 5645 5646 if (bidspiritUser !== undefined && bidspiritUser.number !== undefined && window.bs_data.show_bidder_number !== undefined && window.bs_data.show_bidder_number === 'on') { 5647 let h1Profile = document.querySelector('.bp_profile_page .bp-header h1'); 5648 if (!!h1Profile) { 5649 h1Profile.innerText = window.bs_lang.bidder_number.replace(/\%s/, bidspiritUser.number); 5650 } 5651 } 5652 5653 doLogout(logoutAction); 5654 optOut(); 5655 } 5656 })(); 5657 5658 (function () { 5659 var dateTimeField = $("#dateTimeField, .bp-auction-start-date"); 5660 5661 if (dateTimeField.length) { 5662 dateTimeField.each(function (index, elem) { 5663 printTime($(elem), $(elem).attr("data-time")); 5664 }); 5665 } 5666 })(); 5667 5668 if (bidspiritUser !== null) { 5669 noticeUser(bidspiritUser); 5670 } 5671 5672 (function () { 5673 let profileCustomLink = $('[href="#bp-profile"]'); 5674 if (profileCustomLink.length) { 5675 let profileLink = window.bs_data.link_profile, 5676 bidspiritUser = bidspiritApi.getBidspiritUser(); 5677 5678 profileCustomLink.each(function (index, elem) { 5679 $(elem).off('click').on('click', function (event) { 5680 event.preventDefault(); 5681 if (bidspiritUser) { 5682 window.location.href = profileLink; 5683 } else { 5684 MicroModal.show('modal-login'); 5685 } 5686 }); 5687 }); 5688 } 5689 })(); 5690 } 5691 5692 function userDestroy(bidspiritUser) { 5693 bidspiritUser = null; 5694
5695 if ($("#modal-profile").length) { 5696 MicroModal.close("modal-profile"); 5697 MicroModal.init(microModalInitConfig()); 5698 } 5699 5700 try { 5701 localStorage.removeItem("bidspiritSessionId"); 5702 localStorage.removeItem("bidspiritAuthToken"); 5703 } catch (e) { 5704 console.error("Local storage disabled"); 5705 } 5706 5707 window.location.reload(); 5708 } 5709 5710 function doLogout(logoutAction) { 5711 checkPoint("bp-login", true); 5712 logoutAction.on("click", function (event) { 5713 event.preventDefault(); 5714 bidspiritQuery("users/logout", { 5715 sessionId: bidspiritSessionId 5716 }, function (data) { 5717 if (!checkError(data)) { 5718 userDestroy(bidspiritUser); 5719 } 5720 }); 5721 }); 5722 } 5723 5724 function optOut() { 5725 let optOutUserTrigger = $('#optOutUser'); 5726 if (optOutUserTrigger.length) { 5727 optOutUserTrigger.off('click').on('click', function (event) { 5728 event.preventDefault(); 5729 5730 Swal.fire({ 5731 title: window.bs_lang.want_to_delete_user, 5732 showCancelButton: true, 5733 confirmButtonColor: "#DD3333", 5734 cancelButtonColor: "#3085D6", 5735 confirmButtonText: window.bs_lang.yes_delete_user, 5736 }).then((result) => { 5737 if (result.isConfirmed) { 5738 bidspiritQuery("users/optOut", { 5739 sessionId: bidspiritSessionId 5740 }, function (data) { 5741 if (!checkError(data)) { 5742 userDestroy(bidspiritUser); 5743 } 5744 }); 5745 } 5746 }); 5747 }); 5748 } 5749 } 5750 5751 function printTime(elem, dateTime) { 5752 function getLocalTime(time) { 5753 var str = time; 5754 var re = /\(.+\)/gm; 5755 var found = str.match(re); 5756 5757 if (found !== null) { 5758 return found[0]; 5759 } else { 5760 return ""; 5761 } 5762 } 5763 5764 function addZero(i) { 5765 if (i < 10) { 5766 i = "0" + i; 5767 } 5768 5769 return i; 5770 } 5771 5772 if (bpIsset(window.timeZoneName) && bpIsset(window.timeZoneName) !== "") { 5773 var getAuctionDate = new Date(dateTime), 5774 polylangTimeUse = window.polylang_time, 5775 getAuctionDateDiff = timeShift(dateTime); 5776 } else { 5777 var getAuctionDate = new Date(dateTime), 5778 getAuctionDateDiff = getAuctionDate; 5779 } 5780 5781 if (!(bpIsset(window.timeZoneName) && bpIsset(window.timeZoneName) !== "") && window.browser_time === "off") { 5782 getAuctionDateDiff = new Date(getAuctionDate.getTime()); 5783 } 5784 5785 if (window.format_display_time === "2" || polylangTimeUse === "on") { 5786 var getAuctionDateDay = addZero(getAuctionDateDiff.getDate()), 5787 getAuctionMonth = addZero(getAuctionDateDiff.getMonth() + 1), 5788 getAuctionFullYear = getAuctionDateDiff.getFullYear(), 5789 getAuctionHours = addZero(getAuctionDateDiff.getHours()), 5790 getAuctionMinutes = addZero(getAuctionDateDiff.getMinutes()), 5791 nameDaysArray = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][getAuctionDate.getDay()], 5792 nameMonthArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
5792November", "December"][getAuctionDate.getMonth()]; 5793 } 5794 5795 var customDateForm = elem.attr("data-custom-format"), 5796 customDateFormTime = elem.attr("data-custom-format-time"), 5797 unknownExactDate = Boolean(parseInt(elem.attr("data-unknown-exact-date"))), 5798 unknownDate = elem.attr("data-unknown-date"), 5799 localTime = getLocalTime(getAuctionDateDiff.toString()), 5800 polyLanguage = getCookie("pll_language"); 5801 5802 if (window.browser_time === "off") { 5803 localTime = window.timeZoneLabel !== "" ? "(" + window.timeZoneLabel + ")" : ""; 5804 } 5805 5806 var userLang = polyLanguage !== "" ? polyLanguage : navigator.language || navigator.userLanguage; 5807 var options = { 5808 timeZone: getTimeZoneFromUser(), 5809 formatMatcher: "basic", 5810 weekday: "long", 5811 year: "numeric", 5812 month: "long", 5813 day: "numeric", 5814 hour: "numeric", 5815 minute: "numeric", 5816 timeZoneName: "short" 5817 }; 5818 5819 if (elem.length) { 5820 if (unknownExactDate) { 5821 elem.html(unknownDate); 5822 return; 5823 } 5824 5825 if (window.browser_time === "on" || customDateForm === "") { 5826 if (window.format_display_time === "2") { 5827 elem.html(nameMonthArray + " " + getAuctionDateDay + ", " + getAuctionFullYear + ", " + getAuctionHours + ":" + getAuctionMinutes + " " + localTime); 5828 } else if (polylangTimeUse === "on") { 5829 elem.html(getAuctionDateDiff.toLocaleTimeString(userLang, options)); 5830 } else { 5831 elem.html(getAuctionDateDiff.toLocaleTimeString(getLocaleFromUser(), options)); 5832 } 5833 } else { 5834 elem.html(customDateFormTime); 5835 } 5836 } 5837 } 5838 5839 // === Phone verification (BidSpirit users/phone/* APIs) === 5840 // A verified phone is required to place absentee bids / join live auctions. 5841 var lastVerifyPhoneMethod = "sms"; 5842 5843 function populateVerifyPhoneCountries(defaultPhoneCode) { 5844 function fill(list) { 5845 var $select = $("#verifyPhoneCountry"); 5846 $select.empty(); 5847 $.each(list, function (i, country) { 5848 if (country.phoneCode) { 5849 $select.append($("<option>").val(country.phoneCode).text(country.phoneCode + " (" + country.name + ")")); 5850 } 5851 }); 5852 if (defaultPhoneCode) { 5853 $select.val(defaultPhoneCode); 5854 } 5855 } 5856 5857 var cached = bidspiritApi.getCountriesList(); 5858 if (cached) { 5859 fill(cached); 5860 } else { 5861 bidspiritQuery("settings/getCountriesList", { 5862 sessionId: bidspiritSessionId, 5863 language: LANG 5864 }, function (data) { 5865 if (data.response) { 5866 bidspiritApi.setCountriesList(data.response); 5867 fill(data.response); 5868 } 5869 }); 5870 } 5871 } 5872 5873 function verifyPhoneStatus(message, isError) { 5874 var $status = $("#verifyPhoneStatus"); 5875 $status.text(message).removeClass("hidden"); 5876 if (isError) { 5877 $status.addClass("bp-text-red"); 5878 } else { 5879 $status.removeClass("bp-text-red"); 5880 } 5881 } 5882 5883 function phoneVerificationErrorMessage(errorCode) { 5884 switch (errorCode) { 5885 case "SMS_TO_LANDLINE": 5886 return window.bs_lang.verify_phone_sms_to_landline || "This looks like a landline. Please use \"Send code via call\" instead."; 5887 case "INVALID_PHONE_NUMBER": 5888 return window.bs_lang.verify_phone_invalid || "The phone number is invalid. Please check it and try again."; 5889 case "PHONE_EXISTS": 5890 case "SHOULD_SWITCH_USER": 5891 return window.bs_lang.verify_phone_exists || "This phone number is already verified by another account. Please log in with that account, or contact the auction house for support."; 5892 case "FAILED_TO_SENT_CODE": 5893 default: 5894 return window.bs_lang.verify_phone_failed_send || "Failed to send the verification code, please try again."; 5895 } 5896 } 5897 5898 function sendPhoneVerificationCode(method) { 5899 var countryCode = $("#verifyPhoneCountry").val(), 5900 phone = $.trim($("#verifyPhoneNumber").val()); 5901 5902 if (!phone) { 5903 verifyPhoneStatus(window.bs_lang.verify_phone_enter_number || "Please enter a phone number.", true); 5904 return; 5905 } 5906 5907 lastVerifyPhoneMethod = method; 5908 $("#verifyPhoneSms, #verifyPhoneCall, #verifyPhoneResend").prop("disabled", true); 5909 5910 bidspiritPostQuery("users/phone/sendPhoneVerificationCode", { 5911 sessionId: bidspiritSessionId, 5912 countryCode: countryCode, 5913 phone: phone, 5914 method: method, 5915 language: LANG 5916 }, function (data) { 5917 var res = data.response || {}; 5918 if (res.success) { 5919 $("#verifyPhoneSendStep").addClass("hidden"); 5920 $("#verifyPhoneCodeStep").removeClass("hidden"); 5921 verifyPhoneStatus((window.bs_lang.verify_phone_code_sent || "A verification code was sent to") + " +" + countryCode + phone, false); 5922 $("#verifyPhoneCode").val("").trigger("focus"); 5923 } else { 5924 console.error("[verify phone] sendPhoneVerificationCode failed", { 5925 errorCode: res.errorCode, 5926 errorMessage: res.errorMessage, 5927 sessionIdLen: (bidspiritSessionId || "").length, 5928 hasAuthToken: !!bidspiritApi.getAuthToken() 5929 });
5930 var msg = phoneVerificationErrorMessage(res.errorCode); 5931 var mappedCodes = ["SMS_TO_LANDLINE", "INVALID_PHONE_NUMBER", "PHONE_EXISTS", "SHOULD_SWITCH_USER", "FAILED_TO_SENT_CODE"]; 5932 if (res.errorCode && mappedCodes.indexOf(res.errorCode) === -1) { 5933 // surface any not-yet-mapped code so it can be handled explicitly 5934 msg += " [" + res.errorCode + "]"; 5935 } 5936 verifyPhoneStatus(msg, true); 5937 } 5938 }, function () { 5939 console.error("[verify phone] sendPhoneVerificationCode AJAX request failed (network/CORS)"); 5940 verifyPhoneStatus((window.bs_lang.verify_phone_failed_send || "Failed to send the verification code, please try again.") + " [network]", true); 5941 }, function () { 5942 $("#verifyPhoneSms, #verifyPhoneCall, #verifyPhoneResend").prop("disabled", false); 5943 }); 5944 } 5945 5946 function checkPhoneVerificationCode() { 5947 var countryCode = $("#verifyPhoneCountry").val(), 5948 phone = $.trim($("#verifyPhoneNumber").val()), 5949 code = $.trim($("#verifyPhoneCode").val()); 5950 5951 if (!code) { 5952 verifyPhoneStatus(window.bs_lang.verify_phone_enter_code || "Please enter the code you received.", true); 5953 return; 5954 } 5955 5956 $("#verifyPhoneCheck").prop("disabled", true); 5957 5958 bidspiritPostQuery("users/phone/checkPhoneVerificationCode", { 5959 sessionId: bidspiritSessionId, 5960 countryCode: countryCode, 5961 phone: phone, 5962 verificationCode: code 5963 }, function (data) { 5964 if (!checkError(data)) { 5965 if (data.response && data.response.verified) { 5966 var user = bidspiritApi.getBidspiritUser(); 5967 if (user) { 5968 user.phoneVerified = true; 5969 user.phoneCountryCode = countryCode; 5970 user.phone = phone; 5971 bidspiritApi.setBidspiritUser(user); 5972 } 5973 try { 5974 MicroModal.close("modal-verify-phone"); 5975 } catch (e) { 5976 } 5977 initPhoneVerificationSection(); 5978 noticeSwall("success", window.bs_lang.verify_phone_verified || "Your phone has been verified."); 5979 } else { 5980 verifyPhoneStatus(window.bs_lang.verify_phone_wrong_code || "The code is incorrect. Please try again.", true); 5981 } 5982 } 5983 }, function () { 5984 verifyPhoneStatus(window.bs_lang.verify_phone_failed_send || "Something went wrong, please try again.", true); 5985 }, function () { 5986 $("#verifyPhoneCheck").prop("disabled", false); 5987 }); 5988 } 5989 5990 function bindVerifyPhoneModal() { 5991 $("#verifyPhoneSms").off("click.bpVerify").on("click.bpVerify", function () { 5992 sendPhoneVerificationCode("sms"); 5993 }); 5994 $("#verifyPhoneCall").off("click.bpVerify").on("click.bpVerify", function () { 5995 sendPhoneVerificationCode("call"); 5996 }); 5997 $("#verifyPhoneResend").off("click.bpVerify").on("click.bpVerify", function () { 5998 sendPhoneVerificationCode(lastVerifyPhoneMethod); 5999 }); 6000 $("#verifyPhoneCheck").off("click.bpVerify").on("click.bpVerify", function () { 6001 checkPhoneVerificationCode(); 6002 }); 6003 } 6004 6005 function showVerifyPhoneModal() { 6006 if (!$("#modal-verify-phone").length) { 6007 return; 6008 } 6009 var user = bidspiritApi.getBidspiritUser() || {}; 6010 // reset to the "send code" step 6011 $("#verifyPhoneCodeStep").addClass("hidden"); 6012 $("#verifyPhoneSendStep").removeClass("hidden"); 6013 $("#verifyPhoneCode").val(""); 6014 $("#verifyPhoneStatus").addClass("hidden").text(""); 6015 $("#verifyPhoneNumber").val(user.phone || ""); 6016 populateVerifyPhoneCountries(user.phoneCountryCode); 6017 bindVerifyPhoneModal(); 6018 6019 try { 6020 MicroModal.show("modal-verify-phone", microModalInitConfig()); 6021 } catch (e) { 6022 console.error("verify phone modal", e); 6023 } 6024 } 6025 6026 function initPhoneVerificationSection() { 6027 var $section = $("#phoneVerificationSection"); 6028 if (!$section.length) { 6029 return; 6030 } 6031 var user = bidspiritApi.getBidspiritUser() || {}; 6032 $section.empty(); 6033 if (window.afRequirePhoneVerification === false) { return; } 6034 6035 if (user.phoneVerified) { 6036 $section.append($("<span>
6036").addClass("bp-verify-phone__ok").html( 6037 '<svg class="bp-icon bp-icon-green"><use xlink:href="#check"></use></svg> ' + 6038 (window.bs_lang.verify_phone_verified_label || "Phone verified") 6039 )); 6040 } else { 6041 $("<button>") 6042 .attr("type", "button") 6043 .addClass("bp-verify-phone__cta") 6044 .text(window.bs_lang.verify_phone_cta || "Verify phone") 6045 .on("click", function (event) { 6046 event.preventDefault(); 6047 showVerifyPhoneModal(); 6048 }) 6049 .appendTo($section); 6050 } 6051 } 6052 6053 function submitBid() { 6054 var singleLot = $("#single-lot"), 6055 notApproveStateNotice = window.bs_lang.not_approved_user, 6056 pendingStateNotice = window.bs_lang.pending_user_state; 6057 6058 if (!bidspiritUser) { 6059 try { 6060 MicroModal.show("modal-login", microModalInitConfig()); 6061 } catch (e) { 6062 console.error(e); 6063 } 6064 } else if (bidspiritUser.approvalState === "PENDING") { 6065 noticeSwall("error", window.bs_lang.oops, pendingStateNotice); 6066 } else if (bidspiritUser.approvalState === "INCOMPLETE_PROFILE") { 6067 noticeSwall("error", window.bs_lang.oops, notApproveStateNotice); 6068 } else if (window.afRequirePhoneVerification !== false && !bidspiritUser.phoneVerified) { 6069 showVerifyPhoneModal(); 6070 } else { 6071 var data = getDataForm("bidFormSection"), 6072 modalBidForm = "#modal-bid-content", 6073 lotName = $(modalBidForm).attr("data-name"), 6074 houseInfo = bidspiritApi.getAuctionHouseData(), 6075 auctionInfo = bidspiritApi.getAuctionInfo(), 6076 lotLinkTerm = window.bs_data.page_terms, 6077 additionalNotice = false, 6078 additionalNoticeText = "", 6079 auctionItemInfo = bidspiritApi.getAuctionItemInfo(), 6080 fullPriceVat = auctionItemInfo.item.fullPriceVat, 6081 auctionCommission = auctionInfo.commission; 6082 6083 data.sessionId = bidspiritSessionId; 6084 data.auctionId = currentAuctionNumber; 6085 data.lotIndex = currentItemInfo.lotIndex; 6086 data.bidFormUrl = window.location.href; 6087 data.sendBidEmails = false; 6088 data.sendOverBidEmails = false; 6089 6090 if (parseInt(data.price) >= currentItemInfo.buyoutPrice) { 6091 additionalNotice = true; 6092 additionalNoticeText = window.bs_lang.buyout_notice.replace(/#price#/, formattedPrice(currentItemInfo.buyoutPrice, currencySymbol)); 6093 } 6094 6095 MicroModal.show("modal-bid", microModalInitConfig()); 6096 loadTemplate(modalBidForm, "modal-bid-template", { 6097 index: data.lotIndex, 6098 name: lotName, 6099 currentCurrency: currencySymbol, 6100 price: data.price, 6101 fullPrice: getCommissionPrice(data.price), 6102 fullPriceInfo: getFullPriceInfo(currentItemInfo, auctionInfo, data.price), 6103 linkTerms: lotLinkTerm, 6104 additionalNotice: additionalNotice, 6105 additionalNoticeText: additionalNoticeText, 6106 auctionHouseData: auctionHouseData, 6107 fullPriceVat: fullPriceVat, 6108 auctionCommission: auctionCommission, 6109 user: bidspiritUser, 6110 auctionItemInfo: auctionItemInfo, 6111 itemInfo: currentItemInfo, 6112 settings: auctionSettingsData, 6113 additionalMessage: autoChargingCreditCardMessage(auctionSettingsData) 6114 }, false, function () { 6115 $(modalBidForm).off("click", "#agreeBid").on("click", "#agreeBid", function (event) { 6116 event.preventDefault(); 6117 var bsOptions = window.bs_data, 6118 taxNumberNotRequired = bsOptions.tax_number_required !== undefined && bsOptions.tax_number_required === "off"; 6119 6120 function userGate(bidspiritUser) { 6121 if (bidspiritUser.taxNumber !== undefined && bidspiritUser.taxNumber !== "") { 6122 return true; 6123 } 6124 6125 return false;
6126 } 6127 6128 var subData = getDataForm("subBidFormSection"); 6129 6130 if (subData) { 6131 data.sendBidEmails = subData.sendBidEmails !== undefined && subData.sendBidEmails === "true"; 6132 data.sendOverBidEmails = subData.sendOverBidEmails !== undefined && subData.sendOverBidEmails === "true"; 6133 data.callUserWhenItemIsLive = subData.callUserWhenItemIsLive !== undefined && subData.callUserWhenItemIsLive === "true"; 6134 bidspiritUser.sendBidEmails = data.sendBidEmails; 6135 bidspiritUser.sendOverBidEmails = data.sendOverBidEmails; 6136 } 6137 6138 if (taxNumberNotRequired || userGate(bidspiritUser)) { 6139 var dataAlert = { 6140 sessionId: data.sessionId, 6141 auctionId: data.auctionId, 6142 lotIndex: data.lotIndex, 6143 isOn: true 6144 }; 6145 bidspiritQuery("items/placeBid", data, function (data) { 6146 if (!checkError(data)) { 6147 console.log("test1", data); 6148 handleSubmitResponse(data.response); 6149 bidspiritQuery("items/setItemAlert", dataAlert, function () {}); 6150 data.response.data = { 6151 auctionId: dataAlert.auctionId, 6152 lotIndex: dataAlert.lotIndex, 6153 user: bidspiritUser.email 6154 }; 6155 hangUpEvent("bp:after-items-place-bid", data.response); 6156 6157 // Record bid count 6158 if (typeof AuctionForgeBidCount !== "undefined") { 6159 var bidPostId = $("#af-bid-count-display").attr("data-post-id") || ""; 6160 if (bidPostId) { 6161 $.post(AuctionForgeBidCount.ajaxUrl, { 6162 action: "auctionforge_record_bid", 6163 nonce: AuctionForgeBidCount.nonce, 6164 post_id: bidPostId 6165 }, function(resp) { 6166 if (resp.success && resp.data && resp.data.bid_count !== undefined) { 6167 var $el = $("#af-bid-count-display"); 6168 if ($el.length) { 6169 var svg = $el.find("svg").prop("outerHTML") || ""; 6170 var cnt = resp.data.bid_count; 6171 $el.html(svg + cnt + " " + (cnt === 1 ? "bid" : "bids")); 6172 } 6173 } 6174 }); 6175 } 6176 } 6177 } 6178 }); 6179 MicroModal.close("modal-bid"); 6180 } else { 6181 MicroModal.close("modal-bid"); 6182 noticeSwall("error", window.bs_lang.tax_number_required, window.bs_lang.tax_number_required_label, {}, function () { 6183 var linkProfile = window.bs_data.link_profile; 6184 6185 if (linkProfile !== undefined && linkProfile !== "link") { 6186 window.location = linkProfile; 6187 } 6188 }); 6189 } 6190 }); 6191 $(modalBidForm).off("click", "#dontAgreeBid").on("click", "#dontAgreeBid", function (event) { 6192 event.preventDefault(); 6193 MicroModal.close("modal-bid"); 6194 }); 6195 }); 6196 } 6197 } 6198 6199 function showTermsCondModal() { 6200 bidspiritQuery("docs/getTerms", { 6201 language: LANG 6202 }, function (data) { 6203 let modalBody = document.getElementById("modal-requestApprovalTerms-content"); 6204 6205 if (!!modalBody) { 6206 modalBody.innerHTML = data; 6207 $("#requestApprovalTermsAction").on("click", function (event) { 6208 event.preventDefault();
6209 let $this = $(this), 6210 auctionInfo = bidspiritApi.getAuctionInfo(), 6211 data = {}; 6212 data.sessionId = bidspiritSessionId; 6213 data.auctionId = auctionInfo.id; 6214 $this.prop("disabled", true); 6215 bidspiritPostQuery("approvals/requestToParticipateInAuction", data, function (data) { 6216 if (!checkError(data)) { 6217 MicroModal.close("modal-request-approval-terms"); 6218 approvalInfo(auctionInfo.id); 6219 } 6220 }, function () { 6221 }, function () { 6222 $this.prop("disabled", false); 6223 }); 6224 }); 6225 MicroModal.show("modal-request-approval-terms", microModalInitConfig()); 6226 } 6227 }); 6228 } 6229 6230 function bidProcessAction(modalBidForm, params, data, dataAlert) { 6231 MicroModal.show("modal-bid", microModalInitConfig()); 6232 loadTemplate(modalBidForm, "modal-bid-template", params, false, function () { 6233 $(modalBidForm).off("click", "#agreeBid").on("click", "#agreeBid", function (event) { 6234 event.preventDefault(); 6235 var subData = getDataForm("subBidFormSection"); 6236 6237 if (subData) { 6238 data.sendBidEmails = subData.sendBidEmails !== undefined && subData.sendBidEmails === "true"; 6239 data.sendOverBidEmails = subData.sendOverBidEmails !== undefined && subData.sendOverBidEmails === "true"; 6240 data.callUserWhenItemIsLive = subData.callUserWhenItemIsLive !== undefined && subData.callUserWhenItemIsLive === "true"; 6241 bidspiritUser.sendBidEmails = data.sendBidEmails; 6242 bidspiritUser.sendOverBidEmails = data.sendOverBidEmails; 6243 } 6244 6245 bidspiritQuery("items/placeBid", data, function (data) { 6246 if (!checkError(data)) { 6247 var response = data.response; 6248 6249 let type = "info"; 6250 if (response.leadingBidCode === "ANOTHER_BID_HIGHER" || response.leadingBidCode === "ANOTHER_BID_EARLIER") { 6251 type = "error"; 6252 } 6253 noticeSwall(type, getLeadingBidMessage(response.leadingBidCode)); 6254 6255 bidspiritQuery("items/setItemAlert", dataAlert, function () { 6256 }); 6257 updateDisplay(); 6258 data.response.data = { 6259 auctionId: dataAlert.auctionId, 6260 lotIndex: dataAlert.lotIndex, 6261 user: bidspiritUser.email 6262 }; 6263 hangUpEvent("bp:after-items-place-bid", data.response); 6264 6265 // Record bid count 6266 if (typeof AuctionForgeBidCount !== "undefined") { 6267 var bidPostId = $("#af-bid-count-display").attr("data-post-id") || ""; 6268 if (bidPostId) { 6269 $.post(AuctionForgeBidCount.ajaxUrl, { 6270 action: "auctionforge_record_bid", 6271 nonce: AuctionForgeBidCount.nonce, 6272 post_id: bidPostId 6273 }, function(resp) { 6274 if (resp.success && resp.data && resp.data.bid_count !== undefined) { 6275 var $el = $("#af-bid-count-display"); 6276 if ($el.length) { 6277 var svg = $el.find("svg").prop("outerHTML") || ""; 6278 var cnt = resp.data.bid_count; 6279 $el.html(svg + cnt + " " + (cnt === 1 ? "bid" : "bids")); 6280 } 6281 } 6282 }); 6283 } 6284 } 6285 } 6286 6287 MicroModal.close("modal-bid"); 6288 }); 6289 });
6290 $(modalBidForm).off("click", "#dontAgreeBid").on("click", "#dontAgreeBid", function (event) { 6291 event.preventDefault(); 6292 MicroModal.close("modal-bid"); 6293 }); 6294 }); 6295 } 6296 6297 function submitBidCatalog(lot, minBidPrice, itemInfoData) { 6298 var singleLot = lot, 6299 notApproveStateNotice = window.bs_lang.not_approved_user, 6300 pendingStateNotice = window.bs_lang.pending_user_state; 6301 currentItemInfo = itemInfoData.response.itemsInfo[singleLot.attr("data-lot-index")]; 6302 currentItemInfo.buyoutPrice = minBidPrice; 6303 MicroModal.init(microModalInitConfig()); 6304 6305 if (!bidspiritUser) { 6306 try { 6307 MicroModal.show("modal-login", microModalInitConfig()); 6308 } catch (e) { 6309 console.error(e); 6310 } 6311 } else if (bidspiritUser.approvalState === "PENDING") { 6312 noticeSwall("error", window.bs_lang.oops, pendingStateNotice); 6313 } else if (bidspiritUser.approvalState === "INCOMPLETE_PROFILE") { 6314 noticeSwall("error", window.bs_lang.oops, notApproveStateNotice); 6315 } else if (window.afRequirePhoneVerification !== false && !bidspiritUser.phoneVerified) { 6316 showVerifyPhoneModal(); 6317 } else { 6318 var data = getDataForm("bidFormSection"), 6319 modalBidForm = "#modal-bid-content", 6320 lotName = lot.find(".bp-lot__title a").text().replace(/Lot\s\d+\:/, ""), 6321 lotLinkTerm = window.bs_data.page_terms, 6322 additionalNotice = false, 6323 additionalNoticeText = "", 6324 auctionInfo = bidspiritApi.getAuctionInfo(), 6325 fullPriceVat = Boolean(parseInt(lot.attr("data-full-price-vat"))), 6326 auctionCommission = auctionInfo.commission; 6327 data.sessionId = bidspiritSessionId; 6328 data.auctionId = currentAuctionNumber; 6329 data.lotIndex = currentItemInfo.lotIndex; 6330 data.bidFormUrl = lot.find("a").attr("href"); 6331 data.sendBidEmails = false; 6332 data.sendOverBidEmails = false; 6333 6334 if (parseInt(data.price) >= currentItemInfo.buyoutPrice) { 6335 additionalNotice = true; 6336 additionalNoticeText = window.bs_lang.buyout_notice.replace(/#price#/, formattedPrice(currentItemInfo.buyoutPrice, currencySymbol)); 6337 } 6338 6339 if (data.price === undefined) { 6340 data.price = minBidPrice; 6341 } 6342 6343 var params = { 6344 index: data.lotIndex, 6345 name: lotName, 6346 currentCurrency: currencySymbol, 6347 price: data.price, 6348 fullPrice: getCommissionPrice(data.price, fullPriceVat, auctionCommission), 6349 fullPriceInfo: getFullPriceInfo(currentItemInfo, auctionInfo, data.price), 6350 linkTerms: lotLinkTerm, 6351 additionalNotice: additionalNotice, 6352 additionalNoticeText: additionalNoticeText, 6353 auctionHouseData: auctionHouseData, 6354 fullPriceVat: fullPriceVat, 6355 auctionCommission: auctionCommission, 6356 user: bidspiritUser, 6357 itemInfo: currentItemInfo, 6358 settings: auctionSettingsData, 6359 additionalMessage: autoChargingCreditCardMessage(auctionSettingsData) 6360 }; 6361 6362 function userGate(bidspiritUser) { 6363 if (bidspiritUser.taxNumber !== undefined && bidspiritUser.taxNumber !== "") { 6364 return true; 6365 } 6366 6367 return false; 6368 } 6369 6370 var bsOptions = window.bs_data, 6371 taxNumberNotRequired = bsOptions.tax_number_required !== undefined && bsOptions.tax_number_required === "off"; 6372 6373 if (taxNumberNotRequired || userGate(bidspiritUser)) { 6374 var auctionApprovalState = bidspiritApi.getAuctionApprovalState(); 6375 var dataAlert = { 6376 sessionId: data.sessionId, 6377 auctionId: data.auctionId, 6378 lotIndex: data.lotIndex, 6379 isOn: true 6380 }; 6381 6382 if (auctionInfo.approvalRequired !== undefined && auctionInfo.approvalRequired) { 6383 if (auctionInfo.paymentMethodRequired !== undefined && auctionInfo.paymentMethodRequired === true) { 6384 if (bidspiritApi.getAuctionApprovalState() === "APPROVED") { 6385 bidProcessAction(modalBidForm, params, data, dataAlert); 6386 } else if (bidspiritApi.getAuctionApprovalState() === "NOT_REQUESTED") { 6387 if (paymentMethods.length > 0) { 6388 modalRequestApprovalShow(); 6389 MicroModal.init(microModalInitConfig()); 6390 } else { 6391 addPaymentMethodCallback(); 6392 } 6393 } else if (bidspiritApi.getAuctionApprovalState() === "APPROVAL_REQUESTED") { 6394 noticeSwall("info", "", window.bs_lang.approval_info_approval_requested); 6395 } else { 6396 if (bidspiritApi.getAuctionApprovalState() === "PENDING") { 6397 noticeSwall("error", window.bs_lang.oops, window.bs_lang.pending_user_state); 6398 } else if (bidspiritApi.getAuctionApprovalState() === "INCOMPLETE_PROFILE") { 6399 noticeSwall("error", window.bs_lang.oops, window.bs_lang.not_approved_user); 6400 } 6401 } 6402 } else if (auctionInfo.paymentMethodRequired !== undefined && auctionInfo.paymentMethodRequired === false) { 6403 if (bidspiritApi.getAuctionApprovalState() === "APPROVED") { 6404 bidProcessAction(modalBidForm, params, data, dataAlert); 6405 } else if (bidspiritApi.getAuctionApprovalState() === "NOT_REQUESTED") { 6406 showTermsCondModal(); 6407 } else if (bidspiritApi.getAuctionApprovalState() === "APPROVAL_REQUESTED") { 6408 noticeSwall("info", "", window.bs_lang.approval_info_approval_requested); 6409 } else { 6410 if (bidspiritApi.getAuctionApprovalState() === "PENDING") { 6411 noticeSwall("error", window.bs_lang.oops, window.bs_lang.pending_user_state); 6412 } else if (bidspiritApi.getAuctionApprovalState() === "INCOMPLETE_PROFILE") { 6413 noticeSwall("error", window.bs_lang.oops, window.bs_lang.not_approved_user); 6414 } 6415 } 6416 } else { 6417 bidProcessAction(modalBidForm, params, data, dataAlert); 6418 } 6419 6420 MicroModal.init(microModalInitConfig()); 6421 } else { 6422 bidProcessAction(modalBidForm, params, data, dataAlert); 6423 } 6424 } else { 6425 MicroModal.close("modal-bid"); 6426 noticeSwall("error", window.bs_lang.tax_number_required, window.bs_lang.tax_number_required_label, {}, function () { 6427 var linkProfile = window.bs_data.link_profile; 6428 6429 if (linkProfile !== undefined && linkProfile !== "link") { 6430 window.location = linkProfile; 6431 } 6432 }); 6433 } 6434 } 6435 } 6436 6437 function getApprovalStateInfo(user) { 6438 var userState = $("#profile-account-section"); 6439 6440 if (!user.emailConfirmed) { 6441 return userState.attr("data-confirm-email"); 6442 } 6443 6444 switch (user.approvalState) { 6445 case "INCOMPLETE_PROFILE": 6446 return userState.attr("data-incomplete-profile"); 6447 6448 case "PENDING": 6449 return userState.attr("data-pending"); 6450 } 6451 6452 return ""; 6453 } 6454 6455 function submitUpdateDetails() { 6456 function filterData(data) { 6457 let updatedData = { 6458 data: {}, 6459 errors: {} 6460 }; 6461 6462 if (data.countryCode !== undefined && data.countryCode === "US") { 6463 data.stateCode = data.state; 6464 data.state = ""; 6465 data.province = ""; 6466 } else { 6467 data.stateCode = ""; 6468 } 6469 6470 for (const [key, value] of Object.entries(data)) { 6471 if (key === "") { 6472 continue; 6473 } 6474 6475 if (key === "firstName" || key === "lastName") { 6476 if (value.match(/\@/)) { 6477 updatedData["errors"][key] = window.bs_lang.profile_field_error.replace(/\%s/, key); 6478 } 6479 } 6480 6481 updatedData["data"][key] = value; 6482 } 6483 6484 return updatedData; 6485 } 6486 6487 var data = getDataForm("updateDetailsSection"), 6488 formParent = $("#updateDetailsSection"), 6489 shippingAction = $("#profileShippingCheckbox"), 6490 approvalState = bidspiritUser.approvalState, 6491 postConfirmationLink = formParent.attr("action"); 6492 data.sessionId = bidspiritSessionId; 6493 data.postConfirmationLink = postConfirmationLink; 6494 let tmpData = filterData(data); 6495 data = tmpData["data"]; 6496 6497 if (Object.keys(tmpData["errors"]).length > 0) { 6498 let keys = Object.keys(tmpData["errors"]), 6499 message = window.bs_lang.profile_error; 6500 6501 if (keys[0] !== undefined) { 6502 message = tmpData["errors"][keys[0]]; 6503 } 6504 6505 noticeSwall("error", "Error", message); 6506 } else { 6507 if (approvalState === "PENDING") { 6508 var info = bidspiritApi.getAuctionHouseData(), 6509 title = window.bs_lang.you_are_still_pending_approval.replace(/\%1s/, info.name), 6510 message = window.bs_lang.you_are_still_pending_approval_body.replace(/\%1s/, info.phone).replace(/\%2s/, info.email); 6511 noticeSwall("info", title, message); 6512 } else { 6513 bidspiritPostQuery("users/updateDetails", data, function (response) { 6514 if (response.response.success === false) { 6515 noticeSwall("error", "Error", data.response.errorMessage); 6516 } else { 6517 let userData = response.response, 6518 shippingData = {}; 6519 Promise.all([ 6520 new Promise(function (resolve) { 6521 if (shippingAction[0] !== undefined && !shippingAction.prop('checked')) { 6522 let shippingFields = Object.keys(data) 6523 .filter((key) => key.includes("shipping")) 6524 .reduce((object, key) => { 6525 return Object.assign(object, { 6526 [key.replace(/shipping\./, "")]: data[key] 6527 }); 6528 }, {}); 6529 6530 bidspiritPostQuery("users/updateShippingAddress", 6531 Object.assign({sessionId: bidspiritSessionId}, shippingFields), 6532 function (response) { 6533 if (response.response.success === false) { 6534 shippingData = response.response; 6535 noticeSwall("error", "Error", response.response.errorMessage); 6536 } else { 6537 userData.shipping = response.response; 6538 resolve(); 6539 } 6540 }); 6541 } else { 6542 let user = bidspiritApi.getBidspiritUser(); 6543 if (user.shipping !== undefined) { 6544 bidspiritPostQuery("users/updateShippingAddress", 6545 Object.assign({sessionId: bidspiritSessionId}, { 6546 countryCode: "", 6547 stateCode: "", 6548 state: "", 6549 city: "", 6550 address: "", 6551 zipCode: "" 6552 }), 6553 function () { 6554 shippingData = response.response; 6555 userData.shipping = undefined; 6556 resolve(); 6557 }); 6558 } else { 6559 resolve(); 6560 } 6561 } 6562 }), 6563 ]).then(function (response) { 6564 bidspiritApi.setBidspiritUser(userData); 6565 updateDisplay(); 6566 noticeSwall("info", window.bs_lang.profile_changes_saved, window.bs_lang.profile_changes_saved_body, {}, function () { 6567 if (approvalState !== bidspiritUser.approvalState) { 6568 window.location = postConfirmationLink; 6569 } 6570 }); 6571 }); 6572 } 6573 }); 6574 6575 } 6576 } 6577 } 6578 6579 function handleSubmitResponse(data) { 6580 currentItemInfo.selfAbsenteeBid = data.selfAbsenteeBid; 6581 currentItemInfo.leadingBid = data.leadingBid; 6582 displayBidFormData(currentItemInfo); 6583 6584 let type = "info"; 6585 if (data.leadingBidCode === "ANOTHER_BID_HIGHER" || data.leadingBidCode === "ANOTHER_BID_EARLIER") { 6586 type = "error"; 6587 } 6588 noticeSwall(type, getLeadingBidMessage(data.leadingBidCode)); 6589 } 6590 6591 function disableLoader() { 6592 $("#bsLoader").addClass(window.bs_data.hidden_class); 6593 } 6594 6595 function toggleFavorite(lot, elem, auctionNumber, delLot) { 6596 var lotIndex = lot.attr("data-lot-index"), 6597 wishListClass = "bp__wishlist-active", 6598 isFavorite = !$(elem).hasClass(wishListClass); 6599 6600 if (!bidspiritUser) { 6601 try { 6602 MicroModal.show("modal-login", microModalInitConfig()); 6603 } catch (e) { 6604 console.error(e); 6605 } 6606 } else { 6607 bidspiritQuery("items/setFavorite", { 6608 sessionId: bidspiritSessionId, 6609 auctionId: auctionNumber, 6610 lotIndex: lotIndex, 6611 isFavorite: isFavorite 6612 }, function (data) { 6613 if (!checkError(data)) { 6614 if (data.response.success) { 6615 if (isFavorite) { 6616 $(elem).addClass(wishListClass); 6617 } else { 6618 $(elem).removeClass(wishListClass); 6619 6620 if (delLot) { 6621 lot.remove(); 6622 } 6623 } 6624 } 6625 } 6626 }); 6627 } 6628 } 6629 6630 function getLeadingBidMessage(leadingBidCode) { 6631 var response = ""; 6632 6633 switch (leadingBidCode) { 6634 case "YOU_ARE_THE_HIGH_BIDDER":
6635 response = window.bs_lang.success_high_bidder; 6636 break; 6637 6638 case "ANOTHER_BID_HIGHER": 6639 response = window.bs_lang.higher_your_bid_has_been_outbid; 6640 break; 6641 6642 case "ANOTHER_BID_EARLIER": 6643 response = window.bs_lang.earlier_your_bid_has_been_outbid; 6644 break; 6645 6646 case "SYNC_ERROR": 6647 response = window.bs_lang.sync_error; 6648 break; 6649 } 6650 6651 return response; 6652 } 6653 6654 function tabs() { 6655 $(".tools-wrapper").on("click", ".bp-tabs-link a", function (event) { 6656 event.preventDefault(); 6657 var $this = $(this), 6658 parent = $this.parents(".bp-tabs-block"), 6659 idTab = parent.attr("data-tab-id"), 6660 href = $this.attr("href"); 6661 window.location.href = window.location.origin + window.location.pathname + href; 6662 6663 if ($(href).length) { 6664 parent.find(".nav-link").removeClass("active"); 6665 $("#" + idTab + " > *").removeClass("active"); 6666 $this.addClass("active"); 6667 $(href).addClass("active"); 6668 } 6669 }); 6670 } 6671 6672 function activeTabs() { 6673 var activeTab = $('.bp-tabs-block a[href="' + window.location.hash + '"]'); 6674 6675 if (activeTab.length) { 6676 activeTab.trigger("click"); 6677 } 6678 } 6679 6680 /** 6681 * Global hashchange listener — allows menu links, external links, and 6682 * in-page links to switch profile tabs even when already on the page. 6683 * e.g. a header menu link to /profile/#bp-bills will work from any tab. 6684 */ 6685 $(window).on("hashchange", function() { 6686 var hash = window.location.hash; 6687 if (!hash) return; 6688 6689 var tab = $('.bp-tabs-block a[href="' + hash + '"]'); 6690 if (tab.length) { 6691 tab.trigger("click"); 6692 6693 // Also open the spoiler/accordion on mobile if it's collapsed 6694 var spoilerTrigger = $(hash + " .bp-spoiler-trigger"); 6695 if (spoilerTrigger.length && !spoilerTrigger.hasClass("active")) { 6696 spoilerTrigger.trigger("click"); 6697 } 6698 6699 // Smooth scroll to the tab section 6700 var section = $(hash); 6701 if (section.length) { 6702 $("html, body").animate({ scrollTop: section.offset().top - 100 }, 300); 6703 } 6704 } 6705 }); 6706 6707 function spoiler() { 6708 $(document).on("click", ".bp-spoiler-trigger", function (e) { 6709 e.preventDefault(); 6710 $(this).toggleClass("active"); 6711 $(this).parent().toggleClass("active-spoiler").find(".bp-spoiler-block").first().toggleClass("active"); 6712 }); 6713 } 6714 6715 function loginLink() { 6716 function loadLoginLink(login) { 6717 loadTemplate(".wrpLoginLink", "account-link-profile", { 6718 login: login 6719 }, false, function () { 6720 MicroModal.init(microModalInitConfig()); 6721 }); 6722 6723 if ($(".wrpRegisterLink").length) { 6724 loadTemplate(".wrpRegisterLink", "account-link-register", { 6725 login: login 6726 }, false, function () { 6727 MicroModal.init(microModalInitConfig()); 6728 }); 6729 } 6730 } 6731 6732 var loginLink = $(".bp-login-link"), 6733 menu = loginLink.parents(".menu"); 6734 6735 if (loginLink.length && bidspiritUser) { 6736 loadLoginLink(true); 6737 6738 if (menu !== undefined) { 6739 menu.addClass("user-is-authorize"); 6740 menu.removeClass("user-is-not-authorize"); 6741 } 6742 } else if (!bidspiritUser) { 6743 loadLoginLink(false); 6744 6745 if (menu !== undefined) { 6746 menu.removeClass("user-is-authorize"); 6747 menu.addClass("user-is-not-authorize"); 6748 } 6749 } 6750 } 6751 6752 function resendEmailAction() { 6753 var resendEmailSection = $("#resendEmailSection"); 6754 6755 if (resendEmailSection.length) { 6756 resendEmailSection.on("click", function (event) { 6757 event.preventDefault(); 6758 bidspiritQuery("users/resendConfirmationMail", { 6759 sessionId: bidspiritSessionId, 6760 postConfirmationLink: window.location.href 6761 }, function (data) { 6762 if (!bPcheckError(data)) { 6763 if (data.response.success) { 6764 noticeSwall("success", "Email confirmation sent"); 6765 } else { 6766 noticeSwall("error", "Unknown error"); 6767 } 6768 } 6769 }); 6770 }); 6771 } 6772 } 6773 6774 // Change email before confirmation (users/updateEmail) — lets a user fix an email typo 6775 // during registration. Sits next to the "Resend email" link (#changeEmailSection). 6776 function changeEmailAction() { 6777 var changeEmailSection = $("#changeEmailSection"); 6778 6779 if (!changeEmailSection.length) { 6780 return; 6781 } 6782
6783 changeEmailSection.off("click.bpChangeEmail").on("click.bpChangeEmail", function (event) { 6784 event.preventDefault(); 6785 var user = bidspiritApi.getBidspiritUser() || {}; 6786 6787 Swal.fire({ 6788 title: window.bs_lang.change_email_title || "Change your email", 6789 input: "email", 6790 inputValue: user.email || "", 6791 inputLabel: window.bs_lang.change_email_label || "Enter your correct email address", 6792 showCancelButton: true, 6793 confirmButtonText: window.bs_lang.change_email_confirm || "Send confirmation", 6794 cancelButtonText: window.bs_lang.cancel || "Cancel", 6795 inputValidator: function (value) { 6796 if (!value) { 6797 return window.bs_lang.change_email_required || "Please enter an email address"; 6798 } 6799 } 6800 }).then(function (result) { 6801 if (result.isConfirmed && result.value) { 6802 submitChangeEmail(result.value); 6803 } 6804 }); 6805 }); 6806 } 6807 6808 function submitChangeEmail(newEmail) { 6809 bidspiritPostQuery("users/updateEmail", { 6810 sessionId: bidspiritSessionId, 6811 email: newEmail, 6812 postConfirmationLink: window.location.href 6813 }, function (data) { 6814 var res = (data && data.response) || {}; 6815 6816 if (res.success) { 6817 var user = bidspiritApi.getBidspiritUser(); 6818 if (user) { 6819 user.email = newEmail; 6820 bidspiritApi.setBidspiritUser(user); 6821 } 6822 noticeSwall("success", 6823 window.bs_lang.change_email_sent_title || "Confirmation email sent", 6824 (window.bs_lang.change_email_sent_body || "A new confirmation email was sent to") + " " + newEmail); 6825 updateDisplay(); 6826 } else if (res.errorCode === "USER_EXIST") { 6827 noticeSwall("error", 6828 window.bs_lang.oops || "Oops", 6829 window.bs_lang.change_email_exists || "That email address is already in use. Please use a different one."); 6830 } else { 6831 noticeSwall("error", 6832 window.bs_lang.oops || "Oops", 6833 res.errorMessage || window.bs_lang.change_email_failed || "Could not update your email, please try again."); 6834 } 6835 }, function () { 6836 noticeSwall("error", 6837 window.bs_lang.oops || "Oops", 6838 window.bs_lang.change_email_failed || "Could not update your email, please try again."); 6839 }); 6840 } 6841 6842 function saveFirebaseUser() { 6843 try { 6844 var firebaseTokenFCM = localStorage.getItem("token_firebase_push_id"); 6845 } catch (e) { 6846 firebaseTokenFCM = null; 6847 } 6848 6849 if (firebaseTokenFCM !== null) { 6850 if (bidspiritUser.leadingBidAlertsEnabled !== undefined && bidspiritUser.leadingBidAlertsEnabled !== true) { 6851 bidspiritQuery("users/setLeadingBidAlertsEnabled", { 6852 sessionId: bidspiritSessionId, 6853 isEnabled: true 6854 }, function (data) { 6855 if (!checkError(data)) { 6856 } 6857 }); 6858 } 6859 6860 restQuery("user/login", "POST", { 6861 bidspirit_user_email: bidspiritUser.email, 6862 firebase_id: firebaseTokenFCM 6863 }, function (response) { 6864 console.info(response); 6865 }); 6866 } 6867 } 6868 6869 function widgetSliders() { 6870 new SwiperBP(".widget-lots", { 6871 speed: 400, 6872 slidesPerView: 1, 6873 spaceBetween: 10, 6874 centeredSlides: true, 6875 freeMode: false, 6876 autoplay: { 6877 delay: 4000 6878 }, 6879 breakpoints: { 6880 977: { 6881 slidesPerView: 3, 6882 spaceBetween: 15 6883 }, 6884 1200: { 6885 slidesPerView: 5, 6886 spaceBetween: 30, 6887 centeredSlides: false 6888 } 6889 } 6890 }); 6891 } 6892 6893 function updateLotsWidget() { 6894 if ($(".bt-wi-lots_wrp").length) { 6895 var widgets = $(".bt-wi-lots"); 6896 widgets.each(function (index, widget) { 6897 var lots = $(widget).find(".bp-lot"), 6898 hash = $(widget).attr("data-hash"), 6899 auctions = {}; 6900 6901 if (hash === undefined) { 6902 hash = ""; 6903 } 6904 6905 lots.each(function (index, elem) { 6906 var $this = $(elem), 6907 auctionId = $this.attr("data-auction-id"), 6908 lotId = $this.attr("data-lot-index"); 6909 6910 if (auctions[auctionId] === undefined && auctionId !== "") { 6911 auctions[auctionId] = []; 6912 } 6913 6914 if (lotId !== "") { 6915 auctions[auctionId].push(lotId); 6916 } 6917 }); 6918 $.each(auctions, function (index, items) { 6919 if (items.length > 0 && index !== "undefined") { 6920 bidspiritQuery("items/getItemsInfo", { 6921 sessionId: bidspiritSessionId, 6922 auctionId: index, 6923 lotIndexes: items.join(",") 6924 }, function (data) { 6925 if (!checkError(data)) { 6926 var bidsInfoData = data.response; 6927 6928 if (bidsInfoData.itemsInfo !== undefined && items.length > 0) { 6929 for (var i = 0; i < items.length; i++) { 6930 var itemIndex = items[i], 6931 itemRow = $("#single-lot-" + index + "-" + itemIndex + hash); 6932 6933 if (bidsInfoData.itemsInfo[itemIndex] !== undefined) { 6934 var itemInfo = bidsInfoData.itemsInfo[itemIndex]; 6935 } else { 6936 console.log(itemIndex); 6937 continue; 6938 } 6939 6940 var content = ""; 6941 6942 try { 6943 var dataContent = itemRow.attr("data-content"); 6944 6945 if (dataContent !== undefined) { 6946 content = JSON.parse(urldecode(itemRow.attr("data-content"))); 6947 } 6948 } catch (e) { 6949 console.error("error parse content of lot"); 6950 } 6951 6952 loadTemplate("#single-lot-" + index + "-" + itemIndex + hash + "-content", "lot-content-template", { 6953 auctionInfo: bidsInfoData, 6954 auctionData: bidspiritApi.getAuctionInfo() || {}, 6955 itemInfo: itemInfo, 6956 title: itemRow.find(".bp-lot__title").html(), 6957 link: itemRow.find(".img-block").attr("href"), 6958 content: content, 6959 currency: currencySymbol, 6960 hiddenPrice: false, 6961 postAuctionSaleOpenedUntil: 0, 6962 postAuctionSaleOpened: false, 6963 showEstimatedPriceInItemsList: (itemInfo.estimatedPrice !== undefined), 6964 displayStartPriceInCatalog: (itemInfo.startPrice !== undefined), 6965 bidspiritUser: bidspiritUser, 6966 bidsInCatalog: false, 6967 isShop: Boolean(parseInt($("#catalog-section").attr("data-is-shop"))), 6968 houseInfo: bidspiritApi.getAuctionHouseData() || {}, 6969 settings: bidspiritApi.getAuctionSettingsData() || {},//#B141 task 6970 estimatedPrice: itemRow.attr("data-e
6970stimated-price"), 6971 // nextMinBid: nextMinBid, 6972 }, true, function () { 6973 if (itemInfo !== undefined) { 6974 hangUpEvent("bp:after-getItemsInfo-content-item", itemInfo, itemRow); 6975 } 6976 }); 6977 } 6978 6979 hangUpEvent("bp:after-getItemsInfo-item", bidsInfoData); 6980 } 6981 } 6982 }); 6983 } 6984 }); 6985 }); 6986 } 6987 } 6988 6989 function onPageAction() { 6990 function auctionAlertAction() { 6991 $("body").on("click", ".auction-follow-action", function (event) { 6992 event.preventDefault(); 6993 var $this = $(event.target), 6994 auctionId = $this.attr("data-auction-id"); 6995 bidspiritQuery("auctions/setAuctionAlert", { 6996 sessionId: bidspiritSessionId, 6997 auctionId: auctionId, 6998 isOn: true 6999 }, function (data) { 7000 if (data.response.success) { 7001 noticeSwall("success", "Success", ""); 7002 } else { 7003 noticeSwall("error", window.bs_lang.oops); 7004 } 7005 }); 7006 }); 7007 } 7008 7009 auctionAlertAction(); 7010 } 7011 7012 function singleLotAction() { 7013 if (!!document.querySelector('#catalog-section')) { 7014 let catalogHref = window.location.href.replace(/\#.+/, ''); 7015 localStorage.setItem('catalog', catalogHref); 7016 console.log("update catalog:", catalogHref); 7017 } 7018 7019 if (!!document.querySelector('.goback')) { 7020 $(".goback").each(function (index, elem) { 7021 $(elem).on("click", function (event) { 7022 event.preventDefault(); 7023 let catalog = localStorage.getItem('catalog'), 7024 lotId = $(this).attr('data-id'), 7025 elemHref = $(this).attr('href'); 7026 7027 if (catalog) { 7028 catalog = catalog.replace(/#$/, ''); 7029 } 7030 7031 // If localStorage catalog doesn't match this lot's auction, use the href instead 7032 if (!catalog || (elemHref && catalog.replace(/\/$/, '') !== elemHref.replace(/\/$/, '').replace(/#.*$/, ''))) { 7033 window.location = elemHref + (lotId || ''); 7034 } else { 7035 window.location = catalog + lotId; 7036 } 7037 }); 7038 }); 7039 } 7040 } 7041 7042 document.addEventListener("DOMContentLoaded", function (event) { 7043 try { 7044 if (!bpIsset(window.localStorage)) { 7045 noticeSwall("error", window.bs_lang.storage_not_working); 7046 } 7047 } catch (e) { 7048 noticeSwall("error", window.bs_lang.storage_not_working); 7049 } 7050 7051 initApp(); 7052 init(); 7053 var loginForm = $(".bp-login-api"), 7054 bidForm = $("#bidFormSection"), 7055 loginModal = $("#modal-login"), 7056 registerModal = $("#modal-register"), 7057 registerForm = $(".bp-register-api"), 7058 logoutAction = $("#doLogout"), 7059 forgottenAction = $(".doForgotten"), 7060 wishListButtons = $(".bp-lot .bp__wishlist"), 7061 errorBlockSelector = ".errors-group"; 7062 7063 if (loginForm.length) { 7064 loginForm.on("submit", function (event) { 7065 event.preventDefault(); 7066 submitLogin(event); 7067 }); 7068 } 7069 7070 if (forgottenAction.length) { 7071 forgottenAction.each(function (index, elem) { 7072 var $this = $(elem), 7073 formParent = $(".bp-login-api"); 7074 $this.on("click", function (event) { 7075 event.preventDefault(); 7076 bidspiritPostQuery("users/sendPasswordReset", { 7077 sessionId: bidspiritSessionId, 7078 email: formParent.find("[name='email']").val(), 7079 language: LANG, 7080 postResetPage: window.location.href 7081 }, function (data) { 7082 if (!checkError(data)) { 7083 if (data.response.success) { 7084 noticeSwall("info", window.bs_lang.profile_password_reset); 7085 } else { 7086 noticeSwall("error", window.bs_lang.profile_email_not_found); 7087 } 7088 } 7089 }); 7090 }); 7091 }); 7092 } 7093 7094 if (registerForm.length) { 7095 registerForm.each(function (index, elem) { 7096 $(elem).on("submit", function (event) { 7097 var $this = $(event.target), 7098 acceptPrivacy = $this.attr("data-accept-privacy"); 7099 event.preventDefault(); 7100 var errorBlock = $this.find(errorBlockSelector),
7101 checkboxPersonalData = $(event.target).find('[name="personal-data"]'); 7102 7103 if (errorBlock === undefined) { 7104 errorBlock = registerModal.find(errorBlockSelector); 7105 } 7106 7107 errorBlock.empty(); 7108 7109 if (acceptPrivacy === "on") { 7110 if (checkboxPersonalData.length && checkboxPersonalData.is(":checked")) { 7111 submitRegister(event); 7112 } else { 7113 var error = window.bs_lang["notice_personal_data"]; 7114 errorBlock.empty().append("<p>" + error + "</p>").removeClass(window.bs_data.hidden_class); 7115 } 7116 } else { 7117 submitRegister(event); 7118 } 7119 }); 7120 }); 7121 } 7122 7123 if (bidForm.length) { 7124 bidForm.unbind("submit"); 7125 bidForm.on("submit", function (event) { 7126 event.preventDefault(); 7127 7128 if (!bidspiritUser) { 7129 try { 7130 MicroModal.show("modal-login", microModalInitConfig()); 7131 } catch (e) { 7132 console.error(e); 7133 } 7134 7135 return; 7136 } 7137 7138 var auctionInfo = bidspiritApi.getAuctionInfo(); 7139 7140 if (auctionInfo.state !== "ENDED") { 7141 if (auctionInfo.approvalRequired !== undefined && auctionInfo.approvalRequired) { 7142 if (auctionInfo.paymentMethodRequired !== undefined && auctionInfo.paymentMethodRequired === true) { 7143 if (bidspiritApi.getAuctionApprovalState() === "APPROVED") { 7144 submitBid(); 7145 } else if (bidspiritApi.getAuctionApprovalState() === "NOT_REQUESTED") { 7146 if (paymentMethods.length > 0) { 7147 modalRequestApprovalShow(); 7148 MicroModal.init(microModalInitConfig()); 7149 } else { 7150 addPaymentMethodCallback(); 7151 } 7152 } else if (bidspiritApi.getAuctionApprovalState() === "APPROVAL_REQUESTED") { 7153 noticeSwall("info", "", window.bs_lang.approval_info_approval_requested); 7154 } else { 7155 if (bidspiritApi.getAuctionApprovalState() === "PENDING") { 7156 noticeSwall("error", window.bs_lang.oops, window.bs_lang.pending_user_state); 7157 } else if (bidspiritApi.getAuctionApprovalState() === "INCOMPLETE_PROFILE") { 7158 noticeSwall("error", window.bs_lang.oops, window.bs_lang.not_approved_user); 7159 } 7160 } 7161 } else if (auctionInfo.paymentMethodRequired !== undefined && auctionInfo.paymentMethodRequired === false) { 7162 if (bidspiritApi.getAuctionApprovalState() === "APPROVED") { 7163 submitBid(); 7164 } else if (bidspiritApi.getAuctionApprovalState() === "NOT_REQUESTED") { 7165 showTermsCondModal(); 7166 } else if (bidspiritApi.getAuctionApprovalState() === "APPROVAL_REQUESTED") { 7167 noticeSwall("info", "", window.bs_lang.approval_info_approval_requested); 7168 } else { 7169 if (bidspiritApi.getAuctionApprovalState() === "PENDING") { 7170 noticeSwall("error", window.bs_lang.oops, window.bs_lang.pending_user_state); 7171 } else if (bidspiritApi.getAuctionApprovalState() === "INCOMPLETE_PROFILE") { 7172 noticeSwall("error", window.bs_lang.oops, window.bs_lang.not_approved_user); 7173 } 7174 } 7175 } else { 7176 submitBid(); 7177 } 7178 7179 MicroModal.init(microModalInitConfig()); 7180 } else { 7181 submitBid(); 7182 } 7183 } 7184 }); 7185 } 7186 7187 if (logoutAction.length) { 7188 doLogout(logoutAction); 7189 } 7190 7191 if (loginModal.length) { 7192 loginModal.on("click", "#doRegister", function (event) { 7193 event.preventDefault(); 7194 MicroModal.close("modal-login"); 7195 MicroModal.init(microModalInitConfig()); 7196 MicroModal.show("modal-register"); 7197 }); 7198 } 7199 7200 if (registerModal.length) { 7201 registerModal.on("click", "#doLogin", function (event) { 7202 event.preventDefault(); 7203 MicroModal.close("modal-register"); 7204 MicroModal.init(microModalInitConfig()); 7205 MicroModal.show("modal-login", microModalInitConfig()); 7206 }); 7207 } 7208 7209 $("#single-lot, #catalog-section").on("click", wishListButtons, function (event) { 7210 var elem = event.target, 7211 lot = $(elem).parents(".bp-lot"); 7212 7213 if ($(elem).hasClass("bp__wishlist")) { 7214 event.stopPropagation(); 7215 event.preventDefault(); 7216 toggleFavorite(lot, elem, currentAuctionNumber); 7217 } 7218 }); 7219 $("body").on("click", ".modal-open", function (event) { 7220 var $this = $(this), 7221 target = $this.attr("data-micromodal-trigger"), 7222 parentModal = $this.parents(".bp-modal"); 7223 7224 if (parentModal.length) { 7225 MicroModal.close(parentModal.attr("id")); 7226 } 7227 7228 MicroModal.show(target, microModalInitConfig()); 7229 }); 7230 $("body").on("click", ".click-action", function (event) { 7231 var $this = $(this), 7232 target = $this.attr("data-trigger"), 7233 parentModal = $this.parents(".bp-modal"); 7234 7235 if (parentModal.length) { 7236 MicroModal.close(parentModal.attr("id")); 7237 } 7238 7239 $("#" + target).trigger("click"); 7240 }); 7241 7242 function loadMore() { 7243 var loadMoreButton = $(".bt-wi-lots_more .btn"), 7244 bgColor = $(".bt-wi-lots_wrp").attr("data-bg-color"); 7245 7246 if (loadMoreButton.length) {
7247 loadMoreButton.on("click", function (event) { 7248 event.preventDefault(); 7249 var $this = $(this), 7250 parent = $this.parents(".bt-wi-lots_wrp"), 7251 count = parent.find(".bp-lots .bp-lot").length; 7252 $.ajax({ 7253 type: "post", 7254 dataType: "json", 7255 url: window.wp_data.ajax_url, 7256 data: { 7257 action: "do_lot_list", 7258 security: window.wp_nonce, 7259 count: count 7260 } 7261 }).done(function (response) { 7262 loadTemplate(parent.find(".bp-lots"), "shortcode-lot", { 7263 lots: response.data.lots, 7264 currency: currencySymbol, 7265 bgColor: bgColor 7266 }, false, function () { 7267 }, true); 7268 count = parent.find(".bp-lots .bp-lot").length; 7269 7270 if (count >= response.data.total) { 7271 parent.find(".bt-wi-lots_more").addClass(window.bs_data.hidden_class); 7272 } 7273 }).fail(function () { 7274 console.error("Fatal error"); 7275 }); 7276 }); 7277 } 7278 } 7279 7280 function printNoticeBanner() { 7281 var htmlTemplate = document.getElementById("oldest-browser-template").innerHTML, 7282 data = { 7283 message: window.bs_lang.oldest_browser_text, 7284 linkMessage: window.bs_lang.oldest_browser_link_text, 7285 link: window.bs_data.link_on_not_supported_browsers 7286 }; 7287 htmlTemplate = _.template(htmlTemplate); 7288 $("body").append(htmlTemplate(data)); 7289 } 7290 7291 function ie11supportDisabled() { 7292 if (auctionforgeDetectIE()) { 7293 printNoticeBanner(); 7294 } 7295 } 7296 7297 function incrementTable() { 7298 $("#incrementTable, [href='#incrementTable']").on("click", function (event) { 7299 MicroModal.show("modal-steps", microModalInitConfig()); 7300 loadTemplate("#modal-steps-content", "increment-tables-template", { 7301 data: bidspiritApi.getAuctionInfo().increments, 7302 currency: currencySymbol 7303 }, true); 7304 }); 7305 } 7306 7307 tabs(); 7308 spoiler(); 7309 select2ToolsInit(); 7310 loadMore(); 7311 singleLotAction(); 7312 onPageAction(); 7313 incrementTable(); 7314 ie11supportDisabled(); 7315 }); 7316})(jQuery); 7317 7318function noticeSwall(type, title, message, params, callback) { 7319 if (params === undefined) { 7320 params = {}; 7321 } 7322 7323 var conf = { 7324 icon: type, 7325 title: title, 7326 text: message 7327 }; 7328 conf = jQuery.extend({}, conf, params); 7329 Swal.fire(conf).then(function (result) { 7330 if (result.isConfirmed && callback !== undefined) { 7331 callback(); 7332 } 7333 }); 7334} 7335 7336function getLeftDate(eventDate) { 7337 var timer = jQuery("#auctionStartTimer"), 7338 target = timer.find(".bp-start-countdown"), 7339 archiveDate = timeShift(new Date(eventDate)); 7340 7341 function pluralize(value, unit) { 7342 return value + " " + unit + (value === 1 ? "" : "s"); 7343 } 7344 7345 function renderLeftDate() { 7346 var result = archiveDate.getTime() - new Date().getTime() + 1000; 7347 7348 if (result < 0) { 7349 timer.hide(); 7350 if (getLeftDate._interval) { 7351 clearInterval(getLeftDate._interval); 7352 getLeftDate._interval = null; 7353 } 7354 return; 7355 } 7356 7357 var days = Math.floor(result / 1000 / 60 / 60 / 24), 7358 hours = Math.floor(result / 1000 / 60 / 60 % 24), 7359 minutes = Math.floor(result / 1000 / 60 % 60), 7360 seconds = Math.floor(result / 1000 % 60), 7361 parts = []; 7362 7363 if (days === 0 && hours === 0 && minutes === 0) { 7364 // final minute: count down the seconds so it never sits on "0" 7365 parts.push(pluralize(seconds, "second")); 7366 } else { 7367 if (days > 0) { 7368 parts.push(pluralize(days, "day")); 7369 } 7370 if (days > 0 || hours > 0) { 7371 parts.push(pluralize(hours, "hour")); 7372 } 7373 parts.push(pluralize(minutes, "minute")); 7374 } 7375 7376 var text = parts.length > 1 7377 ? parts.slice(0, -1).join(", ") + " and " + parts[parts.length - 1] 7378 : parts[0]; 7379 7380 if (target.length) { 7381 target.text(text); 7382 } else { 7383 // wrapper missing (e.g. stale cached markup): keep original behaviour 7384 timer.find(".outputDays").text(days); 7385 timer.find(".outputHours").text(hours); 7386 } 7387 } 7388 7389 renderLeftDate(); 7390 if (getLeftDate._interval) { 7391 clearInterval(getLeftDate._interval); 7392 } 7393 getLeftDate._interval = setInterval(renderLeftDate, 1000); 7394} 7395 7396function smartCut(text, limit) { 7397 if (text === undefined) { 7398 return ""; 7399 } 7400 7401 text = text.replace(/<\/?[^>]+(>|$)/g, ""); 7402 var array = text.split(" ").slice(0, limit); 7403 return array.join(" "); 7404} 7405 7406function microModalInitConfig() { 7407 return { 7408 onShow: modal => { 7409 console.info(modal); 7410 }, 7411 onClose: modal => { 7412 console.info(modal); 7413 }, 7414 debugMode: false 7415 }; 7416} 7417 7418function formattedPrice(price, currencySymbol, secondPrice, showDecimals) { 7419 if (currencySymbol === undefined) { 7420 currencySymbol = window.bidSpiritCurrency; 7421 } 7422 7423 if (secondPrice !== undefined && secondPrice === true) { 7424 let auctionInfo = bidspiritApi.getAuctionInfo(); 7425 if (auctionInfo.secondCurrency !== undefined && auctionInfo.secondCurrencyRate !== undefined) { 7426 secondPrice = " (" + formattedPrice((Number(price) * auctionInfo.secondCurrencyRate).toFixed(2), auctionInfo.secondCurrency) + ")"; 7427 } else { 7428 secondPrice = ""; 7429 } 7430 } else { 7431 secondPrice = ""; 7432 } 7433 try { 7434 if (price === undefined || price === null || (typeof price === 'number' && isNaN(price)) || price === 'NaN') { 7435 price = 0; 7436 } 7437 var _fd = (showDecimals === true) ? 2 : 0;
7438 price = Number(String(price).replace(/[^0-9.-]/g, '')).toLocaleString('en-US', {minimumFractionDigits: _fd, maximumFractionDigits: _fd}); 7439 7440 switch (window.bidSpiritLang) { 7441 case "ru": 7442 return price.replace(/(\,)/, " ") + " " + currencySymbol + secondPrice; 7443 7444 default: 7445 return currencySymbol + price + secondPrice; 7446 } 7447 } catch (e) { 7448 return currencySymbol + price + secondPrice; 7449 } 7450} 7451 7452function auctionforgeDetectIE() { 7453 var ua = window.navigator.userAgent; 7454 var msie = ua.indexOf("MSIE "); 7455 7456 if (msie > 0) { 7457 // IE 10 or older => return version number 7458 return true; 7459 } 7460 7461 var trident = ua.indexOf("Trident/"); 7462 7463 if (trident > 0) { 7464 // IE 11 => return version number 7465 return true; 7466 } 7467 7468 var edge = ua.indexOf("Edge/"); 7469 7470 if (edge > 0) { 7471 // Edge (IE 12+) => return version number 7472 return false; 7473 } 7474 7475 return false; 7476} 7477 7478function bp_t(phrase) { 7479 var key = phrase.toLowerCase().replace(/(\s)+/gm, "_"); 7480 if (window.bs_lang[key] !== undefined) { 7481 return window.bs_lang[key]; 7482 } else { 7483 return phrase; 7484 } 7485} 7486 7487function bpGetQueryParams(qs) { 7488 var searchParams = new URLSearchParams(window.location.search); 7489 return searchParams.get(qs); 7490} 7491 7492function bpIsset(variable) { 7493 return typeof variable != "undefined" && variable !== null; 7494} 7495 7496function bpYoutubeIDParser(url) { 7497 var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(?:shorts\/)|(watch\?))\??v?=?([^#&?]*).*/; 7498 var match = url.match(regExp); 7499 return match && match[7].length == 11 ? match[7] : false; 7500} 7501 7502function getTimeZoneFromUser() { 7503 return Intl.DateTimeFormat().resolvedOptions().timeZone; 7504} 7505 7506function convertTZ(date, tzString) { 7507 return new Date((typeof date === "string" ? new Date(date) : date).toLocaleString("en-US", { 7508 timeZone: tzString 7509 })); 7510} 7511 7512function getLocaleFromUser() { 7513 return Intl.DateTimeFormat().resolvedOptions().locale; 7514} 7515 7516function timeShift(deadline, isDTS) { 7517 function createDateAsUTC(date) { 7518 return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds())); 7519 } 7520 7521 Date.prototype.addHours = function (hours) { 7522 var date = new Date(this.valueOf()); 7523 date.setHours(date.getHours() + hours); 7524 return date; 7525 }; 7526 7527 var baseTimeZone = parseInt(window.timeZone), 7528 baseTimeZoneName = window.timeZoneName; 7529 7530 if (bpIsset(baseTimeZoneName) && bpIsset(window.timeZoneName) !== "") { 7531 deadline = createDateAsUTC(new Date(new Date(deadline).toLocaleString("en-US", { 7532 timeZone: "UTC" 7533 }))); 7534 return deadline; 7535 } else { 7536 var timeZone = deadline.getTimezoneOffset() / 60 * -1 - baseTimeZone; 7537 return new Date(deadline.getTime()).addHours(timeZone); 7538 } 7539} 7540 7541function isDisabledReadNotice() { 7542 return false; 7543} 7544 7545(function ($) { 7546 function metaSlider() { 7547 if ($(".bt-wi-slider .swiper-container").length) { 7548 new SwiperBP(".bt-wi-slider .swiper-container", { 7549 slidesPerView: 1, 7550 breakpoints: { 7551 320: { 7552 slidesPerView: 2 7553 }, 7554 640: { 7555 slidesPerView: 3, 7556 spaceBetween: 10 7557 }, 7558 990: { 7559 slidesPerView: 4, 7560 spaceBetween: 15 7561 }, 7562 1200: { 7563 slidesPerView: 5, 7564 spaceBetween: 20 7565 } 7566 }, 7567 autoplay: { 7568 delay: 4000 7569 } 7570 }); 7571 } 7572 } 7573 7574 function inquiryLot() { 7575 function decodeHtmlEntities(html) { 7576 const entities = { 7577 '<': '<', 7578 '>': '>', 7579 '&': '&', 7580 '"': '"', 7581 ''': "'", 7582 }; 7583 return html.replace(/<|>|&|"|'/g, match => entities[match]); 7584 } 7585 7586 function fillFiled(inquiryField) { 7587 inquiryField.each(function (index, elem) { 7588 var qParam = ""; 7589 7590 try { 7591 qParam = decodeHtmlEntities(bpGetQueryParams("bp-inquiry")); 7592 } catch (e) { 7593 console.info(e); 7594 qParam = bpGetQueryParams("bp-inquiry"); 7595 } 7596 $(elem).val(qParam); 7597 }); 7598 } 7599 7600 var inquiryField = $(".inquiry-target-field"), 7601 defaultFields = $(".elementor-form .elementor-field-type-textarea textarea, .wpcf7-form .wpcf7-textarea"); 7602 7603 if (inquiryField.length) { 7604 fillFiled(inquiryField); 7605 } else if (defaultFields.length) { 7606 fillFiled(defaultFields); 7607 } 7608 } 7609 7610 function fallbackCopyTextToClipboard(text) { 7611 var textArea = document.createElement("textarea"); 7612 textArea.value = text; 7613 textArea.style.top = "0"; 7614 textArea.style.left = "0"; 7615 textArea.style.position = "fixed"; 7616 document.body.appendChild(textArea); 7617 textArea.focus(); 7618 textArea.select(); 7619 7620 try { 7621 var successful = document.execCommand("copy"); 7622 var msg = successful ? "successful" : "unsuccessful"; 7623 console.info("Fallback: Copying text command was " + msg); 7624 } catch (err) { 7625 console.error("Fallback: Oops, unable to copy", err); 7626 } 7627 7628 document.body.removeChild(textArea); 7629 } 7630 7631 function copyTextToClipboard(text) { 7632 if (!navigator.clipboard) { 7633 fallbackCopyTextToClipboard(text); 7634 return; 7635 } 7636 7637 navigator.clipboard.writeText(text); 7638 } 7639 7640 function shareLink() { 7641 var shaleLinkBtn = $(".share-btn__link[data-id=link]"); 7642 7643 if (shaleLinkBtn !== undefined) { 7644 shaleLinkBtn.on("click", function (event) { 7645 event.preventDefault(); 7646 var $this = $(this); 7647 7648 if ($this.hasClass("share-btn__link-active")) { 7649 return; 7650 } 7651 7652 copyTextToClipboard(window.location); 7653 $this.html(window.bs_lang.copied).addClass("share-btn__link-active"); 7654 return; 7655 }); 7656 } 7657 } 7658 7659 function countDown() { 7660 function getTimeRemaining(endtime) { 7661 var t = Date.parse(endtime) - Date.parse(new Date()), 7662 index = t <= 0 ? 0 : 1, 7663 seconds = Math.floor(t / 1000 % 60) * index, 7664 minutes = Math.floor(t / 1000 / 60 % 60) * index, 7665 hours = Math.floor(t / (1000 * 60 * 60) % 24) * index, 7666 days = Math.floor(t / (1000 * 60 * 60 * 24)) * index; 7667 return { 7668 total: t, 7669 days: days, 7670 hours: hours, 7671 minutes: minutes, 7672 seconds: seconds 7673 }; 7674 } 7675 7676 function initializeClock(clock, endtime) { 7677 if (clock) { 7678 var daysSpan = clock.querySelector(".bp-days"); 7679 var hoursSpan = clock.querySelector(".bp-hours"); 7680 var minutesSpan = clock.querySelector(".bp-minutes"); 7681 var secondsSpan = clock.querySelector(".bp-seconds"); 7682 7683 function updateClock() { 7684 var t = getTimeRemaining(endtime); 7685 daysSpan.innerHTML = t.days; 7686 hoursSpan.innerHTML = ("0" + t.hours).slice(-2); 7687 minutesSpan.innerHTML = ("0" + t.minutes).slice(-2); 7688 secondsSpan.innerHTML = ("0" + t.seconds).slice(-2); 7689 7690 if (t.total <= 0) { 7691 clearInterval(timeinterval); 7692 } 7693 } 7694 7695 updateClock(); 7696 var timeinterval = setInterval(updateClock, 1000); 7697 } 7698 } 7699 7700 var countdown = $(".bp-countdown"); 7701 7702 if (countdown.length) { 7703 countdown.each(function (index, count) { 7704 var dateTime = $(count).attr("data-time"), 7705 deadline = new Date(Date.parse(dateTime)); 7706 initializeClock(count, timeShift(deadline)); 7707 }); 7708 } 7709 } 7710 7711 function getAuctionCarCallback(response) { 7712 if (_.template !== undefined) { 7713 var carInfoTemplate = document.getElementById("car-info-template"); 7714 7715 if (!bpIsset(carInfoTemplate)) { 7716 return; 7717 } 7718 7719 var html = _.template(carInfoTemplate.innerHTML), 7720 additionalInfoBlock = document.getElementById("additional-info-block"); 7721 7722 response = response.response; 7723 7724 if (response.item !== undefined && response.item.carInfo !== undefined) { 7725 additionalInfoBlock.innerHTML = html({ 7726 data: response.item, 7727 info: response.item.carInfo 7728 }); 7729 } 7730 } 7731 } 7732 7733 function getAuctionApertmentCallback(response) { 7734 if (_.template !== undefined) { 7735 var apartmentTemplate = document.getElementById("apartment-info-template"); 7736 7737 if (!bpIsset(apartmentTemplate)) { 7738 return; 7739 } 7740 7741 var html = _.template(apartmentTemplate.innerHTML), 7742 additionalInfoBlock = document.getElementById("additional-info-block"); 7743 7744 response = response.response; 7745 7746 if (response.item !== undefined && response.item.realEstateInfo !== undefined) { 7747 additionalInfoBlock.innerHTML = html({ 7748 data: response.item, 7749 info: response.item.realEstateInfo 7750 }); 7751 } 7752 } 7753 } 7754 7755 function getAuctionIndustrialCallback(response) { 7756 if (_.template !== undefined) { 7757 var apartmentTemplate = document.getElementById("industrial-info-template"); 7758 7759 if (!bpIsset(apartmentTemplate)) { 7760 return; 7761 } 7762 7763 var html = _.template(apartmentTemplate.innerHTML), 7764 additionalInfoBlock = document.getElementById("additional-info-block"); 7765 7766 response = response.response; 7767 7768 if (response.item !== undefined && response.item.machineInfo !== undefined) { 7769 additionalInfoBlock.innerHTML = html({ 7770 data: response.item, 7771 info: response.item.machineInfo 7772 }); 7773 } 7774 } 7775 } 7776 7777 function afterInitAction() { 7778 let profileLink = $("#bp-profile-link"); 7779 } 7780 7781 function afterLoginAction() { 7782 let href = window.location.href.replace(window.location.search, ""); 7783 if (href === window.bs_data.sign_in_permalink) { 7784 window.location = window.bs_data.link_profile; 7785 } 7786 } 7787 7788 function adminBarTools() { 7789 function adminBarToolsCallback(response) { 7790 $("#wp-admin-bar-bp-single-sync a").on("click", function (event) { 7791 event.preventDefault(); 7792 let data = response.response.item; 7793 $.ajax({ 7794 url: "/wp-json/plugin/v1/sync-lot/", 7795 type: "POST", 7796 dataType: "json", 7797 data: { 7798 item: data, 7799 auctionId: data.auctionId, 7800 itemIndex: data.itemIndex, 7801 language: data.lang, 7802 sessionId: bidspiritApi.getBidspiritSessionId() 7803 } 7804 }).done(function (response) { 7805 noticeSwall("info", window.bs_lang.lot_sync_is_queued); 7806 }).fail(function (response) { 7807 noticeSwall("error", window.bs_lang.not_found); 7808 }).always(function () { 7809 }); 7810 }); 7811 } 7812 7813 if (document.body.classList.contains("admin-bar") && document.body.classList.contains("admin-bar")) { 7814 $(window).on("bp:get-auction-item", adminBarToolsCallback); 7815 } 7816 } 7817 7818 function menuSwitcher(langCode) { 7819 let pllSwitch = jQuery(".bt-header-row ul.cpel-switcher__list:not(.cpel-switcher__lang--active)"), 7820 langSwitch = pllSwitch.find('a[lang^="' + langCode + '"]').attr("href"); 7821 if (langSwitch !== undefined) { 7822 window.location.href = langSwitch; 7823 } 7824 } 7825 7826 $(document).ready(function () { 7827 metaSlider(); 7828 inquiryLot(); 7829 shareLink(); 7830 countDown(); 7831 adminBarTools(); 7832 $(window).on("bp:get-auction-item", getAuctionCarCallback); 7833 $(window).on("bp:get-auction-item", getAuctionApertmentCallback); 7834 $(window).on("bp:get-auction-item", getAuctionIndustrialCallback); 7835 $(window).on("bp:after-init", afterInitAction); 7836 $(window).on("bp:after-login", afterLoginAction); 7837 }); 7838})(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.