Greasy Fork

Greasy Fork is available in English.

Douban Book Bar

显示书籍的豆瓣评分并进行比价

当前为 2014-07-29 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        Douban Book Bar
// @namespace   DoubanBookBar
// @author	Ticshot<[email protected]>
// @commiter    ElvisKang<[email protected]>
// @description 显示书籍的豆瓣评分并进行比价
// @include     *://www.amazon.cn/*
// @include	*://www.amazon.com/*、
// @include	*://item.jd.com/*
// @include	*://product.dangdang.com/*
// @include	*://product.china-pub.com/*
// @include	*://product.suning.com/*
// @version     ver 0.2
// @grant GM_xmlhttpRequest
// ==/UserScript==



(function() {

	var Site = {
		/*
			format of a new support site:
				name : (String) the name of the site 
				cName : (String) Chinese name of the site on douban
				logo : (String) the favicon of the site 
				checker : (RegExp Object) the regular expression to check whether the current site is belong to this site
				isComparable: (bool) whether this site joined into the price comparison 
				getISBN : (function) the function to get ISBN from current site
				createDoubanBar : (function) the function to create bar
			*if isComparable is false , then the variables : cName,logo is optional
		*/

		_siteList: [],
		_curSite: null,

		addSite: function(site) {
			if (Object.prototype.toString.call(site) === '[object Array]') {
				this._siteList = this._siteList.concat(site);
			} else {
				this._siteList = this._siteList.push(site);
			}
		},

		getCurSite: function(href) {
			try {
				if ( !! (this._curSite)) {
					return this._curSite;
				} else {
					for (var i = 0, len = this._siteList.length; i < len; i++) {
						if (Object.prototype.toString.call(this._siteList[i].checker) === "[object RegExp]") {
							if (this._siteList[i].checker.test(href)) {
								this._curSite = this._siteList[i];
								return this._siteList[i];
							}
						} else if (typeof this._siteList[i].checker === "function") {
							if (this._siteList[i].checker(href)) {
								this._curSite = this._siteList[i];
								return this._siteList[i];
							}
						}
					}
				}
			} catch (e) {
				//console.log(e);
				return {};
			}
			return {};
		},

		getComparableSite: function() {
			var comparableSites = [];
			for (var i = 0, len = this._siteList.length; i < len; i++) {
				if (this._siteList[i].isComparable) {
					comparableSites.push(this._siteList[i]);
				}
			}
			return comparableSites;
		},

		supportSite: function() {
			return _siteList.map(function(curSite) {
				return curSite.name;
			});
		}
	};

	var setCss = function(elem, css, fatherDom) {
		css = css || null;
		var elem_style = elem.style ? [elem.style] : (typeof elem !== "string") ? {} : Array.prototype.slice.call((fatherDom || document).querySelectorAll(elem), 0).map(function(e) {
			return e.style;
		});
		for (var name_text in css) {
			var style_name = name_text.replace(/\-[a-zA-z]/g, function(word) {
				return word.substring(1).toUpperCase();
			});
			elem_style.forEach(function(elem_styl) {
				elem_styl[style_name] = css[name_text];
			});
		}
	};

	var setAllCss = function(cssBunch) {
		/*
			cssBunch : Array
			Array container :
				dom : (object) HTMLDOM || selector
				css : (object) 
		*/
		for (var i = 0, len = cssBunch.length; i < len; i--) {
			setCss(cssBunch[i].dom, cssBunch[i].css);
		}
	};

	var setStarStyle = function(star, score, extraCss) {
		//base css
		setCss(star, {
			"background-image": 'url("http://img3.douban.com/pics/movie/bigstars.gif")',
			"width": "75px",
			"height": "14px",
			"display": "inline-block",
			"color": "#666",
			"position": "relative",
			"top": "1px",
			"background-position": "0 " + (-14) * (10 - Math.floor(parseFloat(score) + 0.8)) + "px"
		});

		setCss(star, extraCss);
	};

	var checkScore = function(num_raters, average_score, book_id) {
		var score_row;

		if (num_raters === 0) {
			score_show = '<span style="font-size:13px;">没有人评价这本书</span>';
		} else if (num_raters < 10) {
			score_show = '<span style="font-size:13px;">少于10人评价这本书</span>';
		} else if (num_raters >= 10) {
			score_show = '<span style="padding:5px;">' + average_score + '</span><a id="douban_collections" style="text-decoration:none;font-size:13px" href="http://book.douban.com/subject/' + book_id + '/collections" target="_blank">(共' + num_raters + '人评价)</a>';
		} else {
			score_show = null;
		}

		//console.log(score_show);
		return score_show;
	};

	var getPriceContent = function(icon_link, a_price_data, css) {
		a_price_data = a_price_data || {};
		var price_container = document.createElement("span"),
			link = document.createElement("a"),
			img = document.createElement("img");

		img.src = icon_link;
		img.style.height = "16px";
		img.style.width = "16px";
		link.href = a_price_data.href || "#";
		link.target = "_blank";
		if (a_price_data.price === undefined) {
			link.textContent = "[没找到]";
		} else {
			link.textContent = "¥" + a_price_data.price;
		}
		link.insertBefore(img, link.firstChild);
		price_container.appendChild(link);

		if (css.dom) {
			setAllCss(css);
		} else {
			setCss(price_container, css);
		}

		return price_container;
	};

	var getAllPriceContent = function(siteName, price_infos) {
		var prices = document.createElement("span");

		var price;
		var comparableSites = Site.getComparableSite();
		//console.log(comparableSites);
		prices.id = "show_price";
		//console.log(price_infos);
		for (var i = 0, len = price_infos.length; i < len; i++) {
			for (var j = 0, c_len = comparableSites.length; j < c_len; j++) {
				//console.log("siteName:"+siteName , "comparableSite["+j+"].name:"+comparableSites[j].name , "price_infos["+i+"].site:"+price_infos[i].site , "comparableSites["+j+"].cName:"+comparableSites[j].cName);
				if (siteName !== comparableSites[j].name && price_infos[i].site === comparableSites[j].cName) {
					price = getPriceContent(comparableSites[j].logo, price_infos[i], {
						"padding-left": "8px"
					});
					prices.appendChild(price);
				}
			}
		}
		//console.log(prices);
		if (price_infos.length === 0) {
			prices.innerHTML = "豆瓣上找不到这本书相关的购买信息";
		}

		return prices;
	};

	var createDoubanBar = function(book_info, price_infos, siteName, targetLi) {
		//console.log(JSON.stringify(book_info));
		//setScore
		var score_row = document.createElement("li"),
			label = document.createElement("th"),
			rating = document.createElement("td"),
			stars = document.createElement("span"),
			score = document.createElement("span"),
			raters = document.createElement("a"),
			link = document.createElement("span");
		if (siteName == "amazon") score_row = document.createElement("div");
		var book_id = book_info["id"],
			book_rating = book_info["rating"] || {},
			num_raters = book_rating["numRaters"],
			average_score = book_rating["average"],
			score_show;

		var link_style = link.style,
			score_style = score.style;

		label.innerHTML = "豆瓣评分:";
		label.style.lineHeight = "14px";

		score_show = checkScore(num_raters, average_score, book_id);
		if (score_show) {
			setStarStyle(stars, average_score);
			rating.appendChild(stars);

			link.innerHTML = '<span><a href="http://book.douban.com/subject/' + book_id + '/" target="_blank" >(去豆瓣看这本书)</a></span>';
			link_style.fontSize = "13px";
			link_style.color = "#007722";
			link_style.textDecoration = "none";
			link_style.display = "inline-block";
			link_style.lineHeight = "14px";
		} else {
			score_show = '<span><a href="http://book.douban.com" target="_blank" style="font-size:12px;color:#007722">没在豆瓣找到这本书,去豆瓣逛逛?</a></span>';
		}

		score.innerHTML = '<span>' + score_show + '</span>';
		score_style.marginLeft = "10px";
		score_style.marginRight = "10px";
		score_style.fontSize = "13px";
		score_style.display = "inline-block";
		score_style.lineHeight = "14px";
		rating.appendChild(score);

		rating.appendChild(link);
		rating.colSpan = "3";
		score_row.appendChild(label);
		score_row.appendChild(rating);

		//setPrice
		var price_content = getAllPriceContent(siteName, price_infos),
			price_wrapper = document.createElement("li"),
			price_label = document.createElement("span"),
			price_container = document.createElement("span");
		if (siteName == "amazon") price_wrapper = document.createElement("div");
		price_label.innerHTML = "比&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;价:";
		price_label.style.lineHeight = "14px";
		price_wrapper.appendChild(price_label);

		price_container.colSpan = 3;
		setCss(price_container, {
			"padding-top": "0px"
		});
		price_container.appendChild(price_content);
		price_wrapper.appendChild(price_container);
		if (siteName == "dangdang" || siteName == "amazon") {
			var bar = document.createElement("span");
			bar.appendChild(score_row);
			bar.appendChild(price_wrapper);
			bar.id = "douban_bar";
			if (siteName == "amazon")
				targetLi.parentNode.appendChild(bar);
			else
				targetLi.parentNode.insertBefore(bar, targetLi);
		} else {
			score_row.id = "douban_score";
			price_wrapper.id = "douban_price";
			targetLi.parentNode.insertBefore(score_row, targetLi);
			targetLi.parentNode.insertBefore(price_wrapper, targetLi);
		}
	};

	var Amazon = {

		name: "amazon",

		cName: "亚马逊",

		checker: /(https?:\/\/)?(www)?\.amazon\.(com|cn)\/.*/,

		logo: "http://www.amazon.cn/favicon.ico",

		isComparable: true,

		getISBN: function() {
			var contents = document.querySelectorAll("div.content b");
			var is_book = false;
			try {
				for (var i = 0; i <= contents.length; i++) {
					var info = contents[i];

					if (info.textContent === "ISBN:" || info.textContent === "条形码:") {
						//console.log(info.nextSibling.data.split(",")[0].substring(1));
						return info.nextSibling.data.split(",")[0].substring(1);
					}
				}
				return null;
			} catch (e) {
				return null;
			}
		},

		createBar: function(book_info, price_infos) {
			var targetLi = document.getElementById("priceBlock");
			createDoubanBar(book_info, price_infos, this.name, targetLi);
		}
	};

	var JD = {

		name: "jd",

		cName: "京东商城",

		checker: /(https?:\/\/)?(www|item)?\.jd\.com\/.*/,

		logo: "http://www.jd.com/favicon.ico",

		isComparable: true,

		getISBN: function() {
			try {
				var isbnString = document.querySelector("li.fore4:nth-child(2)").innerHTML;
                return isbnString.split(":")[1];
			} catch (e) {
				return null;
			}
		},
		createBar: function(book_info, price_infos) {
			var targetLi = document.querySelector("#summary-promotion");
			createDoubanBar(book_info, price_infos, this.name, targetLi);
		}

	};

	var Dangdang = {

		name: "dangdang",

		cName: "当当网",

		checker: /(https?:\/\/)?(www|product)?\.dangdang\.com\/.*/,

		logo: "http://www.dangdang.com/favicon.ico",

		isComparable: true,

		getISBN: function() {
			try {
				var isbn = document.querySelector("div.m_t6:nth-child(4) > div:nth-child(2)");
				return isbn.innerHTML;
			} catch (e) {
				return null;
			}
		},
		createBar: function(book_info, price_infos) {
			var targetLi = document.querySelector(".book_messbox");
			createDoubanBar(book_info, price_infos, this.name, targetLi);
		}

	};

	var Chinapub = {

		name: "chinapub",

		cName: "China-pub",

		checker: /(https?:\/\/)?(product|www)\.china\-pub\.com\/.*/,

		logo: "http://www.china-pub.com/favicon.ico",

		isComparable: true,

		getISBN: function() {
			var list = document.querySelectorAll("#con_a_1 li");
			for (var i = 0; i < list.length; i++) {
				if (list[i].innerHTML.split(":")[0] === "ISBN") {
					return list[i].innerHTML.split(":")[1].replace(/\<.*?\>/g, "").match(/[0-9]*/g).join("");
				}
			}
			return null;
		},

		createBar: function(book_info, price_infos) {
			var targetLi = document.getElementsByClassName("pro_buy_bg")[0].previousSibling;
			createDoubanBar(book_info, price_infos, this.name, targetLi);
		}

	};

	var Suning = {

		name: "suning",

		cName: "苏宁易购",

		checker: /(https?:\/\/)?(product)\.suning\.com\/.*/,

		logo: "http://www.suning.com/favicon.ico",

		isComparable: true,

		getISBN: function() {
			try {
				var isbn = document.querySelector("li.li-b:nth-child(11) > span:nth-child(2)");
                return isbn.innerHTML;
			} catch (e) {
				return null;
			}
		},
		createBar: function(book_info, price_infos) {
			var targetLi = document.querySelector("ul.product-info-type:nth-child(3)");
			createDoubanBar(book_info, price_infos, this.name, targetLi);
		}
	};

	var setDoubanData = function(isbn) {
		if (!isbn) {
			return null;
		}

		GM_xmlhttpRequest({
			method: "get",
			url: "http://api.douban.com/v2/book/isbn/" + isbn,
			onload: function(result) {
				//console.log(result);
				var book_info = JSON.parse(result.responseText);
				setDoubanPrice(book_info.id, book_info);
			}
		});
	};

	var setDoubanPrice = function(douban_id, book_info) {
		douban_id = douban_id || null;
		var douban_link = "http://book.douban.com/subject/" + douban_id + "/buylinks";
		var price_infos = [];
		GM_xmlhttpRequest({
			method: "get",
			url: douban_link,
			onload: function(result) {
				//console.log(result.responseText);
				var container = document.createElement("div");
				container.innerHTML = result.responseText;
				var list = document.evaluate('//table[@id="buylink-table"]/tbody/tr', container, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
				//console.log(list);
				var price_check = /[0-9]+(\.[0-9]+)?/;

				for (var i = 1, len = list.snapshotLength; i < len; i++) {
					//console.log(list.snapshotItem(i));
					var part = list.snapshotItem(i);
					var link_info = part.querySelectorAll("td.pl2");

					var price_info = {
						"site": link_info[0].textContent.trim(),
						"href": link_info[0].getElementsByTagName("a")[0].href,
						"price": price_check.exec(link_info[1].textContent.trim())[0]
					};
					price_infos.push(price_info);
				}
				//console.log(price_infos);
				var curSite = Site.getCurSite();
				curSite.createBar(book_info, price_infos);
			}

		});

	};

	var init = function() {
		Site.addSite([Amazon, JD, Dangdang, Chinapub, Suning]);
		var curSite = Site.getCurSite(location.href),
			isbn = curSite.getISBN();
		//console.log(curSite.name);
		// console.log(isbn);
		try {
			setDoubanData(isbn);
		} catch (e) {}

	};

	init();
})();