Сейчас узнаем, какой подарок выпадет именно Вам
Крутите колесо
Как сосчитать срок аренды в корзине в Tilda
Аренда фотоаппарата
Canon
More products

Как сосчитать срок аренды в корзине в Tilda

1
Создали корзину ST100
2
Создали поля:
- текстовый комментарий с надписью - Выберете даты получения и возврата и задали этому тексту ссылку #date-message
- два поля выбора дат с именами datestart и dateend (ограничили выбор прошедших дат, а для даты сдачи и текущий день)
3
В настройках корзины запретили сохранение товара и изменение количества
4
Вставили код в блок Другое - Т123

Mo-ti Level Up
Видео инструкции по добавлению кода и работе с Zero Block.
Как сосчитать срок аренды в корзине в Tilda
Фрагмент видео
Библиотека для примера
<script>
(function () {
    let correction = false;  // коррекция количества (true - уменьшаем, false - оставляем как есть)
    const MIN_RENTAL_DAYS = 3;  // Минимальный срок аренды в днях
    
    // Сообщения
    const MESSAGE_ERROR = `Минимальная аренда ${MIN_RENTAL_DAYS} дн.`;
    const MESSAGE_SUCCESS = "Срок аренды: ";
    
    const CART_SELECTOR = ".t706";
    const DATE_START_SELECTOR = 'input[name="datestart"]';
    const DATE_END_SELECTOR = 'input[name="dateend"]';
    const SUBMIT_BUTTON_SELECTOR = "button.t-submit";
    const MESSAGE_SELECTOR = 'a[href="#date-message"]';
    const QNT_DISPLAY_SELECTOR = '.t706__product-quantity'; 
    const QNT_INPUT_SELECTOR = '.t706__product-quantity input'; 
    
    // Правила коррекции количества (чем больше дней, тем больше вычитаем)
    const CORRECTION_RULES = [
        { threshold: 20, subtract: 5 },
        { threshold: 10, subtract: 2 },
        { threshold: 5, subtract: 1 }
    ];
    

    let isInitialized = false;
    let cartObserver = null;
    let originalOpenCart = null;
    let firstOpenAfterInit = true;
    const processedCarts = new WeakSet();
    
    
    function parseDate(dateString) {
        if (!dateString) return null;
        
        let separator;
        if (dateString.includes('/')) separator = '/';
        else if (dateString.includes('-')) separator = '-';
        else if (dateString.includes('.')) separator = '.';
        else return null;
        
        let parts = dateString.split(separator);
        if (parts.length !== 3) return null;

        let day, month, year;
        
        if (parseInt(parts[0]) > 31) {
            year = parseInt(parts[0]);
            month = parseInt(parts[1]) - 1;
            day = parseInt(parts[2]);
        } else {
            day = parseInt(parts[0]);
            month = parseInt(parts[1]) - 1;
            year = parseInt(parts[2]);
        }
        
        return new Date(year, month, day);
    }
    
    function getDaysDifference(startDate, endDate) {
        if (!startDate || !endDate) return null;
        
        const start = new Date(startDate);
        start.setHours(0, 0, 0, 0);
        const end = new Date(endDate);
        end.setHours(0, 0, 0, 0);
        
        const diffTime = end - start;
        const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
        
        return diffDays;
    }
    
    function toggleClass(element, className, add) {
        if (!element) return;
        if (add) {
            element.classList.add(className);
        } else {
            element.classList.remove(className);
        }
    }
    
    function calculateQuantity(days, applyCorrection) {
        if (!applyCorrection) {
            return days;
        }
        
        let newQuantity = days;
        for (let rule of CORRECTION_RULES) {
            if (days >= rule.threshold) {
                newQuantity = days - rule.subtract;
                break; 
            }
        }
        
        return newQuantity;
    }
    
    function updateQuantity(cartElement, days) {
        const quantityDisplay = cartElement.querySelector(QNT_DISPLAY_SELECTOR);
        if (!quantityDisplay) return;
        
        const startDateInput = cartElement.querySelector(DATE_START_SELECTOR);
        const endDateInput = cartElement.querySelector(DATE_END_SELECTOR);
        
        if (!startDateInput || !endDateInput) return;
        
        const startDate = parseDate(startDateInput.value);
        const endDate = parseDate(endDateInput.value);
        
        if (!startDate || !endDate) return;
        
        const actualDays = getDaysDifference(startDate, endDate);
        if (actualDays !== days) return;
        
        const newQuantity = calculateQuantity(days, correction);
        const qntInput = cartElement.querySelector(QNT_INPUT_SELECTOR);
        
        if (qntInput && parseInt(qntInput.value) === newQuantity) return;
        
        quantityDisplay.click();
        setTimeout(() => {
            const qntInput = cartElement.querySelector(QNT_INPUT_SELECTOR);
            if (qntInput) {
                qntInput.setAttribute('autocomplete', 'off');
                qntInput.setAttribute('autocorrect', 'off');
                qntInput.setAttribute('autocapitalize', 'off');
                qntInput.setAttribute('spellcheck', 'false');

                qntInput.value = newQuantity;

                qntInput.dispatchEvent(new Event('input', { bubbles: true }));
                qntInput.blur();
                const focusoutEvent = new Event('focusout', { bubbles: true });
                qntInput.dispatchEvent(focusoutEvent);
                const enterEvent = new KeyboardEvent('keydown', {
                    key: 'Enter',
                    code: 'Enter',
                    keyCode: 13,
                    bubbles: true
                });
                qntInput.dispatchEvent(enterEvent);
            }
        }, 50);
    }

    function updateDateValidation(cartElement, startDate, endDate) {
        const days = getDaysDifference(startDate, endDate);
        const submitButton = cartElement.querySelector(SUBMIT_BUTTON_SELECTOR);
        const dateEndInput = cartElement.querySelector(DATE_END_SELECTOR);
        const messageElement = cartElement.querySelector(MESSAGE_SELECTOR);
        
        if (days !== null && days < MIN_RENTAL_DAYS) {
            if (submitButton) submitButton.type = "button";
            toggleClass(dateEndInput, "redtext", true);
            if (messageElement) {
                messageElement.textContent = MESSAGE_ERROR;
                toggleClass(messageElement, "redtext", true);
            }
        } else if (days !== null && days >= MIN_RENTAL_DAYS) {
            if (submitButton) submitButton.type = "submit";
            toggleClass(dateEndInput, "redtext", false);
            if (messageElement) {
                messageElement.textContent = MESSAGE_SUCCESS + days + " дн.";
                toggleClass(messageElement, "redtext", false);
            }
            
            updateQuantity(cartElement, days);
        }
    }
    
    function handleDatesChange(cartElement) {
        const startDateInput = cartElement.querySelector(DATE_START_SELECTOR);
        const endDateInput = cartElement.querySelector(DATE_END_SELECTOR);
        
        if (!startDateInput || !endDateInput) return;
        
        const startDate = parseDate(startDateInput.value);
        const endDate = parseDate(endDateInput.value);

        if (startDate && endDate) {
            updateDateValidation(cartElement, startDate, endDate);
        } else if (endDateInput.value && !startDateInput.value) {
            const submitButton = cartElement.querySelector(SUBMIT_BUTTON_SELECTOR);
            if (submitButton) submitButton.type = "button";
        }
    }
    
    function initCartHandlers(cartElement) {
        if (processedCarts.has(cartElement)) return;
        
        const startDateInput = cartElement.querySelector(DATE_START_SELECTOR);
        const endDateInput = cartElement.querySelector(DATE_END_SELECTOR);
        
        if (!startDateInput || !endDateInput) return;

        const handleChange = function() {
            handleDatesChange(cartElement);
        };

        startDateInput.addEventListener('input', handleChange);
        endDateInput.addEventListener('input', handleChange);

        startDateInput.addEventListener('change', handleChange);
        endDateInput.addEventListener('change', handleChange);

        processedCarts.add(cartElement);

        cartElement._dateHandlers = {
            startInput: handleChange,
            endInput: handleChange,
            startChange: handleChange,
            endChange: handleChange
        };

        setTimeout(() => handleDatesChange(cartElement), 100);
    }
    
    function initAllCarts() {
        const cartElements = document.querySelectorAll(CART_SELECTOR);
        
        cartElements.forEach(cartElement => {
            const submitButton = cartElement.querySelector(SUBMIT_BUTTON_SELECTOR);
            if (submitButton && submitButton.type === 'submit') {
                submitButton.type = 'button';
            }
            
            initCartHandlers(cartElement);
        });
    }
    
    function observeCartElements() {
        if (cartObserver) {
            cartObserver.disconnect();
        }
        
        cartObserver = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1) {
                        if (node.matches && node.matches(CART_SELECTOR)) {
                            initCartHandlers(node);
                        } else if (node.querySelectorAll) {
                            const cartElements = node.querySelectorAll(CART_SELECTOR);
                            cartElements.forEach(cartElement => {
                                initCartHandlers(cartElement);
                            });
                        }
                    }
                });
            });
        });
        
        cartObserver.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
    
    function checkCartOnOpen() {
        const cartElements = document.querySelectorAll(CART_SELECTOR);
        cartElements.forEach(cartElement => {
            const startDateInput = cartElement.querySelector(DATE_START_SELECTOR);
            const endDateInput = cartElement.querySelector(DATE_END_SELECTOR);
            
            if (startDateInput && startDateInput.value && endDateInput && endDateInput.value) {
                handleDatesChange(cartElement);
            }
        });
    }

    function overrideCartOpen() {
        if (typeof window.tcart__openCart !== 'undefined' && !originalOpenCart) {
            originalOpenCart = window.tcart__openCart;
            
            window.tcart__openCart = function(...args) {
                const result = originalOpenCart.apply(this, args);
                
                setTimeout(() => {
                    checkCartOnOpen();
                }, 100);
                
                return result;
            };
        }
    }
    
    function init() {
        if (isInitialized) return;
        
        initAllCarts();
        observeCartElements();
        overrideCartOpen();
        
        isInitialized = true;
    }
    
    document.addEventListener("DOMContentLoaded", function() {
        t_onReady(function() {
            setTimeout(function() {
                t_onFuncLoad('tcart__init', function() {
                    init();
                });
            }, 200);
        });
    });
    
})();
</script>

<style>

#allrecords a[href="#date-message"]
{
    color: #000;
    pointer-events: none;
}

#allrecords a.redtext[href="#date-message"] ,
input.redtext {
    color: #ff0000 !important;
}

.t706 button.t-submit[type="button"] {
    pointer-events: none;
    opacity: 0.5;
    filter: grayscale(1);
}

</style>
Made on
Tilda