<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<base href="%@">
	
	<script type="text/javascript">
	//<![CDATA[
	
	   isDebug = false;        
        
        // Fade interval in milliseconds
        // Make this larger if you experience performance issues
        Fadomatic.INTERVAL_MILLIS = 50;
        
        // Creates a fader
        // element - The element to fade
        // speed - The speed to fade at, from 0.0 to 100.0
        // initialOpacity (optional, default 100) - element's starting opacity, 0 to 100
        // minOpacity (optional, default 0) - element's minimum opacity, 0 to 100
        // maxOpacity (optional, default 0) - element's minimum opacity, 0 to 100
        function Fadomatic (element, rate, initialOpacity, minOpacity, maxOpacity) {
          this._element = element;
          this._intervalId = null;
          this._rate = rate;
          this._isFadeOut = true;
        
          // Set initial opacity and bounds
          // NB use 99 instead of 100 to avoid flicker at start of fade
          this._minOpacity = 0;
          this._maxOpacity = 99;
          this._opacity = 99;
        
          if (typeof minOpacity != 'undefined') {
            if (minOpacity < 0) {
              this._minOpacity = 0;
            } else if (minOpacity > 99) {
              this._minOpacity = 99;
            } else {
              this._minOpacity = minOpacity;
            }
          }
        
          if (typeof maxOpacity != 'undefined') {
            if (maxOpacity < 0) {
              this._maxOpacity = 0;
            } else if (maxOpacity > 99) {
              this._maxOpacity = 99;
            } else {
              this._maxOpacity = maxOpacity;
            }
        
            if (this._maxOpacity < this._minOpacity) {
              this._maxOpacity = this._minOpacity;
            }
          }
          
          if (typeof initialOpacity != 'undefined') {
            if (initialOpacity > this._maxOpacity) {
              this._opacity = this._maxOpacity;
            } else if (initialOpacity < this._minOpacity) {
              this._opacity = this._minOpacity;
            } else {
              this._opacity = initialOpacity;
            }
          }
        
          // See if we're using W3C opacity, MSIE filter, or just
          // toggling visiblity
          if(typeof element.style.opacity != 'undefined') {
        
            this._updateOpacity = this._updateOpacityW3c;
        
          } else if(typeof element.style.filter != 'undefined') {
        
            // If there's not an alpha filter on the element already,
            // add one
            if (element.style.filter.indexOf("alpha") == -1) {
        
              // Attempt to preserve existing filters
              var existingFilters="";
              if (element.style.filter) {
                existingFilters = element.style.filter+" ";
              }
              element.style.filter = existingFilters+"alpha(opacity="+this._opacity+")";
            }
        
            this._updateOpacity = this._updateOpacityMSIE;
            
          } else {
        
            this._updateOpacity = this._updateVisibility;
          }
        
          this._updateOpacity();
        }
        
        // Initiates a fade out
        Fadomatic.prototype.fadeOut = function () {
          this._isFadeOut = true;
          this._beginFade();
        }
        
        // Initiates a fade in
        Fadomatic.prototype.fadeIn = function () {
          this._isFadeOut = false;
          this._beginFade();
        }
        
        // Makes the element completely opaque, stops any fade in progress
        Fadomatic.prototype.show = function () {
          this.haltFade();
          this._opacity = this._maxOpacity;
          this._updateOpacity();
        }
        
        // Makes the element completely transparent, stops any fade in progress
        Fadomatic.prototype.hide = function () {
          this.haltFade();
          this._opacity = 0;
          this._updateOpacity();
        }
        
        // Halts any fade in progress
        Fadomatic.prototype.haltFade = function () {
        
          clearInterval(this._intervalId);
        }
        
        // Resumes a fade where it was halted
        Fadomatic.prototype.resumeFade = function () {
        
          this._beginFade();
        }
        
        // Pseudo-private members
        
        Fadomatic.prototype._beginFade = function () {
        
          this.haltFade();
          var objref = this;
          this._intervalId = setInterval(function() { objref._tickFade(); },Fadomatic.INTERVAL_MILLIS);
        }
        
        Fadomatic.prototype._tickFade = function () {
        
          if (this._isFadeOut) {
            this._opacity -= this._rate;
            if (this._opacity < this._minOpacity) {
              this._opacity = this._minOpacity;
              this.haltFade();
            }
          } else {
            this._opacity += this._rate;
            if (this._opacity > this._maxOpacity ) {
              this._opacity = this._maxOpacity;
              this.haltFade();
            }
          }
        
          this._updateOpacity();
        }
        
        Fadomatic.prototype._updateVisibility = function () {
          
          if (this._opacity > 0) {
            this._element.style.visibility = 'visible';
          } else {
            this._element.style.visibility = 'hidden';
          }
        }
        
        Fadomatic.prototype._updateOpacityW3c = function () {
          
          this._element.style.opacity = this._opacity/100;
          this._updateVisibility();
        }
        
        Fadomatic.prototype._updateOpacityMSIE = function () {
          
          this._element.filters.alpha.opacity = this._opacity;
          this._updateVisibility();
        }
        
        Fadomatic.prototype._updateOpacity = null;
        
        
        
	   //Do this on load
		function initEvents() {
			if(document.getElementById("heading") == null){
				document.getElementById("bodyNode").style.marginTop = "5px";
			}
			
            if(isDebug == false) {
	           document.getElementById("debug").style.display = "none";
	       }
	       
	       	       
			alignChat(true);
		}

	   //Debugging function
	   function trace(msg) {
			var node = document.createElement("div");
			var debugCon = document.getElementById("debug");
			node.innerHTML = msg;
			debugCon.appendChild(node);
		}
		
	
		//Appending new content to the message view
		function appendMessage(html) {
			var shouldScroll = nearBottom();
			
			//Remove any existing insertion point
			var insert = document.getElementById("insert");
			
			if(insert) insert.parentNode.removeChild(insert);
			
			//Append the new message to the bottom of our chat block
			var chat = document.getElementById("Chat");
			var range = document.createRange();
			range.selectNode(chat);
			var documentFragment = range.createContextualFragment(html);
      var myFrag = chat.appendChild(documentFragment);
      //var frag = insert.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;

      try {
          var fader = new Fadomatic(myFrag, 9, 0, 0, 95);
          fader.fadeIn();
      } catch(e) {
          trace(e);
      }
			alignChat(true);
		}
		
		
		function appendNextMessage(html){
			var shouldScroll = nearBottom();
			
			//Locate the insertion point
			var insert = document.getElementById("insert");
		
			//make new node
			range = document.createRange();
			range.selectNode(insert.parentNode);
			newNode = range.createContextualFragment(html);
			
			//swap
			var pointer = insert.parentNode;
			insert.parentNode.replaceChild(newNode,insert);
			var els = pointer.getElementsByTagName("div");

			alignChat(true);
		}
		
		
		//Auto-scroll to bottom.  Use nearBottom to determine if a scrollToBottom is desired.
		function nearBottom() {
			return ( document.body.scrollTop >= ( document.body.offsetHeight - ( window.innerHeight * 1.2 ) ) );
		}
		
		var intervall_scroll;
		function scrollToBottom() {
			//document.body.scrollTop = (document.body.scrollHeight-window.innerHeight);
			//return;
			if( intervall_scroll ) clearInterval( intervall_scroll );
			intervall_scroll = setInterval( function() {
				var target_scroll = (document.body.scrollHeight-window.innerHeight);
				var scrolldiff = target_scroll - document.body.scrollTop;
				if ( document.body.scrollTop != target_scroll ) {
					var saved_scroll = document.body.scrollTop;
					document.body.scrollTop += scrolldiff / 5 + ( scrolldiff >= 0 ? (scrolldiff != 0 ) : -1 );
				 } else {
				 	saved_scroll = -1;
					clearInterval( intervall_scroll );
				 }
			} , 10 );
			return;
		}
		
		
		//Dynamically exchange the active stylesheet
		function setStylesheet( id, url ) {
			var code = "<style id=\"" + id + "\" type=\"text/css\" media=\"screen,print\">";
			if( url.length ) code += "@import url( \"" + url + "\" );";
			code += "</style>";
			var range = document.createRange();
			var head = document.getElementsByTagName( "head" ).item(0);
			range.selectNode( head );
			documentFragment = range.createContextualFragment( code );
			head.removeChild( document.getElementById( id ) );
			head.appendChild( documentFragment );
		}
		
		//Swap an image with its alt-tag text on click
		document.onclick = imageCheck;
		function imageCheck() {		
			node = event.target;
			if(node.tagName == 'IMG' && node.alt && node.className!="avatar") {
				a = document.createElement('a');
				a.setAttribute('onclick', 'imageSwap(this)');
				a['src'] = node.src;
        a['alt'] = node.alt;
				a['name'] = node.name;
				a.className = node.className;
				text = document.createTextNode(node.alt);
				a.appendChild(text);
				node.parentNode.replaceChild(a, node);
			}
		}
		function imageSwap(node) {
			shouldScroll = nearBottom();

			//Swap the image/text
			img = document.createElement('img');
            img['src'] = node.src;
			img['alt'] = node.alt;
			img['name'] = node.name;
			img.className = node.className;
			node.parentNode.replaceChild(img, node);

			alignChat(shouldScroll);
		}
		
		//Align our chat to the bottom of the window.  If true is passed, view will also be scrolled down
		function alignChat(shouldScroll) {

			var windowHeight = window.innerHeight;
			
			if(windowHeight > 0) {
				var contentElement = document.getElementById('Chat');
				var contentHeight = contentElement.offsetHeight;
				if (windowHeight - contentHeight > 0) {
					contentElement.style.position = 'relative';
					contentElement.style.top = '0px';
				} else {
					contentElement.style.position = 'static';
				}
			}
			
			if(shouldScroll) scrollToBottom();
		}
		
		function windowDidResize() {
			alignChat(true/*nearBottom()*/); //nearBottom buggy with inavtive tabs
		}
		
		window.onresize = windowDidResize;
		//]]>
	</script>

	<style id="mainStyle" type="text/css" media="screen,print">	@import url( "%@" ); </style>
 %@

</head>
<body id="bodyNode" onload="initEvents()">
%@
<div id="Chat">
</div>
%@
<div id="debug"></div>
</body>
</html>