// ==UserScript==
// @name	AutoCard_MTG
// @namespace	http://shenafu.com/
// @description	Show image of card upon mouseover of autocard link

// @version	1.37
// @author	Lord of Atlantis
// @download	http://www.shenafu.com/magic/autocard_mtg.user.js

// @include	http://wizards.com/*
// @include	http://*.wizards.com/*
// @include	http://gleemax.com/*
// @include	http://*.gleemax.com/*
// @include	http://mtgsalvation.com/*
// @include	http://*.mtgsalvation.com/*
// @include	http://starcitygames.com/*
// @include	http://*.starcitygames.com/*
// @include	http://crystalkeep.com/*
// @include	http://*.crystalkeep.com/*
// @include	http://*.yawgatog.com/*
// @include	http://*.tcgplayer.com/*
// @include	http://*.gamefaqs.com/*
// @include	http://*.blogspot.com/*
// @include	http://*.magic-league.com/*
// @include	http://*.mtgthesource.com/*
// @include	http://puremtgo.com/*
// @include	http://www.themanadrain.com/*
// @include	http://*.mtgvault.com/*
// @include	http://shenafu.com/*
// @include	http://*.shenafu.com/*
// @include	http://daccg.com/*
// @include	http://*.daccg.com/*

// ==/UserScript==

// Opera users put this script in the userjs folder.
// GreaseMonkey rename with extension .user.js.
/*
	MTG Autocard upon Mouseover
	by Dennis Voong
	(a.k.a. Lord of Atlantis @ wizards and mtgsalvation forums)
	[Last updated 2011/10/14 20:55:00 -8:00 Pacific Time US]

	When you move the mouse over a card's name
	at major Magic sites, the card's picture will appear.
	(An option is to require you to double click the mouse button before the
	image will appear.)

	Tested on Opera 11.51 and Firefox 3. However, image quality varies by browser.
	(Opera has much better image quality.)
	I've stop supporting older versions of these browsers.

	Works for the most popular Magic sites, such as
	wizards.com, magicthegathering.com, gleemax.com, gatherer,
	mtgsalvation, starcity, crystalkeep, and whatever is included at the top.

	If you want to include a site not listed, add a similar include line at the top.
	However, it might not work if the link address doesn't meet the criteria.
	If this is the case, contact me, Lord of Atlantis, at mtgsalvation.

	Reversely, if you don't want this script to run for a site that is listed
	(e.g. wizards articles and tcgplayer because they have their own pop up scripts),
	then delete their respective include lines.

	Works for 99.999% of the cards.
	Split cards will work if the article or poster types one or both sides
	separated by slash(es) or space or underscore.
	e.g. any of these should work:  fire/ice ; fire_ice ; fire ice ; fire//ice ;
	fire ; ice
	Dissension split cards require double underscore. Dead__Gone, too.
	Aether should be spelled out so 'ae' are two letters.
	Unicode AE, ae does convert now.
	BFM can be written bfm ; bfm left ; bfm right

	Original creation date: Mar 16, 2007
	Here's the original discussion on why this was created:
	http://boards1.wizards.com/showthread.php?t=809153
	See post #13 to test the cards.

	Special Thanks To:
	Shimakuma from mtg boards: showed how to get Dissension split cards.
	Effovex from mtg boards: userscript @includes.
	ASM from www.thescripts.com for Unicode AE fix.
	Opera team for such a fully-featured yet fast browser.
	Google and mozilla for javascript and DOM answers.
	Magic fans for the inspiration.

	AND OF COURSE, Wizards of the Coast and Richard Garfield
	for this awesome game and easy-to-find images on their website.

	If you have issues, know other sites to add, etc.
	message me, Lord of Atlantis, at mtgsalvation forums, OR
	ask your questions on one of the official forum topics regarding this script,
	URLs below:
	http://shenafu.com/smf/index.php?topic=5.0
	http://forums.mtgsalvation.com/showthread.php?t=137169
*/

