function JargonBuster (jargonFile)
{
	var self				= this;
	self.jargon				= new Object;
	self.jargonCached		= false;
	self.targetContainer	= $('#content');
	self.targetElements		= $('.ui-tabs-panel p, .ui-tabs-panel ul, .ui-tabs-panel ol, .ui-tabs-panel .spec th, .ui-tabs-panel .spec td', self.targetContainer).not ('.tabbernav, .extra-padding, .exclude-jargon'); 
	self.regexPrefix		= '(';
	self.regexPostfix		= ')(?!([a-zA-Z0-9 _:;/#\?&-]*?"?(>| [a-zA-Z0-9_-]*?="?[a-zA-Z0-9 _:;/#\?&-]"?)|.*?</(a|h[1-2]|button|option|script|style|textarea)>|.*?" />))';
	self.regexOptions		= 'gi';
	self.divOffsetX			= -10;
	self.divOffsetY			= -24;
	self.initBubble			= function ()
	{
		$('body').append ('<div id="ajaxNode" style="display: none;">'
						  + '<div id="ajaxNodeTitle">'
						  + '<h3 id="ajaxHeadTitle"></h3>'
						  + '</div>'
						  + '<div id="ajaxNodeText"></div>'
						  + '</div>');
		return ($('#ajaxNode'));
	};
	self.updateBubble		= function (hoveredLink)
	{
		if (!self.divHead)
		{
			self.divHead	= $('#ajaxNodeTitle > h3');
			self.divBody	= $('#ajaxNodeText');
		}
		var thisTerm = hoveredLink.className.split (' ')[1];
		self.divHead.text (self.jargon [thisTerm].term);
		self.divBody.html (self.jargon [thisTerm].description);
	};
	self.positionBubble		= function (x, y)
	{
		self.jargonBubble.css (
		{
			left	: x + self.divOffsetX,
			top		: (y - self.jargonBubble.height ()) + self.divOffsetY
		});
	};
	self.jargonWindow		= function (url)
	{
		window.open (url, 'Jargon', 'width=647,height=680,scrollbars=yes,resizable=yes').focus ();
		return (false);
	};
	self.insertJargon		= function (xml)
	{
		var elementsToProcess	= self.targetElements
		var elementsContent		= new Array;
		elementsToProcess.each (function (index)
		{
			elementsContent [index]	= $(this).html ();
		});
		var xmlTerms = $('jargonterm', xml);
		xmlTerms.each (function (index)
		{
			var thisTerm = $(this);
			self.jargon [thisTerm.attr ('id')] = new Object (
			{
				term		: thisTerm.attr ('term'),
				description	: $('description', thisTerm).text (),
				href		: thisTerm.attr ('href'),
				regex		: thisTerm.attr ('regex')
			});
			var thisSearch	= new RegExp (self.regexPrefix + thisTerm.attr ('regex') + self.regexPostfix, self.regexOptions);
			for (var index = 0; index < elementsContent.length; index++)
			{
				elementsContent [index]	= elementsContent [index].replace (
					thisSearch,
					'\r\n<a class="jargonbuster ' + thisTerm.attr ('id')
					+ '" href="' + thisTerm.attr ('href')
					+ '">$1</a>\r\n'
				);
			}
		});
		elementsToProcess.each (function (index)
		{
			$(this).html (elementsContent [index]);
		});
	};
	self.addJargonEvents	= function ()
	{
		var jargonAnchors	= $('.jargonbuster', self.targetContainer);
		jargonAnchors.click (function (evt)
		{
			self.jargonWindow (this.href);
			return (false);
		});
		jargonAnchors.hover (function (evt)
		{
			self.updateBubble (this);
			self.jargonBubble.css ('display', 'block');
			self.positionBubble (evt.pageX, evt.pageY);
			return (false);
		},
		function (evt)
		{
			self.jargonBubble.css ('display', 'none');
			return (false);
		});
		jargonAnchors.mousemove (function (evt)
		{
			self.positionBubble (evt.pageX, evt.pageY);
			return (false);
		});
	}
	self.fetchJargon		= function (thisUrl)
	{
		$.ajax ({
			type		: 'GET',
			dataType	: 'xml',
			url			: thisUrl ,
			data		:
			{
				sid	: Math.random ()
			},
			success		: function (response)
			{
				$('.jargon-buster').hide ();
				self.insertJargon (response);
				self.addJargonEvents ();
			}
		});
	};
	self.jargonBubble	= self.initBubble ();
	self.fetchJargon (jargonFile);
}

$(document).ready (function () {var jargon = new JargonBuster (dataSource);});