Greasy Fork

Greasy Fork is available in English.

bgmcard

not a card game

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        bgmcard
// @namespace   bgm/uli
// @description not a card game
// @include     http://bgm.tv/*/topic/*
// @include     http://bangumi.tv/*/topic/*
// @include     http://chii.in/*/topic/*
// @version     0.1.4
// @grant       none
// ==/UserScript==


// card css
var card_css = document.createElement("style");
card_css.textContent = [
		".card_container {position: absolute; transition: left 0.5s, right 0.5s, opacity 0.5s; width: 30em; margin: 1em 0 0 1em; padding: 0 1em; border-radius: 8px; z-index: 50; box-shadow: 2px 2px 5px #999; background-color: rgba(255,255,255,0.9); font-size: 13px; color: #444; border-left: 1em solid #F09199;}",
		".card_container_inner {overflow: hidden; margin: 0 -1em; padding: 1em; border-radius: 8px; border-right: 1em solid rgba(255,255,255,0.9);}",
		".card_content {white-space: pre-wrap; transition: all 0.5s ease; margin-left: 0; width: 30em; max-height: 20em; -moz-columns: auto 30em; -webkit-columns: auto 30em;}",
		".card_cover {float: right; border-color: #C7C7C9 #A9A9AB #858486; border-width: 0 1px 1px 0; border-style: solid; max-width: 10em; max-height: 20em; margin: 0 0 0.5em 0.5em;}",
		".card_link {color: #0084B4 !important;}",
		".card_page {padding-right: 1em; border-top: 1px solid #AAA; display: block; transition: width 0.5s; color: transparent; line-height: 0;}",
		".card_charging {color: #369CF8; font-size: 15px; font-style: italic; font-family: Georgia; padding: 1em 0;}",
		""
		].join("\n");

document.body.appendChild(card_css);


var topmost_card = function(ele) {
	var all_container = document.querySelectorAll(".card_container");
	//for (let x of document.querySelectorAll(".card_container")) {
	for (var i = 0; i < all_container.length; i++) {
		all_container[i].style.zIndex = "49";
		all_container[i].style.opacity = "0.8";
	}
	ele.style.zIndex = "50";
	ele.style.opacity = "1";
};

var set_coordinate = function(ele, rect) {
	ele.style.left = window.scrollX + rect.right + "px";
	ele.style.top = window.scrollY + rect.top + "px";
};


// set card --have no card--> refine card -> charge card -> shooting
//          --already had--> release card -> shooting

var refine_card = function(doc, uri) {

	var get_element = function(selectors) {
		var ele = doc.querySelector(selectors);
		if (ele) return ele;
		else {
			var blank_ele = document.createElement("div");
			blank_ele.href = ""; //some have no cover image, will return null
			return blank_ele;
		}
	};

	var title = get_element(".nameSingle").textContent;
	var cover_src = get_element(".cover.thickbox").href;
	var info = get_element("#infobox").textContent;
	var sum_txt = get_element("#subject_summary, .detail").textContent;

	var text_trim_join = function(str) {
		var trim = function(x) {return x.trim()};
		return str.split('\n').filter(trim).map(trim).join('\n');
	};

	var card_txt = ['', text_trim_join(info), sum_txt].join('\n\n');

	var title_link = document.createElement("a");
	title_link.className = "card_link";
	title_link.textContent = text_trim_join(title);
	title_link.href = uri;

	var cover = document.createElement("img");
	cover.className = "card_cover";
	cover.src = cover_src;

	var card = document.createElement("p");
	card.className = "card_content";
	//card.textContent = card_txt;

	var card_page = document.createElement("span");
	card_page.className = "card_page";

	var container_inner = document.createElement("div");
	container_inner.className = "card_container_inner";

	//card.insertBefore(title_link, card.firstChild);
	//card.insertBefore(cover, card.firstChild);
	card.appendChild(cover);
	card.appendChild(title_link);
	card.appendChild(document.createTextNode(card_txt));

	container_inner.appendChild(card);
	container_inner.appendChild(card_page);

	return [container_inner, card, card_page];
};

var charge_card = function(uri, type, id_number) {
	var card_number = type.slice(0, 3) + "#" + id_number;

	var card_charging = document.createElement("div");
	card_charging.className = "card_charging";
	card_charging.innerHTML = "Card <u>" + card_number + "</u> Charging...";

	var container = document.createElement("div");
	container.className = "card_container";
	container.id = uri;

	container.appendChild(card_charging);

	return [container, card_charging];
};