/*
	How the script works.

	Replaces all links that refer to autocard or gatherer to receive
	onmouseover events.

	Article links to autocard look something like this:
	href="javascript:autoCardWindow('Lord_of_Atlantis')"
	href="javascript:autoCardWindow2('Juzam Djinn','')"

	On the discussion boards, the cards have mouseover events that modify
	the status bar, like this:
	onMouseover="window.status='Necropotence'; return true"

	Actually, querying this event returns a multi-line function, like this:
	function (event)
	{
		window.status = "Old Fogey";
		return true;
	}

	Condense this into a single-line string before extracting the card's name.

	For Gatherer, the card name is the text contained in the first td in each tr
	in the table whose id="_gridResults". Since it looks in tr (not links), this is
	done in a separate section.

	MTGSalvation links to magiccards.info:
	http://www.magiccards.info/autocard.php?card=Nightmare

	MTGSalvation attachments also work:
	http://forums.mtgsalvation.com/attachment.php?attachmentid=43144&d=1174759194

	Starcity uses this:
	http://sales.starcitygames.com/cardsearch.php?singlesearch=Skyshroud+Elite

	This script looks for these clues and adds or replaces the onmouseover event
	that instead pops up the image for that card.

	Get the images from here:
	http://wizards.com/global/images/magic/general/winding_wurm.jpg
	http://wizards.com/global/images/magic/tsb/lord_of_atlantis.jpg

	Convert special characters and spaces into underscore.
	(autocard_fixcardname())

	(autocard page that holds this image:
	http://www.wizards.com/magic/autocard.asp?name=cardname
	http://www.wizards.com/magic/autocard.asp?name=lord_of_atlantis
	)

	Images are now preloaded. After it's in your cache, it should
	appear instantaneously thereafter and for subsequent mouseovers.
*/

/*
	KNOWN ISSUES
*/

// CONSTANTS /////////////////////////////////////////////

autocard = {
	// if false, you have to double click mouse button anywhere on the page to toggle on and off
	alwaysOn: true,

	// original size is 200 wide by 285 high
	imgWidth: 300,
	imgHeight: 428,
	//imgId: "autocardimg",
	//imgId2: "autocardimg2",

	cardback: "http://www.wizards.com/global/images/magic/general/cardback.jpg",
	progressBar: "http://www.shenafu.com/images/progressBar_MTG.gif",
	// change to your favorite card search site
	replaceUrl: "http://magiccards.info/query?q=!"
};

// order of downloading images
// cardback last
var AUTOCARD_IMG_RE = new Array(
"http://www.wizards.com/global/images/magic/general/cardname.jpg",
"http://shenafu.com/images/mtg-cardname.jpg",
"http://shenafu.com/imgd/card2img/mtg-cardname.jpg",
"http://shenafu.com/images/mtg-preview-cardname.jpg",
"http://shenafu.com/images/mtg-ymtc-cardname.jpg",
"http://www.wizards.com/global/images/magic/tsb/cardname.jpg",
"http://www.wizards.com/global/images/magic/p3k/cardname.jpg",
"http://www.wizards.com/global/images/magic/portal2/cardname.jpg",
"http://www.wizards.com/global/images/magic/portal/cardname.jpg",
"http://www.wizards.com/global/images/magic/starter/cardname.jpg",
//"http://shenafu.com/images/stc-cardname.jpg",
//"http://shenafu.com/imgd/mtgautocard/cardname.jpg",
//*/
autocard.cardback
);

// actual url to image sources
var imgs = new Array();

