atbmarket.com - price for kilogram

Shows price per kilo for products in catalog/search/product page. Improves voice search expirience with dictanote.co chrome extension

当前为 2024-03-04 提交的版本,查看 最新版本

// ==UserScript==
// @name         atbmarket.com - price for kilogram
// @name:uk      atbmarket.com - ціна за кілограм
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  Shows price per kilo for products in catalog/search/product page. Improves voice search expirience with dictanote.co chrome extension
// @description:uk Показує ціну за кілограм для продуктів у каталозі/пошуку/на сторінці продукту. Покращує роботу голосового пошуку за допомогою розширення dictanote.co для Google Chrome
// @author       Untiy16
// @license      MIT
// @match        https://www.atbmarket.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=atbmarket.com
// @grant        GM_addStyle
// @require      https://code.jquery.com/jquery-3.7.1.min.js
// ==/UserScript==

'use strict';

//regex to parse weight from product title
const regex = /(\d+(?:[\.,]\d+)?)\s*(г|кг|мл|л)(?=($|\s|\W))/m;
const regexTeaBag = /(\d+)\s*(ф\/п)\s*(\*|x|X|х|Х)\s*(\d+(?:[\.,]\d+)?)/m;
let isActive = (localStorage.getItem('pricePerKiloMode') ?? 'true') === 'true';

//Add toggle to quick disable/enable 'price for kilo' functionality
$('.top-header__phone-tablet')
    .clone()
    .insertAfter($('.top-header__phone-tablet'))
    .html(`Ціна за кілограм <input type="checkbox" id="pricePerKiloMode" ${isActive ? 'checked' : ''}>`);

//add class to body and state to localStorage
$(pricePerKiloMode)
    .change(function() {
        isActive = pricePerKiloMode.checked;
        localStorage.setItem('pricePerKiloMode', isActive);
        $('body').toggleClass('price-per-kilo_global--hidden', !isActive);
    })
    .change();

//-------------- TRIGGER VOICE INPUT SECTION START ---------------//
setInterval(() => {
    if ($('#q').is(':visible') && $('#voicein_container').is(':visible')) {
        //trigger site search after voice input
        if (q.value != '' && Multisearch.config.hash != encodeURI(q.value)) {
            Multisearch.config.hash = encodeURI(q.value);
            location.href = `${location.pathname}${Multisearch.config.search_path}${q.value}`;
            // location.reload();
        }

        //erace previous text from search input before inserting
        if ($('#q').is(':visible') && $('#voicein_container').length && $($('#voicein_container')[0].shadowRoot).find('#voicein_voicebox').is(':visible')) {
            q.value = '';
        }
    }
}, 1000);
//-------------- TRIGGER VOICE INPUT SECTION END ---------------//

//-------------- LIST SECTION START ---------------//
//add price per kilo blocks to products in catalog
function handleCatalogItem(item) {
    let title = $(item).find('.catalog-item__title').text().trim();
    let match = getMatch(title);
    if (match !== null) {
        $(item)
            .find('> .catalog-item__bottom')
            .clone()
            .insertAfter($(item).find('> .catalog-item__bottom'))
            .addClass('price_per_kilo catalog-item__price-per-kilo catalog-item__price-per-kilo--value catalog-item__price-per-kilo--hidden')
            .find('.catalog-item__counter').remove();

        let $priceBlock = $(item).find('> .catalog-item__bottom').last();
        insertPricesPerKilo($priceBlock, getFormatedWeight(match));
    }
}

let $products = $('article.catalog-item');
$(document).on('mouseenter mouseleave', 'article.catalog-item', function() {
    if (!$(this).find('.catalog-item__price-per-kilo').length) {
        handleCatalogItem(this);
    }
    $(this).find('.catalog-item__price-per-kilo').toggleClass('catalog-item__price-per-kilo--hidden');
});
//-------------- LIST SECTION END ---------------//