var release_card = function(evt, uri, page_total) {
	evt.preventDefault();

	var container = document.getElementById(uri);
	var tg_c = container.querySelector(".card_content");
	var tg_p = container.querySelector(".card_page");

	tg_c.style.marginLeft = "0";
	tg_p.textContent = "1/" + page_total;
	tg_p.style.width = 1/page_total*100 + "%";

	container.style.display = "block";
	var rect = evt.target.getBoundingClientRect();
	set_coordinate(container, rect);
	topmost_card(container);
};


var set_card = function(e, uri) {
	var ar = uri.split('/');
	var type = ar[ar.length-2];
	var id_number = ar[ar.length-1];

	var set_card_exec = function(evt) {
		evt.preventDefault();

		//var [container, card_charging] = charge_card(uri, type, id_number);
		var temp = charge_card(uri, type, id_number);
		var container = temp[0], card_charging = temp[1];

		var rect = evt.target.getBoundingClientRect();
		set_coordinate(container, rect);

		document.body.firstElementChild.appendChild(container);
		// use body.appendChild will cover up some parts
		topmost_card(container);

		var xhr = new XMLHttpRequest();
		xhr.onload = function() {
			var doc = this.responseXML;

			//var [container_inner, card, card_page] = refine_card(doc, uri, type);
			var temp2 = refine_card(doc, uri, type);
			var container_inner = temp2[0], card = temp2[1], card_page = temp2[2];
			container.replaceChild(container_inner, container.firstChild);

			if (container_inner.scrollHeight > container_inner.clientHeight) {
				card.style.height = "20em";
			}

			//XXX if cover image is not loaded as soon as the card is appended
			//card.scrollWidth will be smaller than when the image is showed
			//need some placeholder or other fix
			var page_total = Math.floor(card.scrollWidth / card.clientWidth);
			card_page.counter = 0;
			card_page.textContent = "1/" + page_total;
			card_page.style.width = 1/page_total*100 + "%";

			container.addEventListener("click", function(ev) {
				var tg = ev.target;
				if (tg.className == "card_link") return;

				if (tg.className != "card_container") {
					if (ev.currentTarget.style.zIndex == "49") {
						topmost_card(ev.currentTarget);
						return;
					}

					var tg_c = ev.currentTarget.querySelector(".card_content");
					page_total = Math.floor(tg_c.scrollWidth / tg_c.clientWidth);

					if (page_total == 1) return;

					if (tg_c.style.marginLeft == '') tg_c.style.marginLeft = "0";

					//XXX select text is also "click"
					var current_margin = parseInt(tg_c.style.marginLeft);
					var counter = card_page.counter;	
					// below is for page turning calc
					if (Math.floor(counter/(page_total-1)) % 2 == 0) {
						tg_c.style.marginLeft = current_margin - 31 + "em";
					} else {
						tg_c.style.marginLeft = current_margin + 31 + "em";
					}
					card_page.counter = card_page.counter + 1;
					if (Math.floor(card_page.counter/(page_total-1)) % 2 == 0)
						var pg_2 = card_page.counter%(page_total-1) + 1;
					else
						var pg_2 = page_total - card_page.counter%(page_total-1);
					card_page.style.width = pg_2/page_total*100 + "%";
					card_page.textContent = pg_2 + "/" + page_total;
				} else {
					// hide card
					ev.currentTarget.style.display = "none";
				}
			});

			// when click link second time, release card directly
			e.removeEventListener("click", set_card_exec);
			var release_card_c = function(evt) {
				return release_card(evt, uri, page_total);
			};
			e.addEventListener("click", release_card_c);
		};

		xhr.timeout = 5000;
		xhr.ontimeout = function() {
			card_charging.textContent = "Shooting failed. Card charging too slow. Try again.";
			e.addEventListener("click", set_card_exec);
		};

		xhr.open("GET", uri);
		xhr.responseType = "document";
		xhr.send();
	};


	e.addEventListener("click", set_card_exec);
}


var links = document.getElementsByTagName("a");
//for (let t of links) {
for (var i = 0; i < links.length; i++) {
	if (/\/(subject|character|person)\/\d+$/.test(links[i].href)) {
		if (links[i].href != document.location.href) set_card(links[i], links[i].href);
	}
}