var AUTOCARD_SPLIT = new Array(
new Array("assault_battery", "assault_battery"),
new Array("pain_suffering", "pain_suffering"),
new Array("spite_malice", "spite_malice"),
new Array("stand_deliver", "stand_deliver"),
new Array("wax_wane", "wax_wane"),
new Array("fire_ice", "fire_ice"),
new Array("illusion_reality", "illusion_reality"),
new Array("life_death", "life_death"),
new Array("night_day", "night_day"),
new Array("order_chaos", "order_chaos"),
new Array("bound_determined", "bound__determined"),
new Array("crime_punishment","crime__punishment"),
new Array("hide_seek","hide__seek"),
new Array("hit_run","hit__run"),
new Array("odds_ends","odds__ends"),
new Array("pure_simple","pure__simple"),
new Array("research_development","research__development"),
new Array("rise_fall","rise__fall"),
new Array("supply_demand","supply__demand"),
new Array("trial_error","trial__error"),
new Array("boom_bust", "boom_bust"),
new Array("dead_gone", "dead__gone"),
new Array("rough_tumble", "rough_tumble"),
new Array("who_what_when_where_why", "who_what_when_where_why"),
new Array("bfm_big_furry_monster", "bfm"),
// cardnames with quotes may not be escaped correctly (e.g. crystal keep)
new Array("pang_tong", "pang_tong_young_phoenix"),
new Array("kongming", "kongming_sleeping_dragon")
);
var AUTOCARD_SPLIT_JOIN = AUTOCARD_SPLIT.join("_");

var AUTOCARD_TRANSFORM = new Array(
new Array("cloistered_youth", "unholy_fiend"),
new Array("thraben_sentry", "thraben_militia"),
new Array("civilized_scholar", "homicidal_brute"),
new Array("delver_of_secrets", "insectile_aberration"),
new Array("ludevics_test_subject", "ludevics_abomination"),
new Array("bloodline_keeper", "lord_of_lineage"),
new Array("screeching_bat", "stalking_vampire"),
new Array("hanweir_watchkeep", "bane_of_hanweir"),
new Array("instigator_gang", "wildblood_pack"),
new Array("kruin_outlaw", "terror_of_kruin_pass"),
new Array("reckless_waif", "merciless_predator"),
new Array("tormented_pariah", "rampaging_werewolf"),
new Array("village_ironsmith", "ironfang"),
new Array("daybreak_ranger", "nightfall_predator"),
new Array("garruk_relentless", "garruk_the_veil_cursed"),
new Array("gatstaf_shepherd", "gatstaf_howler"),
new Array("grizzled_outcasts", "krallenhorde_wantons"),
new Array("mayor_of_avabruck", "howlpack_alpha"),
new Array("ulvenwald_mystics", "ulvenwald_primordials"),
new Array("villagers_of_estwald", "howlpack_of_estwald")
);
var AUTOCARD_TRANSFORM_JOIN = AUTOCARD_TRANSFORM.join("_");


// FUNCTIONS /////////////////////////////////////////////

function autocard_imgloaded(event, cardname, show) {
	var img = autocard.imgEl;
	var img2 = autocard.imgEl2;
	img.setAttribute("cardname", cardname);

	if (show) {
		img.src = imgs[cardname][0];
		//while(!img.complete);
	}
	else {
		img.src = "";
		img2.src = "";
	}

	//* Place IMG at cursor
	img.style.display = "block";

	// + down ; - up
	var y = event.clientY - img.clientHeight - 20;
	if ( y < 0 ) {
		y = event.clientY + 20; // move to bottom half of screen
	}
	if ( (y + img.clientHeight) > window.innerHeight ) {
		y = window.innerHeight - img.clientHeight - 0;
	}

	// + right ; - left
	var x = event.clientX + 20;
	if ( x > document.body.offsetWidth - img.scrollWidth - 70 ) {
		x = x - img.scrollWidth - 40; // move to left of cursor
	}
	if ( x < 0 ) {
		x = 0;
	}

	img.style.top = y + "px";
	img.style.left = x + "px";

	//*/ End Place IMG at cursor

	//transform cards show both img elements
	if (imgs[cardname].transform) {
		var transform = imgs[cardname].transform;
		img2.setAttribute("cardname", transform);
		img2.src = imgs[transform][0];
		img2.style.display = "block";
		img2.style.top = img.style.top;
		img2.style.left = (x + autocard.imgWidth) + "px";
	}

}