//--------------PROD PAGE SECTION START ---------------//
//add price per kilo block on product page
if (location.pathname.includes('/product/')) {
    let title = $('.product-page__title').text().trim();
    let match = getMatch(title);
    if (match !== null) {
        $('.product-about__buy-row').clone().insertAfter($('.product-about__buy-row'));
        let $priceBlock = $('.product-about__buy-row').last();
        $priceBlock.css({'grid-row': 'unset'});
        $priceBlock.addClass('price_per_kilo product-about__price-per-kilo product-about__price-per-kilo--value');
        $priceBlock.find('.product-about__counter').remove();
        insertPricesPerKilo($priceBlock, getFormatedWeight(match));
    }
}
//--------------PROD PAGE SECTION END ---------------//

//--------------SEARCH SECTION START ---------------//
//add price per kilo and relevant price to products in search popap
$(document).on('mouseenter', '.multi-search .multi-item', function() {
    let $this = $(this);
    if ($this.find('.search-custom-price').length || $this.hasClass('search-custom-price--loading')) {
        return false;
    }

    $this.addClass('search-custom-price--loading');
    let title = $this.find('.multi-content a span').text().trim();
    let match = getMatch(title);

    let url = $this.find('.multi-content a').attr('href');
    $.get(url, function(data) {
        let $data = $(data).find('.product-main .product-price--weight');
        let price = parseFloat($data.find('.product-price__top span').text());
        let oldPrice = parseFloat($data.find('.product-price__bottom span').text());
        let card = parseFloat($data.find('.atbcard-sale__price-top span').text());
        $this.find('.multi-oldPrice, .multi-price').hide();
        $(getSearchPricesHtml(match ? getFormatedWeight(match) : 0, price, oldPrice, card)).insertBefore($this.find('.b-addToCart'));
    }).always(function() {
        $this.removeClass('search-custom-price--loading');
    });
});
//--------------SEARCH SECTION END ---------------//


//-------------- HELPERS ---------------//
function getSearchPricesHtml(weight, price, oldPrice = 0, card = 0) {
    let picePerK
    return `
        <div class="search-custom-price">
            ${oldPrice ? `<div class="search-custom-price_bottom">${addTracingZero(oldPrice)}</div>` : ''}
            <div class="search-custom-price_top">${addTracingZero(price)}</div>
            ${card ? `<div class="search-custom-price_card">${addTracingZero(card)}</div>` : ''}
        </div>
        ${weight ?
            `
            <div class="price_per_kilo search-custom-price__price-per-kilo search-custom-price__price-per-kilo--text">-- Ціна за кілограм --</div>
            <div class="search-custom-price price_per_kilo search-custom-price__price-per-kilo .search-custom-price__price-per-kilo--text">
                ${oldPrice ? `<div class="search-custom-price_bottom">${getPricePerKilo(oldPrice, weight).price}</div>` : ''}
                <div class="search-custom-price_top">${getPricePerKilo(price, weight).price}</div>
                ${card ? `<div class="search-custom-price_card">${getPricePerKilo(card, weight).price}</div>` : ''}
            </div>`
            :
            ''
        }
    `;
}

function getPricePerKilo(price, weight) {
    price = Math.round((price * 1000 / weight) * 100) / 100;
    price = price.toString();
    let intPart = price.split('.')[0];
    let decimalPart = price.split('.')[1];
    decimalPart = decimalPart ? decimalPart : '0';
    decimalPart = addTracingZero(decimalPart, true);

    return {
        'price': addTracingZero(price),
        'int': intPart,
        'decimal': decimalPart,
    }

}

function addTracingZero(price, isDecimalPart = false) {
    price = price.toString();
    // price = !price.includes('.') && !isDecimalPart ? `${price}.00` : price;

    return (
            (isDecimalPart && price.length === 2) ||
            (price.includes('.') && price.split('.')[1].length === 2) ||
            (!price.includes('.') && !isDecimalPart)
        )
        ?
        price
        :
        `${price}0`;
}

