/**************************************************************\
  NIFTI - Nimble Inline Font-Titling Images
  
  JavaScript portion v 2.7.2

	CHANGELOG
	2009-08-23	2.7.2	Fixed specificity error - MDL
\**************************************************************/

if (! NIFTI) { var NIFTI = new Object; };
if (! NIFTI.ElementSelection ) { NIFTI.ElementSelection = new Object(); };

NIFTI.BRTagsRegEx = /<br *\/?>/gi;
NIFTI.SUPTagsRegEx = /<\/?sup( [^>]*)?>/gi;
NIFTI.SUBTagsRegEx = /<\/?sub( [^>]*)?>/gi;
NIFTI.BRTagsRegEx = /<br *\/?>/gi;
NIFTI.AllTagsRegEx = /<\/?[^>]+>/gi;
NIFTI.AllWhitespaceRegEx = /\s+/gi;
NIFTI.ForbiddenAltRegEx = /[\u0001-\u0019\u8000-\uFF7F]/g;
NIFTI.BreakCharacter = String.fromCharCode( 0xE48B );
NIFTI.BreakCharactersRegEx = new RegExp(NIFTI.BreakCharacter, "gi");
NIFTI.SuperscriptCharacter = String.fromCharCode( 0xE800 );
NIFTI.SubscriptCharacter = String.fromCharCode( 0xE801 );

NIFTI.TargetURL = "You must call NIFTI.init before using this";
NIFTI.ReplacementSelectors = {};
NIFTI.PreloadedImages = [];
NIFTI.escape = encodeURIComponent || escape;
NIFTI.VMLNS = "NIFTIVML";


(function() {
	var a = "" + navigator.userAgent;
	NIFTI.isIE = !!(window.attachEvent && !window.opera);
	if (NIFTI.isIE) {
		a = a.substr((a.indexOf("MSIE ") + 5), 3);		
		NIFTI.IEversion = parseFloat(a);
	} else {
		NIFTI.IEversion = 0.0;
	}
	NIFTI.useVML = (NIFTI.isIE && (NIFTI.IEversion < 7.0));
	if (NIFTI.useVML) {document.namespaces.add(NIFTI.VMLNS, 'urn:schemas-microsoft-com:vml'); };
})();


NIFTI.init = function( url ) {
	NIFTI.TargetURL = url;
	var sl, oldsl, slspec, oldslspec;
	for (var i = 1; i<arguments.length; i++) {
		sl = NIFTI.ElementSelection.parseSelectString(arguments[i]);
		NIFTI.ReplacementSelectors[ NIFTI.ElementSelection.normalizedSelector(sl) ] = sl;
	}
};

NIFTI.withDOM = function() {
	var selectorlist, selectorurl, elementtext, targetelement;
	var replacedelements = [];
	var i, j, hovers, img, srcurl, hoverurl;

	if (NIFTI.useVML) {
		var style = document.createElement('style');
		document.documentElement.firstChild.insertBefore(style, document.documentElement.firstChild.firstChild);
		var styleSheet = style.styleSheet;
		styleSheet.addRule(NIFTI.VMLNS + '\\:*', '{behavior:url(#default#VML); position:relative; display:inline-block; }');
	}

	for( i in NIFTI.ReplacementSelectors ) {
		selectorlist = NIFTI.ReplacementSelectors[i];
		replacedelements = replacedelements.concat(NIFTI.ElementSelection.getReplaced(selectorlist));
	}
	

	for( j=0; j<replacedelements.length; j++ ) {
		
		targetelement = replacedelements[j];
		if(!targetelement._nifti.replaced) {
			selectorlist = targetelement._nifti.selectors;
			selectorurl = NIFTI.escape(NIFTI.ElementSelection.normalizedSelector(selectorlist));
			hovers = selectorlist[selectorlist.length-1].hover;

			elementtext = NIFTI.normalizeText(targetelement.innerHTML);
			
			srcurl   = NIFTI.TargetURL + "?sel=" + selectorurl + "&text=" + NIFTI.escape(elementtext);
			hoverurl = NIFTI.TargetURL + "?sel=" + selectorurl + "%3Ahover&text=" + NIFTI.escape(elementtext);
			targetelement.style.visibility = "visible";

			if (NIFTI.useVML) {
				var r = targetelement._nifti.rect = document.createElement(NIFTI.VMLNS + ':rect');
				var f = targetelement._nifti.fill = document.createElement(NIFTI.VMLNS + ':fill');
								
				r.stroked = false;
				r.appendChild(f);
				targetelement.innerHTML = "";
				targetelement.appendChild(r);

				NIFTI._attachVMLSize(targetelement, srcurl);

				if ( hovers ) {
					NIFTI._attachVMLHover( targetelement, srcurl, hoverurl );
					img = new Image();
					img.src = hoverurl;
					NIFTI.PreloadedImages.push(img);
				}
			} else {
				targetelement.innerHTML = '<img src="' + srcurl + '" alt="' + elementtext.replace(NIFTI.ForbiddenAltRegEx,' ').replace('"','&quot;') + '" class="NIFTI" style="border:none;" />';
				if ( hovers ) {
					NIFTI._attachNormalHover( targetelement, srcurl, hoverurl );
					img = new Image();
					img.src = hoverurl;
					NIFTI.PreloadedImages.push(img);
				}
			}
			targetelement._nifti.replaced = true;
		}
	}


};

