价格历史 - 亚马逊英国

以非侵入式的方式来展示亚马逊英国商品的历史价格,使用第三方价格服务。

在您安装前,Greasy Fork 希望您知道此脚本声明其包含了一些负面功能。这些功能也许会使脚本作者获利,而不能给您带来任何直接的金钱收益。

此脚本含有追踪您的操作的代码。 脚本作者的说明: 第三方网站可能会搜集、储存或推测你将要购买的物品。

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name               Price History - Amazon UK
// @description        A non-intrusive way to display Amazon UK item's history price, featuring third-party price history.
// @version            1.0.3

// @name:zh-CN         价格历史 - 亚马逊英国
// @description:zh-CN  以非侵入式的方式来展示亚马逊英国商品的历史价格,使用第三方价格服务。

// @antifeature        tracking Third-party site can collect/store/guess what you are going to purchase.
// @antifeature:zh-CN  tracking 第三方网站可能会搜集、储存或推测你将要购买的物品。

// @namespace          uk.jixun
// @match              https://amazon.co.uk/*
// @match              https://www.amazon.co.uk/*
// @match              https://smile.amazon.co.uk/*
// @author             Jixun
// @license            bsd-3-clause
// @run-at             document-start
// @grant              none
// ==/UserScript==

let serviceEl = [];
const services = [{
  name: 'CCC',
  inline: false,
  url: asin => `https://uk.camelcamelcamel.com/product/${asin}`,
}, {
  name: 'Keepa',
  inline: asin => () => {
    const prevImage = $('keepa-history-embed');
    if (prevImage) {
      prevImage.style.display = prevImage.style.display === 'none' ? 'block' : 'none';
      return;
    }
    
    const src = `https://graph.keepa.com/pricehistory.png?asin=${asin}&domain=co.uk`;
    const $img = h('img', {src, id: 'keepa-history-embed', 'referrerPolicy': 'no-referrer'});
    const $price = $('price');
    if ($price) {
      $price.parentNode.insertBefore($img, $price.nextSibling);      
    } else {
      $('olp_feature_div').appendChild($img);
    }
    serviceEl.push($img);
  },
  url: asin => `https://keepa.com/#!product/2-${asin}`,
}];

const serviceStyle = {
  'marginRight': '0.5em',
  'display': 'inline-block',
};

const inlineStyle = {
  background: 'none',
  border: 'none',
};

function insertServices(asin) {
  return services.map(service => h('li', { style: serviceStyle }, [
    service.url && h('a', { href: service.url(asin), target: '_blank', rel: 'noreferrer' }, [service.name]),
    !service.url && h('span', null, [service.name]),
    service.inline && h('span', null, [
      ' (',
      h('a', { href: 'javascript:void(0)', onclick: service.inline(asin) }, 'inline'),
      ')',
    ])
  ]));
}

function $(id) {
  return document.getElementById(id);
}

function insertChildren(root, children = []) {
  if (!children) return;
  if (Array.isArray(children)) {
    for (const c of children) {
      insertChildren(root, c);
    }
    return;
  }
  if (typeof children === 'string') {
    children = document.createTextNode(children);
  }
  root.appendChild(children);
}

function h(tag, attr, ...children) {
  const el = document.createElement(tag);
  if (attr) {
    for(const [name, value] of Object.entries(attr)) {
      if (name === 'style') {
        Object.assign(el.style, value);
      } else {
        el[name] = value;
      }
    }
  }
  insertChildren(el, children);
  return el;
}

function remove(node) {
  node?.parentNode?.removeChild(node);
}

let lastRoot;
function injectPriceCompare() {
  const $asin = $('ASIN');
  if (!$asin || $asin.tagName !== 'INPUT') {
    console.info('asin not found.');
    return;
  }

  // clean up
  serviceEl.forEach(remove);

  const asin = $asin.value;
  const $priceTable = document.querySelector('#price table > tbody') || $('olp_feature_div');
  const root = h('tr', null, [
    h('td', { className: 'a-color-secondary' }, ['History']),
    h('td', null, [
      h('ul', { style: {cssText: 'margin:0'} }, insertServices(asin)),
    ])
  ]);
  $priceTable.appendChild(root);
  serviceEl = [root];
}

function init() {
  const root = $('desktop_buybox');
  if (!root) {
    return;
  }

  const observer = new MutationObserver((mutationsList, observer) => {
    for(const {removedNodes} of mutationsList) {
      console.info(removedNodes);
      if (!removedNodes) continue;
      
      for (const node of removedNodes) {
        if (node.id === 'buybox') {
          injectPriceCompare();
          return;
        }
      }
    }
  });

  // Start observing the target node for configured mutations
  observer.observe(root, { childList: true });
  injectPriceCompare();
}

addEventListener('DOMContentLoaded', init);