const {
    io_wp_local_path,
    io_checkavail,
    io_hidetimes,
    io_user_country,
    io_user_currency,
    io_default_start_time,
    io_default_end_time,
    io_force_blank_timepickers,
    io_hide_end_time,
    io_cart_date_format,
    io_cart_message,
    io_cart_time_format,
    io_multidayquote,
    io_cartdayselect,
    io_cartAllowSameDay,
    io_overnightPickupTime,
    io_incartupsell,
    io_distancecharge,
    io_deliverymethod,
    io_brand,
    io_restrict_times,
    io_restrict_time_start,
    io_restrict_time_end,
    io_default_state,
    io_hide_zero,
    io_weekEndPrice,
    io_weekDayText,
    io_weekEndText,
    io_weekendDefine,
    io_accessory_price,
    io_accessory_select,
    io_upsell_price,
    io_cart_party_planner_email,
    io_cart_party_planner_destination,
    io_cart_current_specials_phone,
    io_cart_current_specials_destination,
    io_hideQuantityAvail,
    io_info_required,
    io_always_display_live_price,
    io_default_delivery_method,
    io_hide_live_prices,
    io_info_required_data,
    io_pagename,
    io_rest_lead_url,
    io_customer_geolocation,
    io_customer_ip,
    io_categoryVariantImages
} = io_cart_vars;

const io_company_timeslots         = JSON.parse(io_cart_vars.io_company_timeslots),
      io_accessory_data            = JSON.parse(io_cart_vars.io_accessory_data),
      io_custom_prices             = JSON.parse(io_cart_vars.io_custom_prices),
      io_delivery_methods          = JSON.parse(io_cart_vars.io_delivery_methods),
      io_delivery_prices           = JSON.parse(io_cart_vars.io_delivery_prices),
      io_delivery_methods_restrict = JSON.parse(io_cart_vars.io_delivery_methods_restrict),
      io_prices                    = JSON.parse(io_cart_vars.io_prices)
/* configurable globals */
var start_default = "11:00 am";
if (io_default_start_time != "") start_default = io_default_start_time;
var end_default = "3:00 pm";
if (io_default_end_time != "") end_default = io_default_end_time;

if (io_user_currency) {
    var currency = io_user_currency;
} else {
    var currency = "USD";
}

if (io_user_country) {
    var country = io_user_country;
} else {
    var country = "US";
}


var timeFormat = "g:i a";
if (io_cart_time_format != "") timeFormat = io_cart_time_format;
var dateFormat = "m/d/yy";
if (io_cart_date_format != "") dateFormat = io_cart_date_format;

var restrictTimes = false;
if (io_restrict_times === "on") restrictTimes = true;
var restrictTimeStart = start_default;
if (io_restrict_time_start != "") restrictTimeStart = io_restrict_time_start;
var restrictTimeEnd = end_default;
if (io_restrict_time_end != "") restrictTimeEnd = io_restrict_time_end;


var multi_day = true;
if (io_multidayquote === "off" || io_cartdayselect == "Single Day") multi_day = false;
var in_cart_upsell = false;
if (io_incartupsell === "on") in_cart_upsell = true;
var io_distance_charge = false;
if (io_distancecharge === "on") io_distance_charge = true;

/* other globals */
var pallet_color1 = ""; /* set in onready */
/* track the date start/end of calendar clicking */
var click_count = 0;

/* for configuring upsell carosel in cart */
var cart_carousel_set = false;

/* for checking when we remove an item from the cart */
var last_remove = 0;
var last_upsell_call = 0;

/* for cart loading animation */
var io_cart_loading_active = false;
var io_cart_loading_count = 0;
var io_cart_loading_fallback_timer = null;

/*var start_default = "11:00";
var end_default = "15:00";
var currency = "EUR";
var timeFormat = "G:i";
var dateFormat = "d/m/yy";*/


/* For weekday weekend pricing */
var use_weekday_weekend = false;
if (io_weekEndPrice == "on") use_weekday_weekend = true;

/* Accessory and Upsell Prices */
var show_accessory_price = false;
if (io_accessory_price == "on") show_accessory_price = true;
var show_upsell_price = false;
if (io_upsell_price == "on") show_upsell_price = true;
var io_page = document.currentScript.getAttribute('page');

/* For customer geolocation shortcode */
var storage_key = 'io_customer_location';

class IO_Rental {
    rentalid="";
    rentalid_str="";
    name="";
    qty=1;
    starttime="";
    endtime="";
    price="";
    conditional_prices=[];
    vendor="";
    giftcard="";
    accessories=[];
    availability;
    cart_id;
    last_api_call=0;
    overrideprice="";
    required="";

    constructor(rentalid, name, qty) {
        this.rentalid = rentalid;
        this.name = name;
        this.qty = qty;
    }

    set accessory(value){
        this.accessories.push(value);
    }
    set conditional_price(value){
        this.conditional_prices.push(value);
        for(let i = 0; i < this.accessories.length; ++i){
            this.accessories[i].conditional_price = value;
        }
    }

    get_acc_property(acc_id, property){
        for(const accessory of this.accessories){
            if(accessory.rentalid==acc_id){
                return accessory[property];
            }else if(accessory.accessories.length > 0){
                let nested = accessory.get_acc_property(acc_id, property);
                if(nested !== null){
                    return nested;
                }
            }
        }
        return null;
    }

    static fromObject(rawData) {
        let rental_obj = new IO_Rental(rawData.rentalid, rawData.name, parseInt(rawData.qty));
        rental_obj.rentalid_str = rawData.rentalid_str;
        rental_obj.starttime = rawData.starttime;
        rental_obj.endtime = rawData.endtime;
        rental_obj.price = parseFloat(rawData.price);
        rental_obj.vendor = rawData.vendor
        rental_obj.giftcard = rawData.giftcard;
        rental_obj.availability = parseInt(rawData.availability);
        rental_obj.cart_id= rawData.cart_id;
        rental_obj.last_api_call = rawData.last_api_call;
        rental_obj.overrideprice = rawData.overrideprice;
        rental_obj.required = rawData.required;
        rental_obj.accessories = [];
        for(let i=0; i<rawData.conditional_prices.length; ++i) {
            rental_obj.conditional_price = rental_obj.mapConditionalPrice(rawData.conditional_prices[i])
        }
        for(let i=0; i<rawData.accessories.length; ++i){
            rental_obj.accessory = IO_Rental.fromObject(rawData.accessories[i]);
        }
        return rental_obj;
    }

    assign(rental){
        this.rentalid = rental.rentalid;
        this.name = rental.name;
        this.rentalid_str = rental.rentalid_str;
        this.starttime = rental.starttime;
        this.endtime = rental.endtime;
        this.price = rental.price;
        this.vendor = rental.vendor;
        this.giftcard = rental.giftcard;
        this.availability = rental.availability;
        this.cart_id = rental.cart_id;
        if(rental.accessories.length){
            this.accessories = [];
            for(let i=0; i<rental.accessories.length; ++i){
                this.accessory = rental.accessories[i];
            }
        }
        if(rental.conditional_prices.length){
            this.conditional_prices = [];
            for(let i=0; i<rental.conditional_prices.length; ++i){
                this.conditional_price = rental.conditional_prices[i];
            }
        }
    }

    find_conditional_price(id, type){
        for(let i = 0; i < this.conditional_prices.length; ++i){
            let cond_price = this.conditional_prices[i];
            if(cond_price.id == id && cond_price.type == type){
                return cond_price;
            }
        }
        return null;
    }

    mapConditionalPrice(conditionalPriceData){
        if(conditionalPriceData){
            let cond_price_event = new IO_Event();
            cond_price_event.starttimestamp = conditionalPriceData.event.starttimestamp
            cond_price_event.endtimestamp = conditionalPriceData.event.endtimestamp
            cond_price_event.delivery_type = conditionalPriceData.event.delivery_type;
            cond_price_event.surface = conditionalPriceData.event.surface;
            let cond_price = new IO_ConditionalPrice(conditionalPriceData.name, conditionalPriceData.id, conditionalPriceData.type,
                cond_price_event.start_date, cond_price_event.end_date, cond_price_event.start_time, cond_price_event.end_time,
                conditionalPriceData.type, cond_price_event.delivery_type, cond_price_event.surface);
            cond_price.price = parseFloat(conditionalPriceData.price);
            return cond_price;
        }
    }

    set start_time(time){
        let date = jQuery("[name='dateStart']").val();
        if(date){
            this.starttime = new Date(date+" "+time).getTime();
            for(let i=0; i < this.accessories.length; ++i){
                this.accessories[i].start_time = time;
            }
        }
    }
    set end_time(time){
        let date = jQuery("[name='dateEnd']").val();
        if(date){
            this.endtime = new Date(date+" "+time).getTime();
            for(let i=0; i < this.accessories.length; ++i){
                this.accessories[i].end_time = time;
            }
        }
    }
    set start_timestamp(timestamp){
        this.starttime = timestamp
        for(let i=0; i < this.accessories.length; ++i){
            this.accessories[i].start_timestamp = timestamp;
        }
    }
    set end_timestamp(timestamp){
        this.endtime = timestamp
        for(let i=0; i < this.accessories.length; ++i){
            this.accessories[i].end_timestamp = timestamp;
        }
    }

    required_accessoires_are_avail(){
        let required_all_avail = true;
        for(let i = 0; i < this.accessories.length; ++i){
            let acc = this.accessories[i];
            if (acc.availability < 0 && acc.required > 0) {
                required_all_avail = false
                break;
            }
        }
        return required_all_avail;
    }
}

class IO_ConditionalPrice{
    /*
    Type Enums:
     Delivery Method
     Weekday/Weekend
     Custom
    */
    name;
    id;
    type;
    event;
    price="";

    constructor(name, id, type, start_date, end_date, start_time, end_time, delivery_method="", surface="") {
        this.name = name;
        this.id = id;
        this.type = type;
        this.event = new IO_Event();
        this.event.start_date = start_date;
        this.event.end_date = end_date;
        this.event.start_time = start_time;
        this.event.end_time = end_time;
        this.event.delivery_type = delivery_method;
        this.event.surface = surface;
    }

    display_conditional_price(){
        let container_id = "";
        let element_class = "";
        switch(this.type){
            case "Custom":
                container_id = "#io_custom_prices_container";
                element_class = ".io_product_cust_price_" + this.id;
                break;
            case "Delivery Method":
                container_id  = "#io_delivery_prices_container";
                element_class = ".io_product_cust_price_delivery_method_" + this.id;
                break;
            case "Weekday/Weekend":
                container_id = "#io_week_prices_container";
                element_class = ".io_product_cust_price_" + this.id;
                break;
        }
        let container = document.querySelector(container_id);
        let cond_price = document.querySelector(element_class);
        if (!cond_price) {
            var first_price = document.querySelector(".io_product_price_box");
            if (first_price != null) {
                cond_price = first_price.cloneNode(true);
                /* clear all classes */
                cond_price.className = "";
                cond_price.classList.add("io_product_price_box");
                cond_price.classList.add(element_class);
                cond_price.querySelector("p:nth-child(2)").innerHTML = "for "+this.name;
                cond_price.querySelector("p:nth-child(1)"). innerHTML = simpleCart.toCurrency(this.price);
            }
        }
        container.append(cond_price);
        jQuery(cond_price).show();
    }


}

class IO_Event{
    starttimestamp;
    endtimestamp;
    delivery_type;
    surface;

    set start_date(date){
        if(this.starttimestamp){
            let start_date_obj = new Date(this.starttimestamp);
            let start_time = getFormattedtime(start_date_obj);
            this.starttimestamp = new Date(date+" "+start_time).getTime();
        }else{
            if(date){
                date = convertDateStringtoDateObject(date);
                this.starttimestamp = date.getTime();
            }
        }
    }
    set end_date(date){
        if(this.endtimestamp){
            let end_date_obj = new Date(this.endtimestamp);
            let end_time = getFormattedtime(end_date_obj);
            this.endtimestamp = new Date(date+" "+end_time).getTime();
        }else{
            if(date) {
                date = convertDateStringtoDateObject(date);
                this.endtimestamp = date.getTime();
            }
        }
    }
    set start_time(time){
        if(this.starttimestamp){
            let start_date_obj = new Date(this.starttimestamp);
            let start_date = getFormatteddate(start_date_obj);
            this.starttimestamp = new Date(start_date+" "+time).getTime();
        }
    }
    set end_time(time){
        if(this.endtimestamp){
            let end_date_obj = new Date(this.endtimestamp);
            let end_date = getFormatteddate(end_date_obj);
            this.endtimestamp = new Date(end_date+" "+time).getTime();
        }
    }

    get start_date() {
        if (this.starttimestamp) return getFormatteddate(new Date(this.starttimestamp));
        return ""
    }
    get end_date(){
        if (this.endtimestamp) return getFormatteddate( new Date(this.endtimestamp) );
        return ""
    }
    get start_time(){
        if (this.starttimestamp) return getFormattedtime( new Date(this.starttimestamp) );
        return ""
    }
    get end_time(){
        if (this.endtimestamp) return getFormattedtime( new Date(this.endtimestamp) );
        return ""
    }
}

class IO_Address{
    street;
    city;
    zip;
    state;
    country;
}

class IO_Venue{
    id;
    address = new IO_Address();

    set street(value){
        this.address.street = value;
    }
    set city(value){
        this.address.city = value;
    }
    set zip(value){
        this.address.zip = value;
    }
    set state(value){
        this.address.state = value;
    }
    set country(value){
        this.address.country = value;
    }

    get street(){
        return this.address.street;
    }
    get city(){
        return this.address.city;
    }
    get zip(){
        return this.address.zip;
    }
    get state(){
        return this.address.state;
    }
    get country(){
        return this.address.country;
    }
}

class IO_Phone{
    number;
    ok_to_text;
}

class IO_Customer{
    address = new IO_Address();
    email;
    phones = {mobile: new IO_Phone(), home: new IO_Phone(), work: new IO_Phone()};
    organization;
    first_name;
    last_name;

    set mobile_phone_number(value){
        this.phones.mobile.number = value;
    }
    set home_phone_number(value){
        this.phones.home.number = value;
    }
    set work_phone_number(value){
        this.phones.work.number = value;
    }

    set street(value){
        this.address.street = value;
    }
    set city(value){
        this.address.city = value;
    }
    set zip(value){
        this.address.zip = value;
    }
    set state(value){
        this.address.state = value;
    }
    set country(value){
        this.address.country = value;
    }

    get street(){
        return this.address.street;
    }
    get city(){
        return this.address.city;
    }
    get zip(){
        return this.address.zip;
    }
    get state(){
        return this.address.state;
    }
    get country(){
        return this.address.country;
    }

    get mobile_phone_number(){
        return this.phones.mobile.number;
    }
    get home_phone_number(){
        return this.phones.home.number;
    }
    get work_phone_number(){
        return this.phones.work.number;
    }
}

class IO_Cache{
    cartCache = {};
    infoCache = {};
    last_api_call = 0;

    last_call_within_time_limit(id, type){
        let time_limit = Date.now() - (5*60*1000); // 5 minutes
        if(type=="info"){
            let rental_obj = this.infoCache[id];
            if(!rental_obj || rental_obj.last_api_call < time_limit){
                //last api call is older than call window or rental_obj not here
                return false;
            }else{
                //last api call is within time window.
                return true;
            }
        }else if(type=="cart"){
            let rental_obj = this.cartCache[id];
            if(!rental_obj || rental_obj.last_api_call < time_limit){
                //last api call is older than call window or rental_obj not here
                return false;
            }else{
                //last api call is within time window.
                return true;
            }
        }else{
            // Somehow bad type
            return false;
        }
    }

    needs_refreshed(id, type){
        if(!this.last_call_within_time_limit(id, type)){
            return true;
        }else{
            return false;
        }
    }

    empty(){
        this.infoCache = {};
        this.cartCache = {};
    }

    set info_cache(rental) {
        if(this.infoCache[rental.rentalid_str]){
            let rental_obj = IO_Rental.fromObject(this.infoCache[rental.rentalid_str]);
            rental_obj.assign(rental);
            rental_obj.last_api_call = this.last_api_call
            this.infoCache[rental.rentalid_str] = rental_obj;
        }else{
            rental.last_api_call = this.last_api_call
            this.infoCache[rental.rentalid_str] = rental;
        }
    }

    set cart_cache(cart_item_obj){
        let rental = cart_item_obj.get("rental_obj");
        let cart_id = cart_item_obj.get("id");
        if(this.cartCache[cart_id]){
            let rental_obj = IO_Rental.fromObject(this.cartCache[cart_id]);
            rental_obj.assign(rental);
            rental_obj.last_api_call = this.last_api_call
            this.cartCache[cart_id] = rental_obj;
        }else{
            rental.last_api_call = this.last_api_call
            this.cartCache[cart_id] = rental;
        }
    }
}

class IO_Data{
    cart = [];
    info = [];
    event;
    venue;
    customer;
    guid;
    cache;
    uid;
    qid;
    page_name = io_pagename;

    constructor(data = null) {
        if (data) {
            // If data is passed in, map it to the current instance
            if(data.cart){
                this.cart = []
                if(data.cart.length > 0){
                    for(let i = 0; i < data.cart.length; ++ i){
                        let rental_obj = IO_Rental.fromObject(data.cart[i]);
                        this.cart.push(rental_obj);
                    }
                }else{
                    this.cart = []
                }
            }
            this.info = data.info || [];
            this.event = new IO_Event();
            this.venue = new IO_Venue();
            this.customer = new IO_Customer();
            this.cache = new IO_Cache();
            this.mapEvent(data.event);
            this.mapVenue(data.venue);
            this.mapCustomer(data.customer);
            this.mapCache(data.cache);
            this.guid = data.guid
            this.uid = data.uid
        } else {
            // Default values if no data is provided
            this.cart = [];
            this.info = [];
            this.event = new IO_Event();
            this.venue = new IO_Venue();
            this.customer = new IO_Customer();
            this.cache = new IO_Cache();
        }
    }

    mapEvent(eventData) {
        if (eventData) {
            this.event.start_date = getFormatteddate(new Date(eventData.starttimestamp)); // Assuming timestamp is in ms
            this.event.end_date = getFormatteddate(new Date(eventData.endtimestamp));
            this.event.start_time = getFormattedtime(new Date(eventData.starttimestamp));
            this.event.end_time = getFormattedtime(new Date(eventData.endtimestamp));
            this.event.delivery_type = eventData.delivery_type || '';
            this.event.surface = eventData.surface || '';
        }
    }

    mapVenue(venueData) {
        this.venue.id = venueData.id || '';
        if (venueData && venueData.address) {
            this.venue.street = venueData.address.street || '';
            this.venue.city = venueData.address.city || '';
            this.venue.zip = venueData.address.zip || '';
            this.venue.state = venueData.address.state || '';
            this.venue.country = venueData.address.country || '';
        }
    }

    mapCustomer(customerData) {
        if (customerData) {
            this.customer.email = customerData.email || '';
            this.customer.first_name = customerData.first_name || '';
            this.customer.last_name = customerData.last_name || '';
            this.customer.organization = customerData.organization || '';
            if (customerData.phones) {
                this.customer.mobile_phone_number = customerData.phones.mobile.number || '';
                this.customer.home_phone_number = customerData.phones.home.number || '';
                this.customer.work_phone_number = customerData.phones.work.number || '';
            }
            if(customerData.address){
                this.customer.street = customerData.address.street || '';
                this.customer.zip = customerData.address.zip || '';
                this.customer.city = customerData.address.city || '';
                this.customer.state = customerData.address.state || '';
                this.customer.country = customerData.address.country || '';
            }
        }
    }

    mapCache(cacheData){
        if(cacheData){
            this.cache.cartCache = cacheData.cartCache;
            this.cache.infoCache = cacheData.infoCache;
            this.cache.last_api_call = cacheData.last_api_call;
        }
    }
    save_io_data(){
        sessionStorage.io_data = JSON.stringify( this );
    }

    set_event_time(start_date, end_date, start_time, end_time){
        this.event.start_date = start_date;
        this.event.end_date = end_date;
        this.event.start_time = start_time;
        this.event.end_time = end_time;
        this.save_io_data();
    }

    event_time_set(){
        return this.event.start_date && this.event.end_date && this.event.start_time && this.event.end_time
    }

    time_change(){
        this.cache.last_api_call = 0;
        this.cache.empty();
        this.save_io_data();
        //updateLead("cart", ["times"]);
    }

    timeslot_change(item){
        let cached = this.get_cart_cache(item.get("id"));
        if(cached){
            cached.last_api_call = 0;
            this.cache.cartCache[item.get("id")] = cached;
            this.save_io_data();
        }
    }

    get event_start_timestamp(){
        return this.event.starttimestamp;
    }

    get event_end_timestamp(){
        return this.event.endtimestamp;
    }

    get event_start_date_str(){
        return this.event.start_date;
    }
    get event_start_time_str(){
        return this.event.start_time;
    }
    get event_end_date_str(){
        return this.event.end_date;
    }
    get event_end_time_str(){
        return this.event.end_time;
    }
    get mobile_phone(){
        return this.customer.mobile_phone_number;
    }
    get home_phone(){
        return this.customer.home_phone_number;
    }
    get work_phone(){
        return this.customer.work_phone_number;
    }

    set venue_street(value){
        this.venue.street = value;
        this.save_io_data();
    }
    set venue_city(value){
        this.venue.city = value;
        this.save_io_data();
    }
    set venue_zip(value){
        this.venue.zip = value;
        this.save_io_data();
    }
    get venue_street(){
        return this.venue.street
    }
    get venue_city(){
        return this.venue.city;
    }
    get venue_zip(){
        return this.venue.zip;
    }
    get venue_state(){
        return this.venue.state;
    }

    get customer_email(){
        return this.customer.email;
    }

    set customer_email(value){
        this.customer.email = value;
        this.save_io_data();
    }
    set customer_street(value){
        this.customer.street = value;
        this.save_io_data();
    }
    set customer_city(value){
        this.customer.city = value;
        this.save_io_data();
    }
    set customer_zip(value){
        this.customer.zip = value;
        this.save_io_data();
    }
    set customer_state(value){
        this.customer.state = value;
        this.save_io_data();
    }
    set mobile_phone(value){
        this.customer.mobile_phone_number = value;
        this.save_io_data();
    }
    set home_phone(value){
        this.customer.home_phone_number = value;
        this.save_io_data();
    }
    set work_phone(value){
        this.customer.work_phone_number = value;
        this.save_io_data();
    }

    static fromObject(rawData) {
        return new IO_Data(rawData); // Call the constructor with the raw data
    }