NIFTI._attachNormalHover = function( targetelement, src, srchover ) {
	targetelement._nifti.onmouseout = targetelement.onmouseout;
	targetelement._nifti.onmouseover = targetelement.onmouseover;
	targetelement.onmouseover = function () {					
		targetelement.getElementsByTagName("img")[0].src = srchover;
		if ( targetelement._nifti.onmouseover ) { targetelement._nifti.onmouseover.apply(targetelement); }
	}
	targetelement.onmouseout = function () {					
		targetelement.getElementsByTagName("img")[0].src = src;
		if ( targetelement._nifti.onmouseout ) { targetelement._nifti.onmouseout.apply(targetelement); }
	}
};

NIFTI._attachVMLHover = function( targetelement, src, srchover ) {
	targetelement._nifti.onmouseout = targetelement.onmouseout;
	targetelement._nifti.onmouseover = targetelement.onmouseover;
	targetelement.onmouseover = function () {					
		targetelement._nifti.fill.src = srchover;
		if ( targetelement._nifti.onmouseover ) { targetelement._nifti.onmouseover.apply(targetelement); }
	}
	targetelement.onmouseout = function () {					
		targetelement._nifti.fill.src = src;
		if ( targetelement._nifti.onmouseout ) { targetelement._nifti.onmouseout.apply(targetelement); }
	}
};

NIFTI._attachVMLSize = function( targetelement, src ) {
	var r = targetelement._nifti.rect;
	var s = targetelement._nifti.sizingimage = new Image();
	var f = targetelement._nifti.fill;
	s.onload = function() {
		r.style.height = s.height + "px";
		r.style.width = s.width + "px";
		f.type = 'frame';				
		f.on = false;
		f.src = src;
		f.on = true;
		f.color = 'none';
	}
	s.src = src;
};

NIFTI.normalizeText = function( text ) {
		return text.replace(NIFTI.SUPTagsRegEx, NIFTI.SuperscriptCharacter).replace(NIFTI.SUBTagsRegEx, NIFTI.SubscriptCharacter).replace(NIFTI.BRTagsRegEx, NIFTI.BreakCharacter).replace(NIFTI.AllTagsRegEx, '').replace(NIFTI.AllWhitespaceRegEx, ' ').replace(NIFTI.BreakCharactersRegEx, "\n").replace("&amp;","&");
}

NIFTI.ElementSelection.normalizedSelector = function ( selectorlist ) {
	// Ignores all pseudo-elements.
	var result = "";
	for( var i=0; i<selectorlist.length; i++ ) {
		result += " " + selectorlist[i].normalized;
	}
	return result.substring(1); // trim leading space
}

NIFTI.specificity = function ( selectorlist ) {
	var result = 0;
	for( var i=0; i<selectorlist.length; i++ ) {
		result += selectorlist[i].specificity;
	}
	return result;
}

NIFTI.ElementSelection.getReplaced = function( selectors ) {
	var i, j;
	
	var parents, results;
	
	parents = [ document.documentElement ];
	results = [];
	for( i=0; i<selectors.length; i++ ) {
		for( j=0; j<parents.length; j++ ) {
			results = results.concat( NIFTI.ElementSelection.getWithinElementOneClause( selectors[i], parents[j] ) );
		}
		parents = results;
		results = [];
	}
	for(i=0; i<parents.length; i++) {
		if(parents[i]._nifti) {
			var oldslspec = parents[i]._nifti.specificity;
			var slspec = NIFTI.specificity(selectors);
			if ( slspec > oldslspec ) { 
				parents[i]._nifti.selectors = selectors;
			}
		}
		else {
			parents[i]._nifti = {};
			parents[i]._nifti.replaced = false;
			parents[i]._nifti.selectors = selectors;
			parents[i]._nifti.specificity = NIFTI.specificity(selectors);
		}
	}
	return parents;
}

