// ==UserScript== // @name 京东单价助手 // @namespace http://greasyfork.org/ // @version 1.06 // @description 京东商品列表页面的增强程序,增强了显示单价功能,帮助你在京东找到最便宜的商品 // @author Yarmu // @match *://search.jd.com/* // @match *://list.jd.com/* // @match *://item.jd.com/* // @grant none // @supportURL https://greasyfork.org/zh-CN/scripts/30522-%E4%BA%AC%E4%B8%9C%E5%8D%95%E4%BB%B7%E5%8A%A9%E6%89%8B // @downloadURL none // ==/UserScript== (function() { var host = window.location.host.toLowerCase(); if (host === 'list.jd.com' || host === 'search.jd.com') { addPriceTipListener('.p-price', addListPriceTip, 1000); } else if (host === 'item.jd.com') { addPriceTipListener('.p-price', addItemPriceTip); addPriceTipListener('.p-price-plus', addItemPriceTip); } })(); function addPriceTipListener(tag, func, time) { var onModifiedFunc = function() { $(this).unbind("DOMSubtreeModified"); func.call(this); $(this).bind("DOMSubtreeModified", onModifiedFunc); }; var eachCallFunc = function() { $(tag).each(function() { if (!$(this).attr('priceTip')) { $(this).attr('priceTip', '1'); onModifiedFunc.call(this); } }); }; eachCallFunc(); if (time) { setInterval(eachCallFunc, time); } } function addListPriceTip() { var priceItem = $(this).find('strong i'); var price = getFloat(priceItem.text()); if (isNaN(price)) { priceItem = $(this).find('strong span'); price = getFloat(priceItem.text()); if (isNaN(price)) { priceItem = $(this).find('strong'); price = getFloat(priceItem.text()); if (isNaN(price)) { priceItem = $(this); price = getFloat(priceItem.text()); } } } if (isNaN(price)) return; var title = null; var index = 0; $(this).parent().find('.p-scroll .ps-wrap .ps-main .ps-item a').each(function(idx) { if ($(this).attr('class') === 'curr' && $(this).attr('title')) { title = $(this).attr('title').trim(); index = idx; return false; } }); var unit = getUnit(title, price); if (unit === null && index === 0) { title = $(this).parent().find('.p-name a em').text().trim(); if (!title) { title = $(this).parent().find('.p-name a').text().trim(); } unit = getUnit(title, price); } if (unit === null) return; var htm = price + ' (' + unit.price + '/' + unit.unit + ')'; title += ' (' + unit.capacity + unit.unit + ')'; priceItem.text(htm); var tipItem = $(this).parent().find('.p-name a'); setTimeout(function() { tipItem.attr('title', title); }, 1000); } function addItemPriceTip() { var priceItem = $(this).find('.price'); var price = getFloat(priceItem.text()); if (isNaN(price)) return; var title = $('.sku-name').text().trim(); var unit = getUnit(title, price); if (unit === null) return; var htm = ' (' + unit.price + '/' + unit.unit + ')'; title = ' (' + unit.capacity + unit.unit + ')'; priceItem.append(htm); if (!window.hasAddItemPriceTip) { window.hasAddItemPriceTip = true; setTimeout(function() { $('#summary-weight .dd').append(title); }, 1000); } } function getUnit(title, price) { if (!title) return null; if (price <= 0) return null; var name = title.replace(/[((][^))]+[))]/ig, ''); var reg1 = /\b((\d+)\s*[个只瓶罐桶条包袋件盒箱组]?\s*[*x×]\s*)(\d+\.?\d*?)\s*(g|kg|ml|l|千克|克|斤|公斤|毫升|升)/ig; var reg2 = /\b(\d+\.?\d*?)\s*(g|kg|ml|l|千克|克|斤|公斤|毫升|升)\/?(\s*[\u4e00-\u9fa5]*\s*[*x×]\s*(\d+))?/ig; var pCap = 3, pUnit = 4, pCount = 1; var reg = reg1; if (!reg.test(name)) { pCap = 1; pUnit = 2; pCount = 4; reg = reg2; if (!reg.test(name)) { name = title; pCap = 3; pUnit = 4; pCount = 1; reg = reg1; if (!reg.test(name)) { pCap = 1; pUnit = 2; pCount = 4; reg = reg2; } } } reg.lastIndex = 0; var match = null; var cap = 0; var un = ''; var isOnlyOne = !/[++送和]/i.test(name); while ((match = reg.exec(name))) { var capacity = parseFloat(match[pCap]); if (match.length > 4 && match[pCount]) { capacity *= parseInt(match[pCount]); } if (capacity <= 0) { continue; } var unit = match[pUnit].toLowerCase(); if (unit === 'g' || unit === '克') { capacity /= 1000; unit = 'kg'; } else if (unit === '千克' || unit === '公斤') { unit = 'kg'; } else if (unit === '斤') { capacity /= 2; unit = 'kg'; } else if (unit === 'ml' || unit === '毫升') { capacity /= 1000; unit = 'L'; } else if (unit === 'l' || unit === '升') { unit = 'L'; } if (un === '' || un === unit) { un = unit; cap += capacity; } if (isOnlyOne) { break; } } if (cap > 0) return { capacity: Math.round(cap * 10000) / 10000, unit: un, price: Math.round(parseFloat(price) / cap * 100) / 100 }; else return null; } function getFloat(str) { str = str.replace('¥','').trim(); if (!/^\d+\.?\d*$/.test(str)) return NaN; return parseFloat(str); }