function autocard_mouseover(event) {

	if ( window.acmd ) {
		var link = event.target;
		if (link.tagName == "IMG") {
			link = link.parentNode;
		}
		var cardname = link.getAttribute("cardname");
		var img = autocard.imgEl;

		if (imgs[cardname].ran) {
			autocard_imgloaded(event, cardname, true);
		} else {
			// show progressbar while loading image in background
			autocard_imgloaded(event, cardname, false);
			img.src = autocard.progressBar;

			var img_temp = autocard.imgTemp;
			img_temp.setAttribute("cardname", cardname);
			img_temp.src = imgs[cardname][0];

			imgs[cardname].ran = true;

			if (imgs[cardname].transform) {
				var transform = imgs[cardname].transform;
				img_temp = autocard.imgEl2;
				img_temp.setAttribute("cardname", transform);
				img_temp.src = imgs[transform][0];
				imgs[transform].ran = true;
			}
		}
	}
}

function autocard_mouseout() {
	var img = autocard.imgEl;
	img.src = ""; // must go before hiding it
	img.style.display = "none";

	var img2 = autocard.imgEl2;
	img2.src = ""; // must go before hiding it
	img2.style.display = "none";
}

function autocard_fiximageurl() {
	var cardname = this.getAttribute("cardname");
	// remove first url
	imgs[cardname].splice(0,1);
	this.src = imgs[cardname][0];
}