NIFTI.ElementSelection.getWithinElementOneClause = function( clause, element ) {
	var result = [];
	if ((! element) || (! clause)) { return result; }

	var possibles;
	if ( clause.tag ) {
		possibles = element.getElementsByTagName( clause.tag );
	} else {
		possibles = element.getElementsByTagName( "*" );
	}
	
	var curr, currclasses, i, j, classok;
	for(i=0; i<possibles.length; i++) {
		curr = possibles[i];
		classok = true;
		if ((clause.id) && (curr.id != clause.id)) { continue; };
		if (clause.classes.length > 0) {
			currclasses = " " + curr.className + " ";
			for( j=0; j<clause.classes.length; j++) {
				if( currclasses.indexOf( clause.classes[j] ) == -1 ) {
					classok = false;
				}
			}
		}
		if (classok) { result.push(curr); };
	}
	
	return result;
}

NIFTI.ElementSelection.parseSelectString = function( selectstring ) {
	var res = [];
	var rawselects = selectstring.split(' ');
	var i, s;
	
	for(i=0; i<rawselects.length; i++) {
		s = NIFTI.ElementSelection._parseSelectClause( rawselects[i] );
		if ( s ) { res.push(s); };
	}
	
	return res;
}

NIFTI.ElementSelection._parseSelectClause = function ( clausestring ) {
	var selector = { tag:null, id:null, classes:[], hover:false, normalized:"", innermostnormalized:"", specificity:0 };
    var modifier, name, rest;
	var cleanclasses = [];
	
	if (clausestring == '') { return null; }

    while (match = clausestring.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
      modifier = match[1], name = match[2], rest = match[3];
      switch (modifier) {
        case '#':       selector.id = name; selector.specificity += 100; break;
        case '.':       selector.classes.push( " " + name + " " ); cleanclasses.push(name); selector.specificity += 10; break;
        case ':':       if(name=='hover') { selector.hover = true; selector.specificity += 10; }; break;
        case '':
        case undefined: selector.tag = name.toLowerCase(); selector.specificity += 1; break;
      }
      clausestring = rest;
    }
	
	cleanclasses.sort();
	
	selector.normalized = (selector.tag?selector.tag:"") + (selector.id?"#"+selector.id:"");
	for( var i = 0; i<cleanclasses.length; i++ ) {
		selector.normalized += "." + cleanclasses[i];
	}
	selector.innermostnormalized = selector.normalized + ( selector.hover ? ":hover" : "" );
	
	return selector;
}

do {
	/* Internet Explorer */
	/*@cc_on @*/
	/*@if (@_win32)
		if ( window.location.protocol != "https:" ) {
			document.write("<sc" + "ript id='__ie_nifti_observeDOMReady' defer='defer' src='javascript:void(0);'><\/sc" + "ript>");
			NIFTI.DOMReadyBrowserDevice = document.getElementById("__ie_nifti_observeDOMReady");
			NIFTI.DOMReadyBrowserDevice.onreadystatechange = function() {
				if (this.readyState == "complete") {
					NIFTI.withDOM(); // call the onload handler
				}
			};
			break;
		}
	/*@end @*/
	
	/* Safari/Konqueror */
	/* WebKit must be tested for before DOM2 standard because WebKit supports document.addEventListener but NOT the 
	   DOMContentLoaded event. */
	if (/WebKit/i.test(navigator.userAgent)) { 
		NIFTI.DOMReadyBrowserDevice = setInterval(function() {
			if (/loaded|complete/.test(document.readyState)) {
				clearInterval(NIFTI.DOMReadyBrowserDevice);
				NIFTI.withDOM(); 
			}
		}, 10);
		break;
	}
	
	/* Mozilla/Opera9/DOM2 Compliant browsers */
	if (document.addEventListener) {
		document.addEventListener("DOMContentLoaded", NIFTI.withDOM, false);
		break;
	}

	/* Anything else */
	if (window.addEventListener) {
		window.addEventListener("load", NIFTI.withDOM, false);
	} else if(window.attachEvent) {
		window.attachEvent("onload", NIFTI.withDOM);
	}

} while(0);