    set last_api_call(timestamp){
        this.cache.last_api_call = timestamp;
        this.save_io_data();
    }
    set info_cache(rental){
        this.cache.info_cache = rental;
        this.save_io_data();
    }
    set cart_cache(cart_item_obj){
        this.cache.cart_cache = cart_item_obj;
        this.save_io_data();
    }
    get_info_cache(rentalid){
        return this.cache.infoCache[rentalid];
    }
    get_cart_cache(cart_id){
        return this.cache.cartCache[cart_id];
    }
    remove_from_cart_cache(cart_item){
        delete this.cache.cartCache[cart_item];
        this.save_io_data();
    }
    cached_item_needs_refreshed(id, type){
        return this.cache.needs_refreshed(id, type);
    }

    refresh_cached_item(id, type){

        if(type=="cart"){
            this.cache.cartCache[id].last_api_call = 0;
        }else if(type=="info"){
            this.cache.infoCache[id].last_api_call = 0;
        }
        this.save_io_data();
    }

    post_relevant_data(){
        let post_data = {};
        post_data.cart = this.cart;
        post_data.info = this.info;
        post_data.customer = this.customer;
        post_data.event = this.event;
        post_data.venue = this.venue;
        post_data.page_name = this.page_name;
        post_data.qid = this.qid;
        post_data.guid = this.guid;
        return post_data;
    }
}
var cart_info_flickity_enabled = false;
main();
function main(){
    /*<editor-fold defaultstate="collapsed" desc="On Ready">*/
    jQuery(document).ready(async function () {
        IoData = await initIoData();
        pallet_color1 = "var( --e-global-color-accent,green )";
        if (pallet_color1 == "rgba(0, 0, 0, 0)" || pallet_color1 == "rgb(255, 255, 255)") pallet_color1 = "rgb(25, 147, 35)";

        /*<editor-fold defaultstate="collapsed" desc="SimpleCart Init">*/
        simpleCart({
            currency: currency,
            cartColumns: [{
                view: "image",
                attr: "image",
                label: "Image"
            },
                {
                    attr: "name",
                    label: "Name"
                },
                {
                    attr: "encoded",
                    label: false
                },
                {
                    attr: "rentalid",
                    label: false
                },
                {
                    attr: "availability",
                    label: false,
                    view: "availability"
                },
                {
                    view: "decrement",
                    label: false,
                    text: "<i class='fa fa-minus' style='color:inherit'></i>"
                },
                {
                    view: "calculate_area",
                    label: false
                },
                {
                    view: "input",
                    attr: "quantity"

                },
                {
                    attr: "qtyincrement",
                    label: false
                },
                {
                    attr: "inputtype",
                    label: false
                },
                {
                    attr: "qtytype",
                    label: false
                },
                {
                    attr: "vendorid",
                    label: false
                },
                {
                    view: "increment",
                    label: false,
                    text: "<i class='fa fa-plus' style='color:inherit'></i>"
                },
                {
                    attr: "accessories",
                    label: false,
                    view:"accessories"
                },
                {
                    attr: "price",
                    label: "Price",
                    view: 'currency'
                },
                {
                    view: "remove",
                    label: false,
                    text: "<i class='fas fa-trash' style='color:" + pallet_color1 + "'></i>"
                },
                {
                    attr: "total",
                    label: "SubTotal",
                    view: 'currency'
                },
                {
                    attr: "timeslots",
                    label: false
                },
                {
                    attr: "timeslots-orig",
                    label: false
                },
                {
                    attr: "href",
                    label: false
                },
                {
                    attr: "linkqty",
                    label: false
                },
                {
                    attr: "acc_dd_parent_limit",
                    label: false
                }
            ],
            checkout: {
                type: "SendForm",
                method: "GET",
                url: io_wp_local_path + "/io_quoteform/",
                extra_data: {
                    /* name: decodeURIComponent("%%page%%".replace(/[+]/gi, " ")), */
                    //clear_rentals: "1",
                    selected_only: "1",
                    wp_checkout: "1"
                }
            }
        });

        simpleCart.bind('update', cart_onUpdate);
        simpleCart.bind('beforeSave', cart_hideTimepickerWrapper);
        simpleCart.bind('beforeRemove', cart_beforeRemove);
        simpleCart.bind('afterRemove', cart_afterRemove);
        simpleCart.bind('afterQtyChange', cart_afterQtyChange);
        simpleCart.bind('beforeCheckout', cart_beforeCheckout);
        simpleCart.bind('afterAdd', cart_afterAdd);
        simpleCart.bind('beforeAdd', cart_beforeAdd);
        simpleCart.bind('load', cart_afterLoad)
        /*</editor-fold>*/

        /* showAvail("%%name_encoded%%"); */
        let io_star_pic = document.querySelector("#io_star_pic");
        if (io_star_pic != null) {
            let io_star_src = io_star_pic.src;
            if (io_star_src.indexOf("0star") > -1 || io_star_src.indexOf("1star") > -1 || io_star_src.indexOf("2star") > -1 ||
                io_star_src.indexOf("3star") > -1) {
                io_star_pic.style.display = "none";
            }
        }

        /*<editor-fold desc="Build Thumb Images">*/
        /* Test For Broken Images */
        let img_box = document.querySelectorAll(".io_image_thumb");
        for (let i of img_box) {
            let io_img_src = i.src;
            if (io_img_src !== null) io_img_src = io_img_src.toLowerCase();
            let io_img_datasrc = i.getAttribute("data-src");
            if (io_img_datasrc === null) {
                io_img_datasrc = "";
            } else {
                io_img_datasrc = io_img_datasrc.toLowerCase();
            }
            if ((io_img_src.indexOf("io_noimage.png") >= 0 || io_img_datasrc.indexOf("io_noimage.png") >= 0) ||
                (io_img_src.indexOf(".jpg") == -1 &&
                    io_img_src.indexOf(".jpe") == -1 &&
                    io_img_src.indexOf(".png") == -1 &&
                    io_img_src.indexOf(".gif") == -1 &&
                    io_img_src.indexOf(".tif") == -1 &&
                    io_img_src.indexOf(".webp") == -1)){
                i.style.display = "none";
            }
        }
        /* hide thumb if only 1 */
        let img2 = document.querySelector("#io_img_thumb2");
        let img1 = document.querySelector("#io_img_thumb1");
        if (img2 == null && img1 != null) {
            document.querySelector("#io_img_thumb1").style.display = "none";
        }
        /*</editor-fold>*/

        let upsell_array = document.querySelectorAll(".io_upsell_li");
        count = 0;
        for (let i of upsell_array) {
            count++;
            let newButton = button_add.cloneNode(true);
            newButton.id = button_add.id + count;
            newButton.classList.remove("elementor-animation-grow");
            newButton.classList.add("elementor-animation-shrink");

            let button_wrap = document.createElement("div");
            button_wrap.classList.add("elementor-widget-button");
            button_wrap.classList.add("io_upsell_button");
            button_wrap.appendChild(newButton);
            i.appendChild(button_wrap);
        }

        if (io_deliverymethod == "on" && jQuery(".calDeliveryMethodLabel").length == 0) {
            let delivery_method_container = jQuery("#ioDeliveryMethodContainer").first();
            delivery_method_container.append('<span class="calDeliveryMethodLabel">Select Delivery Method</span>');
            let delivery_method_html = '<select class="ioDeliveryMethods" onchange="deliveryMethodSelected()">';
            let delivery_methods = Object.keys(io_delivery_methods)
            for (const index in delivery_methods) {
                if (!io_delivery_methods_restrict) {
                    delivery_method_html += '<option value="' + delivery_methods[index] + '">' + delivery_methods[index] + '</option>';
                    if (index == 0 && !getCookie("io_delivery_method")) setCookie("io_delivery_method", delivery_methods[index], 14);
                } else if (!io_delivery_methods_restrict.includes(io_delivery_methods[delivery_methods[index]]["id"])) {
                    delivery_method_html += '<option value="' + delivery_methods[index] + '">' + delivery_methods[index] + '</option>';
                    if (index == 0 && !getCookie("io_delivery_method")) setCookie("io_delivery_method", delivery_methods[index], 14);
                }
            }
            delivery_method_container.append(delivery_method_html);
            delivery_method_container.show();
            if (getCookie("io_delivery_method")) {
                jQuery(".ioDeliveryMethods").val(getCookie("io_delivery_method"));
            }
        } else {
            setCookie("io_delivery_method", "", 14);
        }

        let allow_same_day = 1;
        if (io_cartAllowSameDay == "on") {
            allow_same_day = 0;
        }

        /*<editor-fold desc="Cart Calandar and Time Settings Setup">*/
        //var fullmonth_array = jQuery.datepicker.regional["en"].monthNames;
        jQuery("#cartCalendar").datepicker({
            changeMonth: true,
            changeYear: true,
            //monthNamesShort : fullmonth_array,
            dateFormat: dateFormat,
            rangeSelect: true,
            numberOfMonths: 1,
            stepMonths: 1,
            prevText: "<< Previous Months",
            nextText: "Next Months >>",
            speed: "fast",
            showOn: "both",
            onChangeMonthYear: cal_onChangeMonthYear,
            onSelect: cal_onSelect,
            buttonText: "Calendar",
            minDate: allow_same_day,
            firstDay: 0
        });
        jQuery(".ui-datepicker-trigger").hide();
        if (restrictTimes) {
            jQuery(".timepicker").timepicker({
                startTime: new Date(0, 0, 10, 0, 0, 0),
                endTime: new Date(0, 0, 0, 20, 0, 0, 0),
                minTime: restrictTimeStart,
                maxTime: restrictTimeEnd,
                /*show24Hours: $show24Hours,*/
                timeFormat: timeFormat,
                separator: ":",
                className: "elementor-widget-text-editor",
                step: 15,
                disableTouchKeyboard: true
            }).keypress(function (e) {
                e.preventDefault();
            });
        } else {
            jQuery(".timepicker").timepicker({
                startTime: new Date(0, 0, 10, 0, 0, 0),
                endTime: new Date(0, 0, 0, 20, 0, 0, 0),
                /*show24Hours: $show24Hours,*/
                timeFormat: timeFormat,
                separator: ":",
                className: "elementor-widget-text-editor",
                step: 15,
                disableTouchKeyboard: true
            });
        }

        /* if we have company wide timeslots, alter time select in cart. Do this only if we are set to single day only */
        if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day") {
            let time_select_container = jQuery("#ioCartTimeSelectContainer").first();
            time_select_container.empty();
            let selected_date_html = '<span style="margin-right: 5px !important" class="calTimeLabel">Date</span><i class="fas fa-calendar-check"></i><input style="margin-left: 5px !important" type="text" name="dateStart" class="ioCartDateInput" readonly="readonly" /><input style="display: none !important" type="text" name="dateEnd" class="ioCartDateInput" readonly="readonly" />'
            time_select_container.append(selected_date_html);
            time_select_container.append("<br>")
            time_select_container.append('<span class="calTimeLabel">Select Timeslot</span>');
            let timeslot_html = '<select class="ioCartCompanyTimeslots">';
            for (i = 0; i < io_company_timeslots.length; ++i) {
                timeslot_html += io_company_timeslots[i];
            }
            timeslot_html += "</select>"
            time_select_container.append(timeslot_html);

        }

        // Timeslot element on Quote Form
        const timeslotSelectElement = jQuery(".controls select[name=timeslot]");

        /* jQuery( ".datepicker" ).datepicker({dateFormat: "m/d/yy",minDate:0}); */
        /* jQuery( ".datepicker" ).val(getCookie("checkDate")); */
        start_date = IoData.event_start_date_str;
        end_date = IoData.event_end_date_str;
        start_time = IoData.event_start_time_str;
        end_time = IoData.event_end_time_str;
        jQuery("input[name=dateStart]").val(start_date);
        jQuery("input[name=dateEnd]").val(end_date);
        if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day" && getCookie("company_timeslot_selected")) {
            jQuery(".ioCartCompanyTimeslots").val(getCookie("company_timeslot_selected"));
            // Set it on the quote page too.
            timeslotSelectElement.val(getCookie("company_timeslot_selected"));
        } else {
            jQuery("input[name=timeStart]").val(start_time);
            jQuery("input[name=timeEnd]").val(end_time);
        }

        timeslotSelectElement.on('change', function() {
            // IO-31167: Upon timeslot change on Quote Form,
            // update timeslot cookie value for persistence
            if(this.value) {
                setCookie('company_timeslot_selected', this.value, 14);
            }
        });

        if (jQuery("input[name=dateEnd]").val() != "") {
            setCalBackground();
            jQuery("#cartSubtotal").html(simpleCart.toCurrency(simpleCart.total()));
            if (getCookie("dateApplied") === "true") calCancel();
            else {
                jQuery("input[name=dateStart]").val(getCookie("dateStart"));
                jQuery("input[name=dateEnd]").val(getCookie("dateEnd"));
                if(io_company_timeslots.length != 0 && io_cartdayselect == "single_day" && getCookie("company_timeslot_selected")){
                    jQuery(".ioCartCompanyTimeslots").val(getCookie("company_timeslot_selected"));
                }
                else if(io_force_blank_timepickers == "on")
                {
                    setCookie("timeStart", "", 14);
                    setCookie("timeEnd", "", 14);

                    jQuery('[name=timeStart]').val("");
                    jQuery('[name=timeEnd]').val("");
                }
                else{
                    jQuery("input[name=timeStart]").val(IoData.event_start_time_str);
                    jQuery("input[name=timeEnd]").val(IoData.event_end_time_str);
                }

                jQuery(".changeDateLinkWrapper").hide();
            }
        }
        /*</editor-fold>*/

        if ((window.innerWidth > 500 | window.location.href.indexOf("io_") > -1) && window.location.href.indexOf("io_contactform") == -1) {
            jQuery('a[href*="http"][rel*=img_group]').not("#io_img_big1").fancybox({
                "transitionIn": "none",
                "transitionOut": "none",
                "titlePosition": "over",
                "cyclic": true,
                helpers: {
                    title: {
                        type: "over"
                    }
                },
                beforeShow: function () {
                    this.title = (this.title ? "" + this.title + "" : "") + "Image " + (this.index +
                        1) + " of " + this.group.length;
                }
            });
        } else {
            let imageClick = document.querySelector(".io_product_picbox a#single_image");
            if (imageClick != undefined || imageClick != null) {
                imageClick.addEventListener("click", (e) => {
                    e.preventDefault();
                });
            }
        }
        jQuery("#io-dialog").dialog({
            autoOpen: false,
            resizable: false,
            modal: true,
            dialogClass: "noTitleStuff",
            width: 350,
            open: function () {
                jQuery(".ui-widget-overlay").bind("click", function () {
                    jQuery("#io-dialog").dialog("close");
                })
            }
        });

        /* change jquery calendar next/prev buttons to fa arrows w/matching site color */
        jQuery("#cartCalendar .ui-datepicker-prev").addClass("fas fa-arrow-left").css("color", pallet_color1);
        jQuery("#cartCalendar .ui-datepicker-next").addClass("fas fa-arrow-right").css("color", pallet_color1);

        /* hide sections if not set */
        if (jQuery(".io_product_circuits_right").first().text() == "0") {
            jQuery(".io_product_circuits_right,.io_product_circuits_left").hide();
        }
        if (jQuery(".io_city_list").html() == "") {
            jQuery(".io_landingpages").hide();
        }
        /* using this instead as it will handle custom ones added */
        let io_field_valbox = document.querySelector(".io_product_infobox");
        if (io_field_valbox != null || io_field_valbox != undefined) {
            let io_field_valarr = io_field_valbox.querySelectorAll(".io_product_detail_box");
            for (let i of io_field_valarr) {
                let check = i.querySelector("p:nth-child(2)");
                if (check != null && check.innerText == "") i.style.display = "none";
            }
        }

        /* Hide description if there is no description */
        desc_box = document.querySelector(".io_product_desc")
        if(desc_box != null && desc_box.innerText.length == 0 && desc_box.innerHTML.length == 0){
            desc_detail_box = desc_box.parentElement;
            desc_detail_box.style.display = "none";
        }

        if (document.querySelector(".io_product_reviewbox") != null) {
            if (document.querySelector(".io_product_reviewbox").innerText == "") {
                if (document.querySelector(".io_star_rating") != null) document.querySelector(".io_star_rating a").style.display = "none";
            }
        }

        let rid = jQuery(".io_product_container .item_rentalid").first().text();
        let regex = new RegExp("^io_product_price_.*_" + rid + "$");
        for (const price_index in io_prices) {
            if (regex.test(io_prices[price_index])) {
                use_weekday_weekend = false;
            }
        }

        /* hide end date input. */
        if (!multi_day) {
            /* TODO: Need to wait and see if this is necessary. If so needs to be more involved than this. */
            /* jQuery("input[name=dateEnd]").style("visibility", "hidden"); */
        }
        /* Call page avail now so we can display live price if its enabled */
        setTimeout(function(){
            if(jQuery(".io_acc_accessorydd").text()==1 && jQuery(".io_acc_ispackage").text()!=1){
                jQuery("#bookNowBtn").removeClass("item_add").addClass("item_add_off").trigger("classChange");
                checkAvailPageOnly();
            }else{
                checkAvailPageOnly();
            }
        },50);

        /* Adjust picbox for header heights */
        setTimeout(adjustPicBoxForHeader, 500);

        /* Show buttons for distance charge check if the setting is on. Hide or show map button if applicable*/
        if (io_distance_charge) {
            jQuery(".delivery_charge_check_container").show();
            jQuery(".calc_price_with_map_container").hide();
            jQuery(".checkDeliveryCartContainer").show();
        } else {
            jQuery(".delivery_charge_check_container").hide();
            jQuery(".calc_price_with_map_container").hide();
            jQuery(".checkDeliveryCartContainer").hide();
        }
        if (io_brand == "EH") {
            jQuery(".delivery_charge_check_container").hide();
            jQuery(".eh_additional_description").show();
        }
        if (jQuery(".io_product_infobox .item_inputtype").text() === "Map") {
            jQuery(".delivery_charge_check_container").hide();
            jQuery(".checkDeliveryCartContainer").hide();
            jQuery(".calc_price_with_map_container").show();
        }

        /* If we have delivery set in cookie, be sure to show the charge in the cart. */
        if (getCookie("deliveryFee") && simpleCart.items().length > 0) {
            setDeliverySubtotal(getCookie("deliveryFee"));
            jQuery("#deliverSubtotalContainer").show();
            jQuery("#checkDeliveryMessage").hide();
        } else {
            jQuery("#deliverSubtotalContainer").hide();
        }

        /* moved back here for IO-22561 */
        if (simpleCart.items().length > 0) {
            let headerBookButton = jQuery("a[href$='io_quoteform/']");
            headerBookButton.addClass("ioCart_link");
            headerBookButton.attr("href", "javascript:;");
        }
        jQuery(".cartInfo").unbind("click").one("click", function (event) {
            event.stopPropagation();
            event.stopImmediatePropagation();
            cartShow();
        });
        jQuery(".ioCart,.ioCart_link").unbind("click").one("click", function (event) {
            event.stopPropagation();
            event.stopImmediatePropagation();
            cartShow();
        });

        /* hide if click outside cart */
        jQuery(document).mouseup(function (e) {
            var container = jQuery("#cartPopover");
            var cartButton = jQuery(".cartInfo, .ioCart, .ioCart_link");
            var addButton = jQuery(".item_add");
            var timePicker = jQuery(".ui-timepicker-wrapper");

            if (jQuery(".cartInfo, .ioCart, .ioCart_link").hasClass("open")) {
                if(!container.is(e.target) && container.has(e.target).length === 0 && !cartButton.is(e.target) && cartButton.has(e.target).length === 0 && !addButton.is(e.target) &&  addButton.has(e.target).length === 0 && !timePicker.is(e.target) &&  timePicker.has(e.target).length === 0 && !jQuery(".address_entry").is(e.target) &&  jQuery(".address_entry").has(e.target).length === 0){
                    cartHide();
                }
            }
        });

        if (!IoData.venue_state && io_default_state) {
            IoData.venue_state = io_default_state;
        }
        if (country != "US") {
            jQuery("#io_cd_state").replaceWith('<input id="io_cd_state" style="display: table-cell" name="state" type="text"></input>');
            jQuery("#io_cdl_zip_label").text("Postal code");
            if (country == "CA") {
                jQuery("#io_cdl_state_label").text("Province");
            } else if (country == "AU") {
                jQuery("#io_cdl_city_label").text("Suburb");
            }
        } else {
            jQuery("#io_cd_zip").attr("type", "number");
        }
        /* Set up on change events to stop end timepickers from allowing users to pick times before start time */
        setTimeout(restrictEndTimepickers, 500);
        if(io_hide_end_time == "on" && io_default_duration > 0){
            jQuery('[name="timeEnd"]').parent().hide();
            // Hide end time stuff on checkout page and in the text.
            jQuery(".io_event_body_time .control-group:nth-child(2)").hide();
            jQuery(".io_event_body_time_display_text").text(jQuery(".io_event_body_time_display_text").text().replace(/\s*→.*/, ""))
            jQuery('[name="timeStart"]').change(function(){
                const regex = /^(\d{1,2}):(\d{2})(?:\s*([AP]M))?$/i;
                const match = this.value.match(regex);

                let hours = parseInt(match[1], 10);
                const minutes = parseInt(match[2], 10);
                const period = match[3] ? match[3].toUpperCase() : null;

                if (period) {
                    if (period === "PM" && hours !== 12) hours += 12;
                    if (period === "AM" && hours === 12) hours = 0;
                }

                const baseDate = new Date(1970, 0, 1, hours, minutes);
                const newTime = new Date(baseDate.getTime() + io_default_duration * 3600000);

                if (period) {
                    // 12-hour
                    let newHours = newTime.getHours();
                    const newMinutes = newTime.getMinutes();
                    const newPeriod = newHours >= 12 ? "PM" : "AM";
                    newHours = newHours % 12;
                    if (newHours === 0) newHours = 12;
                    let end_time = `${newHours}:${newMinutes.toString().padStart(2, "0")} ${newPeriod}`;
                    jQuery('[name="timeEnd"]').val(end_time);
                } else {
                    // 24 hour
                    let end_time = `${newTime.getHours().toString().padStart(2, "0")}:${newTime.getMinutes().toString().padStart(2, "0")}`;
                    jQuery('[name="timeEnd"]').val(end_time);
                }
            });
        }

        /* If we have a custom message in cart, display it. */
        if (io_cart_message) {
            show_cart_message();
        }

        /* code for day select in cart */
        set_day_select();
        endDisplay();

        checkRestrictedDeliveries()
        /* If we are using the information gathering tool, we do not want to show this message. */
        if (live_pricing_is_on() && io_info_required == "off") {
            if (!IoData.event_time_set() && io_always_display_live_price != "on") {
                jQuery("#item_live_price_time_set_message").show();
            } else {
                jQuery("#item_live_price_time_set_message").hide();
            }
        }


        /* Check if information gathering header exists. If it does, Remove set even button and add some classes on onclicks */
        if (jQuery("#ioInfoHeader").length) {
            remove_set_event_buttton();
            add_classes_and_onClicks();
            header_increment_step();
        }

        /* If they have same day selection allowed, need to update checkout page datepicker on delay to make sure it works */
        if (io_cartAllowSameDay == "on") {
            setTimeout(allow_same_day_select_on_checkout, 500);
        }

        if (io_info_required_data && io_info_required == "on") {
            let io_required_data = io_info_required_data;
            jQuery("#ioAdditonalInformationContainer").show();
            for (const [data, value] of Object.entries(io_required_data)) {
                if (value == 1) {
                    jQuery("#io_info_modal_" + data).css("display", "inline-flex")
                    jQuery("#io_im_" + data).val(getCookie(data));
                }
            }
            show_or_hide_required_info_message()
        }
        if (jQuery(".bootstrap-timepicker").length == 0) {
            if (!/Mobi|Android/i.test(navigator.userAgent)) {
                jQuery("#cartPopover").scroll(function () {
                    jQuery("[name=timeStart]").timepicker("hide");
                    jQuery("[name=timeEnd]").timepicker("hide");
                });
                jQuery(window).scroll(function () {
                    jQuery("#cartPopover [name=timeStart]").timepicker("hide");
                    jQuery("#cartPopover [name=timeEnd]").timepicker("hide");
                });
            }
        }

        if (jQuery(".io_product_infobox .item_inputtype").text() == "Map") {
            simpleCart.items().forEach(function (item, index) {
                if (item.get("rentalid") === jQuery(".io_product_infobox .item_rentalid").text()) {
                    if (item.get("quantity") > 1) {
                        let units;
                        if (jQuery(".io_product_infobox .item_qtytype").text() == "Area") {
                            units = "sq meters"
                            if (country === "US") units = "sq feet"
                        } else if (jQuery(".io_product_infobox .item_qtytype").text() == "Perimeter") {
                            units = "meters"
                            if (country === "US") units = "feet"
                        }
                        set_price_on_item_page(units, item.get("quantity"));
                    }
                }
            });
        }
        /* IO-21808 */
        jQuery(".io_product_price_box").each(function () {
            let classes = jQuery(this).attr("class");
            jQuery(this).attr("class", classes.replace(":", "_"));
        });

        /* Set time instructions (IO-21496) */
        if(!jQuery('[name="dateStart"]').val()) {
            set_cart_time_instructions();
        }


        if ( any_cart_info_settings_on() ) {
            jQuery("#cartPartyBuilderFormContainer").show()

            if(io_cart_party_planner_email === "off" || !io_cart_party_planner_destination){
                jQuery("#cartPartyBuilderEmailContainer").remove();
            }
            if(io_cart_current_specials_phone === "off" || !io_cart_current_specials_destination){
                jQuery("#cartPartyBuilderPhoneContainer").remove();
            }
            if(io_distancecharge === "off"){
                jQuery("#cartPartyBuilderAddressContainer").remove();
            }
        }

        if (io_brand == "PW") {
            jQuery(".io_product_price_box").attr("style", "display: none !important;");
            jQuery(".io_product_price_sqfoot").attr("style", "display: grid !important;");
        }

        //setTimeout(simpleCart.init, 100);
        if(jQuery("#cartPartyBuilderFormContainer").children().length > 1){
            cart_info_flickity_enabled = true
            jQuery("#cartPartyBuilderFormContainer").flickity({
                wrapAround: true,
                draggable: false,
                cellAlign: 'center',
                //autoPlay: 3000,
                pageDots: false,
                groupCells: false,
                resize: true,
                prevNextButtons: true
            });
        }

        if(IoData.customer_email){
            try{
                jQuery("#cartPartyBuilderEmailInput").val(IoData.customer_email);
                if(cart_info_flickity_enabled){
                    jQuery("#cartPartyBuilderFormContainer").flickity("next", true, true);
                }
            }catch (e) {console.warn(e)}

        }
        if(IoData.mobile_phone){
            try{
                jQuery("#cartPartyBuilderPhoneInput").val(IoData.mobile_phone);
                if(cart_info_flickity_enabled) {
                    jQuery("#cartPartyBuilderFormContainer").flickity("next", true, true);
                }
            }catch (e) {console.warn(e)}
        }
        if(IoData.venue_street){
            try{
                jQuery("#cartPartyBuilderStreetInput").val(IoData.venue_street);
            }catch (e) {console.warn(e)}
        }
        if(IoData.venue_city){
            try{
                jQuery("#cartPartyBuilderCityInput").val(IoData.venue_city);
            }catch (e) {console.warn(e)}
        }
        if(IoData.venue_zip){
            try{
                jQuery("#cartPartyBuilderZipInput").val(IoData.venue_zip);
            }catch (e) {console.warn(e)}
        }
        if(IoData.venue_state){
            try{
                var stateInput = jQuery("#cartPartyBuilderStateInput");
                if(stateInput.length > 0){
                    // Check if it's a select element
                    if(stateInput.is('select')){
                        // Set the selected option for select dropdown
                        stateInput.find('option').prop('selected', false); // Deselect all options first
                        stateInput.find('option[value="' + IoData.venue_state + '"]').prop('selected', true);
                    } else {
                        // Set the value for text input
                        stateInput.val(IoData.venue_state);
                    }
                }
            }catch (e) {console.warn(e)}
        }

        if(IoData.event_time_set()){
            close_time_select();
            jQuery("#cartDateRange").html(smartFormatDateRange())
        }

        if(party_planner_all_address_set() && cart_info_flickity_enabled){
            jQuery("#cartPartyBuilderFormContainer").flickity("next", true, true);
        }
        if(all_party_planner_info_gathered()){
            jQuery("#cartPartyBuilderFormContainer").hide();
        }

        jQuery(".io_item2_list_inner").each(function (){
            rid = jQuery(this).find(".item_rentalid").text();
            acc = io_accessory_data[rid];
            if(acc){
                jQuery(this).append('<p class="item_accobj" style="display:none;">'+JSON.stringify(acc)+'</p>');
            }
        });
        jQuery(".io_product_infobox").each(function (){
            rid = jQuery(this).find(".item_rentalid").text();
            acc = io_accessory_data[rid];
            if(acc){
                jQuery(this).append('<p class="item_accobj" style="display:none;">'+JSON.stringify(acc)+'</p>');
            }
        });

        jQuery(document).on("change", ".io_cust_email", set_customer_email);
        jQuery(document).on("change", ".io_cust_mobile_phone,.io_cust_home_phone,.io_cust_work_phone", set_customer_phone);
        jQuery(document).on("change", ".io_venue_address,.io_venue_city,.io_venue_zip,io_venue_state" +
            ".io_cust_address,.io_cust_city,.io_cust_zip,.io_cust_state", set_address);

        var times = getAvailTimes();
        if(jQuery(".io_product_infobox").length > 0){
            var times = getAvailTimes();
            getUpsellsCall(times[0],times[1],times[2],jQuery(".io_product_infobox .item_rentalid").first().text(), updatePageUpsell);
        }

        document.addEventListener("click", function (event) {
            // If the clicked element is a dropdown toggle, handle toggling.
            if (event.target.matches(".io-cart-dropdown-toggle")) {
                event.preventDefault();
                const cart_dropdown = event.target.parentElement;
                cart_dropdown.classList.toggle("show");
            } else {
                // Close any currently open dropdowns if clicked elsewhere.
                document.querySelectorAll(".io-cart-dropdown.show").forEach(function (cart_dropdown) {
                    cart_dropdown.classList.remove("show");
                });
            }
        });

        if(io_hide_zero == 1){
            jQuery(".io_product_price_top_left").each(function (){
                if(Number(this.innerText.replace(/[^0-9.-]+/g,"")) == 0){
                    jQuery(this).parent().attr('style','display:none !important');
                }
            });
            jQuery(".io_product_price_left").each(function (){
                if(Number(this.innerText.replace(/[^0-9.-]+/g,"")) == 0){
                    jQuery(this).parent().attr('style','display:none !important');
                }
            });
        }
      if (io_categoryVariantImages == 'on'){
          jQuery(".io_category_thumbox").show();
          jQuery('.view-product-button').addClass('view-product-button2')
      }
        let giftcard_value = jQuery(".item_giftcardvalue");
        if(giftcard_value && giftcard_value.text()){
            jQuery(".delivery_charge_check_container").hide();
        }
        if (io_customer_geolocation == 'on') initializeGeolocation();

        updateAddToCartButtons();
        // end of on-ready
    });
    /*</editor-fold>*/
}

