<?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>