開発^3

Web開発、宇宙開発、ゲーム開発の3種類についてつらつらと

Colorful Google Calendaを直してみた。

ほったらかしだったColorful Google Caledarを直してみた。
外部からのツッコミはやっぱり有効。と(メモメモ


明日ぐらいまで動かして問題なければCodeReposにコミットしよう。
2009/03/11 00:55追記:コミットした。
詳細とインストールはこちら
Colorful Google Calendar(Greasemonkey Script)

// ==UserScript==
// @name           Colorful Google Calendar
// @namespace      http://d.hatena.ne.jp/sheile/
// @description    Google Calendarに土日色を付与します
// @include        http://www.google.com/calendar/render*
// @include        https://www.google.com/calendar/render*
// ==/UserScript==

(function ()
{
	//	各曜日の文字色
	var saturdayColor = "blue";
	var sundayColor = "red";
	var otherColor = "black";

	//	各曜日の背景色
	var saturdayBackgroundColor = "#CCCCFF";
	var sundayBackgroundColor = "#FFCCCC";

	var saturdaySelectedBackgroundColor = "#8888EE";
	var sundaySelectedBackgroundColor = "#EE8888";

	//	ミニカレンダーの背景色を付けるか否か(true / false)
	var isColorfulMiniCalendar = true;

	var prevCol = {};

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

	document.addEventListener("DOMSubtreeModified", onSubTreeModified, false);

	//-----------------------------------------------------------
	//	DOM変化時にカレンダー着色ロジックを呼び出す
	//-----------------------------------------------------------
	var isRefresh = false;
	function onSubTreeModified()
	{
		if(isRefresh == false) {
			setTimeout(addColor, 10);
			isRefresh = true;
		}
	}

	//-----------------------------------------------------------
	//	カレンダーを着色する
	//-----------------------------------------------------------
	function addColor()
	{
		isRefresh = false;
		
		//	対象カラム取得
		var targetColumns = getTargetColumns();

		if(isColorfulMiniCalendar) {
			paintMiniCalendar(targetColumns);
		}

		if(targetColumns["Saturday"] == undefined || targetColumns["Sunday"] == undefined) return;
		if(isNeedPaintMain(targetColumns)) {
			paintMainCalendar(targetColumns);
		}
	}


	//-----------------------------------------------------------
	//	着色対象のカラムを返す
	//-----------------------------------------------------------
	function getTargetColumns()
	{
		//	ミニカレンダーの着色列
		var targetColumns = {};
		matchResult = $("dp_0_cur").innerHTML.match(/([0-9]{4})年\s*([0-9]{1,2})月/);
		var miniBaseDate = new Date(matchResult[1], matchResult[2] - 1, 0);
		miniBaseDate.setDate($("dp_0_row_0").childNodes[0].innerHTML);

		targetColumns["MiniSaturday"] = 6 - miniBaseDate.getDay();
		targetColumns["MiniSunday"] = (7 - miniBaseDate.getDay()) % 7;

		//	メインカレンダーの着色列
		var xpath = "";
		xpath += "descendant::td[";
		xpath += "contains(@class,'dp-weekday-selected') or ";
		xpath += "contains(@class,'dp-weekend-selected')";
		xpath += "][1]";
		var selectedDate = document.evaluate(xpath, $("dp_0"), null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
		if(selectedDate == null) return targetColumns;

		var baseDate = new Date(matchResult[1], matchResult[2] - 1, 1);
		if(selectedDate.className.indexOf("DP_offmonth") != -1) baseDate.setTime(baseDate.getTime() - 24 * 3600 * 1000);
		baseDate.setDate(parseInt(selectedDate.innerHTML));

		targetColumns["Saturday"] = 6 - baseDate.getDay();
		targetColumns["Sunday"] = (7 - baseDate.getDay()) % 7;

		return targetColumns;
	}


	//-----------------------------------------------------------
	//	左上のミニカレンダー着色
	//-----------------------------------------------------------
	function paintMiniCalendar(targetColumns)
	{
		var headers = document.getElementsByClassName("dp-cell dp-dayh");
		//	ミニカレンダー
		for(var i = 0; i < 7; i++) {
			var days = $("dp_0_row_" + i).childNodes;

			//	土曜日
			var satTarget = days[targetColumns["MiniSaturday"]];
			paintMiniCalendarBackground(satTarget, saturdayBackgroundColor, saturdaySelectedBackgroundColor);

			//	日曜日
			var sunTarget = days[targetColumns["MiniSunday"]];
			paintMiniCalendarBackground(sunTarget, sundayBackgroundColor, sundaySelectedBackgroundColor);
		}

		headers[targetColumns["MiniSaturday"]].style.color = saturdayColor;
		headers[targetColumns["MiniSunday"]].style.color = sundayColor;

		return false;
	}


	//-----------------------------------------------------------
	//	ミニカレンダーの背景色が正しく付けられているかを確認
	//-----------------------------------------------------------
	function paintMiniCalendarBackground(target, normalColor, selectedColor)
	{
		if(target.className.indexOf("dp-today-selected") != -1) return;
		
		var isSelected = (target.className.indexOf("dp-weekend-selected") != -1);
		target.style.backgroundColor = isSelected ? selectedColor : normalColor;
	}

	//-----------------------------------------------------------
	//	メインカレンダーに着色する必要があるか否かを返す
	//-----------------------------------------------------------
	function isNeedPaintMain(targetColumns)
	{
		//	予定リストは着色不要
		return $("mode-list").parentNode.className != "modelinkOn";
	}


	//-----------------------------------------------------------
	//	メインのカレンダーを着色
	//-----------------------------------------------------------
	function paintMainCalendar(targetColumns)
	{
		if($("mode-month").parentNode.className != "modelinkOn") {
			var colMax = document.getElementsByClassName("tg-daywrapper").length;
			//	背景色
			addBackgroundColor("Saturday", targetColumns["Saturday"], saturdayBackgroundColor, colMax);
			addBackgroundColor("Sunday", targetColumns["Sunday"], sundayBackgroundColor, colMax);
		} else {
			var cells = document.getElementsByClassName("st-bg");
			for(var i = 0; i < cells.length; i++) {
				if(cells[i].className.indexOf("st-bg-today") == -1) {
					if(i % 7 == targetColumns["Saturday"]) cells[i].style.backgroundColor = saturdayBackgroundColor;
					if(i % 7 == targetColumns["Sunday"])   cells[i].style.backgroundColor = sundayBackgroundColor;
				}
			}
		}
	}


	//-----------------------------------------------------------
	//	背景色用の要素を追加
	//-----------------------------------------------------------
	function addBackgroundColor(id, col, color, colMax)
	{
		var bgElement = $("__addBackgroundColor" + id);
		if(col < 0 || col >= colMax) {
			if(bgElement != null) {
				bgElement.parentNode.removeChild(bgElement);
			}
			prevCol[id] = col;
			return;
		}

		//	複数回の呼び出しが行われる為、多重挿入を抑制
		if(bgElement != undefined) {
			if(col == prevCol[id]) return;
			bgElement.parentNode.removeChild(bgElement);
		}

		var div = document.createElement("DIV");
		div.id = "__addBackgroundColor" + id;
		div.style.height = "1008px";
		div.style.marginBottom = "-1008px";
		div.style.backgroundColor = color;

		var targetNode = document.getElementsByClassName("tg-daywrapper")[col];
		targetNode.parentNode.insertBefore(div, $("tgDay" + col));

		prevCol[id] = col;
	}


})();