function autocard_fixcardname(cardname, link) {
	if ( !link.attachment ) {
		// remove set info
		cardname = cardname.replace(/&.*=.*/g, "");
		cardname = cardname.replace(/\|.*/g, "");

		// needs testing to see if any card won't work after changing to lowercase
		cardname = cardname.toLowerCase();

		// remove bold, italics tags
		cardname = cardname.replace(/<\/?b>/ig, "");
		cardname = cardname.replace(/<\/?i>/ig, "");
		cardname = cardname.replace(/%3c\/?b%3e/ig, ""); // </?b>
		cardname = cardname.replace(/%3c\/?i%3e/ig, ""); // </?i>

		// token cards
		cardname = cardname.replace(/token card/ig, "token");

		// fix strange characters

		// ( UTF-8 | caps | lowercase )
		cardname = cardname.replace(/\(r\)/ig, ""); // (R), registered
		cardname = cardname.replace(/(%c2%ae|\xae)/ig, ""); // ?
		cardname = cardname.replace(/(%c3%86|\xc6|\xe6)/ig, "ae"); // AE
		cardname = cardname.replace(/%[cCeE]6/ig, "ae"); // AE
		cardname = cardname.replace(/(%c3%a9|\xc9|\xe9)/ig, "e"); // É
		cardname = cardname.replace(/%[cCeE]9/ig, "e"); // É
		cardname = cardname.replace(/%20/g, " "); // space
		cardname = cardname.replace(/(%27|%92|%60|%[bB]4)/g, "'"); // apostrophe, grave, acute
		cardname = cardname.replace(/(%[eE]2%80%99)/g, ""); // dumb quote
		cardname = cardname.replace(/%2[cC]/g, ","); // comma
		cardname = cardname.replace(/%2[fF]/g, ","); // slash
		cardname = cardname.replace(/:(\s|_)*/g, "_"); // colon then any # of spaces or underscore
		cardname = cardname.replace(/[ _]*\/\/[ _]*/g, "_"); // "//" or " // " or "_//_"
		cardname = cardname.replace(/\s*\/\s*/g, "_"); // " / "
		cardname = cardname.replace(/\s+/g, "_"); // spaces
		cardname = cardname.replace(/\+/g, "_"); // +
		cardname = cardname.replace(/,/g, ""); // comma
		cardname = cardname.replace(/\./g, ""); // period
		cardname = cardname.replace(/`/g, ""); // back quote
		cardname = cardname.replace(/'/g, ""); // apostrophe
		cardname = cardname.replace(/(\"|%22)/g, ""); // double quote
		cardname = cardname.replace(/\[/g, ""); // [
		cardname = cardname.replace(/\]/g, ""); // ]
		//cardname = cardname.replace(/:/g, ""); // :
		cardname = cardname.replace(/!/g, ""); // !
		cardname = cardname.replace(/\?/g, ""); // ?
		cardname = cardname.replace(/(\&|\amp;|%26)/g, ""); // ampersand, ex. R&D
		cardname = cardname.replace(/\\/g, ""); // \ backslash
		cardname = cardname.replace(/%5c/g, ""); // \ backslash

		// Lorwyn keeps dash; underscore also works
		cardname = cardname.replace(/-/g, "_"); // -
		if ( cardname.match(/^_*$/)) {
			cardname = cardname.replace(/_{6,}/g, "_____"); // _____ (at least 5 long)
		}
		else {
			// trim underscores
			cardname = cardname.replace(/^_+/g, "");
			cardname = cardname.replace(/_+$/g, "");
			cardname = cardname.replace(/_+/g, "_");
		}

		// split cards
		var cardtemp = cardname;
		if ( AUTOCARD_SPLIT_JOIN.match(cardtemp) ) {
			for (var k=0, l=AUTOCARD_SPLIT.length; k<l; k++) {
				var splitcard = AUTOCARD_SPLIT[k];
				if ( splitcard[0].match( cardtemp ) ) {
					cardname = splitcard[1];
				}
			}
		}

		// transform cards, extra img element
		var transform;
		if ( AUTOCARD_TRANSFORM_JOIN.match(cardname) ) {
			for (var k=0, l=AUTOCARD_TRANSFORM.length; k<l; k++) {
				var splitcard = AUTOCARD_TRANSFORM[k];
				if ( splitcard[0].match( cardname ) ) {
					transform = splitcard[1];
				}
				else if ( splitcard[1].match( cardname ) ) {
					transform = splitcard[0];
				}
			}
		}

		// finally, replace with actual URL to image
		link.setAttribute("cardname",cardname);
		imgs[cardname] = new Array();
		if (transform) {
			imgs[transform] = new Array();
			imgs[cardname].transform = transform;
			imgs[transform].transform = cardname;
		}
		for (var i=0; i < AUTOCARD_IMG_RE.length; i++) {
			var src = AUTOCARD_IMG_RE[i].replace("cardname", cardname);
			imgs[cardname][i] = src;
			if (transform) {
				src = AUTOCARD_IMG_RE[i].replace("cardname", transform);
				imgs[transform][i] = src;
			}
		}
	}
	else {
		// this is actually an attachment in forums
		// eg spoilers in the rumor mill
		link.setAttribute("cardname",cardname);
		imgs[cardname] = new Array();
		imgs[cardname][0] = cardname;
	}

	return cardname;
}

function autocard_findcard(link) {
	var cardname = "";
	var href = link.href;
	var url = document.URL;

	// magic articles
	if (link.getAttribute("onmouseover")=="OpenTip(event, this)") {
		cardname = link.getAttribute("keyValue").replace(/.*\('/g, "");
		cardname = cardname.replace(/'.*\)/g, "");
	}

	// new gatherer, old wizards boards
	// href="http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=185054"
	// image URL http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=185054&type=card
	else if (href.match(/gatherer.wizards.com\/.*\?multiverseid/)) {
		if (link.id.match(/cardTitle/)) {
			cardname = link.innerHTML.replace(/^LL/g, "L");
			// some freaky thing with Look at Me, I'm R&D producess LL
		}
		else if (link.id.match(/cardImageLink/)) {
			cardname = link.childNodes[1].getAttribute('alt');
		}
	}

	// new wizards boards, puremtgo
	//http://gatherer.wizards.com/Pages/Card/Details.aspx?name=Artisan%20of%20Kozilek
	else if (href.match(/Card\/Details.aspx\?name/))  {
		cardname = href.replace(/.*=/g, "");
		cardname = cardname.replace(/undefined/g, "");
	}
	//http://gatherer.wizards.com/Pages/Search/Default.aspx?name=+[Artisan]+[of]+[Kozilek]
	else if (href.match(/gatherer.wizards.com\/Pages\/Search\/Default.aspx\?name/))  {
		cardname = href.replace(/.*=/g, "");
		cardname = cardname.replace(/undefined/g, "");
	}

	// starcitygames
	// http://sales.starcitygames.com/cardsearch.php?singlesearch=Skyshroud+Elite
	if (href.match(/starcitygames.com\/+cardsearch/) ) {
		cardname = href.replace(/.*=/g);
		cardname = cardname.replace(/undefined/g, "");
	}

	// mtgsalvation, magic-league
	else if (href.match(/magiccards.info/)) {
		// http://magiccards.info/query?q=Shock
		if (href.match(/query/) ) {
			cardname = link.href.replace(/.*q=(.*)&?.*/g, "$1");
		}
		else if (href.match(/autocard/) ) {
			// http://www.magiccards.info/autocard.php?card=Nightmare
			// http://www.magiccards.info/autocard/Nightmare
			cardname = href.replace(/.*(card=|card\/)/g);
			cardname = cardname.replace(/undefined/g, "");
		}
		else if (href.match(/html$/) ) {
			// http://magiccards.info/ts/en/196.html
			// link doesn't have name info
			// maybe poster put the name of the card, if lucky
			cardname = link.innerHTML;
		}
		else if (href.match(/jpg$/)) {
			// http://magiccards.info/scans/en/arena/5.jpg
			cardname = href;
			link.attachment = true;
		}
	}

	// forum attachment, eg spoilers on mtgsalvation, SMF
	// http://forums.mtgsalvation.com/attachment.php?attachmentid=43144&d=1174759194
	else if (href.match(/attachment\.php/) ) {
		cardname = href;
		link.attachment = true;
	}

	// crystalkeep, index listing
	// http://www.crystalkeep.com/cgi-bin/magicsearch.cgi?cardName=Bound%20(Bound/Determined)
	else if (href.match(/crystalkeep.com\/cgi-bin\/magicsearch/) && !href.match(/cardType/) ) {
		cardname = href.replace(/.*=/g);
		cardname = cardname.replace(/undefined/g, "");
		cardname = cardname.replace(/(.*)(\(|%28)(.*)(\/|%2[fF]).*(\)|%29).*/g, "$3"); // split cards
	}

	// crystalkeep, search listing
	// <A NAME="AEtherflame Wall">
	else if (url.match(/crystalkeep.com\/cgi-bin\/magicsearch/) ) {
		if (link.name) {
			cardname = link.name;
			cardname = cardname.replace(/.*\((.*\/.*)\)/g, "$1"); // split cards
		}
	}

	// yawgatog.com, Oracle card changes
	// <a href="./?id=0">Angry Mob <span>
	else if (url.match(/www.yawgatog.com/) ) {
		if (link.innerHTML.match(/.+\[Click to view/) ) {
			cardname = link.innerHTML.replace(/ <SPAN.*<\/SPAN>/ig);
			cardname = cardname.replace(/undefined/g, "");
		}
	}

	// puremtgo
	// http://www.mtgotraders.com/store/7E_Counterspell.html
	else if (href.match(/www.mtgotraders.com\/store/) ) {
		cardname = href.replace(/[^_]+_(.+).html/g, "$1");
		cardname = cardname.replace(/undefined/g, "");
	}
	//mtgvault
	// http://www.mtgvault.com/ViewCard.aspx?CardName=Kjeldoran%20Outpost&Edition=ALL
	// http://www.mtgvault.com/ViewCard.aspx?CardName=Ad%20Nauseam
	else if (href.match(/CardName=.*(&Edition.*)?/)) {
		cardname = href.replace(/.*CardName=(.*)/g, "$1");
	}
	return cardname;
}

function autocard_link2name(link) {
	// find card's name
	var cardname = autocard_findcard(link);

	// if card is found, then do mouseover event
	if ( cardname != "" ) {
		cardname = autocard_fixcardname(cardname, link);

		// remove website's popup function
		if (link.hasAttribute("onmouseover")) {
			link.setAttribute("onmouseover", null);
		}
		// community.wizards.com has inline span that uses css instead of javascript
		var span = link.getElementsByClassName("linkCardHoverImage");
		if (span.length) {
			link.removeChild(span[0]);
		}

		link.addEventListener("mouseover", autocard_mouseover, true);
		link.addEventListener("mouseout", autocard_mouseout, false);
	}
}

function autocard_createimg() {
	var img = document.createElement('img');
	//img.id = autocard.imgId;
	img.style.display = "none";
	img.width = autocard.imgWidth;
	img.height = autocard.imgHeight;
	img.style.position = "fixed";
	img.style.top = 0;
	img.style.left = 0;
	img.style.zIndex = 999999;

	// preload cardback and progress bar
	img.src = autocard.cardback;
	while(!img.complete);
	img.src = autocard.progressBar;
	while(!img.complete);
	img.style.backgroundImage = autocard.cardback;
	//img.style.backgroundColor = "663300";
	img.addEventListener("mouseout", autocard_mouseout, false);

	img = document.body.appendChild(img);
	autocard.imgEl = img;

	var img2 = document.createElement('img');
	//img2.id = autocard.imgId2;
	img2.style.display = "none";
	img2.width = autocard.imgWidth;
	img2.height = autocard.imgHeight;
	img2.style.position = "fixed";
	img2.style.top = 0;
	img2.style.left = 0;
	img2.style.zIndex = 999999;

	// preload cardback and progress bar
	img2.style.backgroundImage = autocard.cardback;
	//img.style.backgroundColor = "663300";
	img2.addEventListener("mouseout", autocard_mouseout, false);
	img2.addEventListener("error", autocard_fiximageurl, false);

	img2 = document.body.appendChild(img2);
	autocard.imgEl2 = img2;

	img_temp = document.createElement('img');
	img_temp.id = "img_temp";
	img_temp.style.visibility = "hidden";
	img_temp = document.body.appendChild(img_temp);
	img_temp.addEventListener("error", autocard_fiximageurl, false);
	img_temp.addEventListener("load", function(event) {autocard_imgloaded(event, this.getAttribute("cardname"), true);}, false);
	autocard.imgTemp = img_temp;

	return img;
}

function autocard_mtg() {
	// make an img for where the image is shown
	var img = autocard_createimg();
	// look for and store all links in the page
	var urls = document.getElementsByTagName("A");

	// if link matches criteria, add mouseover event
	for (i=0; i<urls.length;i++) {
		var link = urls[i];
		autocard_link2name(link);
	}

	window.acmd = false;
	if ( autocard.alwaysOn ) {
		window.acmd = true;
	}
	else
	{
		// add window event to toggle on or off
		window.addEventListener('dblclick', function() {
			window.acmd = !window.acmd;
			return false;
		}, true);
	}

	return false;
}

// INTERFACING EVENTS /////////////////////////////////////////////

function autocard_text2link() {
	// helper for browser menu commands
	// eg select an unlinked card name, right click to open menu, choose "Autocard link" to create a link for all unlinked text that match the selected strng
	if (window.getSelection) {
		var userSelection = window.getSelection();
		var userRange= userSelection.getRangeAt(0);
		var x = userRange.startContainer;
		// some elements like headers dont default to text type
		if (!x.nodeName || x.nodeName != "#text") {
			x = x.childNodes[0];
		}

		// below code inspired from text2link userjs

		if (x.nodeName == "#text") {
			var regex = new RegExp(userSelection, "g");
			var text = x.nodeValue.split(regex);

			if (text.length > 1) {
				var cards = x.nodeValue.match(regex);
				var index = 0, p = x.parentNode;
				var n = document.createDocumentFragment();
				n.appendChild(document.createTextNode(text[index]));

				while(index < cards.length) {
					var link = document.createElement('a');
					link.href = autocard.replaceUrl + userSelection;
					autocard_fixcardname(userSelection.toString(), link);
					link.addEventListener("mouseover", autocard_mouseover, false);
					link.addEventListener("mouseout", autocard_mouseout, false);
					link.appendChild(document.createTextNode(userSelection));
					n.appendChild(link, x);
					index++;
					n.appendChild(document.createTextNode(text[index]), x);
				}
				p.replaceChild(n, x);
			}
		}
	}
}

window.addEventListener('load', function() { autocard_mtg(); }, false);

// if new anchors are added later, parse those links
// e.g. card search engines using AJAX
window.addEventListener('DOMNodeInserted', function(event) {
	if (event.target.tagName=="A") {
		autocard_link2name(event.target);
	}
}, false);