/*<editor-fold defaultstate="collapsed" desc="Rental Page Functions">*/
function updatePageUpsell(data){
    let page_carousel = jQuery(".page-carousel");
    data.forEach(function(upsell){
      cell = createPageCarouselCell(upsell["image"], upsell["name"], upsell["page"], upsell["rental_id"]);
      page_carousel.append(cell);
    });
    makeCarousel(page_carousel);
    setTimeout(pageFlickityRefresh, 500);
    if(io_upsell_price == "on"){
      let times = getAvailTimes();
      let rental_objs = getUpsellIDforPrice();
      IoData.info = rental_objs;
      createOrUpdateLead("info", ["price"], true);
    }
  }
function createPageCarouselCell(image, name, page, rental_id){
    cell = `<div class="io_page_carousel_cell"> <a href="`+page+`" class="page-carousel-link"> <img class="page-carousel-image skip-lazy" src="`+image+`"> <p class="page-carousel-name"> `+name+` </p> <span class="page-carousel-rid" id="rid`+rental_id+`" style="display:none">`+rental_id+`</span> </a> </div>`;
    return cell;
}
function pageFlickityRefresh(){
    jQuery(".page-carousel").flickity("resize");
}
function order_acc_obj_relate(){
    let new_acc_obj_relate = new Map();
    if(!jQuery.isEmptyObject(acc_obj_relate) && !jQuery.isEmptyObject(acc_obj_order)){
      for(const [index, rid] of Object.entries(acc_obj_order)){
        new_acc_obj_relate.set(rid, acc_obj_relate[rid])
      }
    }
    return new_acc_obj_relate
}
/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Session Storage Functions">*/
async function getLead(io_data){
    let url = io_rest_lead_url;
    const post_data = {guid:io_data.guid, lead:io_data.post_relevant_data(), recalc:[], type:"", action:"get"};
    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(post_data)
    });
    const data = await response.json();
    return data;
}

async function updateLead(type, recalc=[], upsell=null){
    let url = io_rest_lead_url;

    let post_data = {guid:IoData.guid, lead:IoData.post_relevant_data(), recalc:recalc, type:type, action:"update"}
    if(type=="cart"){
        ioCartLoaderIncrement();
    }
    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(post_data)
    });
    const data = await response.json();
    if(type=="cart"){
        ioCartLoaderDecrement();
    }
    IoData.last_api_call = Date.now();
    IoData[type] = [];
    for(let i = 0; i < data["lead"][type].length; ++i){
        let rental_obj = IO_Rental.fromObject(data["lead"][type][i]);
        IoData[type].push(rental_obj);
    }
    if(data.cart_id){
        IoData.qid = data.cart_id
    }
    if(data.uid){
        IoData.uid = data.uid;
    }
    IoData.save_io_data();
    if(type=="cart"){
        updateCartAvail();
    }else if(type=="info" && !upsell){
        updatePageAvail();
    }else if(type=="info" && upsell){
        displayUpsellPrices()
    }
}

async function createLead(type, data){
    let url = io_rest_lead_url;
    const post_data = {guid:data.guid, lead:data.post_relevant_data(), recalc:[], type:type, action:"create"};
    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(post_data)
    });
    const io_data_result = await response.json();
    if(io_data_result.cart_id){
        IoData.qid = io_data_result.cart_id
    }
    return io_data_result.lead;
}

function createOrUpdateLead(type, recalc=[], upsell=null){
    if(IoData[type].length > 0){
        if(IoData.guid){
            updateLead(type, recalc, upsell)
        }else{
            let data = new IO_Data();
            data.guid = getCookie("guid");
            createLead(type, data);
        }
    }
}

async function initIoData(){
    return await buildIoData()
};

async function buildIoData(){
    if(!sessionStorage.io_data){
        let data = new IO_Data();
        if(getCookie("guid")){
            data.guid = getCookie("guid");
        }else{
            //Get a guid from IO.
            data.guid = await fetchAndSetCookie("guid");
        }
        let get_lead_response = await getLead(data);
        let io_data_result = typeof get_lead_response === 'string' ? JSON.parse(get_lead_response) : get_lead_response;
        data = IO_Data.fromObject(io_data_result.lead);
        if(io_data_result.cart_id){
            data.qid = io_data_result.cart_id
        }
        if(io_data_result.uid){
            data.uid = io_data_result.uid
        }
        data.save_io_data();
        return data;
    }else{
        return set_io_data_from_string_obj(sessionStorage.io_data)
    }
}

function set_io_data_from_string_obj(io_data_str){
    let io_data_obj = Object.assign(new IO_Data(), JSON.parse(io_data_str));
    //Iterate through cart and info and make them IO_Rental objects
    io_data_obj.event = set_io_event_obj_from_literal_obj(io_data_obj.event);
    io_data_obj.venue = set_io_venue_obj_from_literal_obj(io_data_obj.venue);
    io_data_obj.customer = set_io_customer_obj_from_literal_obj(io_data_obj.customer);
    io_data_obj.cache = set_io_cache_obj_from_literal_obj(io_data_obj.cache);
    return io_data_obj;
}

function set_io_event_obj_from_literal_obj(io_event_literal_obj){
    return Object.assign(new IO_Event(), io_event_literal_obj);
}

function set_io_venue_obj_from_literal_obj(io_venue_literal_obj){
    let venue_obj = Object.assign(new IO_Venue(), io_venue_literal_obj);
    venue_obj.address = set_io_address_obj_from_literal_obj(venue_obj.address);
    return venue_obj;

}

function set_io_address_obj_from_literal_obj(io_address_literal_obj){
    return Object.assign(new IO_Address(), io_address_literal_obj);
}

function set_io_customer_obj_from_literal_obj(io_customer_literal_obj){
    let customer_obj = Object.assign(new IO_Customer(), io_customer_literal_obj);
    customer_obj.address = set_io_address_obj_from_literal_obj(customer_obj.address);
    customer_obj.phones = set_customer_phones_from_literal_obj(customer_obj.phones);
    return customer_obj
}

function set_io_cache_obj_from_literal_obj(io_cache_literal_obj){
    let cache_obj = Object.assign(new IO_Cache(), io_cache_literal_obj);
    return cache_obj;
}

function set_customer_phones_from_literal_obj(customer_phones_obj){
    customer_phones_obj.mobile = Object.assign(new IO_Phone(), customer_phones_obj.mobile);
    customer_phones_obj.home = Object.assign(new IO_Phone(), customer_phones_obj.home);
    customer_phones_obj.work = Object.assign(new IO_Phone(), customer_phones_obj.work);
    return customer_phones_obj;
}

function set_customer_email(){
    let valid_regex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    let email = jQuery(this).val();
    if (email) {
        if (email.match(valid_regex)) {
            IoData.customer_email = email
            //window.open(io_cart_party_planner_destination, '_blank').focus();
        }
    }
}

function set_customer_phone(){
    let valid_regex = /^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/;
    let phone_num = jQuery(this).val();
    if (phone_num) {
        if (phone_num.match(valid_regex)) {
            let phone_type = jQuery(this).attr("class").split("_")[2]+"_phone";
            IoData[phone_type] = phone_num;
        }
    }
}

function set_address(){
    let field = jQuery(this).val();
    if(field){
        let field_type = jQuery(this).attr("class").split("_")[2];
        switch (field_type){
            case 'io_venue_address':
                IoData.venue_street = field;
                break;
            case 'io_venue_city':
                IoData.venue_city = field;
                break;
            case 'io_venue_zip':
                IoData.venue_zip = field;
                break;
            case 'io_venue_state':
                IoData.venue_state = field;
                break;
            case 'io_cust_address':
                IoData.customer_street = field;
                break;
            case 'io_cust_city':
                IoData.customer_city = field;
                break;
            case 'io_cust_zip':
                IoData.customer_zip = field;
                break;
            case 'io_cust_state':
                IoData.customer_state = field;
                break;
        }
    }
}
/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Party Planner Functions">*/

function all_party_planner_info_gathered() {
    // If we have these settings enabled, and they are not yet set then consider this false.
    // If the settings are off, and they aren't set, we don't care in that case consider it true.
    let email_gathered = true;
    let phone_gathered = true;
    let address_gathered = true;
    if(io_cart_party_planner_email === "on" && io_cart_party_planner_destination && !IoData.customer_email){
        email_gathered = false;
    }
    if(io_cart_current_specials_phone === "on" && io_cart_current_specials_destination && !IoData.mobile_phone){
        phone_gathered = false;
    }
    if(io_distancecharge === "on" && !party_planner_all_address_set()){
        address_gathered = false
    }
    return email_gathered && phone_gathered && address_gathered;
}

function party_planner_all_address_set(){
    return IoData.venue_street && IoData.venue_city && IoData.venue_zip;
}

function io_party_planner_address_submit() {
    let street = jQuery("#cartPartyBuilderStreetInput").val();
    let city = jQuery("#cartPartyBuilderCityInput").val();
    let zip = jQuery("#cartPartyBuilderZipInput").val();
    let state = jQuery("#cartPartyBuilderStateInput").val();
    if (street) {
        IoData.venue_street = street;
    }
    if (city) {
        IoData.venue_city = city;
    }
    if(zip){
        IoData.venue_zip = zip;
    }
    if(state){
        IoData.venue_state = state;
    }
    ioCartLoaderIncrement();
    createOrUpdateLead("cart")
    ioCartLoaderDecrement();

    if(party_planner_all_address_set() && cart_info_flickity_enabled){
        jQuery("#cartPartyBuilderFormContainer").flickity("next", true)
    }
    if(all_party_planner_info_gathered()){
        jQuery("#cartPartyBuilderFormContainer").hide();
    }
}

function io_party_planner_phone_submit() {
    let valid_regex = /^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/;
    let phone = jQuery("#cartPartyBuilderPhoneInput").val();
    if (phone) {
        if (phone.match(valid_regex)) {
            IoData.mobile_phone = phone;
            ioCartLoaderIncrement();
            createOrUpdateLead("cart");
            ioCartLoaderDecrement();
            if(cart_info_flickity_enabled){
                jQuery("#cartPartyBuilderFormContainer").flickity("next", true);
            }
            //window.open(io_cart_party_planner_destination, '_blank').focus();
        } else {
            jQuery("#cartPartyBuilderPhoneWarning").show();
        }
    } else {
        jQuery("#cartPartyBuilderPhoneWarning").show();
    }
    if(all_party_planner_info_gathered()){
        jQuery("#cartPartyBuilderFormContainer").hide();
    }
}