function getFormatedWeight(match) {
   return (match[2] === 'кг'
    || match[2] === 'л')
        ? match[1].replaceAll(',', '.') * 1000 : parseInt(match[1]);
}

function insertPricesPerKilo($priceBlock, weight) {
    let $cardPrice = $priceBlock.find('.atbcard-sale__price-top');
    if ($cardPrice.length) {
        let price = getPricePerKilo($cardPrice.attr('value'), weight);
        $cardPrice.html(`<span>${price.int}.<sup class="product-price__coin">${price.decimal}</sup></span>`)
    }

    let $topPrice = $priceBlock.find('.product-price__top');
    if ($topPrice.length) {
        let price = getPricePerKilo(parseFloat($topPrice[0].innerText), weight);
        $topPrice = $topPrice.find('> span').eq(0);
        $topPrice.html(`<span>${price.int}.<sup class="product-price__coin">${price.decimal}</sup></span>`)
        $topPrice.next().find('span').text('/кг');
    }

    let $bottomPrice = $priceBlock.find('.product-price__bottom');
    if ($bottomPrice.length) {
        let price = getPricePerKilo(parseFloat($bottomPrice[0].innerText), weight);
        $bottomPrice = $bottomPrice.find('> span').eq(0);
        $bottomPrice.html(`<span>${price.int}.<sup class="product-price__coin">${price.decimal}</sup></span>`)
    }
}

function getMatch(title) {
    let teabagMatch = regexTeaBag.exec(title);
    
    if (teabagMatch !== null) {
        return [
            '',
            eval(teabagMatch[0].replace('ф/п', '').replaceAll(' ', '').replace(',', '.').replace(/x|X|х|Х/, '*')),
            'г'
        ];
    } else {
        return regex.exec(title);
    }
}

//-------------- STYLES ---------------//

GM_addStyle(`
    .catalog-item__price-per-kilo--hidden {
        display: none !important;
    }

    .price-per-kilo_global--hidden .price_per_kilo {
        display: none !important;
    }

    .search-custom-price {
        display: flex;
        align-items: center;
        margin-bottom: 10px;
    }

    .search-custom-price_bottom,
    .search-custom-price_top,
    .search-custom-price_card {
        font-weight: 600;
        margin-right: 5px;
    }

    .search-custom-price_bottom:last-child,
    .search-custom-price_top:last-child,
    .search-custom-price_card:last-child {
        margin-right: 0px;
    }

    .search-custom-price_bottom {
        text-decoration: line-through;
        color: var(--text-grey);
    }

    .search-custom-price_top {
        color: var(--text-color);
    }

    .search-custom-price_bottom + .search-custom-price_top {
        color: var(--accent-color) !important;
    }

    .search-custom-price_card {
        width: fit-content;
        padding: 2px 4px;
        color: var(--accent-light);
        background: #28aa4e;
        border-radius: 4px;
    }

    .search-custom-price__price-per-kilo--text {
        margin-top: -10px;
        font-weight: 600;
        font-size: 12px;
        color: var(--text-color);
    }

    .product-about__price-per-kilo {
        margin-top: 15px;
        position: relative;
    }

    .product-about__price-per-kilo::before {
        content: '------- Ціна за кілограм -------';
        position: absolute;
        top: -30px;
        left: 0;
        font-weight: bold;
    }

    .catalog-item__price-per-kilo {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        margin-top: 50px !important
    }

    .catalog-item__price-per-kilo .atbcard-sale {
        position: static;
    }

    .catalog-item__price-per-kilo::before {
        content: '------- Ціна за кілограм -------';
        position: absolute;
        top: -15px;
        left: 0;
        font-weight: bold;
        transform: translateY(-100%);
    }

    .multi-results .multi-label {
        width: min-content;
    }
`);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址