There are 2 previous versions of this script.
// GCal Event Color Codes
// This scripts allows you to activate and alternate set of color codes
// for events in your Google Calendars. Define a category name starting with !
// and give the colors you want for the background and border of the event.
// The color coding is enabled and disabled by clicking on the little calendar icon
// added to the corner of the main calendar frame. Any questions can be directed to
// mjeffryes+userscripts@gmail.com. Enjoy!
// ==UserScript==
// @name GCal Event Color Codes
// @namespace http://www.hmc.edu/~mjeffryes
// @description Color codes GCal events using tags
// @include http://www.google.tld/calendar/*
// @include https://www.google.tld/calendar/*
// ==/UserScript==
///////////////////////////////////////////////////////////////////////////////////////////
//color-tag lookup:
//["tag", "border color" "fill color", "extra tag list"]
tags = [
["travel", "rgb(108,148,118)", "rgb(148,188,158)", ["trip","flight"] ],
["sleep", "rgb(0,32,113)", "rgb(50,82,168)", ["nap"]],
["fun", "rgb(51,163,163)", "rgb(92,217,217)", ["comics"]],
["quiet", "rgb(79,118,54)", "rgb(119,158,94)", ["pondering","reading","review"]],
["people", "rgb(153,72,153)", "rgb(197,120,197)", ["sam & max","hanging"]],
["hw", "rgb(103,51,0)", "rgb(143,86,40)", []],
["food", "rgb(0,170,0)", "rgb(46,216,42)", ["dinner","lunch","bfast","breakfast"]],
["admin", "rgb(185,20,20)", "rgb(225,53,53)", ["email","store", "finance"]],
["class", "rgb(36,106,136)", "rgb(76,146,176)", ["VLSI","infocom","clinic"]],
["maint", "rgb(185,114,83)", "rgb(225,154,123)", ["wakeup","prep for bed","exercise"]],
["church", "rgb(165,165,0)", "rgb(205,205,0)", ["bible study"]],
["projects", "rgb(0,90,5)", "rgb(16,136,32)", []],
["work", "rgb(50,50,59)", "rgb(90,90,90)", ["Rhizome","RS"]],
["service", "rgb(110,40,70)", "rgb(150,80,110)", ["IV setup"]],
["none", "rgb(0,0,0)", "rgb(0,0,0)"], []]; //special tag, do not remove
///////////////////////////////////////////////////////////////////////////////////////////
//load a new ColorCoder object on start
window.addEventListener("load", function() { unsafeWindow.gccc = new GCalColorCoder(); }, false);
///////////////////////////////////////////////////////////////////////////////////////////
//GCalColorCoder class
function GCalColorCoder()
{
//register toggles
this.tag_prefix = (makeMenuToggle("GCal_tag_sym",true,"Use '!'","Use '#'","Tag prefix"))?'!':'#';
this.on = {'color': makeMenuToggle("GCal_color_on",true,"GCCC Colors","Default Colors","On Page Load"),
'sum' : makeMenuToggle("GCal_sum_on",true,"Sums Off","Sums On","On Page Load")};
//initialize event tags
this.loadTags();
this.xsearch = document.createExpression(
'//dl[@class="cbrd" and not(@id)] | //div[contains(@class,"ca-evp") and (contains(@class,"rb-n") or contains(@class,"te")) and not(@id)]'
, null);
document.body.addEventListener("DOMSubtreeModified", function(){unsafeWindow.gccc.tagNodes();}, false);
//Add stylesheet and UI elements
this.style = addGlobalStyle(this.makeCSS());
this.insert(single_xpath('//div[@class="nb_0"]'));
//sync
this.update();
}
GCalColorCoder.prototype = {
name: "gccc",
icons: {
'color': { true: "images/icon_success.gif", false: "images/icon_r_no.gif"},
'sum' : { true: "images/opentriangle.gif", false: "images/triangle.gif"},
},
//create a stylesheet for tagged nodes
makeCSS: function(){
style = "";
for (i in tags) {
style += 'dl#' + tags[i][0] + '.cbrd { ' +
'border-color: ' + tags[i][1] + ' !important; ' +
'background-color: ' + tags[i][2] + ' !important; } ' +
'dl#' + tags[i][0] + '.cbrd dt, div#' + tags[i][0] + '.rb-n' +
' { background-color: ' + tags[i][1] + ' !important; } ' +
'div#' + tags[i][0] + '.te { color: ' + tags[i][1] + ' !important; }';
}
return style;
},
//load tags
loadTags: function(){
this.tags = new Array();
for(var i = 0; i<tags.length;i++){
pattern = [tags[i][0]].concat(tags[i][3]).join('|');
this.tags[i]= { tag: tags[i][0], regexp: new RegExp( pattern,'i') };
}
this.tag_regexp = new RegExp( this.tag_prefix + "[a-z]+");
},
// sync page state with object state
update: function(){ this.style.disabled = !this.on['color']; this.tagNodes(); },
// search for events that don't have an id field and set it to the right tag
tagNodes: function(){
xresult = this.xsearch.evaluate(document, XPathResult.ANY_UNORDERED_NODE_TYPE, null);
if(node = xresult.singleNodeValue)
{
node.setAttribute('id', this.matchTag(node.textContent));
}
},
matchTag: function(text){
if(match = this.tag_regexp.exec(text))
text = String(match).substring(1);
for (x in this.tags){
if(this.tags[x].regexp.exec(text))
return this.tags[x].tag;
}
return "none";
},
//toggle color codes on and off
toggle: function(btnid){
this.on[btnid] = !this.on[btnid];
this.buttons[btnid].childNodes[1].src = this.icons[btnid][this.on[btnid]];
window.setTimeout(GM_setValue, 0, "GCal_"+btnid+"_on", this.on[btnid]);
this.update();
},
//insert the visual elements
insert: function(loc){
this.div = document.createElement('div');
this.div.setAttribute('class','nb_0');
this.div.setAttribute('style', 'padding-top: 12px;');
this.div.innerHTML =
'<div style="width: 100%; height: 2px;">' +
'<div class="t1 chromeColor"></div><div class="t2 chromeColor"></div> </div>' +
'<h2 id="'+ this.name +'" class="calHeader normalText"></h2>';
loc.parentNode.insertBefore(this.div, loc);
title_div = single_xpath("//div//h2[@id='"+this.name+"']");
this.buttons = new Object();
//this.insertbutton(title_div, 'sum');
this.insertbutton(title_div, 'color');
},
//insert a toggle button
insertbutton: function(loc, btnid){
this.buttons[btnid] = document.createElement('div');
this.buttons[btnid].innerHTML='Color Codes: <img src="' + this.icons[btnid][this.on[btnid]] + '"/>';
this.buttons[btnid].setAttribute('onclick', this.name+'.toggle(\''+btnid+'\')');
loc.appendChild(this.buttons[btnid]);
},
};
//////////////////////////////////////////////////////////////////////////////////////////
//Helper code for adding global css rules (http://diveintogreasemonkey.org/patterns/add-css.html)
function addGlobalStyle(css) {
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) { return; }
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
return style;
}
//////////////////////////////////////////////////////////////////////////////////////////
//Helper code snippit for adding menu toggle items (http://wiki.greasespot.net/Code_snippets)
function makeMenuToggle(key, defaultValue, toggleOn, toggleOff, prefix) {
// Add menu toggle and return value
GM_registerMenuCommand((prefix ? prefix+": " : "") + (window[key] ? toggleOff : toggleOn), function() {
GM_setValue(key, !window[key]);
});
return GM_getValue(key, defaultValue);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//XPath Helpers
function xpath(query) {
return document.evaluate(query, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
}
function single_xpath(query) {
return xpath(query).snapshotItem(0);
}