function io_party_planner_email_submit() {
    let valid_regex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    let email = jQuery("#cartPartyBuilderEmailInput").val();
    if (email) {
        if (email.match(valid_regex)) {
            IoData.customer_email = email;
            ioCartLoaderIncrement();
            createOrUpdateLead("cart");
            ioCartLoaderDecrement();
            if(cart_info_flickity_enabled) {
                jQuery("#cartPartyBuilderFormContainer").flickity("next", true);
            }
            //window.open(io_cart_party_planner_destination, '_blank').focus();
        } else {
            jQuery("#cartPartyBuilderEmailWarning").show();
        }
    } else {
        jQuery("#cartPartyBuilderEmailWarning").show();
    }
    if(all_party_planner_info_gathered()){
        jQuery("#cartPartyBuilderFormContainer").hide();
    }
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Helper Functions">*/
function phraseUpdateCount(inputElement)
{
    //read the text and strip out spaces
    const fullText = inputElement.value;
    const lettersOnly  = fullText.replace(/\s+/g, "");
    const count = lettersOnly.length;

    const cookieKey = inputElement.classList[0];

    document.querySelector(".item_quantity").textContent = count;

    setCookie(cookieKey, fullText, 45);
}

function set_day_select(){
    if (io_cartdayselect == "dropdown_options" && io_multidayquote === "on") {
        if(!jQuery("#whatday").length){
            jQuery(".ui-datepicker-title").addClass("day-options-on").append(make_what_day_select());
        }
        saved_whatday = getCookie("io_whatday");
        if (saved_whatday) jQuery("#whatday").val(saved_whatday);
    }
}

function make_what_day_select(){
    return `<div id="div-overnight">
        <select style="color:black;" name="whatday" id="whatday" onchange="endDisplay()">
            <option value="Same Day" selected="selected">Single Day</option>
            <option value="Overnight">Overnight</option>
            <option value="Multi-Day">Multi-Day</option>
        </select>
      </div>`;
}
function any_cart_info_settings_on() {
    return (io_cart_party_planner_email === "on" && io_cart_party_planner_destination) ||
        (io_cart_current_specials_phone === "on" && io_cart_current_specials_destination) ||
        io_distancecharge === "on";
}

function rid_in_batch(rid, batch_ids) {
    let result = batch_ids.filter(function (batch) {
        if (batch.includes(this)) return true;
    }, rid);
    return result
}

function set_cart_time_instructions() {
    /* Making it clearer that customers need to set the time in order to see pricing and availability. */
    let instructions_container = jQuery("<p id=\"ioCartTimeInstructions\"></p>");
    let instructions = "";

    if (multi_day) {
      instructions += "Select your event date or date range using the calendar";
    } else {
        instructions += "Select your event date using the calendar";
    }
    instructions += ".";
    instructions_container.text(instructions);
    jQuery("#cartCalendar").append(instructions_container);
}

function live_pricing_is_on() {
    /*
    Checks to see if live pricing is on. Assumes it is on unless one of the following conditions:
       The setting Hide Live Price is on.
       The setting Show Weekend/Weekday Pricing is off.
       Delivery method pricing is enabled by default.
       We are on an item page that uses delivery method pricing.
       Custom pricing is enabled by default.
       We are on an item page that uses custom pricing.
    */
    if (io_hide_live_prices == 1 ||
        io_weekEndPrice != "on" ||
        io_delivery_prices["default"].length != 0 ||
        jQuery(".io_product_infobox .item_rentalid").innerText in io_delivery_prices["override"] ||
        io_custom_prices["default"].length != 0 ||
        jQuery(".io_product_infobox .item_rentalid").innerText in io_custom_prices["override"]) {
        return false;
    }
    return true;
}

function allow_same_day_select_on_checkout() {
    jQuery(".jquery-datepicker").datepicker("option", "minDate", 0);
}

function show_or_hide_required_info_message() {
    if (io_info_required == "on") {
        if (!all_info_provided()) {
            jQuery("#io_all_prices").hide();
            jQuery("#item_additonal_info_open_message").show();
        } else {
            jQuery("#io_all_prices").show();
            jQuery("#item_additonal_info_open_message").hide();
        }
    }
}

function all_info_provided() {
    /* This is used for when the "Hide all pricing on page until information is provided" setting is on price settings. */
    let all_data_provided = true;
    let io_required_data = io_info_required_data;
    for (const [data, value] of Object.entries(io_required_data)) {
        if (value == 1) {
            if (!getCookie(data)) {
                all_data_provided = false
            }
        }
    }

    if (live_pricing_is_on() && !IoData.event_time_set()) {
        all_data_provided = false;
    }

    return all_data_provided;
}

function show_cart_message() {
    message_container = jQuery("#cartCustomMessage");
    message_container.html(io_cart_message);
    message_container.show();
}


function deliveryMethodSelected() {
    setCookie("io_delivery_method", jQuery(".ioDeliveryMethods option:selected").text(), 14);
    checkRestrictedDeliveries();
}

function adjustPicBoxForHeader() {
    /* For some reason its hard to get css with querySelector so we use jQuery to get the picbox. */
    pic_box = jQuery(".io_product_picbox");
    io_header = document.querySelector(".io_header");
    if (pic_box != null && pic_box.css("position") == "sticky") {
        if (io_header != null) {
            header_height = io_header.offsetHeight;
            pic_box.css("top", (10 + header_height).toString() + "px");
        } else {
            possible_headers = document.querySelectorAll("header,section")
            possible_headers.forEach((ele) => {
                if (ele.style.top == "0px" && (ele.style.position == "fixed" || ele.style.position == "sticky")) {
                    header = ele;
                    header_height = header.offsetHeight;
                    pic_box.css("top", (10 + header_height).toString() + "px");

                }
            });
        }
    }
}

function cart_times_all_set() {
    if (jQuery("#ioCartTimeSelectContainer [name=dateStart]").val() == "") {
        return false;
    }
    if (io_hidetimes === "off" || io_hidetimes === "") {
        if (jQuery("#ioCartTimeSelectContainer [name=timeStart]").val() == "") {
            return false;
        }
        if (jQuery("#ioCartTimeSelectContainer [name=timeEnd]").val() == "") {
            return false;
        }
    }

    return true;
}

function checkRestrictedDeliveries() {
    let items = simpleCart.items()
    let restrictions_found = false;
    for (i in items) {
        let rid = items[i].get("rentalid");
        if (typeof jQuery(".ioDeliveryMethods").val() != "undefined") {
            if (io_delivery_methods[jQuery(".ioDeliveryMethods").val()]["restricted"].includes(rid)) {
                jQuery("#deliveryMethodWarning").show();
                restrictions_found = true;
            }
        }
    }
    if (!restrictions_found) {
        jQuery("#deliveryMethodWarning").hide();
    }
}

function display_cart_warning(item) {
    let cart_warning_container = jQuery("#cartWarning");
    // Check if an event date if not we should tell them to set it.
    event_times = getAvailTimes();
    if (!event_times[0] || !event_times[1]) {
        cart_warning_container.text("Please set the date and time for your event above.");
      cart_warning_container.show();
        return false;
    }

    let item_name = item.get("name");
    let item_timeslots = item.get("timeslots");
    let timeslot_name = getTimeslotName(item_timeslots);

    let stop_loop = false;
    if (item_timeslots) {
        if (jQuery(item_timeslots).nodeName == "SELECT") {
            /* NOTE: It should not be possible for timeslots to be empty.
                   But in the event they somehow are, we should have this here. */
            /* timeslots */
            var timeslot_sel_range = jQuery(".item-timeslots [name=\"" + timeslot_name + "\"] option:selected").val();
            if (typeof timeslot_sel_range != "undefined") {
                var [start_time, end_time] = break_timeslot_sel_range(timeslot_sel_range);
            }
        } else {
            /*  timepickers */
            let [start_timepicker, end_timepicker] = get_cart_timepickers(timeslot_name);
            var start_time = start_timepicker.value;
            var end_time = end_timepicker.value;
        }
        if (!start_time || !end_time) {
            cart_warning_container.text("Please select a time range for the following item: " + item_name);
            cart_warning_container.show()
            stop_loop = true;
        }
    } else {
        cart_warning_container.text("Some items are not available on this date.");
        cart_warning_container.show()
    }
    return stop_loop
}

function setCookie(cname, cvalue, exdays) {
    // Store values in localStorage with an io_ prefix for uniqueness and emulate expiration
    try {
        var expiresAt = (typeof exdays === 'number' && exdays > 0)
            ? Date.now() + (exdays * 24 * 60 * 60 * 1000)
            : null;
        var payload = JSON.stringify({ v: String(cvalue), e: expiresAt });
        window.localStorage.setItem(cname, payload);
    } catch (e) {
        // Swallow errors to keep behavior similar to cookie writes silently failing
        console.log(e);
    }
}

function getCookie(cname) {
    // Read values from localStorage honoring expiration; return empty string if missing/expired
    try {
        var raw = window.localStorage.getItem(cname);
        if (!raw) return "";
        try {
            var obj = JSON.parse(raw);
            if (obj && typeof obj === 'object') {
                if (obj.e && Date.now() > obj.e) {
                    window.localStorage.removeItem(cname);
                    return "";
                }
                return (obj.v != null) ? String(obj.v) : "";
            }
        } catch (e) {
            return String(raw);
        }
        return "";
    } catch (e) {
        return "";
    }
}


async function fetchAndSetCookie(name) {
    const requestInit = { credentials: "include" };
    return fetch("https://rental.software/include/get_cookie.php?name=" + encodeURIComponent(name), requestInit)
        .then((res) => res.json())
        .then((data) => handleResponse(name, data));
}

function handleResponse(name, response) {
    var currentCookieValue = getCookie(name);
    if (!!response.value && currentCookieValue !== response.value) {
        setCookie(name, response.value, 14);
    }
    return response.value;
}

function break_timeslot_sel_range(timeslot_sel_range) {
    /* Takes a time range given by selected timeslot and gets the start and end time removing meridiem.*/
    timeslot_sel_arr = timeslot_sel_range.split(" - ");
    var start_time = timeslot_sel_arr[0].replace("am", " am").replace("pm", " pm").replace("  ", " ");
    var end_time = timeslot_sel_arr[1].replace("am", " am").replace("pm", " pm").replace("  ", " ");

    return Array(start_time, end_time);
}

function getAvailTimes() {
    /*
    Commonly used helper function. Accomplishes two things:
    Returns an array containing start_date, start_time, and event duration.
    Sets cookies for start and end date, and start and end time.

    Uses the inputs available in the cart if they are filled out, so dateStart, dateEnd, timeStart, and timeEnd.
    If timeslots are being used in cart it chooses the selected timeslot and breaks it on - and gets the start ane end time from that.
    */
    let start_date = jQuery("input[name=dateStart]").val();
    let end_date = jQuery("input[name=dateEnd]").val();
    if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day") {
        let cart_company_timeslot_selected = jQuery(".ioCartCompanyTimeslots option:selected").first().val();
        if (cart_company_timeslot_selected) {
            setCookie("company_timeslot_selected", cart_company_timeslot_selected, 14);
            cart_company_timeslot_selected = cart_company_timeslot_selected.split("-");
            var start_time = cart_company_timeslot_selected[0].trim();
            var end_time = cart_company_timeslot_selected[1].trim();
        }
    } else {
        var start_time = jQuery("input[name=timeStart]").val();
        var end_time = jQuery("input[name=timeEnd]").val();
    }

    if (start_date.length == 0) {
        start_date = IoData.event_start_date_str;
        end_date = IoData.event_end_date_str;
        start_time = IoData.event_start_time_str;
        end_time = IoData.event_end_time_str;
    }

    if(io_force_blank_timepickers != "on")  {
        if(start_time.length == 0) {
            start_time = start_default;
        }
        if(end_time.length == 0) {
            end_time = end_default;
        }
    }


    /* no past dates */
    if (start_date.length != 0 && convertDateStringtoDateObject(start_date, start_time) < new Date()) {
        start_date = "";
        end_date = "";
    }
    /* setCookie("checkDate", start_date, 14); */
    IoData.set_event_time(start_date, end_date, start_time, end_time);
    /* If we are using the information gathering tool, we do not want to show this message.*/
    if (live_pricing_is_on() && io_info_required == "off") {
        if (!IoData.event_time_set() && io_always_display_live_price != "on") {
            jQuery("#item_live_price_time_set_message").show();
        } else {
            jQuery("#item_live_price_time_set_message").hide();
        }
    }

    var newDate1 = convertDateStringtoDateObject(start_date, start_time);
    var newDate2 = convertDateStringtoDateObject(end_date, end_time);
    let time_duration = ((newDate2 - newDate1) / 3600) / 1000;
    return [start_date, start_time, time_duration];
}

function getAllRentalIDsFromCart() {
    let rental_ids = "";
    jQuery("[id^='cartItem_']").each(function () {
        children = this.children
        for (let i = 0; i < children.length; ++i) {
            if (children[i].className == "item-rentalid") {
                rental_ids += children[i].innerText + "|";
                break;
            }
        }
    });
    return rental_ids
}

function make_live_price_editable_time(times, delivery_method = null) {
    if (!delivery_method) delivery_method = getCookie("io_delivery_method");
    let ele_text = "";
    if (times[0]) ele_text = "on " + times[0] + " ";
    if (times[2] === 0) times[2] = 1;
    if (io_hidetimes != "on" && !isNaN(times[2])) ele_text += "for " + times[2] + " hours ";
    if (delivery_method) ele_text += "for " + delivery_method + ". ";
    ele_text += '<span style="cursor:pointer; color:blue; text-decoration:underline;" onclick=checkAvailDateClick()>edit</span>';
    return ele_text;
}

function determine_item_type_by_rid(rental_id){
    if(rental_id.includes(":")){
        if(rental_id.includes("_")){
            split_on_colon = rental_id.split(":");
            main_id = split_on_colon[0];
            split_on_underscore = split_on_colon[1].split("_");
            second_id = split_on_colon[0];
            if($main_id == $second_id){
                return 'linen (1 level)';
            }else{
                return 'linen (2 levels)';
            }
        } else{
            return 'separate_unit';
        }
    } else if(rental_id.split('_').length - 1 == 1){
        return 'accessory';
    } else if(rental_id.split('_').length - 1 == 2){
        return 'dropdown_accessory';
    }else{
        return 'item';
    }
}

function add_required_accessories(rental_obj){
    if(io_accessory_data[rental_obj.rentalid]){
        for(const [acc_id, accessory] of Object.entries(io_accessory_data[rental_obj.rentalid].accessories)){
            if(accessory.required > 0){
                acc_obj = new IO_Rental(acc_id, accessory.name, accessory.required);
                acc_obj.overrideprice = accessory.overrideprice;
                acc_obj.required = accessory.required;
                rental_obj.accessory = acc_obj;
            }
        }
    }
    return rental_obj;
}

function add_included_accessories(rental_obj, rental_id, rental_name){
    if (rental_id.includes("_")) {
        // Linen on item page.
        [main_id, after_colon] = rental_id.split(":");
        [second_id, third_id] = after_colon.split("_");
        if (second_id == main_id) {
            // 1 level
            [main_name, second_name] = rental_name.split(":");
            rental_obj.name = main_name;
            rental_obj.rentalid = main_id;
            accessory = new IO_Rental(third_id, second_name, rental_obj.qty);
            accessory.starttime = IoData.event_start_timestamp;
            accessory.endtime = IoData.event_end_timestamp;
            rental_obj.accessory = accessory;
        } else {
            // 2 levels
            [main_name, second_name, third_name] = rental_name.split(":");
            rental_obj.name = main_name;
            rental_obj.rentalid = main_id;
            second_accessory = new IO_Rental(second_id, second_name, rental_obj.qty);
            second_accessory.starttime = IoData.event_start_timestamp;
            second_accessory.endtime = IoData.event_end_timestamp;
            third_accessory = new IO_Rental(third_id, third_name, rental_obj.qty);
            third_accessory.starttime = IoData.event_start_timestamp;
            third_accessory.endtime = IoData.event_end_timestamp;
            second_accessory.accessory = third_accessory;
            rental_obj.accessory = second_accessory;
        }
    } else {
        // Separate unit on item page or category page.
        accessory_id = rental_id.split(":")[1];
        rental_obj.rentalid = rental_id.split(":")[0];
        accessory = new IO_Rental(accessory_id, rental_name, rental_obj.qty);
        accessory.starttime = IoData.event_start_timestamp;
        accessory.endtime = IoData.event_end_timestamp;
        rental_obj.accessory = accessory;
    }
    rental_obj.starttime = IoData.event_start_timestamp;
    rental_obj.endtime = IoData.event_end_timestamp;
    return rental_obj;
}

function is_element_in_viewport(el) {
    if (!el || !el.length) return false;
    let rect = el[0].getBoundingClientRect();
    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
}

function is_element_near_viewport(el, threshold) {
    if (!el || !el.length) return false;
    threshold = threshold || 300;
    let rect = el[0].getBoundingClientRect();
    return rect.top <= (window.innerHeight + threshold);
}
function create_category_rental_object($item) {
    let rental_id = $item.find(".item_rentalid").text();
    let rental_name = $item.find(".item_name").text();
    let rental_qty = parseInt($item.find(".item_qtyincrement").text());

    let rental_obj = new IO_Rental(rental_id, rental_name, rental_qty);
    rental_obj.rentalid_str = rental_id;

    if (rental_id.includes(":")) {
        rental_obj = add_included_accessories(rental_obj, rental_id, rental_name);
    }
    rental_obj = add_required_accessories(rental_obj);
    rental_obj.vendor = $item.find(".item_vendorid").text().trim();
    rental_obj.giftcard = $item.find(".item_giftcardvalue").text().trim();
    rental_obj.start_timestamp = IoData.event_start_timestamp;
    rental_obj.end_timestamp = IoData.event_end_timestamp;

    return rental_obj;
}

function observe_item_for_availability($item) {
    // Create global observer if it doesn't exist
    if (!window.io_availability_observer) {
        window.io_availability_observer = new IntersectionObserver(
            function(entries) {
                let items_to_check = [];

                entries.forEach(function(entry) {
                    if (entry.isIntersecting) {
                        let $element = jQuery(entry.target);
                        let $itemInner = $element.find('.io_item2_list_inner');

                        // Check if already processed
                        if ($itemInner.attr('data-avail-checked') === 'true') {
                            window.io_availability_observer.unobserve(entry.target);
                            return;
                        }

                        let rental_id = $itemInner.find(".item_rentalid").text();

                        if(IoData.cached_item_needs_refreshed(rental_id, "info")) {
                            let rental_obj = create_category_rental_object($itemInner);
                            items_to_check.push(rental_obj);
                        } else {
                            let cached_rental = IO_Rental.fromObject(IoData.get_info_cache(rental_id));
                            updatePageAvail([cached_rental]);
                        }

                        $itemInner.attr('data-avail-checked', 'true');
                        $element.addClass("io-checking-availability");
                        window.io_availability_observer.unobserve(entry.target);
                    }
                });

                if (items_to_check.length) {
                    IoData.info = items_to_check;
                    createOrUpdateLead("info", ["availability", "price"]);
                }
            },
            {
                root: null,
                rootMargin: '300px',
                threshold: 0.01
            }
        );
    }

    window.io_availability_observer.observe($item.parent()[0]);
}


/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Info Header Functions">*/
function init_date_timepicker_for_info_header() {
    jQuery(".ioInfoDatepicker").datepicker({
        changeMonth: true,
        changeYear: true,
        dateFormat: dateFormat,
        rangeSelect: true,
        numberOfMonths: 1,
        stepMonths: 1,
        speed: "fast",
        showOn: "both",
        onChangeMonthYear: cal_onChangeMonthYear,
        buttonText: "Calendar",
        minDate: 1,
        firstDay: 0
    });
    jQuery("#ioHeaderDateStart").datepicker("option", {
        onSelect: function () {
            set_info_header_end_date();
            saveInfoHeader();
            // Add more functions if needed
        }
    });

    if (restrictTimes) {
        jQuery(".ioInfoTimepicker").timepicker({
            startTime: new Date(0, 0, 10, 0, 0, 0),
            endTime: new Date(0, 0, 0, 20, 0, 0, 0),
            minTime: restrictTimeStart,
            maxTime: restrictTimeEnd,
            /*show24Hours: $show24Hours,*/
            timeFormat: timeFormat,
            separator: ":",
            className: "elementor-widget-text-editor",
            step: 15,
            disableTouchKeyboard: true
        });
    } else {
        jQuery(".ioInfoTimepicker").timepicker({
            startTime: new Date(0, 0, 10, 0, 0, 0),
            endTime: new Date(0, 0, 0, 20, 0, 0, 0),
            /*show24Hours: $show24Hours,*/
            timeFormat: timeFormat,
            separator: ":",
            className: "elementor-widget-text-editor",
            step: 15,
            disableTouchKeyboard: true
        });
    }
    setTimeout(setUpTimeRestrictions_infoHeaderTimepickers, 500);
}

function saveInfoHeader() {
    let info_header_start_date = jQuery("[id$=ioHeaderDateStart]");
    let info_header_end_date = jQuery("[id$=ioHeaderDateEnd]");
    let info_header_start_time = jQuery("[id$=ioHeaderTimeStart]");
    let info_header_end_time = jQuery("[id$=ioHeaderTimeEnd]");
    let info_header_address = jQuery("[id$=ioHeaderAddress]");
    let info_header_city = jQuery("[id$=ioHeaderCity]");
    let info_header_state = jQuery("[id$=ioHeaderState]");
    let info_header_zip = jQuery("[id$=ioHeaderZipCode]");
    let info_header_phone = jQuery("[id$=ioHeaderPhone]");
    let info_header_email = jQuery("[id$=ioHeaderEmail]");

    if (info_header_start_time.val() || info_header_end_time.val() || info_header_start_date.val()
        || info_header_end_date.val()){
        IoData.set_event_time(info_header_start_date.val(), info_header_end_date.val(),
            info_header_start_time.val(), info_header_end_time.val());
    }
    if (info_header_address.val()) IoData.venue_street = info_header_address.val();
    if (info_header_city.val()) IoData.venue_city = info_header_city.val();
    if (info_header_state.val()) IoData.venue_state = info_header_state.val();
    if (info_header_zip.val()) IoData.venue_zip = info_header_zip.val();
    if (info_header_phone.val()) IoData.mobile_phone = info_header_phone.val();
    if (info_header_email.val()) IoData.customer_email = info_header_phone.val();

    /* Set information in the cart. */
    calCancel();

    header_increment_step();

    /* Stop form from doing anything else for elementor */
    // jpa - still allow, turn off actions in form if wanted. to turn off io lead submission use the plugin settings
    //event.preventDefault();
    //event.stopPropagation();
    return true;
}

function set_info_header_values() {
    let info_header_start_date = jQuery("[id$=ioHeaderDateStart]");
    let info_header_end_date = jQuery("[id$=ioHeaderDateEnd]");
    let info_header_start_time = jQuery("[id$=ioHeaderTimeStart]");
    let info_header_end_time = jQuery("[id$=ioHeaderTimeEnd]");
    let info_header_street = jQuery("[id$=ioHeaderAddress]");
    let info_header_city = jQuery("[id$=ioHeaderCity]");
    let info_header_state = jQuery("[id$=ioHeaderState]");
    let info_header_zip = jQuery("[id$=ioHeaderZipCode]");
    let info_header_phone = jQuery("[id$=ioHeaderPhone]");
    let info_header_email = jQuery("[id$=ioHeaderEmail]");

    if (getCookie("timeStart")) info_header_start_time.val(getCookie("timeStart"));
    if (getCookie("timeEnd")) info_header_end_time.val(getCookie("timeEnd"));
    if (getCookie("dateStart")) info_header_start_date.val(getCookie("dateStart"));
    if (getCookie("dateEnd")) info_header_end_date.val(getCookie("dateEnd"));
    if (getCookie("address")) info_header_street.val(getCookie("address"));
    if (getCookie("city")) info_header_city.val(getCookie("city"));
    if (getCookie("state")) info_header_state.val(getCookie("state"));
    if (getCookie("zip")) info_header_zip.val(getCookie("zip"));
    if (getCookie("phone")) info_header_phone.val(getCookie("phone"));
    if (getCookie("email")) info_header_email.val(getCookie("email"));
}

function add_classes_and_onClicks() {

    /* First set up for dates */
    let info_header_start_date = jQuery("#ioHeaderDateStart");
    let info_header_end_date = jQuery("#ioHeaderDateEnd");
    info_header_start_date.addClass("ioInfoDatepicker");
    info_header_end_date.addClass("ioInfoDatepicker");

    /* Now Timepickers */
    let info_header_start_time = jQuery("#ioHeaderTimeStart");
    let info_header_end_time = jQuery("#ioHeaderTimeEnd");
    info_header_start_time.addClass("ioInfoTimepicker");
    info_header_end_time.addClass("ioInfoTimepicker");

    /* Add the onClick to the button */
    let button = jQuery("#ioInfoHeaderSubmit");
    button.click(saveInfoHeader);
    button.css("cursor", "pointer");

    /* Init datepicker and timepickers */
    init_date_timepicker_for_info_header();

    /* Lastly set the values if they are set already */
    set_info_header_values();
}

function remove_set_event_buttton() {
    let set_event_button = jQuery(".pageDateRangeWrapper");
    if (set_event_button.length > 0) set_event_button.hide();
}

function set_info_header_end_date() {
    if (!jQuery("#ioHeaderDateEnd").val()) {
        jQuery("#ioHeaderDateEnd").val(jQuery("#ioHeaderDateStart").val())
    }
    jQuery("#ioHeaderDateEnd").datepicker("option", {minDate: new Date(jQuery("#ioHeaderDateStart").val())});
}

