您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sorts items by price per unit (e.g. `per kg` or `per litre`) in Carrefour online shops in Poland.
// ==UserScript== // @name carrefour per unit price sorter // @name:pl carrefour sortowanie po cenie jednostki // @namespace cprn // @license GPLv3 // @match https://*.carrefour.pl/* // @grant none // @version 0.3 // @esversion 11 // @author cprn // @run-at document-idle // @date 2025-04-26 17:17:26 // @description Sorts items by price per unit (e.g. `per kg` or `per litre`) in Carrefour online shops in Poland. // @description:pl Sortuje produkty po cenie za jednostkę (np. za `kg` albo `l`) w sklepie internetowym polskiego Carrefoura. // ==/UserScript== // vim copy to clipboard: // map ,r :wa<cr>gg"+yGzz (function() { 'use strict'; const DEBUG = 1; function discoverClasses() { let priceTag = null; ['zł/1 l', 'zł/1 kg'].every(s => { let xpath = `//p[contains(., '${s}')]`; priceTag = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; return priceTag === null; }); if (!priceTag) { console.error("Could not find priceTag"); return null; } return { item: priceTag.parentNode.parentNode.parentNode.parentNode.classList[0], perUnitStrip: priceTag.parentNode.classList[0], mass: priceTag.parentNode.children[0].classList[0], perMass: priceTag.parentNode.previousSibling.children[0].children[0].classList[0], }; } function perUnitPrice(e, classes) { let perUnit = e.getElementsByClassName(classes.perUnitStrip)[0]?.lastChild; let perMass = e.getElementsByClassName(classes.perMass)[0]; let mass = e.getElementsByClassName(classes.mass)[0]?.lastChild; if (!perUnit || !mass) { console.debug('unknown price', e); return Infinity; // Treat unknowns as very expensive } else if (mass.innerText == '1 l' || mass.innerText == '1 kg') { var price = ''.concat(perMass.children[0].innerText, '.', perMass.children[1].innerText); } else { var price = perUnit.innerText.slice(0, -7).replace(',', '.'); } return parseFloat(price); } function sortItems() { const classes = discoverClasses(); if (!classes) { console.error("cprn: no classes found"); return; } const items = Array.from(document.getElementsByClassName(classes.item)); const parent = items[0]?.parentNode; if (!parent) { console.error("cprn: no parent found"); return; } DEBUG && console.debug('cprn: first item', items[0]) DEBUG && console.debug('cprn: items container', items[0].parentNode) DEBUG && console.debug('cprn: classes\n--------------------\n' + 'item: ' + classes.item, document.getElementsByClassName(classes.item)[0], '\n' + 'perUnitStrip: ' + classes.perUnitStrip, document.getElementsByClassName(classes.perUnitStrip)[0], '\n' + 'mass: ' + classes.mass, document.getElementsByClassName(classes.mass)[0], '\n' + 'perMass: ' + classes.perMass, document.getElementsByClassName(classes.perMass)[0], '\n' + 'perUnit: ', perUnitPrice(items[0], classes ) ); console.log('cprn: solving world hunger...') items.sort((a, b) => perUnitPrice(a, classes) - perUnitPrice(b, classes)); items.forEach(item => parent.appendChild(item)); console.log('cprn: done') } function waitForPage() { const check = setInterval(() => { if (document.readyState === 'complete') { clearInterval(check); setTimeout(sortItems, 1000); } }, 300); } waitForPage(); })();