// Tribalwar_image_embedder.user.js
// Version 1.1
// 02-16-2008
//
// Happy Valentine's Day + 2 Tribalwar
// Author: -Bane
//
// 1.1c Features:
// - If an image fails to load, the link still remains and an error message is indicated.
//
// 1.1b Features:
// - Config option to turn off smart image resizing (in case of conflicts with other image sizing scripts).
// - All config options are now preceded with TW (to hopefully disambiguate from any other scripts).
//
// 1.1a Bug fixes:
// - Changed the fake events from clicks to "complete" events
// (images with click event handlers already, such as smilies in the reply window,
// were getting "clicked" on page load).
//
// 1.1 Features:
// - Auto resizes all images to fit within the tables.
// - If an image gets resized, you can click on it to view it in its full glory (zoom in)
// - Click again to zoom out.
//
// 1.0 Features:
// - Click on image to view it (or use prefs to do it for you)
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "Tribalwar Image Embedder", and click Uninstall.
//
// --------------------------------------------------------------------
// ==UserScript==
// @name Tribalwar Image Embedder
// @namespace http://webspace.utexas.edu/jag2682/
// @description v1.1c. Embeds images (either by clicking or automatically depending on preference). Auto-resizes images that are too large to fit within the post table.
// @include http://*tribalwar.com/forums/*
// ==/UserScript==
if(!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s*/, "").replace(/\s*$/, "");
}
}
var hotlinkPref = GM_getValue("hotlinkPref");
if(!hotlinkPref) {
GM_setValue("hotlinkPref","off");
hotlinkPref = "off";
}
var resizePref = GM_getValue("resizePref");
if(!resizePref) {
GM_setValue("resizePref","on");
resizePref = "on";
}
if(resizePref == "on") {
setMaxWidth(false);
window.addEventListener("resize", function(e) { setMaxWidth(true); }, false);
}
var links = document.links;
var imgExtensions = [".tif", ".tiff", ".png", ".bmp", ".jpeg", ".gif", ".jpg"];
for(var i = links.length - 1; i >= 0; i--) {
var href = links[i].getAttribute("href");
var link = links[i];
for(var j = imgExtensions.length - 1; j >= 0; j--) {
var ext = imgExtensions[j];
if(href.toLowerCase().substring(href.length - ext.length) == ext) {
link.setAttribute("title", href);
link.setAttribute("href","javascript:void(0)");
link.removeAttribute("target");
link.addEventListener("click", replaceWithImage, false);
if(hotlinkPref == "on") {
event = document.createEvent("MouseEvents");
event.initMouseEvent("click", false, false, window, 0, 0, 0, 0, 0, false, false, false, false, 2, null);
link.dispatchEvent(event);
}
break; // Don't search the rest of the extensions like a retard
}
}
}
function replaceWithImage(e) {
if(!e) var e = window.event;
var obj = window.event ? e.srcElement : e.target;
if(obj.nodeName.toLowerCase() == "img") {
// Clicking on image-link gives image, not link.
obj = obj.parentNode;
}
var img = new Image();
img.src = obj.getAttribute("title");
img.alt = obj.firstChild.nodeValue;
img.border = 0;
img.addEventListener("error", imageError, false);
if(resizePref == "on") {
if(!img.complete) {
img.addEventListener("load", resizeImageCallback, false);
} else {
img.addEventListener("complete", resizeImageCallback, true);
var event = document.createEvent("Events");
event.initEvent("complete", false, false);
img.dispatchEvent(event);
}
}
var prevNode = obj.previousSibling;
while(prevNode && prevNode.nodeType == 3 && prevNode.nodeValue.trim().length == 0) {
prevNode = prevNode.previousSibling;
}
var nextNode = obj.nextSibling;
while(nextNode && nextNode.nodeType == 3 && nextNode.nodeValue.trim().length == 0) {
nextNode = nextNode.nextSibling;
}
if(prevNode && prevNode.nodeType == 3) {
obj.parentNode.insertBefore(document.createElement("br"), obj);
}
obj.parentNode.insertBefore(img, obj);
if(nextNode && nextNode.nodeType == 3) {
obj.parentNode.insertBefore(document.createElement("br"), obj);
}
obj.parentNode.removeChild(obj);
}
function resizeImageCallback(event) {
if(!event) var event = window.event;
var img = window.event ? event.srcElement : event.target;
if(event.type == "load") {
img = event.currentTarget;
}
var width = img.width;
var height = img.height;
var maxWidth = parseInt(GM_getValue("maxWidth"));
if(!img.getAttribute("defaultWidth")) {
// Never seen image before
img.setAttribute("defaultWidth", width);
img.setAttribute("defaultHeight", height);
zoomOut(img);
if(event.type == "load" || event.type == "complete") {
if(event.type == "complete") {
img.removeEventListener("complete", resizeImageCallback, true);
}
img.addEventListener("click", resizeImageCallback, false);
}
} else if(event.type == "click" || event.type == "complete") {
if(img.style.cursor == "-moz-zoom-in") {
if(width == maxWidth) {
// Click to zoom in
zoomIn(img);
} else {
// maxWidth has changed...
// This "click" was actually a window resize
zoomOut(img);
}
var defaultWidth = parseInt(img.getAttribute("defaultWidth"));
if(defaultWidth < maxWidth) {
img.style.cursor = "";
}
} else if(img.style.cursor == "-moz-zoom-out") {
zoomOut(img);
var defaultWidth = parseInt(img.getAttribute("defaultWidth"));
if(defaultWidth < maxWidth) {
img.style.cursor = "";
}
} else {
zoomOut(img);
}
}
}
function setMaxWidth(calledByResize) {
var maxWidth = document.body.clientWidth;
var allDiv = document.getElementsByTagName("div");
var foundPost = false;
for(var i = allDiv.length - 1; i >= 0; i--) {
var div = allDiv[i];
if(nodeIsPost(div)) {
foundPost = true;
maxWidth = Math.min(div.offsetWidth, maxWidth);
}
}
GM_setValue("maxWidth", Math.floor(maxWidth));
var images = document.images;
for(var i = images.length - 1; i >= 0; i--) {
var parent = images[i];
if(foundPost) {
// Only run this code if we found a post. Otherwise the body is the limit.
while(parent = parent.parentNode) {
if(parent.nodeName.toLowerCase() == "div") {
if(nodeIsPost(parent)) {
break;
}
}
}
if(!parent) {
continue;
}
}
// Every image in the post table gets a handler
if(!calledByResize && !images[i].complete) {
images[i].addEventListener("load", resizeImageCallback, false);
}
if(!calledByResize || images[i].style.cursor != "-moz-zoom-out") {
if(images[i].complete) {
images[i].addEventListener("complete", resizeImageCallback, true);
var event = document.createEvent("Events");
event.initEvent("complete", false, false);
images[i].dispatchEvent(event);
}
}
}
}
function imageError(event) {
if(!event) var event = window.event;
var img = event.currentTarget;
var link = document.createElement("a");
link.setAttribute("href", img.src);
link.setAttribute("target", "_blank");
link.appendChild(document.createTextNode("[TW Embedder: Failed to load] " + img.alt));
img.parentNode.insertBefore(link,img);
img.parentNode.removeChild(img);
}
function zoomOut(img) {
var defaultWidth = parseInt(img.getAttribute("defaultWidth"));
var width = img.width;
var height = img.height;
var maxWidth = parseInt(GM_getValue("maxWidth"));
if(defaultWidth > maxWidth) {
var delta = maxWidth / width;
img.setAttribute("width", maxWidth);
img.setAttribute("height", Math.floor(height * delta));
img.style.cursor = "-moz-zoom-in";
}
}
function zoomIn(img) {
img.setAttribute("width", img.getAttribute("defaultWidth"));
img.setAttribute("height", img.getAttribute("defaultHeight"));
img.style.cursor = "-moz-zoom-out";
}
function nodeIsPost(node) {
var id = node.getAttribute("id");
return (id && id.indexOf("post_message") >= 0);
}
GM_registerMenuCommand("TW Embedder: View image on click", function(event) {
GM_setValue("hotlinkPref","off");
});
GM_registerMenuCommand("TW Embedder: View image automatically", function(event) {
GM_setValue("hotlinkPref","on");
});
GM_registerMenuCommand("TW Embedder: Image Resizing (on)", function(event) {
GM_setValue("resizePref","on");
});
GM_registerMenuCommand("TW Embedder: Image Resizing (off)", function(event) {
GM_setValue("resizePref","off");
});