function header_increment_step() {
    let active = jQuery(".io-step-active");

    switch (active.attr("id")) {
        case "io-step-1":
            if (/Mobi|Android/i.test(navigator.userAgent)) {
                jQuery("#io-step-2,#io-step-3,#io-step-4").hide();
            }
            if (check_header_step_one(active)) {
                active.removeClass("io-step-active");
                active.addClass("io-step-done")
                jQuery("#io-step-2").addClass("io-step-active")
                header_increment_step();
            }
            break;
        case "io-step-2":
            if (/Mobi|Android/i.test(navigator.userAgent)) {
                jQuery("#io-step-2,#io-step-3,#io-step-4").show();
            }
            if (simpleCart.items().length > 0) {
                active.removeClass("io-step-active");
                active.addClass("io-step-done")
                jQuery("#io-step-3").addClass("io-step-active")
                header_increment_step();
            }
            break;
        case "io-step-3":
            if (/Mobi|Android/i.test(navigator.userAgent)) {
                jQuery("#io-step-2,#io-step-3,#io-step-4").show();
            }
            if (document.location.href.indexOf("io_quoteconfirm") >= 0) {
                active.removeClass("io-step-active");
                active.addClass("io-step-done")
                jQuery("#io-step-4").addClass("io-step-active")
                header_increment_step();
            }
            break;
        case "io-step-4":
            if (/Mobi|Android/i.test(navigator.userAgent)) {
                jQuery("#io-step-2,#io-step-3,#io-step-4").show();
            }
            break;
    }
}

function check_header_step_one(active) {
    var allInputs = active.find('input');

    for (var i = 0; i < allInputs.length; i++) {
        if (jQuery(allInputs[i]).val() === "") {
            return false; // Return false if any input is empty
        }
    }
    return true; // Return true if all inputs have a value
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Main Image Functions">*/

/* when clicking the thumb swatches under main image (2nd image for an item) */
function updateMainPic(img) {
    /* calling image */
    let thumb_id = img.id;
    let big_id = thumb_id.replace('thumb', 'big');

    /* main image we are updating */
    let main_img = document.querySelector(".io_image_big");

    let img_big = document.querySelector("#" + big_id);
    main_img.src = img_big.href;
    /* document.querySelector("#single_image").href =img_big.href; */
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Calendar Functions">*/
function calApply() {
    /* reset timeslots if filtering is on */
    filterTimeslotsByDay_itemTimeslots();
    IoData.time_change();
    simpleCart.update();

    /* Prevent zero-duration selection: disallow identical start and end date/time */
    try
    {
      var ds = jQuery("input[name=dateStart]").val();
      var de = jQuery("input[name=dateEnd]").val();
      var ts = jQuery("input[name=timeStart]").val();
      var te = jQuery("input[name=timeEnd]").val();
      if(ts && te && ds && de)
      {
        var s24 = convert12HourTo24Hour(ts);
        var e24 = convert12HourTo24Hour(te);
        var sObj = buildDateObj(ds.split("/"), s24);
        var eObj = buildDateObj(de.split("/"), e24);
        if(sObj && eObj && typeof sObj.getTime === 'function' && typeof eObj.getTime === 'function')
        {
          if(eObj.getTime() === sObj.getTime())
          {
            alert("Please choose an end time that's after the start time.");
            jQuery("input[name=timeEnd]").val("");
            return false;
          }
        }
      }
    }catch(e){}
    /* End prevent zero-duration selection */

    if (cart_times_all_set()) {
        ioCartLoaderActivate();
        setCookie("dateApplied", "true", 1)
        checkAvailAll();
        updateAddToCartButtons();
        // If no availability calls were made, hide loader shortly after
        setTimeout(function(){
            if(io_cart_loading_active && io_cart_loading_count === 0){
                io_cart_loading_active = false;
                ioCartShowOverlay(false);
            }
        }, 300);
        calCancel();
    }


    let io_required_data = io_info_required_data;
    for (const [data, value] of Object.entries(io_required_data)) {
        if (value == 1) {
            setCookie(data, jQuery("#io_im_" + data).val(), 14);
        }
    }

    /* Check if information gathering header exists. If it does, update the times on there. */
    if (jQuery("#ioInfoHeader").length) {
        jQuery("#ioHeaderTimeStart").val(jQuery("[name=timeStart]").val());
        jQuery("#ioHeaderTimeEnd").val(jQuery("[name=timeEnd]").val());
        jQuery("#ioHeaderDateStart").val(jQuery("[name=dateStart]").val());
        jQuery("#ioHeaderDateEnd").val(jQuery("[name=dateEnd]").val());
        header_increment_step();
    }

    show_or_hide_required_info_message()
    /* if(!cartStayOpen) cartHide(); */
}

function calCancel() {
    click_count = 0;
    start_date = IoData.event_start_date_str;
    end_date = IoData.event_end_date_str;
    start_time = IoData.event_start_time_str;
    end_time = IoData.event_end_time_str;
    jQuery("input[name=dateStart]").val(start_date);
    jQuery("input[name=dateEnd]").val(end_date);
    if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day" && getCookie("company_timeslot_selected")) {
        jQuery(".ioCartCompanyTimeslots").val(getCookie("company_timeslot_selected"));
    } else {
        jQuery("input[name=timeStart]").val(start_time);
        jQuery("input[name=timeEnd]").val(end_time);
    }
    setCalBackground();

    close_time_select();

}

function close_time_select(){
    jQuery("#cartDateRange").html(smartFormatDateRange())
    jQuery("#cartCalendar, #cartTimePicker").hide();
    jQuery("#cartDateRange").show();
    jQuery(".changeDateLinkWrapper").show();
}


function calSetDateRange() {
    jQuery(".changeDateLinkWrapper").hide();
    jQuery("#cartCalendarTimePickerContainer").show();
    jQuery("#cartCalendar, #cartTimePicker").show();
    jQuery("#cartDateRange").hide();
}

function smartFormatDateRange() {
    let start_date = IoData.event_start_date_str;
    let end_date = IoData.event_end_date_str;
    if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day") {
        let cart_company_timeslot_selected = jQuery(".ioCartCompanyTimeslots option:selected").first().val();
        if (cart_company_timeslot_selected) {
            setCookie("company_timeslot_selected", cart_company_timeslot_selected, 14);
            cart_company_timeslot_selected = cart_company_timeslot_selected.split("-");
            var start_time = cart_company_timeslot_selected[0].trim();
            var end_time = cart_company_timeslot_selected[1].trim();
        }
    } else {
        var start_time = IoData.event_start_time_str;
        var end_time = IoData.event_end_time_str;
    }

    let text = "";
    text = start_date;
    if (io_hidetimes != "on") text += " " + start_time;

    if (start_date == end_date) {
        if (io_hidetimes != "on") {
            text += "  <i class='fas fa-arrow-right' style='padding:5px;'></i> ";
            text += end_time;
        }
    } else {
        text += "  <i class='fas fa-arrow-right' style='padding:5px;'></i> ";
        text += end_date;
        if (io_hidetimes != "on") text += " " + end_time;
    }
    /* text += "  <i class='fas fa-pencil-alt' style='margin-left:9px;color:"+pallet_color1+";'></i> "; */

    return text;
}


function resetCalButtons() {
    jQuery("#cartCalendar .ui-datepicker-prev").addClass("fas fa-arrow-left").css("color", pallet_color1);
    jQuery("#cartCalendar .ui-datepicker-next").addClass("fas fa-arrow-right").css("color", pallet_color1);
}

function cal_onChangeMonthYear(year, month, obj) {
    // Use requestAnimationFrame to wait for DOM update without setTimeout delay
    // This executes after the browser's next paint, ensuring the datepicker DOM is rebuilt
    requestAnimationFrame(function() {
        resetCalButtons();
        setCalBackground();
        set_day_select();
    });
}

function cal_onSelect(dateText, obj) {
    requestAnimationFrame(function() {
        resetCalButtons();
        set_day_select();
    });

    if(jQuery("#ioCartTimeInstructions")){
        jQuery("#ioCartTimeInstructions").hide();
    }
    let whatday_choice = "";
    if (io_cartdayselect === "dropdown_options" && io_multidayquote === "on") {
        let choice_obj = jQuery("#whatday");
        if (choice_obj) {
            whatday_choice = choice_obj.val();
        }
    }

    click_count++;
    end_timepicker = jQuery("input[name=timeEnd]");
    let timeStart = jQuery("input[name=timeStart]").val();
    if(io_force_blank_timepickers != "on"){
        if (timeStart == "") {
            jQuery("input[name=timeStart]").val(start_default);
            jQuery("input[name=timeEnd]").val(end_default);
        }
    }

    if ((click_count == 1 && !multi_day) || whatday_choice==="Same Day" || whatday_choice==="Overnight") {
        jQuery("input[name=dateStart]").val(dateText);
        jQuery("input[name=dateEnd]").val(dateText)
        end_timepicker.timepicker("option", {"minTime": jQuery("input[name=timeStart]").val()});
        if (EndTimeLessThanStartTime(
            jQuery("input[name=timeStart]").val(),
            end_timepicker.val(),
            jQuery("[name='dateStart']").val(),
            jQuery("[name='dateEnd']").val())) {
            end_timepicker.val("");
        }
        if (io_cartAllowSameDay == "on") {
            restrictStartTimepickerOnSameDaySelect(dateText, jQuery("input[name=timeStart]"), end_timepicker);
        }
        click_count = 0; // Reset for single-day modes
    } else if (click_count == 1) {
        // First click in multi-day mode: set only start date
        jQuery("input[name=dateStart]").val(dateText);
        jQuery("input[name=dateEnd]").val(dateText); // Set end same as start initially for display
        end_timepicker.timepicker("option", {"minTime": jQuery("input[name=timeStart]").val()});
        if (EndTimeLessThanStartTime(
            jQuery("input[name=timeStart]").val(),
            end_timepicker.val(),
            dateText,
            dateText)) {
            end_timepicker.val("");
        }
        if (io_cartAllowSameDay == "on") {
            restrictStartTimepickerOnSameDaySelect(dateText, jQuery("input[name=timeStart]"), end_timepicker);
        }
    } else if (click_count == 2) {
        jQuery("input[name=dateEnd]").val(dateText);
        let start_date_str = jQuery("input[name=dateStart]").val();
        let start_date_obj = convertDateStringtoDateObject(start_date_str);
        let end_date_obj = convertDateStringtoDateObject(dateText);
        if (end_date_obj < start_date_obj) {
            jQuery("input[name=dateStart]").val(dateText);
            if (io_cartAllowSameDay == "on") {
                restrictStartTimepickerOnSameDaySelect(dateText, jQuery("input[name=timeStart]"), end_timepicker);
            }
            click_count = 1;
        } else {
            // Check if start and end dates are the same
            if (start_date_str === dateText) {
                // Same day: restrict end time to be after start time
                end_timepicker.timepicker("option", {"minTime": jQuery("input[name=timeStart]").val()});
                // Clear end time if it's now invalid
                if (EndTimeLessThanStartTime(
                    jQuery("input[name=timeStart]").val(),
                    end_timepicker.val(),
                    start_date_str,
                    dateText)) {
                    end_timepicker.val("");
                }
            } else {
                // Different days: use global restriction
                end_timepicker.timepicker("option", {"minTime": io_restrict_time_start});
            }
            click_count = 0;
        }
    } else {
        click_count = 0;
    }
    //custom code for suncoast_event
    if (whatday_choice === 'Overnight') {
        let startdate = jQuery("[name=dateStart]").val();
        let endcalc_date_obj = new Date(buildDateobjectstring(startdate, dateFormat, io_overnightPickupTime));
        let duration_hrs = 24;
        let end_date_obj = new Date(endcalc_date_obj.getTime() + duration_hrs * 60 * 60 * 1000);
        if (!isNaN(end_date_obj)) {
            jQuery("[name=dateEnd]").val(getFormatteddate(end_date_obj));
            jQuery("[name=timeEnd]").val(getFormattedtime(end_date_obj));
            jQuery("[name=timeEnd]").attr('readonly', 'readonly');
        }
    }

    filterTimeslotsByDay_companyTimeslots();

    setTimeout(setCalBackground, 10);
}

function endDisplay() {
    let choice = jQuery("#whatday").val();
    setCookie("io_whatday", choice, 14);

    let dateStart = jQuery("[name=dateStart]");
    let timeStart = jQuery("[name=timeStart]");
    let dateEnd = jQuery("[name=dateEnd]");
    let timeEnd = jQuery("[name=timeEnd]");

    if (choice === 'Overnight') {
        let startdate = dateStart.val();
        let endcalc_date_obj = new Date(buildDateobjectstring(startdate, dateFormat, io_overnightPickupTime));
        let duration_hrs = 24;
        let end_date_obj = new Date(endcalc_date_obj.getTime() + duration_hrs * 60 * 60 * 1000);
        if (!isNaN(end_date_obj)) {
            dateEnd.val(getFormatteddate(end_date_obj));
            timeEnd.val(getFormattedtime(end_date_obj));
            timeEnd.attr('readonly', 'readonly');
        }
    } else if (choice === 'Multi-Day') {
        timeEnd.removeAttr('readonly');
    } else { // Same Day
        if(dateStart.val() != dateEnd.val()){
            dateEnd.val(dateStart.val());
        }
        timeEnd.removeAttr('readonly');
        
        // Set minTime restriction for same-day end timepicker
        timeEnd.timepicker("option", {"minTime": timeStart.val()});
        
        if (EndTimeLessThanStartTime(timeStart.val(), timeEnd.val(), dateStart.val(), dateEnd.val())) {
            timeEnd.val("");
        }
    }

    // Update calendar display and UI
    setTimeout(setCalBackground, 10);
    filterTimeslotsByDay_companyTimeslots();
}

function setCalBackground() {
    let dateStart_string = jQuery("input[name=dateStart]").val();
    let dateEnd_string = jQuery("input[name=dateEnd]").val();

    if (dateFormat == "d/m/yy") {
        let dateStartArray = dateStart_string.split("/");
        let dateEndArray = dateEnd_string.split("/");
        var dateStart = new Date(dateStartArray[2], Number(dateStartArray[1]) - 1, dateStartArray[0]);
        var dateEnd = new Date(dateEndArray[2], Number(dateEndArray[1]) - 1, dateEndArray[0]);
    } else {
        var dateStart = new Date(dateStart_string);
        var dateEnd = new Date(dateEnd_string);
    }


    let sday = dateStart.getDate();
    let smonth = dateStart.getMonth();
    let syear = dateStart.getFullYear();

    let eday = dateEnd.getDate();
    let emonth = dateEnd.getMonth();
    let eyear = dateEnd.getFullYear();

    /* clear any (in case of cancel) */
    jQuery(".ui-datepicker-calendar [data-handler=selectDay]").css("background-color", "initial");

    /* set the selected ones */
    jQuery("#cartCalendar [data-month=" + smonth + "][data-year=" + syear + "], #cartCalendar [data-month=" +
        emonth + "][data-year=" + eyear + "]").each(function (i) {
        let cday = jQuery(this).find("a").first().text();
        let cmonth = jQuery(this).attr("data-month");
        let cyear = jQuery(this).attr("data-year");
        /* let dateCurrent = new Date(Date.UTC(cyear,cmonth,cday,12)); */
        let dateCurrent = new Date(cyear, cmonth, cday);
        if (click_count == 1 && dateEnd_string.length == 0) dateEnd = dateStart;
        if (dateCurrent.getTime() == dateStart.getTime() && dateCurrent.getTime() == dateEnd.getTime()) {
            jQuery(this).css("border-radius", "6px 6px 6px 6px");
        } else if (dateCurrent.getTime() == dateStart.getTime()) {
            jQuery(this).css("border-radius", "6px 0 0 6px");
        } else if (dateCurrent.getTime() == dateEnd.getTime()) {
            jQuery(this).css("border-radius", "0 6px 6px 0");
        }

        if (dateCurrent >= dateStart && dateCurrent <= dateEnd) {
            jQuery(this).css("background-color", pallet_color1);
        }


    });
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Timeslot/Timepicker Functions">*/

/* called from simplecart */
function timeslotChange() {
    checkAvailCart();
}

function filterTimeslotsByDay_companyTimeslots() {
    var weekday = new Array();
    weekday[0] = "Sunday";
    weekday[1] = "Monday";
    weekday[2] = "Tuesday";
    weekday[3] = "Wednesday";
    weekday[4] = "Thursday";
    weekday[5] = "Friday";
    weekday[6] = "Saturday";
    let times = getAvailTimes();
    let start_date = times[0];
    let day = weekday[new Date(start_date).getDay()];

    let selected_option_label = jQuery(".ioCartCompanyTimeslots option:selected").first().text().toLowerCase();
    if (optionHasDay(weekday, selected_option_label)) {
        if (selected_option_label.indexOf(day.toLowerCase()) === -1) {
            jQuery(".ioCartCompanyTimeslots").val("");
        }
    }
    if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day") {
        jQuery(".ioCartCompanyTimeslots > option").each(function () {
            if (optionHasDay(weekday, this.text.toLowerCase())) {
                for (i = 0; i < weekday.length; ++i) {
                    if (day.toLowerCase() == weekday[i].toLowerCase() && this.text.toLowerCase().indexOf(day.toLowerCase()) !== -1) {
                        jQuery(this).show();
                        day_missing = false;
                    } else if (day.toLowerCase() != weekday[i].toLowerCase() && this.text.toLowerCase().indexOf(day.toLowerCase()) === -1) {
                        jQuery(this).hide();
                    }
                }
            }
        });
    }
}

function filterTimeslotsByDay_itemTimeslots() {
    var weekday = new Array();
    weekday[0] = "Sunday";
    weekday[1] = "Monday";
    weekday[2] = "Tuesday";
    weekday[3] = "Wednesday";
    weekday[4] = "Thursday";
    weekday[5] = "Friday";
    weekday[6] = "Saturday";

    let times = getAvailTimes();
    let start_date = times[0];
    let day = weekday[new Date(start_date).getDay()];

    simpleCart.each(function (item, x) {
        var timeslots_html = item.get('timeslots');
        if (typeof timeslots_html != "undefined" && jQuery.parseHTML(timeslots_html)[0].nodeName == "SELECT") {
            if (timeslots_html.length > 0) {
                var timeslot_name = getTimeslotName(timeslots_html);
                if (typeof item.get("timeslots-orig") == "undefined") {
                    var timeslots_obj = jQuery.parseHTML(timeslots_html);
                } else {
                    var timeslots_obj = jQuery.parseHTML(item.get('timeslots-orig'));
                }
                jQuery(timeslots_obj).find("option").each(function () {
                    if (optionHasDay(weekday, this.text.toLowerCase())) {
                        for (i = 0; i < weekday.length; ++i) {
                            if (day.toLowerCase() == weekday[i].toLowerCase() && this.text.toLowerCase().indexOf(day.toLowerCase()) !== -1) {
                                /* jQuery(this).show(); */
                            } else if (day.toLowerCase() != weekday[i].toLowerCase() && this.text.toLowerCase().indexOf(day.toLowerCase()) === -1) {
                                jQuery(this).remove();
                            }
                        }
                    }
                });
                if (typeof item.get("timeslots-orig") == "undefined") item.set("timeslots-orig", item.get("timeslots"));
                item.set("timeslots", '<select class="simpleCart_timeslots" name="' + timeslot_name + '">' + jQuery(timeslots_obj).html() + '</select>');
            }
        }
    });
}

function optionHasDay(weekdays, option_label) {
    for (i = 0; i < weekdays.length; ++i) {
        if (option_label.indexOf(weekdays[i].toLowerCase()) !== -1) {
            return true;
        }
    }
    return false;
}

function getTimeslotName(timeslots_html) {
    if (typeof timeslots_html == "undefined") return "";
    var timeslot_name_s = timeslots_html.indexOf('name="');
    timeslot_name_s += 6;
    var timeslot_name_e = timeslots_html.indexOf('"', timeslot_name_s);
    var timeslot_name = timeslots_html.substr(timeslot_name_s, timeslot_name_e - timeslot_name_s);
    return timeslot_name;
}

function setTimeslotSelected(item, timeslot_name) {
    jQuery(".item-timeslots [name=\"" + timeslot_name + "\"] option").not(":selected").removeAttr("selected");
    jQuery(".item-timeslots [name=\"" + timeslot_name + "\"] option:selected").attr("selected", "selected");
    if (jQuery(".item-timeslots [name=\"" + timeslot_name + "\"]").length > 0) {
        item.set("timeslots", jQuery(".item-timeslots [name=\"" + timeslot_name + "\"]")[0].outerHTML);
    }

    /* set on quote page */
    jQuery(".controls [name=\"" + timeslot_name + "\"] option").not(":selected").removeAttr("selected");
    jQuery(".controls [name=\"" + timeslot_name + "\"] option[value='" + jQuery(".item-timeslots [name=\"" + timeslot_name + "\"] option:selected").val() + "']").attr("selected", "selected");
}

function setTimePicker(item, timepicker_name) {
    let [start_timepicker, end_timepicker] = get_cart_timepickers(timepicker_name);
    let start_time = start_timepicker.value;
    let end_time = end_timepicker.value;

    if (!start_time) {
        start_timepicker.style.borderColor = "red";
    } else {
        start_timepicker.style.borderColor = "";
    }
    if (!end_time) {
        end_timepicker.style.borderColor = "red";
    } else {
        end_timepicker.style.borderColor = "";
    }

    let start_timepicker_html = start_timepicker.outerHTML;
    let end_timepicker_html = end_timepicker.outerHTML;
    if (document.querySelectorAll(".item-timeslots [name=\"" + timepicker_name + "\"]").length > 0) {
        start_timepicker_html = addOrReplaceValueInTimepicker(start_timepicker_html, start_time);
        end_timepicker_html = addOrReplaceValueInTimepicker(end_timepicker_html, end_time);
        item.set("timeslots", '<div name="' + timepicker_name + '"> Start: ' + start_timepicker_html + ' End: ' + end_timepicker_html + '</div>');
    }
    /* set on quote page */
    /* For linen type items with timepickers */
    let rental_id = item.get("rentalid");
    let split_on_colon = rental_id.split(":");
    if (split_on_colon.length > 1) {
        fix_time_name_for_linen_rid(timepicker_name, split_on_colon, start_time, end_time, rental_id)
    } else {
        let quote_page_start_timepicker = document.querySelectorAll(".controls [name=\"" + timepicker_name.replace("io_timepicker_", "starttime_") + "\"]")[0];
        let quote_page_end_timepicker = document.querySelectorAll(".controls [name=\"" + timepicker_name.replace("io_timepicker_", "endtime_") + "\"]")[0];
        if (quote_page_start_timepicker != null && quote_page_end_timepicker != null) {
            quote_page_start_timepicker.value = start_time;
            quote_page_end_timepicker.value = end_time;
        }
    }
}

