By Luke Baker
Has no other scripts.
// ==UserScript==
// @name Power Gmail Tweaks
// @namespace http://lukebaker.org/greasemonkey
// @description Adds cross-computer persistent seaches (stored in a contact) and a fixed font size button.
// @include http://mail.google.com/mail/*
// @include https://mail.google.com/mail/*
// @exclude http://mail.google.com/mail/help/*
// @exclude https://mail.google.com/mail/help/*
// ==/UserScript==
(function() {
const CONTACT_NAME = "zzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqq";
const CONTACT_ID_RE = /\["\w+","(\w+)","zzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqq","zzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqq",/;
const CONTACT_NOTE_RE = /\["\w+","\w+","zzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqq","zzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqqzzqq","[^"]+","[^"]+",\[\]\n,\["n","([^"]+)"\]/;
function getCookie(name) {
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(document.cookie);
return (value != null) ? unescape(value[1]) : null;
}
function getSid() {
var gmailsid = getCookie("GX");
// too long, let's shorten it
var wanted_size = 32;
var sid = "";
var chunk = 0;
for (var i=0; i < gmailsid.length; i++) {
chunk += gmailsid.charCodeAt(i);
if ((i+1) % Math.ceil(gmailsid.length / wanted_size) == 0) {
if (i % 2 == 0) {
sid += String.fromCharCode((chunk % 26) + 65);
}
else {
sid += String.fromCharCode((chunk % 26) + 97);
}
}
}
return (sid != "") ? sid : "powergmailtweak";
}
function setCookie(name, value) {
var today = new Date();
// plus 3 minutes
var expiry = new Date(today.getTime() + 3 * 60 * 1000);
document.cookie = name + "=" + escape(value) +
"; expires=" + expiry.toGMTString() +
"; path=/";
}
function getGmailCookie(name) {
//var gmailUid = getCookie("GMAIL_AT");
var gmailUid = getSid();
var gmailData = unescape(getCookie(gmailUid));
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(gmailData);
return (gmailUid != null && gmailData != null && value != null) ? unescape(value[1]) : null;
}
function setGmailCookie(name, value) {
//var gmailUid = getCookie("GMAIL_AT");
var gmailUid = getSid();
var gmailData = unescape(getCookie(gmailUid));
var gmailCookieData = getGmailCookie(name);
var contactID = getGmailCookie("contact_id");
// nothing to do if old and new value are the same
if (gmailCookieData == value) { return; }
name = name + "=";
if (gmailCookieData != null) {
var newData = gmailData.replace(name + gmailCookieData + ";", name + value + ";");
setCookie(gmailUid, newData);
editContact(contactID, escape(newData), null);
}
else {
if (gmailData == "null" || !gmailData) {
setCookie(gmailUid, name + value + ";");
editContact(contactID, escape(name + value + ";"), null);
}
else {
setCookie(gmailUid, gmailData + name + value + ";");
editContact(contactID, escape(gmailData + name + value + ";"), null);
}
}
}
function getProtoDomain() {
const DOMAIN_RE = /(https?:\/\/.*?)\//;
var match = DOMAIN_RE.exec(window.location.href);
return (match) ? match[1] : "";
}
// to be loaded on each page load
function zzqqInit(nextFunction) {
//var gmailUid = getCookie("GMAIL_AT");
var gmailUid = getSid();
if (getCookie(gmailUid) == "loading") { return; }
if (gmailUid && getCookie(gmailUid)) {
setCookie(gmailUid, getCookie(gmailUid));
nextFunction();
}
else {
setCookie(gmailUid, "loading");
getContactID(cookieSetup);
}
}
cookieSetup = function (contactID) {
if (contactID && contactID != null) {
// download note data and store locally
getNoteData(contactID, saveNoteData);
}
else {
createContact(setContactID);
}
}
setContactID = function (contactID) {
//var gmailUid = getCookie("GMAIL_AT");
var gmailUid = getSid();
setCookie(gmailUid, "contact_id="+contactID+";");
editContact(contactID, escape("contact_id="+contactID+";"), null);
}
saveNoteData = function (contactID, note) {
// maybe add checking to make sure contactID and note contact_id match
//var gmailUid = getCookie("GMAIL_AT");
var gmailUid = getSid();
setCookie(gmailUid, note);
}
function getContactID(nextFunction) {
var queryUrl = getProtoDomain() + "/mail/?view=cl&search=contacts&pnl=s&q=" + CONTACT_NAME;
GM_xmlhttpRequest({
method: 'GET',
url: queryUrl,
onload: function(responseDetails) {
var match = CONTACT_ID_RE.exec(responseDetails.responseText);
var contactID = (match) ? match[1] : null;
nextFunction(contactID);
},
onerror: function(responseDetails) {
alert("Request for contact resulted in error code: " + responseDetails.status);
}
});
}
function getNoteData(contactID, nextFunction) {
var queryUrl = getProtoDomain() + "/mail/?view=ct&search=contacts&cvm=2&ct_id=" + contactID;
GM_xmlhttpRequest({
method: 'GET',
url: queryUrl,
onload: function(responseDetails) {
var match = CONTACT_NOTE_RE.exec(responseDetails.responseText);
var note = (match) ? match[1] : null;
nextFunction(contactID, unescape(note));
},
onerror: function(responseDetails) {
alert("Request for contact note resulted in error code: " + responseDetails.status);
}
});
}
function createContact(nextFunction) {
return editContact(-1, "", nextFunction);
}
function editContact(contactID, noteData, nextFunction) {
var postURL = getProtoDomain() + "/mail/?&ik=&view=up"
var gmail_at = getCookie("GMAIL_AT");
var post_data = "act=ec&at=" + gmail_at + "&ct_id=" + contactID + "&ct_nm=" + CONTACT_NAME +
"&ct_em=" + CONTACT_NAME + "%40gmail.com&ctf_n=" + escape(noteData);
GM_xmlhttpRequest({
method: 'POST',
url: postURL,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: post_data,
onload: function(responseDetails) {
// if we're doing contact creation find new contactID
if (contactID == -1) {
var match = CONTACT_ID_RE.exec(responseDetails.responseText);
if (match) {
nextFunction(match[1]);
} else {
alert("Contact creation failed.");
}
}
},
onerror: function(responseDetails) {
alert("Contact operation resulted in error code: " + responseDetails.status);
}
});
}
// END OF GMAIL COOKIE STUFF
// START OF PERSITENT SEARCHING STUFF
// Utility functions
function getObjectMethodClosure(object, method) {
return function() {
return object[method]();
}
}
function getObjectMethodClosure1(object, method) {
return function(arg) {
return object[method](arg);
}
}
function getDateString(date) {
return date.getFullYear() + "/" +
(date.getMonth() + 1) + "/" +
date.getDate();
}
// Shorthand
var newNode = getObjectMethodClosure1(document, "createElement");
var newText = getObjectMethodClosure1(document, "createTextNode");
var getNode = getObjectMethodClosure1(document, "getElementById");
// Contants
const MONOSPACE_RULE = ".mb, textarea.tb {font-family: monospace !important;}";
const NORMAL_RULE = ".mb, textarea.tb {}";
const MESSAGE_BODY_FONT_RULE_INDEX = 0;
const RULES = new Array(
// Block in sidebar
".searchesBlock {-moz-border-radius: 5px; background: #fad163; margin: 20px 7px 0 0; padding: 3px;}",
".refreshButton {display: block; cursor: pointer; float: right; margin-top: -2px;}",
".searchesBlockList {background: white;}",
".listItem {color: #ca9c22;}",
".editLink {text-align: right; color: #ca9c22; padding: 2px 5px 5px 0;}",
// Edit page
".searchesContainer {-moz-border-radius: 10px; background: #fad163; padding: 10px;}",
".innerContainer {background: #fff7d7; text-align: center; padding: 10px;}",
".searchesList {width: 100%;}",
".searchesList th {text-align: left; font-size: 90%;}",
".searchesList td {padding: 10px 0 10px 0; vertical-align: bottom;}",
".searchesList td.divider {background: #fad163; height: 3px; padding: 0;}",
".editItem {font-size: 80%;}",
".labelCell {width: 210px;}",
".labelCell input {width: 200px;}",
".cancelButton {margin-right: 5px;}",
".editCell {}",
".editCell input {width: 100%}",
".saveButton {margin-left: 5px; font-weight: bold;}"
);
const TOGGLE_FONT_IMAGE = "data:image/gif;base64,R0lGODlhEAAQAIABAAAAzP%2F%2" +
"F%2FyH5BAEAAAEALAAAAAAQABAAAAImjI%2BJwO28wIGG1rjUlFrZvoHJVz0SGXBqymXphU5" +
"Y17Kg%2BnixKBYAOw%3D%3D";
const REFRESH_IMAGE = "data:image/gif;base64,R0lGODlhDQAPANU5AM%2BtUs6sUunDX" +
"PfPYt65WK%2BTRaiMQvXNYfDJX9m1VtSxVIBrM7GURsKiTZqBPeS%2FWo94OZmAPebBW6WK" +
"QbiaSdOwU35qMpV9O4t0N4NuNI12OIFsM9u3V7mbSaaLQtazVcyqUZ6EP%2BC7WX1oMbudS" +
"semT62QRPjPYuvFXXtmMbSXR%2BK9WohyNvLKYOfBXPPLYJB4Ob6fS5R8O%2B3GXqGGQK%2" +
"BSRauPROG9WW5cK%2F%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADkALAAAAAANA" +
"A8AAAZvwJxwSMzdiKcAg8YIDEyG4QPjABAUhgUuInQtAsQaDqcRwj7EUmY8yiUuReJtQInF" +
"h5JEAXQX3mwzD305FSRGBAN3Eys5HWM4LAdDIiFCCmMbAkMcMghCBDgpEAUNKg4eL0MoFgI" +
"tAA0AnkQHmoNBADs%3D";
const RESULT_SIZE_RE = /D\(\["ts",(\d+),(\d+),(\d+),/;
const DEFAULT_SEARCHES = {
"has:attachment": "Attachments",
"after:today": "Today",
"after:oneweekago": "Last Week"
};
const MESSAGE_ID_CACHE_COOKIE = "PersistentSearchesMessageIdCache"
const SEARCHES_COOKIE = "PersistentSearches";
const SEARCHES_COLLAPSED_COOKIE = "PersistentSearchesCollapsedCookie";
const ONE_DAY = 24 * 60 * 60 * 1000;
// Globals
var styleSheet = null;
var currentRule = NORMAL_RULE;
var searches = new Array();
var searchesBlock = null;
var searchesBlockHeader = null;
var searchesBlockList = null;
var editLink = null;
var hiddenNodes = null;
var searchesContainer = null;
var searchesList = null;
var toggleFontLink = null;
function initializePersistentSearches() {
var labelsBlock = getNode("nb_0");
if (!labelsBlock) {
return;
}
searchesBlock = newNode("div");
searchesBlock.id = "nb_9";
searchesBlock.className = "searchesBlock";
// header
searchesBlockHeader = newNode("div");
searchesBlockHeader.className = "s h";
searchesBlock.appendChild(searchesBlockHeader);
var refreshButton = newNode("img");
refreshButton.src = REFRESH_IMAGE;
refreshButton.className = "refreshButton";
refreshButton.width = 13;
refreshButton.height = 15;
//refreshButton.onclick = refreshPersistentSearches;
refreshButton.addEventListener("click", refreshPersistentSearches, true);
searchesBlockHeader.appendChild(refreshButton);
searchesBlockHeader.triangleImage = newNode("img");
searchesBlockHeader.triangleImage.src = "/mail/images/opentriangle.gif";
searchesBlockHeader.triangleImage.width = 11;
searchesBlockHeader.triangleImage.height = 11;
//searchesBlockHeader.triangleImage.onclick = togglePersistentSearches;
searchesBlockHeader.triangleImage.addEventListener("click", togglePersistentSearches, true);
searchesBlockHeader.appendChild(searchesBlockHeader.triangleImage);
var searchesText = newNode("span");
searchesText.appendChild(newText(" Searches"));
//searchesText.onclick = togglePersistentSearches;
searchesText.addEventListener("click", toggleMessageBodyFont, togglePersistentSearches);
searchesBlockHeader.appendChild(searchesText);
// searches list
searchesBlockList = newNode("div");
searchesBlockList.className = "searchesBlockList";
searchesBlock.appendChild(searchesBlockList);
editLink = newNode("div");
editLink.appendChild(newText("Edit searches"));
editLink.className = "lk cs editLink";
//editLink.onclick = editPersistentSearches;
editLink.addEventListener("click", editPersistentSearches, true);
searchesBlockList.appendChild(editLink);
if (getGmailCookie(SEARCHES_COOKIE)) {
restorePersistentSearches();
} else {
for (var query in DEFAULT_SEARCHES) {
addPersistentSearch(new PersistentSearch(query, DEFAULT_SEARCHES[query]));
}
savePersistentSearches();
}
insertSearchesBlock();
if (getGmailCookie(SEARCHES_COLLAPSED_COOKIE) == "1") {
togglePersistentSearches();
}
checkSearchesBlockParent();
}
function refreshPersistentSearches() {
for (var i=0; i < searches.length; i++) {
searches[i].getResultSize(true);
}
return false;
}
function insertSearchesBlock() {
var labelsBlock = getNode("nb_0");
if (!labelsBlock) {
return;
}
getNode("nav").insertBefore(searchesBlock, labelsBlock.nextSibling);
}
// For some reason, when naving back to the Inbox after viewing a message, we seem
// to get removed from the nav section, so we have to add ourselves back. This only
// happens if we're a child of the "nav" div, and nowhere else (but that's the place
// where we're supposed to go, so we have no choice)
function checkSearchesBlockParent() {
if (searchesBlock.parentNode != getNode("nav")) {
insertSearchesBlock();
}
window.setTimeout(checkSearchesBlockParent, 200);
}
function restorePersistentSearches() {
var serializedSearches = getGmailCookie(SEARCHES_COOKIE).split("|");
for (var i=0; i < serializedSearches.length; i++) {
var search = PersistentSearch.prototype.fromString(serializedSearches[i]);
addPersistentSearch(search);
}
}
function savePersistentSearches() {
var serializedSearches = new Array();
for (var i=0; i < searches.length; i++) {
serializedSearches.push(searches[i].toString());
}
setGmailCookie(SEARCHES_COOKIE, serializedSearches.join("|"));
}
function clearPersistentSearches() {
for (var i=0; i < searches.length; i++) {
var item = searches[i].getListItem();
if (item.parentNode) {
item.parentNode.removeChild(item);
}
}
searches = new Array();
}
function addPersistentSearch(search) {
searches.push(search);
searchesBlockList.insertBefore(search.getListItem(), editLink);
//savePersistentSearches();
}
function editPersistentSearches(event) {
var container = getNode("co");
hiddenNodes = new Array();
for (var i = container.firstChild; i; i = i.nextSibling) {
hiddenNodes.push(i);
i.style.display = "none";
}
searchesContainer = newNode("div");
searchesContainer.className = "searchesContainer";
searchesContainer.innerHTML += "<b>Persistent Searches</b>";
container.appendChild(searchesContainer);
var innerContainer = newNode("div");
innerContainer.className = "innerContainer";
innerContainer.innerHTML +=
'<p>Use <a href="http://gmail.google.com/support/bin/answer.py?answer=7190" target="_blank">operators</a> ' +
'to specify queries. <code>today</code>, <code>yesterday</code> and <code>oneweekago</code> ' +
'are also supported as values for the <code>before:</code> and <code>after:</code> ' +
'operators. Delete an item\'s query to remove it.</p>';
searchesContainer.appendChild(innerContainer);
searchesList = newNode("table");
searchesList.className = "searchesList";
innerContainer.appendChild(searchesList);
var headerRow = newNode("tr");
searchesList.appendChild(headerRow);
headerRow.appendChild(newNode("th")).appendChild(newText("Label"));
headerRow.appendChild(newNode("th")).appendChild(newText("Query"));
for (var i=0; i < searches.length; i++) {
searchesList.appendChild(searches[i].getEditItem());
var dividerRow = newNode("tr");
var dividerCell = dividerRow.appendChild(newNode("td"));
dividerCell.className = "divider";
dividerCell.colSpan = 3;
searchesList.appendChild(dividerRow);
}
var newSearch = new PersistentSearch("", "");
var newItem = newSearch.getEditItem();
newItem.firstChild.innerHTML =
"<h4>Create a new persistent search:</h4>" +
newItem.firstChild.innerHTML;
searchesList.appendChild(newItem);
var cancelButton = newNode("button");
cancelButton.appendChild(newText("Cancel"));
cancelButton.className = "cancelButton";
//cancelButton.onclick = cancelEditPersistentSearches;
cancelButton.addEventListener("click", cancelEditPersistentSearches, true);
innerContainer.appendChild(cancelButton);
var saveButton = newNode("button");
saveButton.appendChild(newText("Save Changes"));
saveButton.className = "saveButton";
//saveButton.onclick = saveEditPersistentSearches;
saveButton.addEventListener("click", saveEditPersistentSearches, true);
innerContainer.appendChild(saveButton);
// Make clicks outside the edit area hide it
//getNode("nav").onclick = cancelEditPersistentSearches;
getNode("nav").addEventListener("click", cancelEditPersistentSearches, true);
// Since we're in a child of the "nav" element, the above handler will get
// triggered immediately unless we stop this event from propagating
event.stopPropagation();
return false;
}
function cancelEditPersistentSearches() {
searchesContainer.parentNode.removeChild(searchesContainer);
searchesContainer = null;
for (var i=0; i < hiddenNodes.length; i++) {
hiddenNodes[i].style.display = "";
}
//getNode("nav").onclick = null;
getNode("nav").removeEventListener("click", cancelEditPersistentSearches, true);
return true;
}
function saveEditPersistentSearches() {
clearPersistentSearches();
for (var row = searchesList.firstChild; row; row = row.nextSibling) {
var cells = row.getElementsByTagName("td");
if (cells.length != 2) {
continue;
}
var label = cells[0].getElementsByTagName("input")[0].value;
var query = cells[1].getElementsByTagName("input")[0].value;
if (label && query) {
var search = new PersistentSearch(query, label);
addPersistentSearch(search);
savePersistentSearches();
}
}
// cancelling just hides everything, which is what we want to do
cancelEditPersistentSearches();
}
function togglePersistentSearches() {
if (searchesBlockList.style.display == "none") {
searchesBlockList.style.display = "";
searchesBlockHeader.triangleImage.src = "/mail/images/opentriangle.gif";
setGmailCookie(SEARCHES_COLLAPSED_COOKIE, "0");
} else {
searchesBlockList.style.display = "none";
searchesBlockHeader.triangleImage.src = "/mail/images/triangle.gif";
setGmailCookie(SEARCHES_COLLAPSED_COOKIE, "1");
}
return false;
}
function PersistentSearch(query, label) {
this.query = query;
this.label = label;
this.totalResults = -1;
this.unreadResults = -1;
this.listItem = null;
this.editItem = null;
this.resultSizeItem = null;
}
PersistentSearch.prototype.toString = function() {
var serialized = new Array();
for (var property in this) {
if (typeof(this[property]) != "function" &&
typeof(this[property]) != "object") {
serialized.push(property + "=" + this[property]);
}
}
return serialized.join("&");
}
PersistentSearch.prototype.fromString = function(serialized) {
var properties = serialized.split("&");
var search = new PersistentSearch("", "");
for (var i=0; i < properties.length; i++) {
var keyValue = properties[i].split("=");
search[keyValue[0]] = keyValue[1];
}
return search;
}
PersistentSearch.prototype.getListItem = function() {
if (!this.listItem) {
this.listItem = newNode("div");
this.listItem.className = "lk cs listItem";
this.listItem.appendChild(newText(this.label));
this.resultSizeItem = newNode("span");
this.listItem.appendChild(this.resultSizeItem);
this.getResultSize(false);
//this.listItem.onclick = getObjectMethodClosure(this, "execute");
this.listItem.addEventListener("click", getObjectMethodClosure(this, "execute"), true);
}
return this.listItem;
}
PersistentSearch.prototype.getEditItem = function() {
if (!this.editItem) {
this.editItem = newNode("tr");
this.editItem.className = "editItem";
var labelCell = newNode("td");
labelCell.className = "labelCell";
var labelInput = newNode("input");
labelInput.value = this.label;
labelCell.appendChild(labelInput);
this.editItem.appendChild(labelCell);
var editCell = newNode("td");
editCell.className = "editCell";
var queryInput = newNode("input");
queryInput.value = this.getEditableQuery();
editCell.appendChild(queryInput);
this.editItem.appendChild(editCell);
}
return this.editItem;
}
PersistentSearch.prototype.execute = function() {
var searchForm = getNode("s");
searchForm.elements.namedItem("q").value = this.getRunnableQuery();
// XXX: there appears to be a bug in XPCNativeWrappers where unwrappedWindow.top
// returns a wrapped object.
top = unsafeWindow.top;
if (top.wrappedJSObject) {
top = top.wrappedJSObject;
}
top.js._MH_OnSearch(unsafeWindow, 0);
}
PersistentSearch.prototype.getRunnableQuery = function() {
var query = this.query;
var today = new Date();
var yesterday = new Date(today.getTime() - ONE_DAY);
var oneWeekAgo = new Date(today.getTime() - 7 * ONE_DAY);
query = query.replace(/:today/g, ":" + getDateString(today));
query = query.replace(/:yesterday/g, ":" + getDateString(yesterday));
query = query.replace(/:oneweekago/g, ":" + getDateString(oneWeekAgo));
return query;
}
PersistentSearch.prototype.getEditableQuery = function() {
return this.query;
}
PersistentSearch.prototype.getResultSize = function(needsRefresh) {
if (this.totalResults == -1 || this.unreadResults == -1) {
needsRefresh = true;
} else {
this.updateResultSizeItem();
}
if (needsRefresh) {
this.resultSizeItem.style.display = "none";
this.runQuery(this.getRunnableQuery(),
getObjectMethodClosure1(this, "getUnreadResultSize"));
}
}
PersistentSearch.prototype.runQuery = function(query, continuationFunction) {
var queryUrl = getProtoDomain() + "/mail/?search=query&q=" + escape(query) + "&view=tl";
GM_xmlhttpRequest({
method: 'GET',
url: queryUrl,
onload: function(responseDetails) {
var match = RESULT_SIZE_RE.exec(responseDetails.responseText);
if (match) {
var resultSize = match[3];
continuationFunction(resultSize);
} else {
alert("Couldn't find result size in search query.");
}
},
onerror: function(responseDetails) {
alert("Search failed with status code " + responseDetails.status);
}
});
}
PersistentSearch.prototype.getUnreadResultSize = function(totalResults) {
this.totalResults = totalResults;
this.runQuery(this.getRunnableQuery() + " is:unread",
getObjectMethodClosure1(this, "updateResultSize"));
}
PersistentSearch.prototype.updateResultSize = function(unreadResults) {
this.unreadResults = unreadResults;
savePersistentSearches();
this.updateResultSizeItem();
}
PersistentSearch.prototype.updateResultSizeItem = function() {
if (this.resultSizeItem) {
// Clear existing contents
var child;
this.resultSizeItem.style.display = "";
while (child = this.resultSizeItem.firstChild) {
this.resultSizeItem.removeChild(child);
}
// Update with new values
this.resultSizeItem.appendChild(newText(" ("));
var unread = newNode(this.unreadResults > 0 ? "b" : "span");
unread.appendChild(newText(this.unreadResults));
this.resultSizeItem.appendChild(unread);
this.resultSizeItem.appendChild(newText("/" + this.totalResults + ")"));
}
}
function initializeToggleFont() {
var linksContainer = getNode("ap");
if (!linksContainer) {
return;
}
toggleFontLink = newNode("div");
toggleFontLink.className = "al";
toggleFontLink.addEventListener("click", toggleMessageBodyFont, true);
toggleFontLink.innerHTML =
'<span class="l">' +
'<img class="ai" width="16" height="16" src="' + TOGGLE_FONT_IMAGE + '">' +
'<u>Toggle font</u>' +
'</span>';
linksContainer.appendChild(toggleFontLink);
checkToggleFontParent();
}
function checkToggleFontParent() {
if (toggleFontLink.parentNode != getNode("ap")) {
getNode("ap").appendChild(toggleFontLink);
}
window.setTimeout(checkToggleFontParent, 200);
}
function toggleMessageBodyFont() {
styleSheet.deleteRule(MESSAGE_BODY_FONT_RULE_INDEX);
if (currentRule == NORMAL_RULE) {
currentRule = MONOSPACE_RULE;
} else {
currentRule = NORMAL_RULE;
}
styleSheet.insertRule(currentRule, MESSAGE_BODY_FONT_RULE_INDEX);
}
function initializeStyles() {
var styleNode = newNode("style");
document.body.appendChild(styleNode);
styleSheet = document.styleSheets[document.styleSheets.length - 1];
for (var i=0; i < RULES.length; i++) {
styleSheet.insertRule(RULES[i], 0);
}
styleSheet.insertRule(NORMAL_RULE, MESSAGE_BODY_FONT_RULE_INDEX);
}
initialFunction = function () {
initializeStyles();
initializeToggleFont();
initializePersistentSearches();
}
zzqqInit(initialFunction);
//alert(getSid());
})();