Major Fixes & Improvements [Custom Code]
-
I’ve taken the charge to update the Javascript and all our issues have been resolved. I don’t see a way to contribute (no github), so I’m uploading it here
🔧 Major Fixes:
- Popup Issue Fixed:
- Added
event.stopPropagation()to prevent event bubbling - Check for existing popups before creating new ones
- Improved overlay click handling with delay
- Added
- Better Event Management:
- Proper event listener cleanup
- Centralized popup closing function
- Improved message handling
- Enhanced User Experience:
- Better visual styling for locker details
- Custom alert option for validation
- Escape key support to close popup
- Page visibility handling
🎯 Key Features:
- Popup Mode: Button that opens map in overlay
- Embedded Mode: Map embedded directly in checkout
- Multi-language Support: Greek and English
- Country Support: Greece (GR) and Cyprus (CY)
- Validation: Prevents order completion without locker selection
- Persistence: Remembers selected locker in localStorage
- Auto-cleanup: Clears selection when country/postal code changes
🔄 How It Works:
- Initialization: Sets up button/embedded map based on settings
- Locker Selection: Opens appropriate map widget
- Data Handling: Receives locker data via postMessage API
- Display: Shows selected locker details with styling
- Validation: Ensures locker is selected before order placement
- Cleanup: Manages state when shipping method changes
How to make the improvements:
- Head over to box-now-delivery plugin > js > box-now-delivery.js
- You can create a backup, if you wish or delete and re-install the plugin to revert changes later.
- Paste the code from below
- Clear any caching mechanisms such as Object Cache, etc.
- Try the checkout again
(function ($) {
/**
* Add the Box Now Delivery button or embedded map.
*/
function addButton() {
if (
$("#box_now_delivery_button").length === 0 &&
boxNowDeliverySettings.displayMode === "popup"
) {
var buttonText = boxNowDeliverySettings.buttonText || "Pick a locker";
$('label[for="shipping_method_0_box_now_delivery"]').after(
'<button type="button" id="box_now_delivery_button" style="display:none;">' +
buttonText +
"</button>"
);
attachButtonClickListener();
} else if (boxNowDeliverySettings.displayMode === "embedded") {
$('label[for="shipping_method_0_box_now_delivery"]').after(
'<div id="box_now_delivery_embedded_map" style="display:none;"></div>'
);
embedMap();
}
applyButtonStyles();
}
/**
* Apply the custom styles for the Box Now Delivery button.
*/
function applyButtonStyles() {
var buttonColor = boxNowDeliverySettings.buttonColor || "#84C33F";
// Remove existing styles first to avoid duplicates
$("#box-now-delivery-button-styles").remove();
var styleBlock =<br> <style id="box-now-delivery-button-styles"><br> #box_now_delivery_button {<br> background-color: ${buttonColor} !important;<br> color: #fff !important;<br> padding: 8px 16px !important;<br> border: none !important;<br> border-radius: 4px !important;<br> cursor: pointer !important;<br> margin-left: 10px !important;<br> font-size: 14px !important;<br> }<br> #box_now_delivery_button:hover {<br> opacity: 0.9 !important;<br> }<br> </style><br>;
$("head").append(styleBlock);
}
/**
* Attach click event listener to the Box Now Delivery button.
*/
function attachButtonClickListener() {
$("#box_now_delivery_button").off("click").on("click", function (event) {
event.preventDefault();
event.stopPropagation(); // Prevent event bubbling
// Check if popup already exists
if ($("#box_now_delivery_overlay").length > 0) {
return; // Don't create another popup
}
createPopupMap();
});
}
/**
* Get the selected country from billing form
*/
function GetUserCountry() {
// Get the selected country from the billing_country select input
const selectedCountry = $('select[name="billing_country"]').val();
return selectedCountry;
}
/**
* Embed the map to the page.
*/
function embedMap() {
var iframe = $("#box_now_delivery_embedded_map iframe");
if (iframe.length === 0) {
iframe = createEmbeddedIframe();
var lockerDetailsContainer = $("<div>", {
id: "box_now_selected_locker_details",
css: {
display: "none",
marginTop: "10px",
},
});
// Create a new div to hold the locker information
var lockerInfoContainer = $("<div>", {
id: "locker_info_container",
});
$("#box_now_delivery_embedded_map")
.css({
position: "relative",
width: "100%",
height: "400px", // Set a fixed height for embedded map
})
.append(iframe)
.append(lockerInfoContainer.append(lockerDetailsContainer));
// Add the load event listener to the iframe
iframe.on("load", function () {
// Add the event listener for the embedded map
const embeddedMessageHandler = function (event) {
if (typeof event.data.boxnowClose !== "undefined") {
// Handle the close event for embedded map
} else if (typeof event.data === 'object' && event.data.boxnowLockerId) {
updateLockerDetailsContainer(event.data);
}
};
window.addEventListener("message", embeddedMessageHandler);
});
}
if ($("#shipping_method_0_box_now_delivery").is(":checked")) {
$("#box_now_delivery_embedded_map").show();
} else {
$("#box_now_delivery_embedded_map").hide();
}
}
/**
* Centralized popup closing function
*/
function closePopup() {
$("#box_now_delivery_overlay").remove();
$("iframe[src^='https://widget-v5.boxnow.gr/popup.html']").remove();
$("iframe[src^='https://widget-v5.boxnow.cy/popup.html']").remove();
}
/**
* Create overlay for the popup iframe
*/
function createOverlay() {
// Remove any existing overlay first
$("#box_now_delivery_overlay").remove();
var overlay = $("<div>", {
id: "box_now_delivery_overlay",
css: {
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
backgroundColor: "rgba(0, 0, 0, 0.5)",
zIndex: 9998,
cursor: "pointer"
},
});
// Add a small delay before attaching the click handler
// This prevents immediate closure from event bubbling
setTimeout(() => {
overlay.on("click", function (e) {
// Only close if clicking directly on overlay, not on child elements
if (e.target === this) {
closePopup();
}
});
}, 100);
$("body").append(overlay);
}
/**
* Create an iframe for the popup map.
*/
function createPopupMap() {
// Remove any existing popup first
closePopup();
let gpsOption = boxNowDeliverySettings.gps_option;
let partnerId = boxNowDeliverySettings.partnerId;
let postalCode = $('input[name="billing_postcode"]').val();
let country = GetUserCountry();
console.log("Selected country:", country);
let src;
if (country === "CY") {
src = "https://widget-v5.boxnow.cy/popup.html";
} else {
src = "https://widget-v5.boxnow.gr/popup.html";
}
// Build URL parameters properly
let params = [];
if (partnerId) {
params.push("partnerId=" + partnerId);
}
if (gpsOption === "off") {
params.push("gps=no");
params.push("zip=" + encodeURIComponent(postalCode));
params.push("autoclose=yes");
params.push("autoselect=no");
} else {
params.push("gps=yes");
params.push("autoclose=yes");
params.push("autoselect=no");
}
if (params.length > 0) {
src += "?" + params.join("&");
}
let iframe = $("<iframe>", {
src: src,
css: {
position: "fixed",
top: "50%",
left: "50%",
width: "90%",
maxWidth: "800px",
height: "80%",
maxHeight: "600px",
border: 0,
borderRadius: "10px",
transform: "translate(-50%, -50%)",
zIndex: 9999,
boxShadow: "0 4px 20px rgba(0,0,0,0.3)"
},
});
// Improved message event listener
const popupMessageHandler = function (event) {
if (event.data === "closeIframe" ||
(typeof event.data === 'object' && event.data.boxnowClose !== undefined)) {
closePopup();
window.removeEventListener("message", popupMessageHandler);
} else if (typeof event.data === 'object' && event.data.boxnowLockerId) {
updateLockerDetailsContainer(event.data);
closePopup(); // Close popup after selection
window.removeEventListener("message", popupMessageHandler);
}
};
window.addEventListener("message", popupMessageHandler);
createOverlay();
$("body").append(iframe);
}
/**
* Create an iframe for the embedded map.
*/
function createEmbeddedIframe() {
let gpsOption = boxNowDeliverySettings.gps_option;
let partnerId = boxNowDeliverySettings.partnerId;
let postalCode = $('input[name="billing_postcode"]').val();
let country = GetUserCountry();
let src;
if (country === "CY") {
src = "https://widget-v5.boxnow.cy";
} else {
src = "https://widget-v5.boxnow.gr";
}
// Build URL parameters properly
let params = [];
if (partnerId) {
params.push("partnerId=" + partnerId);
}
if (gpsOption === "off") {
params.push("gps=no");
params.push("zip=" + encodeURIComponent(postalCode));
} else {
params.push("gps=yes");
}
if (params.length > 0) {
src += "?" + params.join("&");
}
return $("<iframe>", {
src: src,
css: {
width: "100%",
height: "100%",
border: 0,
},
});
}
/**
* Update the locker details container with selected locker data.
*
* @param {object} lockerData Locker data object.
*/
function updateLockerDetailsContainer(lockerData) {
// Check if locker data is valid
if (
!lockerData ||
lockerData.boxnowLockerId === undefined ||
lockerData.boxnowLockerAddressLine1 === undefined ||
lockerData.boxnowLockerPostalCode === undefined ||
lockerData.boxnowLockerName === undefined
) {
console.log("Invalid locker data received:", lockerData);
return;
}
// Get the selected locker details
var locker_id = lockerData.boxnowLockerId;
var locker_address = lockerData.boxnowLockerAddressLine1;
var locker_postal_code = lockerData.boxnowLockerPostalCode;
var locker_name = lockerData.boxnowLockerName;
// Store in localStorage
localStorage.setItem("box_now_selected_locker", JSON.stringify(lockerData));
// Ensure the locker details container exists
if ($("#box_now_selected_locker_details").length === 0) {
if (boxNowDeliverySettings.displayMode === "popup") {
$("#box_now_delivery_button").after(
'<div id="box_now_selected_locker_details" style="display:none;"></div>'
);
} else {
$("#locker_info_container").append(
'<div id="box_now_selected_locker_details" style="display:none;"></div>'
);
}
}
// Add or update hidden input field to store locker_id
if ($("#_boxnow_locker_id").length === 0) {
$("<input>")
.attr({
type: "hidden",
id: "_boxnow_locker_id",
name: "_boxnow_locker_id",
value: locker_id,
})
.appendTo("#box_now_selected_locker_details");
} else {
$("#_boxnow_locker_id").val(locker_id);
}
// Get the language of the webpage
var language = document.documentElement.lang || "el";
// Define the content for English
var englishContent =<br><div style="font-family: Arial, sans-serif; margin-top: 10px; padding: 15px; background-color: #f9f9f9; border-radius: 5px; border-left: 4px solid #84C33F;"><br> <p style="margin-bottom: 10px; color: #84C33F; font-size: 16px;"><b>✓ Selected Locker</b></p><br> <p style="margin-bottom: 5px; font-size: 14px;"><b>Locker Name:</b> ${locker_name}</p><br> <p style="margin-bottom: 5px; font-size: 14px;"><b>Address:</b> ${locker_address}</p><br> <p style="margin-bottom: 0; font-size: 14px;"><b>Postal Code:</b> ${locker_postal_code}</p><br></div>;
// Define the content for Greek
var greekContent =<br><div style="font-family: Arial, sans-serif; margin-top: 10px; padding: 15px; background-color: #f9f9f9; border-radius: 5px; border-left: 4px solid #84C33F;"><br> <p style="margin-bottom: 10px; color: #84C33F; font-size: 16px;"><b>✓ Επιλεγμένο Locker</b></p><br> <p style="margin-bottom: 5px; font-size: 14px;"><b>Όνομα Locker:</b> ${locker_name}</p><br> <p style="margin-bottom: 5px; font-size: 14px;"><b>Διεύθυνση:</b> ${locker_address}</p><br> <p style="margin-bottom: 0; font-size: 14px;"><b>ΤΚ:</b> ${locker_postal_code}</p><br></div>;
// Choose the correct content based on the language
var content = language === "el" ? greekContent : englishContent;
// Update the locker details container
$("#box_now_selected_locker_details").html(content).show();
// Add or update hidden input field to store complete locker information
if ($("#box_now_selected_locker_input").length === 0) {
$("<input>")
.attr({
type: "hidden",
id: "box_now_selected_locker_input",
name: "box_now_selected_locker",
value: JSON.stringify(lockerData),
})
.appendTo("#box_now_selected_locker_details");
} else {
$("#box_now_selected_locker_input").val(JSON.stringify(lockerData));
}
console.log("Locker details updated:", lockerData);
}
/**
* Show the selected locker details from local storage.
*/
function showSelectedLockerDetailsFromLocalStorage() {
var lockerData = localStorage.getItem("box_now_selected_locker");
if (lockerData) {
try {
updateLockerDetailsContainer(JSON.parse(lockerData));
} catch (e) {
console.error("Error parsing locker data from localStorage:", e);
localStorage.removeItem("box_now_selected_locker");
}
}
}
/**
* Toggle the Box Now Delivery button or embedded map based on the selected shipping method.
*/
function toggleBoxNowDelivery() {
if (boxNowDeliverySettings.displayMode === "popup") {
toggleBoxNowDeliveryButton();
} else if (boxNowDeliverySettings.displayMode === "embedded") {
embedMap();
}
}
/**
* Toggle the Box Now Delivery button visibility based on the selected shipping method.
*/
function toggleBoxNowDeliveryButton() {
var boxButton = $("#box_now_delivery_button");
var lockerDetails = $("#box_now_selected_locker_details");
// Set the background color
boxButton.css("background-color", boxNowDeliverySettings.buttonColor);
if ($("#shipping_method_0_box_now_delivery").is(":checked")) {
boxButton.show();
showSelectedLockerDetailsFromLocalStorage();
} else if ($('input[name="shipping_method[0]"]:checked').length > 0) {
boxButton.hide();
lockerDetails.hide();
} else if (
$('input[type="hidden"][name="shipping_method[0]"]').val() ===
"box_now_delivery"
) {
boxButton.show();
showSelectedLockerDetailsFromLocalStorage();
} else {
boxButton.hide();
lockerDetails.hide();
}
}
/**
* Remove the selected locker details from local storage and hide the locker details container
*/
function clearSelectedLockerDetails() {
localStorage.removeItem("box_now_selected_locker");
$("#box_now_selected_locker_details").hide().empty();
$("#_boxnow_locker_id").remove();
$("#box_now_selected_locker_input").remove();
console.log("Locker details cleared");
}
/**
* Initialize the script.
*/
function init() {
addButton();
toggleBoxNowDelivery();
if ($("#shipping_method_0_box_now_delivery").is(":checked")) {
showSelectedLockerDetailsFromLocalStorage();
}
}
// Document ready event
$(document).ready(function () {
/**
* Add validation for order placement to ensure locker selection.
*/
function addOrderValidation() {
$(document.body).on("click", "#place_order", function (event) {
var lockerData = localStorage.getItem("box_now_selected_locker");
if (
!lockerData &&
($('input[type="radio"][name="shipping_method[0]"]:checked').val() ===
"box_now_delivery" ||
$('input[type="hidden"][name="shipping_method[0]"]').val() ===
"box_now_delivery")
) {
event.preventDefault();
event.stopImmediatePropagation();
var message = boxNowDeliverySettings.lockerNotSelectedMessage ||
"Please select a locker first!";
// Show a better styled alert
if (typeof boxNowDeliverySettings.showCustomAlert !== 'undefined' &&
boxNowDeliverySettings.showCustomAlert) {
showCustomAlert(message);
} else {
alert(message);
}
return false;
}
});
}
/**
* Show custom styled alert
*/
function showCustomAlert(message) {
var alertHtml =<br> <div id="box_now_alert_overlay" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); z-index: 10000; display: flex; align-items: center; justify-content: center;"><br> <div style="background: white; padding: 20px; border-radius: 10px; max-width: 400px; text-align: center; box-shadow: 0 4px 20px rgba(0,0,0,0.3);"><br> <p style="margin-bottom: 20px; font-size: 16px; color: #333;">${message}</p><br> <button onclick="$('#box_now_alert_overlay').remove()" style="background-color: #84C33F; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-size: 14px;">OK</button><br> </div><br> </div><br>;
$('body').append(alertHtml);
}
// Initialize the plugin
init();
// Show the selected locker details from localStorage on page load
showSelectedLockerDetailsFromLocalStorage();
// Reinitialize when checkout is updated
$(document.body).on("updated_checkout", function () {
setTimeout(function() {
init();
}, 100);
});
// Handle shipping method changes
$(document.body).on(
"change",
'input[type="radio"][name="shipping_method[0]"]',
function() {
setTimeout(function() {
toggleBoxNowDelivery();
}, 50);
}
);
// Clear locker details when country changes
$('body').on('change', '#billing_country', function(){
clearSelectedLockerDetails();
});
// Clear locker details when postal code changes significantly
var postalCodeTimeout;
$('body').on('input', '#billing_postcode', function(){
clearTimeout(postalCodeTimeout);
postalCodeTimeout = setTimeout(function() {
if ($("#shipping_method_0_box_now_delivery").is(":checked")) {
clearSelectedLockerDetails();
}
}, 1000);
});
// Add order validation
addOrderValidation();
// Handle page visibility change (prevents issues with popups)
$(document).on('visibilitychange', function() {
if (document.hidden) {
closePopup();
}
});
// Close popup on escape key
$(document).on('keydown', function(e) {
if (e.key === 'Escape' && $("#box_now_delivery_overlay").length > 0) {
closePopup();
}
});
console.log("Box Now Delivery plugin initialized successfully");
});
})(jQuery); - Popup Issue Fixed:
Viewing 1 replies (of 1 total)
Viewing 1 replies (of 1 total)
The topic ‘Major Fixes & Improvements [Custom Code]’ is closed to new replies.