function fix_time_name_for_linen_rid(time_name, split_rid, start_time, end_time, rental_id) {
    for (let x = 0; x < split_rid.length; x++) {
        temp_timepicker_name = time_name.replace(rental_id, split_rid[x]);
        let quote_page_start_timepicker = document.querySelectorAll(".controls [name=\"" + temp_timepicker_name.replace("io_timepicker_", "starttime_") + "\"]")[0];
        let quote_page_end_timepicker = document.querySelectorAll(".controls [name=\"" + temp_timepicker_name.replace("io_timepicker_", "endtime_") + "\"]")[0];
        if (quote_page_start_timepicker != null && quote_page_end_timepicker != null) {
            quote_page_start_timepicker.value = start_time;
            quote_page_end_timepicker.value = end_time;
        }
    }
}

function addOrReplaceValueInTimepicker(timepicker_html, time_value) {
    if (timepicker_html.includes("value=")) {
        timepicker_html = [timepicker_html.slice(0, timepicker_html.indexOf("value=")), 'value="' + time_value + '"', timepicker_html.slice(timepicker_html.length - 1)].join("");
    } else {
        /* No value defined. Add it at the end of the outer html. */
        let position = timepicker_html.lastIndexOf(">");
        timepicker_html = [timepicker_html.slice(0, position), ' value="' + time_value + '"', timepicker_html.slice(position)].join("");
    }
    return timepicker_html
}

function restrictEndTimepickers() {
    setUpTimeRestrictions_cartTimepickers()
    setUpTimeRestrictions_timeBasedItems()
}

function setUpTimeRestrictions_timeBasedItems() {
    jQuery("input[name^=start_timeslot_]").change(function () {
        end_timepicker = jQuery("input[name='" + this.name.replace("start", "end") + "']");
        end_timepicker = jQuery(end_timepicker[end_timepicker.length - 1]);
        end_timepicker.timepicker("option", {"minTime": jQuery(this).val()});
        if (EndTimeLessThanStartTime(jQuery(this).val(), end_timepicker.val(), "0/0/0", "0/0/0")) {
            end_timepicker.val("");
        }
    });
}

function setUpTimeRestrictions_cartTimepickers() {
    jQuery("input[name=timeStart]").change(function () {
        end_timepicker = jQuery("[name='" + this.name.replace("Start", "End") + "']");
        if (jQuery("[name='dateStart']").val() === jQuery("input[name='dateEnd']").val()) {
            end_timepicker.timepicker("option", {"minTime": jQuery(this).val()});
            if (EndTimeLessThanStartTime(
                jQuery(this).val(),
                end_timepicker.val(),
                jQuery("[name='dateStart']").val(),
                jQuery("[name='dateEnd']").val())) {
                end_timepicker.val("");
            }
        }
    });
}

function setUpTimeRestrictions_infoHeaderTimepickers() {
    jQuery("#ioHeaderTimeStart").change(function () {
        end_timepicker = jQuery("#ioHeaderTimeEnd");
        if (jQuery("#ioHeaderDateStart").val() === jQuery("#ioHeaderDateEnd").val()) {
            end_timepicker.timepicker("option", {"minTime": jQuery(this).val()});
            if (EndTimeLessThanStartTime(
                jQuery(this).val(),
                end_timepicker.val(),
                jQuery("#ioHeaderDateStart").val(),
                jQuery("#ioHeaderDateEnd").val())) {
                end_timepicker.val("");
            }
        }
    });
}

/*
  helper function to see if the value from a start timepicker is less than the string value of an end timepicker.

  param start_time: string representation of the start time picker. 12hr or 24hr.
  param end_time: string representation of the end time picker. 12hr or 24hr.
  param start_date: string representation of the start date, seperated by "/". Can be wither d/m/y or m/d/y. Pass "0/0/0" if dates do not matter.
  param end_date: string representation of the end date, seperated by "/". Can be wither d/m/y or m/d/y. Pass "0/0/0" if dates do not matter.

*/
function EndTimeLessThanStartTime(start_time, end_time, start_date, end_date) {
    if (!start_time || !end_time) return false;
    start_time = convert12HourTo24Hour(start_time);
    end_time = convert12HourTo24Hour(end_time);
    var split_start_date = start_date.split("/");
    var split_end_date = end_date.split("/");
    var startDate = buildDateObj(split_start_date, start_time);
    var endDate = buildDateObj(split_end_date, end_time);
    if (endDate < startDate) {
        return true;
    } else {
        return false;
    }
}

function get_cart_timepickers(timepicker_name) {
    let start_timepicker = document.getElementsByName(timepicker_name.replace("io_timepicker_", "start_timeslot_"));
    let end_timepicker = document.getElementsByName(timepicker_name.replace("io_timepicker_", "end_timeslot_"));
    start_timepicker = start_timepicker[start_timepicker.length - 1];
    end_timepicker = end_timepicker[end_timepicker.length - 1];
    return Array(start_timepicker, end_timepicker);
}

function restrictStartTimepickerOnSameDaySelect(start_date_str, start_timepicker, end_timepicker) {
    let selected_date_obj = convertDateStringtoDateObject(start_date_str);
    let current_date_obj = new Date();
    if (current_date_obj.getDate() == selected_date_obj.getDate() &&
        current_date_obj.getMonth() == selected_date_obj.getMonth() &&
        current_date_obj.getYear() == selected_date_obj.getYear()) {
        let next_hour_time_stamp = current_date_obj.setMinutes(60);
        let next_hour_str = getFormattedtime(new Date(next_hour_time_stamp))
        start_timepicker.timepicker("option", {"minTime": next_hour_str});

        /* If the time in the input box is less than the time we just restricted too, then clear time inputs */
        restricted_time_obj = convertDateStringtoDateObject(start_date_str, next_hour_str);
        currently_selected_time_obj = convertDateStringtoDateObject(start_date_str, start_timepicker.val());
        if (currently_selected_time_obj < restricted_time_obj) {
            start_timepicker.val(next_hour_str);
            end_timepicker.val("");
            end_timepicker.timepicker("option", {"minTime": next_hour_str});
        }
    } else {
        start_timepicker.timepicker("option", {"minTime": restrictTimeStart});
    }
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Simple Cart Bound Functions">*/
function cart_onUpdate() {
    /* need slight delay so simplecart updates before this runs */
    setTimeout(cart_onUpdate2, 500);
    try {
        for (var i = 0; i < document.getElementsByClassName("ioCart").length; i++) {
            document.getElementsByClassName("ioCart")[i].setAttribute("cnt", simpleCart.items().length);
        }
    } catch (e) {}
}

function cart_onUpdate2() {
    jQuery("#cartSubtotal").html(simpleCart.toCurrency(simpleCart.total()));
    if (io_checkavail == "off") return;
    jQuery("#cartWarning").hide();
    let hasUnavail = false;
    let gift_cards_only = true;
    if (simpleCart.items().length == 0) gift_cards_only = false;
    simpleCart.each(function (item, x) {
        let item_id = item.get("id");
        if (!item.get("giftcardvalue") || !item.get("giftcardvalue").trim()) {
            gift_cards_only = false;
        }
        let availability = item.get("availability");
        let stop_loop = false;
        if (availability < 0) {
            stop_loop = display_cart_warning(item);
            hasUnavail = true;
        }
        if (stop_loop) {
            return false;
        }
    });

    if (gift_cards_only) {
        jQuery("#cartCalendarTimePickerContainer").hide();
    } else {
        jQuery("#cartCalendarTimePickerContainer").show();
    }

    if (hasUnavail && io_checkavail != "off") {
        jQuery(".simpleCart_checkout").removeClass("simpleCart_checkout").addClass("simpleCart_checkout_off").trigger("classChange").click(cartShow);
    } else if (io_checkavail != "off") {
        jQuery(".simpleCart_checkout_off").removeClass("simpleCart_checkout_off").addClass("simpleCart_checkout").trigger("classChange");
    }
    /*
    add_cart_buttons = document.querySelectorAll("[class*=add_cart_]");
    if (add_cart_buttons) {
        for (let i = 0; i < add_cart_buttons.length; ++i) {
            add_cart_buttons[i].innerHTML = add_cart_buttons[i].innerHTML.replace("fa-cart-arrow-down", "fa-shopping-cart");
            add_cart_buttons[i].innerHTML = add_cart_buttons[i].innerHTML.replace("Added to Cart", "Add to Cart");
            add_cart_buttons[i].style.filter = "brightness(100%)";
            simpleCart.each(function (item, x) {
                if (add_cart_buttons[i].className.includes(item.get("rentalid"))) {
                    add_cart_buttons[i].innerHTML = add_cart_buttons[i].innerHTML.replace("fa-shopping-cart", "fa-cart-arrow-down");
                    add_cart_buttons[i].innerHTML = add_cart_buttons[i].innerHTML.replace("Add to Cart", "Added to Cart");
                    add_cart_buttons[i].style.filter = "brightness(90%)";
                }
            });
        }
    }
    */

    /* init time-based items */
    if (document.location.href.indexOf("io_quoteform") == -1) {
        let today = new Date();
        let io_dd = today.getDate();
        let io_mm = today.getMonth() + 1;
        let io_yyyy = today.getFullYear();
        if (restrictTimes) {
            jQuery(".item-timeslots .timepicker").each(function () {
                if (this.name.includes("end")) {
                    start_timepicker = jQuery("input[name='" + this.name.replace("end", "start") + "']");
                    start_timepicker = jQuery(start_timepicker[start_timepicker.length - 1]);

                    if (io_force_blank_timepickers == "on") {
                        start_timepicker.val("");
                        jQuery(this).timepicker({
                            startTime: "",
                            endTime:   "",
                            minTime:   restrictTimeStart,
                            maxTime:   restrictTimeEnd,
                            timeFormat: timeFormat,
                            separator:  ":",
                            className:  "elementor-widget-text-editor",
                            step: 15,
                            disableTouchKeyboard: true
                        });
                    }
                    else {
                        // Existing logic if "force blank" is not active
                        if (start_timepicker.val() != "") {
                            jQuery(this).timepicker({
                                startTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + start_default),
                                endTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + end_default),
                                minTime: start_timepicker.val(),
                                maxTime: restrictTimeEnd,
                                timeFormat: timeFormat,
                                separator: ":",
                                className: "elementor-widget-text-editor",
                                step: 15,
                                disableTouchKeyboard: true
                            });
                        } else {
                            jQuery(this).timepicker({
                                startTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + start_default),
                                endTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + end_default),
                                minTime: restrictTimeStart,
                                maxTime: restrictTimeEnd,
                                timeFormat: timeFormat,
                                separator: ":",
                                className: "elementor-widget-text-editor",
                                step: 15,
                                disableTouchKeyboard: true
                            });
                        }
                    }

                }
                else {
                    if (io_force_blank_timepickers == "on")
                    {
                        start_timepicker.val("");
                        jQuery(this).timepicker({
                            startTime: "",
                            endTime:   "",
                            minTime:   restrictTimeStart,
                            maxTime:   restrictTimeEnd,
                            timeFormat: timeFormat,
                            separator:  ":",
                            className:  "elementor-widget-text-editor",
                            step: 15,
                            disableTouchKeyboard: true
                        });
                    }
                    else {
                        jQuery(this).timepicker({
                            startTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + start_default),
                            endTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + end_default),
                            minTime: restrictTimeStart,
                            maxTime: restrictTimeEnd,
                            timeFormat: timeFormat,
                            separator: ":",
                            className: "elementor-widget-text-editor",
                            step: 15,
                            disableTouchKeyboard: true
                        });
                    }
                }
            });
        } else {
            jQuery(".item-timeslots .timepicker").each(function () {
                if (this.name.includes("end") != -1) {
                    start_timepicker = jQuery("input[name='" + this.name.replace("end", "start") + "']");
                    start_timepicker = jQuery(start_timepicker[start_timepicker.length - 1]);
                    if (io_force_blank_timepickers == "on")
                    {
                        start_timepicker.val("");
                        jQuery(this).timepicker({
                            startTime: "",
                            endTime:   "",
                            minTime:   restrictTimeStart,
                            maxTime:   restrictTimeEnd,
                            timeFormat: timeFormat,
                            separator:  ":",
                            className:  "elementor-widget-text-editor",
                            step: 15,
                            disableTouchKeyboard: true
                        });
                    }
                    else
                    {
                        if (start_timepicker.val() != "") {
                            jQuery(this).timepicker({
                                startTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + start_default),
                                endTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + end_default),
                                minTime: start_timepicker.val(),
                                timeFormat: timeFormat,
                                separator: ":",
                                className: "elementor-widget-text-editor",
                                step: 15,
                                disableTouchKeyboard: true
                            });
                        } else {
                            jQuery(this).timepicker({
                                startTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + start_default),
                                endTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + end_default),
                                timeFormat: timeFormat,
                                separator: ":",
                                className: "elementor-widget-text-editor",
                                step: 15,
                                disableTouchKeyboard: true
                            });
                        }
                    }
                }
                else
                {
                    if (io_force_blank_timepickers == "on")
                    {
                        start_timepicker.val("");
                        jQuery(this).timepicker({
                            startTime: "",
                            endTime:   "",
                            minTime:   restrictTimeStart,
                            maxTime:   restrictTimeEnd,
                            timeFormat: timeFormat,
                            separator:  ":",
                            className:  "elementor-widget-text-editor",
                            step: 15,
                            disableTouchKeyboard: true
                        });
                    }
                    else
                    {
                        jQuery(this).timepicker({
                            startTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + start_default),
                            endTime: new Date(io_mm + "/" + io_dd + "/" + io_yyyy + " " + end_default),
                            timeFormat: timeFormat,
                            separator: ":",
                            className: "elementor-widget-text-editor",
                            step: 15,
                            disableTouchKeyboard: true
                        });
                    }
                }
            });
        }
        setUpTimeRestrictions_timeBasedItems();
        if (!IoData.event_time_set()) {
            jQuery(".itemRow .item-total").hide();
        } else {
            jQuery(".itemRow .item-total").show();
        }
    }
}

function cart_beforeCheckout(data) {
    /*
    data.startdate = jQuery("input[name=dateStart]").val();
    data.enddate = jQuery("input[name=dateEnd]").val();
    data.io_custguid = guid;
    if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day") {
        let cart_company_timeslot_selected = jQuery(".ioCartCompanyTimeslots option:selected").first().val();
        if (cart_company_timeslot_selected) {
            setCookie("company_timeslot_selected", cart_company_timeslot_selected, 14);
            cart_company_timeslot_selected = cart_company_timeslot_selected.split("-");
            data.starttime = cart_company_timeslot_selected[0];
            data.endtime = cart_company_timeslot_selected[1];
        }
    } else {
        data.starttime = jQuery("input[name=timeStart]").val();
        data.endtime = jQuery("input[name=timeEnd]").val();
    }*/
}

function cart_beforeAdd(item) {
    if(item.get("rental_obj")){
        item.get("rental_obj").cart_id = item.get("id");
    }
    var main_id = jQuery(".io_product_container .item_rentalid").first().text();
    var item_id = item.get("rentalid");

    timeslots = item.get("timeslots");
    if (timeslots) {
        if (timeslots.indexOf("<select") !== -1) {
            timeslot_name_id_start_pos = timeslots.lastIndexOf('name="timeslot_') + 'name="timeslot_'.length;
            timeslot_name_id_end_pos = timeslots.indexOf('"', timeslot_name_id_start_pos);
            new_timeslots = [timeslots.slice(0, timeslot_name_id_start_pos), item_id, timeslots.slice(timeslot_name_id_end_pos, timeslots.length)]
            new_timeslots = new_timeslots.join("")
            item.set("timeslots", new_timeslots);
        } else if (timeslots.indexOf("<div name=\"io_timepicker_") !== -1) {
            timeslot_name_id_start_pos = timeslots.lastIndexOf('name="io_timepicker_') + 'name="io_timepicker_'.length;
            timeslot_name_id_end_pos = timeslots.indexOf('"', timeslot_name_id_start_pos);
            new_timeslots = [timeslots.slice(0, timeslot_name_id_start_pos), item_id, timeslots.slice(timeslot_name_id_end_pos, timeslots.length)]
            new_timeslots = new_timeslots.join("")

            timeslot_name_id_start_pos = new_timeslots.lastIndexOf('name="start_timeslot_') + 'name="start_timeslot_'.length;
            timeslot_name_id_end_pos = new_timeslots.indexOf('"', timeslot_name_id_start_pos);
            new_timeslots = [new_timeslots.slice(0, timeslot_name_id_start_pos), item_id, new_timeslots.slice(timeslot_name_id_end_pos, new_timeslots.length)]
            new_timeslots = new_timeslots.join("")

            timeslot_name_id_start_pos = new_timeslots.lastIndexOf('name="end_timeslot_') + 'name="end_timeslot_'.length;
            timeslot_name_id_end_pos = new_timeslots.indexOf('"', timeslot_name_id_start_pos);
            new_timeslots = [new_timeslots.slice(0, timeslot_name_id_start_pos), item_id, new_timeslots.slice(timeslot_name_id_end_pos, new_timeslots.length)]
            new_timeslots = new_timeslots.join("")

            item.set("timeslots", new_timeslots);
        }
    }

    /* IO-14857 */
    if (jQuery(".io_product_measurement_price").length > 0) {
        let units;
        if (jQuery(".io_product_infobox .item_qtytype").text() == "Area") {
            units = "sq meters"
            if (country === "US") units = "sq feet"
        } else if (jQuery(".io_product_infobox .item_qtytype").text() == "Perimeter") {
            units = "meters"
            if (country === "US") units = "feet"
        }
        item.set("units", units);
        item.set("quantity", jQuery(".io_measure_price_raw_measurement").text());
    }
}

function cart_afterAdd(item) {
    ioCartLoaderActivate();
    setTimeout(function(){ if(io_cart_loading_active && io_cart_loading_count === 0){ io_cart_loading_active=false; ioCartShowOverlay(false);} }, 300);
    if(item.get("timeslots") && item.get("timeslots").includes("<select")){
        let timeslot_name = getTimeslotName(item.get("timeslots"));
        let timeslot_sel_range = jQuery(".item-timeslots [name=\"" + timeslot_name + "\"] option:selected").val();
        var [start_time, end_time] = break_timeslot_sel_range(timeslot_sel_range);
        rental_obj = item.get("rental_obj");
        rental_obj.start_timestamp = start_time;
        rental_obj.end_timestamp = end_time;
        item.set("rental_obj", rental_obj);
    }else if(!item.get("timeslots") && IoData.event_time_set()){
        rental_obj = item.get("rental_obj");
        rental_obj.start_timestamp = IoData.event_start_timestamp;
        rental_obj.end_timestamp = IoData.event_end_timestamp;
        item.set("rental_obj", rental_obj);
    }
    checkAvailCartOnly();

    let last_upsell_call_time = Date.now() - last_upsell_call;
    if (in_cart_upsell && last_upsell_call_time > 2000) {
        let rental_ids = "";

        /* Get the last element in the cart. This is the last item added. */
        last_added = jQuery("[id^='cartItem_']").last();
        if (last_added.length) {
            last_added_children = last_added.children();
            for (let i = 0; i < last_added_children.length; ++i) {
                if (last_added_children[i].className == "item-rentalid") {
                    rental_ids += last_added_children[i].innerText + "|";
                }
            }
        }

        if (rental_ids.length > 0 && jQuery("#cartPopover").attr("class") == "cartIn") {
            var times = getAvailTimes();
            last_upsell_call = Date.now();
            getUpsellsCall(times[0], times[1], times[2], rental_ids, updateCartUpsell);
        } else {
            jQuery("#cart-carousel-container").hide();
        }
    }
    if (io_company_timeslots.length != 0 && io_cartdayselect == "single_day") {
        filterTimeslotsByDay_itemTimeslots();
        simpleCart.update();
    }

    if (jQuery(".cartInfo.open,.ioCart.open, .ioCart_link.open").length == 0) {
        setTimeout(function () {
            cartShow();
        }, 100);
    }

    if (simpleCart.items().length == 0) {
        jQuery(".simpleCart_checkout").hide()
    } else {
        jQuery(".simpleCart_checkout").show();
    }

    if (simpleCart.items().length > 0) {
        let headerBookButton = jQuery("a[href$='io_quoteform/']");
        headerBookButton.addClass("ioCart_link");
        headerBookButton.attr("href", "javascript:;");
    }

    checkRestrictedDeliveries()

    if (jQuery("#ioInfoHeader").length) {
        header_increment_step();
    }
}

function cart_afterQtyChange(changed_item) {
    IoData.refresh_cached_item(changed_item.get("id"), "cart");
    /*loading animation*/
    //ioCartLoaderActivate();
    setTimeout(function(){ if(io_cart_loading_active && io_cart_loading_count === 0){ io_cart_loading_active=false; ioCartShowOverlay(false);} }, 300);
    checkAvailCart();
    //checkAvailCartTimeslots();
}

function cart_hideTimepickerWrapper() {
    jQuery(".ui-timepicker-wrapper").hide();
}

function cart_beforeRemove() {
    last_remove = Date.now();
}

function cart_afterRemove(removed_item) {
    IoData.remove_from_cart_cache(removed_item.get("id"));
    checkAvailCart();
    last_upsell_call_time = Date.now() - last_upsell_call;
    if (in_cart_upsell && last_upsell_call_time > 2000) {
        rental_ids = getAllRentalIDsFromCart();
        if (rental_ids.length > 0 && jQuery("#cartPopover").attr("class") == "cartIn") {
            var times = getAvailTimes();
            last_upsell_call = Date.now();
            getUpsellsCall(times[0], times[1], times[2], rental_ids, updateCartUpsell);
        } else {
            jQuery("#cart-carousel-container").hide();
        }
    }

    /* IO-24060
    simpleCart.items().forEach(function (item, index) {
        let expression = '^' + removed_item.get('rentalid') + '(?:[_:]\\d+)*';
        if (item.get("rentalid").match(expression)) {
            item.remove();
        }
    });*/


    //checkAvailCartTimeslots();
    checkRestrictedDeliveries();
    if (simpleCart.items().length == 0) {
        jQuery(".simpleCart_checkout").hide()
    } else {
        jQuery(".simpleCart_checkout").show();
    }

    if (jQuery("#ioInfoHeader").length && simpleCart.items().length == 0) {
        jQuery("#io-step-3").removeClass("io-step-active");
        jQuery("#io-step-2").addClass("io-step-active");
        jQuery("#io-step-2").removeClass("io-step-done")
    }

    simpleCart.items().forEach(function (item){
       cart_id = item.get("id");
       IoData.refresh_cached_item(cart_id, "cart");
    });
    checkAvailCartOnly();
}
  function cart_afterLoad(){
    var items_removed = false;
    simpleCart.items().forEach(function(item){
      if(item.get("pagename") != io_pagename){
        item.remove()
        items_removed = true;
      }
    })
    if(items_removed){
      alert("Some items in the cart are from a different location and have been removed.");
    }
  }
