79 lines
3.8 KiB
JavaScript
79 lines
3.8 KiB
JavaScript
// ==UserScript==
|
||
// @name [e-dostavka.by, gipermall.by] price comparison
|
||
// @namespace http://tampermonkey.net/
|
||
// @version 2.0
|
||
// @description Show prices per kilo, compare between sites
|
||
// @author fulloftsars
|
||
// @match https://e-dostavka.by/*
|
||
// @match https://gipermall.by/*
|
||
// @grant unsafeWindow
|
||
// @grant GM.xmlHttpRequest
|
||
// @require https://cdnjs.cloudflare.com/ajax/libs/arrive/2.4.1/arrive.min.js
|
||
// @require https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js
|
||
// @require https://unpkg.com/ohm-js@0.14.0/dist/ohm.min.js
|
||
// ==/UserScript==
|
||
|
||
(function () {
|
||
'use strict';
|
||
const price = (() => {
|
||
const float = n => parseFloat(n.sourceString)
|
||
const priceG = ohm.grammar(`Price { Price = digit+ "р." digit+ "к." Price? }`)
|
||
const priceS = priceG.createSemantics().addOperation('val', {
|
||
Price: (rub, _2, kop, _4, _5) => float(rub) * 100 + float(kop),
|
||
})
|
||
const weightG = ohm.grammar(`Weight {
|
||
Exp = BS* AnyWeight BS* AnyWeight? BS*
|
||
AnyWeight = MulWeight | Weight
|
||
Weight = float (OneUnit | ThUnit)
|
||
OneUnit = Dot<"г"> | Dot<"мл"> | Dot<"шт"> | Dot<"см">
|
||
ThUnit = Dot<"кг"> | Dot<"л"> | Dot<"м">
|
||
Dot<R> = R "."*
|
||
MulWeight = float ("x" | "х" | "*") Weight
|
||
BS = ~AnyWeight any
|
||
float = (digit digit* "." digit) -- fl
|
||
| digit+
|
||
}`)
|
||
const weightS = weightG.createSemantics().addOperation('val', {
|
||
Exp: (_, weight, __, ___, _____) => weight.val(),
|
||
Weight: (n, u) => float(n) * u.val(),
|
||
OneUnit: _ => 1, ThUnit: _ => 1000,
|
||
MulWeight: (d, _, w) => float(d) * w.val(),
|
||
})
|
||
const interpret = (g, s) => (text) => s(g.match(text))
|
||
return (price, weight) => (interpret(priceG, priceS)(price).val() / interpret(weightG, weightS)(weight).val() / 100 * 1000)
|
||
})()
|
||
const $ = unsafeWindow.jQuery; // somehow, when @including jquery, infinite scroll stops working.
|
||
const template = $("<a/>").css({
|
||
'background-color': '#fbba00',
|
||
'color': 'black', // default is #cb4f2b
|
||
'padding': '2px',
|
||
'border-radius': '5px',
|
||
'font-size': '14px',
|
||
'font-family': 'MyriadProCondencedBoldItalic',
|
||
'position': 'absolute',
|
||
'right': '5px'
|
||
}).attr('target', '_blank')
|
||
$(document).arrive(".products_card", { existing: true }, div => {
|
||
const normalizedPrice = price(
|
||
$(div).find('div > form > div.prices__wrapper > div > div.prices_block > div > div.price').text(),
|
||
$(div).find('a.fancy_ajax').text()
|
||
)
|
||
const button = template.clone()
|
||
const url = (R.test(/e-dostavka/, location.host) ? R.identity : R.flip)(R.replace)('e-dostavka', 'gipermall', $(div).find('a.fancy_ajax').attr('href'))
|
||
$(div).find('a.fa').replaceWith(button)
|
||
button.text(normalizedPrice.toFixed(2))
|
||
GM.xmlHttpRequest({
|
||
method: 'GET', url, onload: page => {
|
||
try {
|
||
const html = $($.parseHTML(page.responseText))
|
||
const competingPrice = price(
|
||
html.find('div.services_wrap:nth-child(3) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1)').text(),
|
||
html.find('.template_1_columns > h1:nth-child(2)').text()
|
||
)
|
||
const difference = Math.abs(1 - competingPrice / normalizedPrice) * 100
|
||
button.text((i, _) => `${_} (${competingPrice >= normalizedPrice ? '>' : '<'}${difference.toFixed(0)}%)`).prop('href', url)
|
||
} catch (e) { }
|
||
}
|
||
});
|
||
});
|
||
})(); |