/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Date/Time Object/String Conversion Functions">*/
function getFormatteddate(date_obj) {
    if (dateFormat.substring(0, 1) == 'd') {
        let month = date_obj.getMonth() + 1;
        formatteddate = date_obj.getDate() + '/' + month + '/' + date_obj.getFullYear();
    } else {
        let month = date_obj.getMonth() + 1;
        formatteddate = month + '/' + date_obj.getDate() + '/' + date_obj.getFullYear();
    }
    return formatteddate;
}

function getFormattedtime(date_obj) {
    var hour24 = false;
    var ampm = 'am';
    var starttime = jQuery('[name=timeStart]').val();
    if (starttime.length > 0 && starttime.indexOf('m') == -1) hour24 = true;
    if (hour24) { //24 hour return
        return date_obj.getHours() + ':' + pad(date_obj.getMinutes(), 2);
    } else { //12 hour return
        var hour = date_obj.getHours();
        if (hour == 12) ampm = 'pm';
        if (hour == 0) hour = 12;
        if (hour > 12) {
            hour -= 12;
            ampm = 'pm';
        }
        return hour + ':' + pad(date_obj.getMinutes(), 2) + ' ' + ampm;
    }
}

function buildDateobjectstring(date, dateformat, time) {
    var ampm = 'am';
    var hour24 = false;
    if (typeof date == "undefined") return;
    if (typeof dateformat == "undefined") return;
    var start_arr = date.split('/');
    if (dateformat.substring(0, 1) == 'd') {
        date = start_arr[2] + '/' + pad(start_arr[1], 2) + '/' + pad(start_arr[0], 2);
    } else {
        date = start_arr[2] + '/' + pad(start_arr[0], 2) + '/' + pad(start_arr[1], 2);
    }
    if(time.length>0 && time.indexOf('m')==-1) hour24 = true;
    if(hour24){
        try{
            var time_arr = time.split(':');
            var hour = parseInt(time_arr[0]);
            var min = pad(time_arr[1], 2);
            time = hour + ':' + min + ':00';
        }catch(err){
            time = "";
        }
    }else {
        try {
            time = time.replace('am', "").replace(' ', "");
            if (time.indexOf('pm') != -1) ampm = 'pm';
            time = time.replace('pm', "").replace(' ', "");
            var time_arr = time.split(':');
            var hour = parseInt(time_arr[0]);
            var min = pad(time_arr[1], 2);
            if (ampm == 'pm') {
                if (hour < 12) hour += 12;
            } else if (ampm == 'am' && hour == 12) {
                hour -= 12;
            }
            hour = pad(hour, 2);
            time = hour + ':' + min + ':00';
        } catch (err) {
            time = "";
        }
    }
    return date + ' ' + time;
}

function pad(num, size) {
    var s = num + "";
    while (s.length < size) s = "0" + s;
    return s;
}

function convertDateStringtoDateObject(date_str, time_str = null) {
    if (date_str) {
        split_date_str = date_str.split("/");
        /* Parse start and end time. */
        if (time_str) {
            /* Check and see if we are in 12 hour format, if so convert it to 24 hour format. */
            split_time_str = convert12HourTo24Hour(time_str);
        } else {
            /* If we do not have a time, then default to zeros */
            split_time_str = [0, 0];
        }
        /* Create date object based off our set date format. */
        date_obj = buildDateObj(split_date_str, split_time_str);
        return date_obj;
    } else {
        return new Date();
    }
}

function buildDateObj(split_date_str, split_time_str) {
    if (dateFormat == "d/m/yy") {
        return new Date(split_date_str[2], (+split_date_str[1] - 1).toString(), split_date_str[0],
            split_time_str[0], split_time_str[1]);
    } else {
        return new Date(split_date_str[2], (+split_date_str[0] - 1).toString(), split_date_str[1],
            split_time_str[0], split_time_str[1]);
    }
}

function convert12HourTo24Hour(time_str) {
    /* This function returns an array containing hours and minutes of provided string in 24 hour format. */
    /* This is primarily used for creating JS Date objects */
    split_time = time_str.split(":");

    /* We are in 12 hour format if there is an "m" attached to minutes portion. */
    if (split_time[1].toLowerCase().search("m") != -1) {
        let separated_minutes = split_time[1].split(" ");
        if (separated_minutes.length == 1) {
            split_time[1] = split_time[1].replace("am", " am");
            split_time[1] = split_time[1].replace("pm", " pm");
            separated_minutes = split_time[1].split(" ");
        }
        let minutes = separated_minutes[0];
        let modifier = separated_minutes[1];
        split_time[1] = minutes;

        /* First assume that if the hours are 12, then its midnight. */
        if (split_time[0] == "12") {
            split_time[0] = "00";
        }
        /* Second if there is a "p" in the modifier, then add twelve to the hours. */
        if (typeof modifier != "undefined") {
            if (modifier.toLowerCase().search("p") != -1) {
                split_time[0] = (parseInt(split_time[0], 10) + 12);
            }
        }
    }
    return split_time;
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Cart Show and Hide">*/
function cartShow() {
    jQuery("#cartPopover").show();
    jQuery("#cartPopover").removeClass("cartOut");
    jQuery("#cartPopover").addClass("cartIn");
    try{
        setTimeout(cartFlickityRefresh, 500);
    }catch(e){}
    jQuery(".cartInfo,.ioCart,.ioCart_link").addClass("open");
    if (/Mobi|Android/i.test(navigator.userAgent)) {
        document.body.style.overflow = "hidden";
    }
    /* jQuery(this).one("click", cartHide); */
    jQuery(".cartInfo").unbind("click").one("click", function (event) {
        event.stopPropagation();
        event.stopImmediatePropagation();
        cartHide();
    });
    jQuery(".ioCart, .ioCart_link").unbind("click").one("click", function (event) {
        event.stopPropagation();
        event.stopImmediatePropagation();
        cartHide();
    });
    jQuery(".cartIcon").removeClass("fa-shopping-cart").addClass("fa-close");
    if (simpleCart.items().length == 0) {
        jQuery(".simpleCart_checkout").hide()
    } else {
        jQuery(".simpleCart_checkout").show();
    }

    checkAvailCartOnly();

    last_upsell_call_time = Date.now() - last_upsell_call;
    if (in_cart_upsell && last_upsell_call_time > 2000) {
        rental_ids = getAllRentalIDsFromCart();
        if (rental_ids.length > 0 && jQuery("#cartPopover").attr("class") == "cartIn") {
            var times = getAvailTimes();
            last_upsell_call = Date.now();
            getUpsellsCall(times[0], times[1], times[2], rental_ids, updateCartUpsell);
        } else {
            jQuery("#cart-carousel-container").hide();
        }
    }

    if(!IoData.event_time_set()){
        jQuery("#cartCalendar, #cartTimePicker").show();
    }else{
        jQuery("#cartDateRange").show();
    }
}

function cartHide() {
    jQuery("#cartPopover").removeClass("cartIn");
    jQuery("#cartPopover").addClass("cartOut");
    if (/Mobi|Android/i.test(navigator.userAgent)) {
        document.body.style.overflow = "auto";
    }
    /* jQuery("#cartPopover").hide(); */
    jQuery(".cartInfo,.ioCart, .ioCart_link").removeClass("open");
    /* jQuery(this).one("click", cartShow); */
    jQuery(".cartInfo").unbind("click").one("click", function (event) {
        event.stopPropagation();
        event.stopImmediatePropagation();
        cartShow();
    });
    jQuery(".ioCart, .ioCart_link").unbind("click").one("click", function (event) {
        event.stopPropagation();
        event.stopImmediatePropagation();
        cartShow();
    });
    jQuery(".cartIcon").removeClass("fa-close").addClass("fa-shopping-cart");
}

/*
function set_date_cookie(){
  if(this.id.indexOf("start_") !== -1){
      setCookie("dateStart", this.value, 14);
  } else if(this.id.indexOf("end_") !== -1){
      setCookie("dateEnd", this.value, 14);
  }
}
*/
jQuery(document).ready(function () {
    setTimeout(simpleCart.init, 3);
});
/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Check availability All Call">*/
function checkAvailAll() {
    checkAvailCart();
    //checkAvailCartTimeslots();
    checkAvailPage();
    if (addressCookiesSet() && io_distance_charge) {
        runDeliveryCall(true);
    }
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Check availability - Page">*/

/* Helper: generate temporary event times for conditional price display when no date is set.
   These are LOCAL only and must NEVER be saved to IoData. */
function get_temp_event_times(duration_hours) {
    duration_hours = duration_hours || 1;
    let now = new Date();
    let end = new Date(now.getTime() + duration_hours * 60 * 60 * 1000);
    return {
        start_date: getFormatteddate(now),
        end_date: getFormatteddate(end),
        start_time: getFormattedtime(now),
        end_time: getFormattedtime(end),
        start_timestamp: now.getTime(),
        end_timestamp: end.getTime()
    };
}

/* for items on page not in cart */
function checkAvailPage() {
    let page_rentals = [];
    let cached_rentals = [];
    let has_event_time = IoData.event_time_set();
    let temp_times = has_event_time ? null : get_temp_event_times(1);
    // Rental page here. Need to think of separate, and linen type items.
    jQuery(".io_product_infobox").each(function(){
        let rental_id = jQuery(this).find(".item_rentalid").text();
        let first_id = rental_id.split(":")[0];
        let rental_name = jQuery(this).find(".item_name").text();
        let rental_qty = parseInt(jQuery(this).find(".item_qtyincrement").text());
        jQuery(".io_product_container").addClass("io-checking-availability");
        if(IoData.cached_item_needs_refreshed(rental_id, "info")) {
            rental_obj = new IO_Rental(rental_id, rental_name, rental_qty);
            rental_obj.rentalid_str = rental_id;
            if (rental_id.includes(":")) {
                rental_obj = add_included_accessories(rental_obj, rental_id, rental_name);
            }
            rental_obj = add_required_accessories(rental_obj);
            rental_obj.vendor = jQuery(this).find(".item_vendorid").text().trim();
            rental_obj.giftcard = jQuery(this).find(".item_giftcardvalue").text().trim();

            rental_obj = get_cond_prices(rental_obj);

            rental_obj.start_timestamp = has_event_time ? IoData.event_start_timestamp : temp_times.start_timestamp;
            rental_obj.end_timestamp = has_event_time ? IoData.event_end_timestamp : temp_times.end_timestamp;

            page_rentals.push(rental_obj);
        }else{
            rental_obj = IO_Rental.fromObject(IoData.get_info_cache(rental_id));
            if(!missing_conditional_prices(rental_obj)){
                cached_rentals.push(rental_obj);
            }else{
                rental_obj = get_cond_prices(rental_obj);
                page_rentals.push(rental_obj);
            }
        }
    });

    // Category Pages here. Only thing to worry about is show as separate situations.
    if(('IntersectionObserver' in window)){
        jQuery(".io_item2_list_inner").each(function(){
            let $item = jQuery(this);
            let rental_id = $item.find(".item_rentalid").text();
            let first_id = rental_id.split(":")[0];
            let rental_name = $item.find(".item_name").text();
            let rental_qty = parseInt($item.find(".item_qtyincrement").text());

            // Check if item is in viewport or near it (within 300px)
            if (is_element_in_viewport($item.parent()) || is_element_near_viewport($item.parent(), 300)) {
                if (IoData.cached_item_needs_refreshed(rental_id, "info")) {
                    rental_obj = new IO_Rental(rental_id, rental_name, rental_qty);
                    rental_obj.rentalid_str = rental_id;
                    if (rental_id.includes(":")) {
                        // Separate unit on category page.
                        rental_obj = add_included_accessories(rental_obj, rental_id, rental_name);
                    }
                    rental_obj = add_required_accessories(rental_obj);
                    rental_obj.vendor = jQuery(this).find(".item_vendorid").text().trim();
                    rental_obj.giftcard = jQuery(this).find(".item_giftcardvalue").text().trim();
                    rental_obj.start_timestamp = has_event_time ? IoData.event_start_timestamp : temp_times.start_timestamp;
                    rental_obj.end_timestamp = has_event_time ? IoData.event_end_timestamp : temp_times.end_timestamp;
                    page_rentals.push(rental_obj);
                } else {
                    cached_rentals.push(IO_Rental.fromObject(IoData.get_info_cache(rental_id)));
                }
                $item.attr('data-avail-checked', 'true');
                $item.parent().addClass("io-checking-availability");
            } else {
                $item.attr('data-avail-checked', 'false');
                observe_item_for_availability($item);
            }
        });
    } else{
        let $item = jQuery(this);
        let rental_id = $item.find(".item_rentalid").text();
        let first_id = rental_id.split(":")[0];
        let rental_name = $item.find(".item_name").text();
        let rental_qty = parseInt($item.find(".item_qtyincrement").text());

        if (IoData.cached_item_needs_refreshed(rental_id, "info")) {
            rental_obj = new IO_Rental(rental_id, rental_name, rental_qty);
            rental_obj.rentalid_str = rental_id;
            if (rental_id.includes(":")) {
                // Separate unit on category page.
                rental_obj = add_included_accessories(rental_obj, rental_id, rental_name);
            }
            rental_obj = add_required_accessories(rental_obj);
            rental_obj.vendor = jQuery(this).find(".item_vendorid").text().trim();
            rental_obj.giftcard = jQuery(this).find(".item_giftcardvalue").text().trim();
            rental_obj.start_timestamp = has_event_time ? IoData.event_start_timestamp : temp_times.start_timestamp;
            rental_obj.end_timestamp = has_event_time ? IoData.event_end_timestamp : temp_times.end_timestamp;
            page_rentals.push(rental_obj);
        } else {
            cached_rentals.push(IO_Rental.fromObject(IoData.get_info_cache(rental_id)));
        }
    }

    if(page_rentals.length){
        IoData.info = page_rentals;
        createOrUpdateLead("info", ["availability", "price"]);
    }
    if(cached_rentals.length){
        updatePageAvail(cached_rentals)
    }
}

function get_cond_prices(rental_obj){
    rental_id = rental_obj.rentalid;
    let has_event_time = IoData.event_time_set();

    if(io_delivery_prices){
        if(Object.keys(io_delivery_prices["override"]).includes(rental_id)){
            var delivery_prices = io_delivery_prices["override"][rental_id]
        }else{
            var delivery_prices = io_delivery_prices["default"]
        }
        let d_times = has_event_time ? null : get_temp_event_times(1);
        let d_start_date = has_event_time ? IoData.event_start_date_str : d_times.start_date;
        let d_end_date = has_event_time ? IoData.event_end_date_str : d_times.end_date;
        let d_start_time = has_event_time ? IoData.event_start_time_str : d_times.start_time;
        let d_end_time = has_event_time ? IoData.event_end_time_str : d_times.end_time;
        for(delivery_method_name in io_delivery_methods){
            if(delivery_prices.includes(io_delivery_methods[delivery_method_name]["id"])){
                let cond_price = new IO_ConditionalPrice(delivery_method_name,
                    io_delivery_methods[delivery_method_name]["id"], "Delivery Method",
                    d_start_date, d_end_date,
                    d_start_time, d_end_time, delivery_method_name);
                rental_obj.conditional_price = cond_price;
            }
        }
    }
    if(io_custom_prices){
        //Check if in override first then if not in override use default
        if (Object.keys(io_custom_prices["override"]).includes(rental_id)) {
            var custom_prices = io_custom_prices["override"][rental_id]
        } else {
            var custom_prices = io_custom_prices["default"]
        }

        for (let i = 0; i < custom_prices.length; ++i) {
            let c_times = has_event_time ? null : get_temp_event_times(parseFloat(custom_prices[i]['duration']));
            let start_date = has_event_time ? IoData.event_start_date_str : c_times.start_date;
            let start_time = has_event_time ? IoData.event_start_time_str : c_times.start_time;
            let end_date_obj = new Date(start_date + " " + start_time);
            let end_timestamp = end_date_obj.setTime(end_date_obj.getTime() + parseFloat(custom_prices[i]['duration']) * 60 * 60 * 1000)
            let cond_price = new IO_ConditionalPrice(custom_prices[i]["name"], custom_prices[i]["id"], "Custom",
                start_date, getFormatteddate(end_date_obj),
                start_time, getFormattedtime(end_date_obj));
            rental_obj.conditional_price = cond_price;
        }
    }
    if(use_weekday_weekend){
        let avail_times = has_event_time ? getAvailTimes() : [getFormatteddate(new Date()), null, null];
        let week_weekend = get_week_weekend_times(avail_times, rental_id);
        let weekday_end_date_obj = new Date(week_weekend['weekday'][0] + " " + week_weekend['weekday'][1]);
        weekday_end_date_obj.setTime(weekday_end_date_obj.getTime() + parseFloat(week_weekend['weekday'][2]) * 60 * 60 * 1000)
        let weekend_end_date_obj = new Date(week_weekend['weekend'][0] + " " + week_weekend['weekend'][1]);
        weekend_end_date_obj.setTime(weekend_end_date_obj.getTime() + parseFloat(week_weekend['weekend'][2]) * 60 * 60 * 1000)
        let weekday_cond_price = new IO_ConditionalPrice(io_weekDayText, "Weekday", "Weekday/Weekend",
            week_weekend['weekday'][0], getFormatteddate(weekday_end_date_obj),
            week_weekend['weekday'][1], getFormattedtime(weekday_end_date_obj));
        let weekend_cond_price = new IO_ConditionalPrice(io_weekEndText, "Weekend", "Weekday/Weekend",
            week_weekend['weekend'][0], getFormatteddate(weekend_end_date_obj),
            week_weekend['weekend'][1], getFormattedtime(weekend_end_date_obj));
        rental_obj.conditional_price = weekday_cond_price;
        rental_obj.conditional_price = weekend_cond_price;
    }
    return rental_obj;
}

function missing_conditional_prices(rental_obj){
    let rental_id = rental_obj.rentalid;
    delivery_missing = false;
    custom_missing = false;
    week_missing = false;
    if(io_delivery_prices){
        if(Object.keys(io_delivery_prices["override"]).includes(rental_id)){
            var delivery_prices = io_delivery_prices["override"][rental_id]
        }else{
            var delivery_prices = io_delivery_prices["default"]
        }
        for(let i = 0; i < delivery_prices.length; ++i){
            if(!rental_obj.find_conditional_price(delivery_prices[i], "Delivery Method")){
                delivery_missing = true;
                break;
            }
        }
    }
    if(io_custom_prices){
        if(Object.keys(io_custom_prices["override"]).includes(rental_id)){
            var custom_prices = io_custom_prices["override"][rental_id]
        }else{
            var custom_prices = io_custom_prices["default"]
        }
        for(let i = 0; i < custom_prices.length; ++i){
            if(!rental_obj.find_conditional_price(custom_prices[i].id, "Custom")){
                custom_missing = true;
                break;
            }
        }
    }
    if(use_weekday_weekend){
        if(!rental_obj.find_conditional_price("Weekday", "Weekday/Weekend") ||
           !rental_obj.find_conditional_price("Weekend", "Weekday/Weekend")){
            week_missing = true
        }
    }

    if(delivery_missing || custom_missing || week_missing){
        return true;
    }else{
        return false;
    }
}

function get_week_weekend_times(times, rid) {
    /* Create a copy instead of reference.*/
    let temp_times = JSON.parse(JSON.stringify(times));
    let start_date = temp_times[0];
    if (!start_date) {
        start_date = getFormatteddate(new Date());
        temp_times[0] = start_date;
    }
    temp_times[1] = io_default_start_time
    var newDate1 = convertDateStringtoDateObject(start_date, io_default_start_time);
    var newDate2 = convertDateStringtoDateObject(start_date, io_default_end_time);
    let time_duration = ((newDate2 - newDate1) / 3600) / 1000;
    temp_times[2] = time_duration;
    let day = new Date(start_date).getDay();
    let weekday_weekend = {};
    weekday_weekend["rid"] = rid;
    if (io_weekendDefine == "friday-sunday") {
        if (day == 5 || day == 6 || day == 0) {
            weekday_weekend["weekend"] = JSON.parse(JSON.stringify(temp_times));
            temp_times[0] = getNextMonday(temp_times[0]);
            weekday_weekend["weekday"] = JSON.parse(JSON.stringify(temp_times));
        } else if (day == 1 || day == 2 || day == 3 || day == 4) {
            weekday_weekend["weekday"] = JSON.parse(JSON.stringify(temp_times));
            temp_times[0] = getNextSaturday(temp_times[0]);
            weekday_weekend["weekend"] = JSON.parse(JSON.stringify(temp_times));
        }
    } else if (io_weekendDefine == "saturday-sunday") {
        if (day == 6 || day == 0) {
            weekday_weekend["weekend"] = JSON.parse(JSON.stringify(temp_times));
            temp_times[0] = getNextMonday(temp_times[0]);
            weekday_weekend["weekday"] = JSON.parse(JSON.stringify(temp_times));
        } else if (day == 1 || day == 2 || day == 3 || day == 4 || day == 5) {
            weekday_weekend["weekday"] = JSON.parse(JSON.stringify(temp_times));
            temp_times[0] = getNextSaturday(temp_times[0]);
            weekday_weekend["weekend"] = JSON.parse(JSON.stringify(temp_times));
        }
    }
    return weekday_weekend;
}

/*
  helper function found here:
  https://bobbyhadz.com/blog/javascript-get-date-of-next-monday#:~:text=To%20get%20the%20next%20Monday%2C%20we%3A&text=If%20the%20remainder%20is%20equal,month%20for%20the%20next%20Monday.
*/
function getNextMonday(date_str) {
    const date_obj = parseDate(date_str, dateFormat);

    const nextMonday = new Date(
        date_obj.setDate(
            date_obj.getDate() + ((7 - date_obj.getDay() + 1) % 7 || 7),
        ),
    );

    return getFormatteddate(nextMonday);
}

  function parseDate(date_str, format) {
      var parts = date_str.split(/[/.-]/);
      var day, month, year;

      if (format === "m/d/yy") {
          month = parseInt(parts[0]) - 1;
          day = parseInt(parts[1]);
          year = parseInt(parts[2]) + (parts[2].length === 2 ? 2000 : 0);
      } else if (format === "d/m/yy") {
          day = parseInt(parts[0]);
          month = parseInt(parts[1]) - 1;
          year = parseInt(parts[2]) + (parts[2].length === 2 ? 2000 : 0);
      } else if (format === "yy/m/d") {
          year = parseInt(parts[0]) + (parts[0].length === 2 ? 2000 : 0);
          month = parseInt(parts[1]) - 1;
          day = parseInt(parts[2]);
      } else {
          throw new Error("Unsupported date format");
      }

      return new Date(year, month, day);
  }

/* modified from function above */
function getNextSaturday(date_str) {
    const date_obj = parseDate(date_str, dateFormat);

    const next_friday = new Date(
        date_obj.setDate(
            date_obj.getDate() + ((7 - date_obj.getDay() + 6) % 7 || 7),
        ),
    );

    return getFormatteddate(next_friday);
}

function updatePageAvail(cached_rentals=null) {
    if(!cached_rentals){
        var rentals = IoData["info"];
    }else{
        var rentals = cached_rentals;
    }
    for(const rental of rentals){
        let rental_id_string = rental.rentalid_str;
        if(rental_id_string.includes(":")){
            if(rental_id_string.includes("_")){
                // Linen on item page.
                [main_id, after_colon] = rental_id_string.split(":");
                [second_id, third_id] = after_colon.split("_");
                if(second_id == main_id){
                    acc_qty_avail = rental.get_acc_property(third_id, "availability")
                    main_qty_avail = rental.availability;
                    // Use the lower of the two qty_avail since this is two items represented as one.
                    qty_avail = main_qty_avail < acc_qty_avail ? main_qty_avail : acc_qty_avail;
                    //if(!rental.required_accessoires_are_avail()) qty_avail = -1;
                    updatePageAvailChangePage(qty_avail, rental_id_string);
                }else{
                    // 2 levels
                    third_qty_avail =  rental.get_acc_property(third_id, "availability")
                    second_qty_avail = rental.get_acc_property(second_id, "availability")
                    main_qty_avail = rental.availability;
                    // Use the lowest of the three qty_avail since this is three items represented as one.
                    qty_avail = (second_qty_avail < third_qty_avail) ? second_qty_avail : third_qty_avail;
                    qty_avail = (main_qty_avail < qty_avail) ? main_qty_avail : qty_avail;
                    //if(!rental.required_accessoires_are_avail()) qty_avail = -1;
                    updatePageAvailChangePage(qty_avail, rental_id_string);
                }
            }else{
                //Separate units on category or item page.
                [main_id, acc_id] = rental_id_string.split(":");
                acc_qty_avail = rental.get_acc_property(acc_id, "availability")
                main_qty_avail = rental.availability;
                // Use the lower of the two qty_avail since this is two items represented as one.
                qty_avail = main_qty_avail < acc_qty_avail ? main_qty_avail : acc_qty_avail;
                //if(!rental.required_accessoires_are_avail()) qty_avail = -1;
                updatePageAvailChangePage(qty_avail, rental_id_string);
            }
        }else{
            qty_avail = rental.availability;
            if(!rental.required_accessoires_are_avail()) qty_avail = -1;
            updatePageAvailChangePage(qty_avail, rental_id_string);
        }
        if(jQuery(".io_product_container").length && jQuery(".io_product_container .item_rentalid").first().text() === rental_id_string){
            jQuery("#io_custom_prices_container").empty();
            jQuery("#io_delivery_prices_container").empty();
            jQuery("#io_week_prices_container").empty();
            for(let i = 0; i < rental.conditional_prices.length; ++i){
                rental.conditional_prices[i].display_conditional_price();
            }
        }
        if(!cached_rentals){
            IoData.info_cache = rental;
        }
    }
}

function updatePageAvailChangePage(qty, rental_id){
    jQuery(".cat_div_"+rental_id.replace(":", "\\\:")).removeClass("io-checking-availability");
    if (qty < 0) {
        /* cat,all-item,widget */
        if (io_checkavail == "warn") {
            jQuery(".add_cart_" + rental_id.replace(":", "\\\:") + " .item_add").removeClass("item_add").addClass("item_add_off").trigger("classChange");
            jQuery(".unavailable_message_" + rental_id.replace(":", "\\\:")).show();
        }
        if (io_checkavail == "hide") jQuery(".add_cart_" + rental_id).parent().parent().hide();

        /* product page */
        if (jQuery(".io_product_container").length && io_checkavail != "off" && jQuery(".io_product_container .item_rentalid").first().text() === rental_id) {
            if(rental_id.includes(":") && rental_id.includes(":")){
                rental_id = rental_id.split(":")[0];
            }
            jQuery(".add_cart_" + rental_id.replace(":", "\\\:") + " .item_add").first().removeClass("item_add").addClass("item_add_off").trigger("classChange");
            jQuery(".io_product_container .unavailable_message").show();
        }
        jQuery(".io_product_container").removeClass("io-checking-availability");
    } else if (qty >= 0) {
        if (io_checkavail == "warn") {
            jQuery(".add_cart_" + rental_id.replace(":", "\\\:") + " .item_add_off").removeClass("item_add_off").addClass("item_add").trigger("classChange");
            jQuery(".unavailable_message_" + rental_id.replace(":", "\\\:")).hide();
        }
        if (io_checkavail == "hide") jQuery(".add_cart_" + rental_id).parent().parent().show();

        /* product page */
        if (jQuery(".io_product_container").length && io_checkavail != "off" && jQuery(".io_product_container .item_rentalid").first().text() === rental_id) {
            if(rental_id.includes(":") && rental_id.includes(":")){
                rental_id = rental_id.split(":")[0];
            }
            jQuery(".add_cart_" + rental_id.replace(":", "\\\:") + " .item_add_off").removeClass("item_add_off").addClass("item_add").trigger("classChange");
            jQuery(".io_product_container .unavailable_message").hide();
        }
        jQuery(".io_product_container").removeClass("io-checking-availability");
    }
}

function checkAvailDateClick() {
    cartShow();
    /* expand the date picker */
    setTimeout(calSetDateRange, 100);
}

function updateAddToCartButtons() {
    var dateSet = IoData.event_time_set();
    if (dateSet) {
        jQuery(".item_add, .item_add_set_date").each(function () {
            jQuery(this).off("click.setdate");
            jQuery(this).removeClass("item_add_set_date").addClass("item_add");
            jQuery(this).html('<i class="fas fa-shopping-cart"></i> Add to Cart');
        });
    } else {
        jQuery(".item_add, .item_add_set_date").each(function () {
            jQuery(this).removeClass("item_add").addClass("item_add_set_date");
            jQuery(this).html('<i class="fas fa-calendar-alt"></i> Set Date');
            jQuery(this).off("click.setdate").on("click.setdate", function (e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                checkAvailDateClick();
            });
        });
    }
}

function checkAvailPageOnly() {
    checkAvailPage();
    if (addressCookiesSet() && io_distance_charge) {
        runDeliveryCall(true);
    }
}

function getUpsellIDforPrice() {
    let upsell_rentals = [];
    let cached_upsell_rentals = [];
    let page_cells = jQuery(".io_page_carousel_cell").toArray();
    for (let current_upsell = 0; current_upsell < page_cells.length; current_upsell++) {
        let page_cell = page_cells[current_upsell];
        let rid = jQuery(page_cell).find(".page-carousel-rid").text();
        let first_id = rid.split(":")[0];
        let name = jQuery(page_cell).find(".page-carousel-name").text();
        if(IoData.cached_item_needs_refreshed(rid, "info")){
            let rental_obj = new IO_Rental(first_id, name, 1);
            rental_obj.rentalid_str = rid;
            if (rid.includes(":")) {
                // Separate unit on category page.
                rental_obj = add_included_accessories(rental_obj, rid, name);
            }
            rental_obj = add_required_accessories(rental_obj);
            rental_obj.start_timestamp = IoData.event_start_timestamp;
            rental_obj.end_timestamp = IoData.event_end_timestamp;
            upsell_rentals.push(rental_obj);
        }else{
            cached_upsell_rentals.push(IO_Rental.fromObject(IoData.get_info_cache(rid)));
        }
    }
    if(cached_upsell_rentals.length){
        displayUpsellPrices(cached_upsell_rentals);
    }
    return upsell_rentals;
}

function displayUpsellPrices(cached_rentals=null) {
    if(!cached_rentals){
        var rentals = IoData["info"];
    }else{
        var rentals = cached_rentals;
    }
    for(const rental of rentals){
        let upsell_price = rental.price;
        let rid = rental.rentalid_str;
        if (io_hide_zero == 1 && upsell_price > 0) {
            let id_string = "#rid" + rid;
            let formatted_price = simpleCart.toCurrency(upsell_price);
            let price_display = '<span class="page-carousel-price"> ' + formatted_price + ' </span>';
            jQuery(id_string).after(price_display);
        } else if (io_hide_zero == 0) {
            let id_string = "#rid" + rid;
            let formatted_price = simpleCart.toCurrency(upsell_price);
            let price_display = '<span class="page-carousel-price"> ' + formatted_price + ' </span>';
            jQuery(id_string).after(price_display);
        }
        pageFlickityRefresh();
    }
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Check availability - Cart">*/
function showAvailInCartFromCache(){
    let cart_items = simpleCart.items();
    for(let i = 0; i<cart_items.length; ++i){

    }
}

function checkAvailCartOnly() {
    checkAvailCart();
    //checkAvailCartTimeslots();
    if (addressCookiesSet() && io_distance_charge) {
        runDeliveryCall(true);
    }
}


function checkAvailCart() {
    let cart_rentals = [];
    let cached_rentals = [];
    let cart_items = simpleCart.items();
    for(let i = 0; i<cart_items.length; ++i){
        if(cart_items[i].get("timeslots")){
            let timeslot_html = cart_items[i].get("timeslots");
            if(!timeslot_html.includes("<select")){
                rental_id = cart_items[i].get("rentalid");
                if(!jQuery(".item-timeslots [name='start_timeslot_"+rental_id+"']").val() || !jQuery(".item-timeslots [name='end_timeslot_"+rental_id+"']").val()){
                    continue
                }
            }
        }
        let cart_rental_obj = cart_items[i].get("rental_obj");

        // Update item times: use item-specific timeslot times if set, otherwise use event times
        let item_timeslots = cart_items[i].get("timeslots");
        if(item_timeslots){
            let timeslot_name = getTimeslotName(item_timeslots);
            if(item_timeslots.includes("<select")){
                // Select-based timeslots
                let timeslot_sel_range = jQuery(".item-timeslots [name=\"" + timeslot_name + "\"] option:selected").val();
                if(timeslot_sel_range){
                    let [ts_start_time, ts_end_time] = break_timeslot_sel_range(timeslot_sel_range);
                    cart_rental_obj.start_time = ts_start_time;
                    cart_rental_obj.end_time = ts_end_time;
                }
            }else{
                // Timepicker-based timeslots
                let [start_timepicker, end_timepicker] = get_cart_timepickers(timeslot_name);
                if(start_timepicker && end_timepicker && start_timepicker.value && end_timepicker.value){
                    cart_rental_obj.start_time = start_timepicker.value;
                    cart_rental_obj.end_time = end_timepicker.value;
                }
            }
        }else{
            // No item-specific timeslots — use event times
            cart_rental_obj.start_timestamp = IoData.event_start_timestamp;
            cart_rental_obj.end_timestamp = IoData.event_end_timestamp;
        }

        if(IoData.cached_item_needs_refreshed(cart_items[i].get("id"), "cart")) {
            cart_rentals.push(cart_rental_obj);
            // Set checking state on item to persist through cart regeneration
            cart_items[i].set("checking_availability", true);
        }else{
            cached_rental = IoData.get_cart_cache(cart_items[i].get("id"));
            cached_rental.cart_id = cart_rental_obj.cart_id;
            cached_rentals.push(cached_rental);
        }
    }
    if(cart_rentals.length>0){
        // Want to be sure the call includes all rentals in the cart to maintain lead.
        cart_rentals = [...cart_rentals, ...cached_rentals]
        IoData.cart = cart_rentals;
        ioCartLoaderIncrement();
        createOrUpdateLead("cart", ["availability", "price"]);
        ioCartLoaderDecrement();
    }else if(cached_rentals.length>0){
        updateCartAvail(cached_rentals);
    }else{
        IoData.cart = [];
        IoData.save_io_data()
    }
}

function updateCartAvail(cached_rentals = null) {
    let rental_objs_arr = [];
    if(cached_rentals){
        rental_objs_arr = cached_rentals;
    }else{
        rental_objs_arr = IoData.cart;
    }
    let cart_items = simpleCart.items();
    for(let i = 0; i < cart_items.length; ++i){
        var item = cart_items[i];
        var rental_obj = rental_objs_arr.find((obj) => obj.cart_id === item.get("id"));
        if(rental_obj){
            item.set("rental_obj", rental_obj);
            set_cart_item_avail(item);
            set_cart_item_price(item);
            if(!cached_rentals){
                IoData.cart_cache = item;
            }
            // Clear checking state after availability check completes
            item.set("checking_availability", false);
        }
    }
    simpleCart.update();
}

function set_cart_item_avail(item){
    const rental_obj = item.get("rental_obj");
    let availability = get_lowest_avail(rental_obj);
    // TODO: Do not show message unelss it is not available.
    //Separate units on category or item page.
    item.set("availability", availability);
    /*
    if(availability < 0){
        jQuery("#cartItem_"+item.id()+" .item-availability").removeClass("hidden_availability");
        if(io_hideQuantityAvail == "off"){

        }else{
            qty = availability + rental_obj.qty;
            item.set("availability", "not available");
        }
    }else{
        jQuery("#cartItem_"+item.id()+" .item-availability").addClass("hidden_availability");
        qty = availability + rental_obj.qty;
        item.set("availability", qty.toString()+" available");
    }*/
}
function set_cart_item_price(item){
    const rental_obj = item.get("rental_obj");
    let price = 0;
    price = get_total_price(rental_obj, price);
    item.set("price", price)
}

function get_lowest_avail(obj){
    let lowest = obj.availability;

    for(let i = 0; i < obj.accessories.length; ++i){
        let acc_lowest = get_lowest_avail(obj.accessories[i]);
        if(acc_lowest < lowest){
            lowest = acc_lowest;
        }
    }

    return lowest;
}
function get_total_price(obj, total){
    if(!obj.overrideprice || obj.overrideprice == 0){
        total += obj.price
    }

    for(let i = 0; i < obj.accessories.length; ++i){
        total = get_total_price_accessory(obj.accessories[i], total);
    }
    return total;
}
function get_total_price_accessory(obj, total){
    if(!obj.overrideprice || obj.overrideprice == 0){
        total += obj.price * obj.qty;
    }

    for(let i = 0; i < obj.accessories.length; ++i){
            total = get_total_price_accessory(obj.accessories[i], total);
    }
    return total;
}
/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Upsell Carousels">*/
function updateCartUpsell(data) {
    let cart_carousel = jQuery(".cart-carousel");
    viewport = jQuery(".cart-carousel .flickity-viewport");
    if (viewport.length > 0) {
        cart_carousel.flickity("destroy");
    }
    cart_carousel.empty();
    data.forEach(function (upsell) {
        cell = createCartCarouselCell(upsell["image"], upsell["name"], upsell["page"]);
        cart_carousel.append(cell);
    });
    makeCarousel(cart_carousel);
    jQuery("#cart-carousel-container").show();
    jQuery(".cart-carousel").flickity("resize");
}

function cartFlickityRefresh() {
    jQuery(".cart-carousel").flickity("resize");
    if (cart_info_flickity_enabled) {
        jQuery("#cartPartyBuilderFormContainer").flickity("resize");
    }
}
//IO-14031
function isMobile() {
    // Modern detection
    if (navigator.userAgentData && navigator.userAgentData.mobile !== undefined) {
        return navigator.userAgentData.mobile;
    }

    // Fallback for older browsers
    return /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent) ||
        ('ontouchstart' in window && navigator.maxTouchPoints > 0);
}

function makeCarousel(cart_carousel) {
    cart_carousel.flickity({
        wrapAround: true,
        draggable: isMobile(),
        cellAlign: 'left',
        //autoPlay: 3000,
        groupCells: true,
        resize: true
    });
    cart_carousel_set = true;
}

function createCartCarouselCell(image, name, page) {
    cell = '<div class="io_cart_carousel_cell"> <a href=' + page + ' class="cart-carousel-link"> <img class="cart-carousel-image" src=' + image + '> <p class="cart-carousel-name"> ' + name + ' </p> </a> </div>';
    return cell;
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Ajax Calls">*/


function getUpsellsCall(start_date, start_time, time_duration, rental_ids, returnFunc) {
    if (rental_ids.replace(/[|]/g, "").length == 0) {
        return;
    }
    let url = "https://rental.software/quotes/in_cart_upsell.php?callback=?";
    if (window.location.href.indexOf("localhost") > -1) {
        //url = "http://localhost/bugs/quotes/in_cart_upsell.php?callback=?"
        url = "http://localhost/io/bugs/quotes/in_cart_upsell.php?callback=?"
    }
    url +=
        "&name=" + encodeURIComponent(io_pagename) +
        "&startdate=" + start_date +
        "&starttime=" + start_time +
        "&duration=" + time_duration +
        "&usecushion=1" +
        "&include_price=1" +
        "&showlocations=0" +
        "&rental_ids=" + rental_ids;
    //IO-25557
    if (window.location.href.indexOf("dev.rental.software") > -1)//if it is a dev site, we need to send
    {
        let pattern = /(https:\/\/dev\.rental\.software\/[^\/]+\/)/;
        let matches = window.location.href.match(pattern);
        matches && matches.length > 0 ? url += "&site=" + matches[0] : 0;
    } else {
        url += "&site=" + window.location.host;
    }
    jQuery.getJSON(url, returnFunc);
}
/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Loading Animation Helpers">*/

/**
 * Toggles the visibility of the cart loading overlay.
 *
 * @param {boolean} show - A boolean value to determine whether to show or hide the overlay.
 *                         If true, the overlay becomes visible; if false, it is hidden.
 * @return {void} This function does not return a value.
 */
function ioCartShowOverlay(show)
{
    try
    {
        var overlay = document.getElementById('ioCartLoadingOverlay');
        if (!overlay) return;
        if (show)
        {
            overlay.style.display = 'flex';
            overlay.setAttribute('aria-hidden', 'false');
        }
        else
        {
            overlay.style.display = 'none';
            overlay.setAttribute('aria-hidden', 'true');
        }
    }
    catch (e)
    {}
}

/**
 * Activates the cart loader by setting the loading state to active, initializing the loading count,
 * and displaying the overlay. Includes a fallback to deactivate the loader if no response is received
 * within a specified timeout period.
 *
 * @return {void} This method does not return a value.
 */
function ioCartLoaderActivate()
{
    io_cart_loading_active = true;
    io_cart_loading_count = 0;
    ioCartShowOverlay(true);

    //fallback in case the availability call doesn't come back
    if (io_cart_loading_fallback_timer) clearTimeout(io_cart_loading_fallback_timer);
    io_cart_loading_fallback_timer = setTimeout(function () {
        if (io_cart_loading_active) {
            io_cart_loading_active = false;
            io_cart_loading_count = 0;
            ioCartShowOverlay(false);
        }
    }, 15000);
}

/**
 * Increments the count of active cart loading operations and ensures the cart overlay is displayed.
 *
 * This method increases the `io_cart_loading_count` if the `io_cart_loading_active` flag is set to true.
 * It also calls the `ioCartShowOverlay` function with a true value to show the overlay.
 *
 * @return {void} This function does not return any value.
 */
function ioCartLoaderIncrement()
{
    if (io_cart_loading_active)
    {
        io_cart_loading_count++;
        ioCartShowOverlay(true);
    }
}

/**
 * Decrements the `io_cart_loading_count` if `io_cart_loading_active` is true.
 * If the count reaches zero, it deactivates the loader, removes the overlay,
 * and clears the fallback timer
 */
function ioCartLoaderDecrement()
{
    if (io_cart_loading_active)
    {
        io_cart_loading_count = Math.max(0, io_cart_loading_count - 1);

        if (io_cart_loading_count === 0)
        {
            io_cart_loading_active = false;
            ioCartShowOverlay(false);

            if (io_cart_loading_fallback_timer)
            {
                clearTimeout(io_cart_loading_fallback_timer);
                io_cart_loading_fallback_timer = null;
            }
        }
    }
}

/*</editor-fold>*/

/*<editor-fold defaultstate="collapsed" desc="Customer Geolocation Functions">*/
function setLocationInLocalStorage(city)
{
    try
    {
        const location_data =
            {
                city: city,
                timestamp: Date.now()
            };
        localStorage.setItem(storage_key, JSON.stringify(location_data));
        return true;
    }
    catch (e)
    {
        console.warn('Failed to save location to localStorage:', e);
        return false;
    }
}

function getLocationFromLocalStorage()
{
    try
    {
        const location_data = localStorage.getItem(storage_key);
        if (location_data)
        {
            return JSON.parse(location_data);
        }

    }
    catch (e)
    {
        console.warn('Failed to retrieve location from localStorage:', e);
    }
    return null;
}

function displayLocation(city)
{
    const location_element = jQuery('.io_geo_city');
    const container_element = jQuery('#io_customer_geolocation');

    if (location_element.length && container_element.length)
    {
        location_element.text(`${city}`);
        container_element.show();
        return true;
    }
    return false;
}

function getCityFromIO(returnFunc)
{
    var url = "https://rental.software/include/geolocation_handler.php?callback=?";
    if(window.location.href.indexOf("localhost") > -1)
    {
        url = "http://localhost//features//include/geolocation_handler.php?callback=?";
    }
    url +=
        "&name=" + encodeURIComponent("%%page%%") +
        "&ip=" + encodeURIComponent(io_customer_ip);

    jQuery.getJSON(url, returnFunc);
}

function initializeGeolocation()
{
    try
    {
        // Check local storage first
        const cached_location = getLocationFromLocalStorage();
        if (cached_location && cached_location.city)
        {
            if (displayLocation(cached_location.city))
            {
                return;
            }
        }

        // If no cached location, call the handler to get location
        getCityFromIO(function(location_data)
        {
            if (location_data && location_data.city && !location_data.error)
            {
                // Display and store the location
                if (displayLocation(location_data.city))
                {
                    setLocationInLocalStorage(location_data.city);
                }
            }
            else
            {
                console.warn('Failed to get location:', location_data ? location_data.error : 'Unknown error');
            }
        });
    }
    catch (error)
    {
        console.error('Geolocation initialization failed:', error);
    }
}
/*</editor-fold>*/