/* Nifty Corners Cube - rounded corners with CSS and Javascript
Copyright 2006 Alessandro Fulciniti (a.fulciniti@html.it)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

var niftyOk=(document.getElementById && document.createElement && Array.prototype.push);
var niftyCss=false;

String.prototype.find=function(what){
return(this.indexOf(what)>=0 ? true : false);
}

var oldonload=window.onload;
if(typeof(NiftyLoad)!='function') NiftyLoad=function(){};
if(typeof(oldonload)=='function')
    window.onload=function(){oldonload();AddCss();NiftyLoad()};
else window.onload=function(){AddCss();NiftyLoad()};

function AddCss(){
niftyCss=true;
var l=CreateEl("link");
l.setAttribute("type","text/css");
l.setAttribute("rel","stylesheet");
l.setAttribute("href","/javascripts/thirdparty/NiftyCube/niftyCorners.css");
l.setAttribute("media","screen");
document.getElementsByTagName("head")[0].appendChild(l);
}

function Nifty(selector,options){
if(niftyOk==false) return;
if(niftyCss==false) AddCss();
var i,v=selector.split(","),h=0;
if(options==null) options="";
if(options.find("fixed-height"))
    h=getElementsBySelector(v[0])[0].offsetHeight;
for(i=0;i<v.length;i++)
    Rounded(v[i],options);
if(options.find("height")) SameHeight(selector,h);
}

function Rounded(selector,options){
var i,top="",bottom="",v=new Array();
if(options!=""){
    options=options.replace("left","tl bl");
    options=options.replace("right","tr br");
    options=options.replace("top","tr tl");
    options=options.replace("bottom","br bl");
    options=options.replace("transparent","alias");
    if(options.find("tl")){
        top="both";
        if(!options.find("tr")) top="left";
        }
    else if(options.find("tr")) top="right";
    if(options.find("bl")){
        bottom="both";
        if(!options.find("br")) bottom="left";
        }
    else if(options.find("br")) bottom="right";
    }
if(top=="" && bottom=="" && !options.find("none")){top="both";bottom="both";}
v=getElementsBySelector(selector);
for(i=0;i<v.length;i++){
    FixIE(v[i]);
    if(top!="") AddTop(v[i],top,options);
    if(bottom!="") AddBottom(v[i],bottom,options);
    }
}

function AddTop(el,side,options){
var d=CreateEl("b"),lim=4,border="",p,i,btype="r",bk,color;
d.style.marginLeft="-"+getPadding(el,"Left")+"px";
d.style.marginRight="-"+getPadding(el,"Right")+"px";
if(options.find("alias") || (color=getBk(el))=="transparent"){
    color="transparent";bk="transparent"; border=getParentBk(el);btype="t";
    }
else{
    bk=getParentBk(el); border=Mix(color,bk);
    }
d.style.background=bk;
d.className="niftycorners";
p=getPadding(el,"Top");
if(options.find("small")){
    d.style.marginBottom=(p-2)+"px";
    btype+="s"; lim=2;
    }
else if(options.find("big")){
    d.style.marginBottom=(p-10)+"px";
    btype+="b"; lim=8;
    }
else d.style.marginBottom=(p-5)+"px";
for(i=1;i<=lim;i++)
    d.appendChild(CreateStrip(i,side,color,border,btype));
el.style.paddingTop="0";
el.insertBefore(d,el.firstChild);
}

function AddBottom(el,side,options){
var d=CreateEl("b"),lim=4,border="",p,i,btype="r",bk,color;
d.style.marginLeft="-"+getPadding(el,"Left")+"px";
d.style.marginRight="-"+getPadding(el,"Right")+"px";
if(options.find("alias") || (color=getBk(el))=="transparent"){
    color="transparent";bk="transparent"; border=getParentBk(el);btype="t";
    }
else{
    bk=getParentBk(el); border=Mix(color,bk);
    }
d.style.background=bk;
d.className="niftycorners";
p=getPadding(el,"Bottom");
if(options.find("small")){
    d.style.marginTop=(p-2)+"px";
    btype+="s"; lim=2;
    }
else if(options.find("big")){
    d.style.marginTop=(p-10)+"px";
    btype+="b"; lim=8;
    }
else d.style.marginTop=(p-5)+"px";
for(i=lim;i>0;i--)
    d.appendChild(CreateStrip(i,side,color,border,btype));
el.style.paddingBottom=0;
el.appendChild(d);
}

function CreateStrip(index,side,color,border,btype){
var x=CreateEl("b");
x.className=btype+index;
x.style.backgroundColor=color;
x.style.borderColor=border;
if(side=="left"){
    x.style.borderRightWidth="0";
    x.style.marginRight="0";
    }
else if(side=="right"){
    x.style.borderLeftWidth="0";
    x.style.marginLeft="0";
    }
return(x);
}

function CreateEl(x){
return(document.createElement(x));
}

function FixIE(el){
if(el.currentStyle!=null && el.currentStyle.hasLayout!=null && el.currentStyle.hasLayout==false)
    el.style.display="inline-block";
}

function SameHeight(selector,maxh){
var i,v=selector.split(","),t,j,els=[],gap;
for(i=0;i<v.length;i++){
    t=getElementsBySelector(v[i]);
    els=els.concat(t);
    }
for(i=0;i<els.length;i++){
    if(els[i].offsetHeight>maxh) maxh=els[i].offsetHeight;
    els[i].style.height="auto";
    }
for(i=0;i<els.length;i++){
    gap=maxh-els[i].offsetHeight;
    if(gap>0){
        t=CreateEl("b");t.className="niftyfill";t.style.height=gap+"px";
        nc=els[i].lastChild;
        if(nc.className=="niftycorners")
            els[i].insertBefore(t,nc);
        else els[i].appendChild(t);
        }
    }
}

function getElementsBySelector(selector){
var i,j,selid="",selclass="",tag=selector,tag2="",v2,k,f,a,s=[],objlist=[],c;
if(selector.find("#")){ //id selector like "tag#id"
    if(selector.find(" ")){  //descendant selector like "tag#id tag"
        s=selector.split(" ");
        var fs=s[0].split("#");
        if(fs.length==1) return(objlist);
        f=document.getElementById(fs[1]);
        if(f){
            v=f.getElementsByTagName(s[1]);
            for(i=0;i<v.length;i++) objlist.push(v[i]);
            }
        return(objlist);
        }
    else{
        s=selector.split("#");
        tag=s[0];
        selid=s[1];
        if(selid!=""){
            f=document.getElementById(selid);
            if(f) objlist.push(f);
            return(objlist);
            }
        }
    }
if(selector.find(".")){      //class selector like "tag.class"
    s=selector.split(".");
    tag=s[0];
    selclass=s[1];
    if(selclass.find(" ")){   //descendant selector like tag1.classname tag2
        s=selclass.split(" ");
        selclass=s[0];
        tag2=s[1];
        }
    }
var v=document.getElementsByTagName(tag);  // tag selector like "tag"
if(selclass==""){
    for(i=0;i<v.length;i++) objlist.push(v[i]);
    return(objlist);
    }
for(i=0;i<v.length;i++){
    c=v[i].className.split(" ");
    for(j=0;j<c.length;j++){
        if(c[j]==selclass){
            if(tag2=="") objlist.push(v[i]);
            else{
                v2=v[i].getElementsByTagName(tag2);
                for(k=0;k<v2.length;k++) objlist.push(v2[k]);
                }
            }
        }
    }
return(objlist);
}

function getParentBk(x){
var el=x.parentNode,c;
while(el.tagName.toUpperCase()!="HTML" && (c=getBk(el))=="transparent")
    el=el.parentNode;
if(c=="transparent") c="#FFFFFF";
return(c);
}

function getBk(x){
var c=getStyleProp(x,"backgroundColor");
if(c==null || c=="transparent" || c.find("rgba(0, 0, 0, 0)"))
    return("transparent");
if(c.find("rgb")) c=rgb2hex(c);
return(c);
}

function getPadding(x,side){
var p=getStyleProp(x,"padding"+side);
if(p==null || !p.find("px")) return(0);
return(parseInt(p));
}

function getStyleProp(x,prop){
if(x.currentStyle)
    return(x.currentStyle[prop]);
if(document.defaultView.getComputedStyle)
    return(document.defaultView.getComputedStyle(x,'')[prop]);
return(null);
}

function rgb2hex(value){
var hex="",v,h,i;
var regexp=/([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)/;
var h=regexp.exec(value);
for(i=1;i<4;i++){
    v=parseInt(h[i]).toString(16);
    if(v.length==1) hex+="0"+v;
    else hex+=v;
    }
return("#"+hex);
}

function Mix(c1,c2){
var i,step1,step2,x,y,r=new Array(3);
if(c1.length==4)step1=1;
else step1=2;
if(c2.length==4) step2=1;
else step2=2;
for(i=0;i<3;i++){
    x=parseInt(c1.substr(1+step1*i,step1),16);
    if(step1==1) x=16*x+x;
    y=parseInt(c2.substr(1+step2*i,step2),16);
    if(step2==1) y=16*y+y;
    r[i]=Math.floor((x*50+y*50)/100);
    r[i]=r[i].toString(16);
    if(r[i].length==1) r[i]="0"+r[i];
    }
return("#"+r[0]+r[1]+r[2]);
}

/**
 * COMMON JAVASCRIPT FUNCTIONS
 * by webmaster@subimage.com
 *
 */

/**
 * Other event handlers use this to set up basic
 * event objects...
 */
function getEventSource(e) {
	/* Cookie-cutter code to find the source of the event */
	if (typeof e == 'undefined') {
		var e = window.event;
	}
	var source;
	if (typeof e.target != 'undefined') {
		source = e.target;
	} else if (typeof e.srcElement != 'undefined') {
		source = e.srcElement;
	} else {
		return false;
	}
	return source;
	/* End cookie-cutter code */
}

/**
 * X-browser event handler attachment
 *
 * @argument obj - the object to attach event to
 * @argument evType - name of the event - DONT ADD "on", pass only "mouseover", etc
 * @argument fn - function to call
 */
function addEvent(obj, evType, fn){
	if (obj == null) return false;

	if (obj.addEventListener){
		obj.addEventListener(evType, fn, false);
		return true;
	} else if (obj.attachEvent){
		var r = obj.attachEvent("on"+evType, fn);
		return r;
	} else {
		return false;
	}
}
function removeEvent(obj, evType, fn, useCapture){
  if (obj.removeEventListener){
    obj.removeEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.detachEvent){
    var r = obj.detachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be removed");
  }
}


/**
 * Code below taken from - http://www.evolt.org/article/document_body_doctype_switching_and_more/17/30655/
 *
 * Modified 4/22/04 to work with Opera/Moz (by webmaster at subimage dot com)
 *
 * Gets the full width/height because it's different for most browsers.
 */
function getViewportHeight() {
	if (window.innerHeight!=window.undefined) return window.innerHeight;
	if (document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;
	if (document.body) return document.body.clientHeight; 

	return window.undefined; 
}
function getViewportWidth() {
	var offset = 17;
	var width = null;
	if (window.innerWidth!=window.undefined) return window.innerWidth; 
	if (document.compatMode=='CSS1Compat') return document.documentElement.clientWidth; 
	if (document.body) return document.body.clientWidth; 
}

/**
 * Gets the real scroll top
 */
function getScrollTop() {
	if (self.pageYOffset) // all except Explorer
	{
		return self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop)
		// Explorer 6 Strict
	{
		return document.documentElement.scrollTop;
	}
	else if (document.body) // all other Explorers
	{
		return document.body.scrollTop;
	}
}
function getScrollLeft() {
	if (self.pageXOffset) // all except Explorer
	{
		return self.pageXOffset;
	}
	else if (document.documentElement && document.documentElement.scrollLeft)
		// Explorer 6 Strict
	{
		return document.documentElement.scrollLeft;
	}
	else if (document.body) // all other Explorers
	{
		return document.body.scrollLeft;
	}
}

/**
 * Prettifies our tables applying the proper CSS class after a DOM modification 
 */
function stripedTable() {
	if (document.getElementById && document.getElementsByTagName) {  
		var allTables = document.getElementsByTagName('TABLE');
		if (!allTables) { return; }

		for (var i = 0; i < allTables.length; i++) {
			if (allTables[i].className.match(/[\w\s ]*list[\w\s ]*/)) {
				var trs = allTables[i].getElementsByTagName("tr");
				for (var j = 0; j < trs.length; j++) {
					if (trs[j].className.indexOf('footer') != -1) {
						continue;
					}
					if (j % 2 == 0) {
						trs[j].className = "even";
					} else {
						trs[j].className = "odd";
					}
				}
			}
		}
	}
}

/**
 * Called from the modal window usually.
 *
 * Refreshes the content in the main window.
 */
function returnRefresh() {
	window.location.reload(true);
}

/**
 * Shows sub tab of content pane passed in.
 * Hides the rest.
 */
function showSubTab(pane_id, tab_link) {
	// Loop through content panes and show the right one
	for (var i=0; i<gPanes.length; i++) {
		if (pane_id == gPanes[i]) {
			Element.show(gPanes[i]);
		} else {
			Element.hide(gPanes[i]);
		}
	}
	// Loop through tabs and assign the right style
	var tabs = $('sub_tabs');
	var active_tab = tab_link.parentNode;
	for (var i=0; i<tabs.childNodes.length; i++) {
		if (active_tab == tabs.childNodes[i]) {
			tabs.childNodes[i].className = "active";
		} else {
			tabs.childNodes[i].className = "";
		}
	}
}

function highlightItem(item_id) {
	new Effect.Highlight($(item_id));
}

/**
 * SUBMODAL v1.5
 * Used for displaying DHTML only popups instead of using buggy modal windows.
 *
 * By Seth Banks (webmaster at subimage dot com)
 * http://www.subimage.com/
 *
 * Contributions by:
 * 	Eric Angel - tab index code
 * 	Scott - hiding/showing selects for IE users
 *	Todd Huss - inserting modal dynamically and anchor classes
 *
 * Up to date code can be found at http://www.subimage.com/dhtml/subModal
 * 
 *
 * This code is free for you to use anywhere, just keep this comment block.
 */

// Popup code
var gPopupMask = null;
var gPopupContainer = null;
var gPopFrame = null;
var gReturnFunc;
var gPopupIsShown = false;
var gDefaultPage = "/loading.html";
var gHideSelects = false;
var gReturnVal = null;
// We can set this from within the modal to ALWAYS call the return function,
// even from the close box.
var gCallReturnFunc = false;

var gTabIndexes = new Array();
// Pre-defined list of tags we want to disable/enable tabbing into
var gTabbableTags = new Array("A","BUTTON","TEXTAREA","INPUT","IFRAME");	

// If using Mozilla or Firefox, use Tab-key trap.
if (!document.all) {
	document.onkeypress = keyDownHandler;
}



/**
 * Initializes popup code on load.	
 */
function initPopUp() {
	// Add the HTML to the body
    try
    {
        theBody = document.getElementsByTagName('BODY')[0];
        popmask = document.createElement('div');
        popmask.id = 'popupMask';
        popcont = document.createElement('div');
        popcont.id = 'popupContainer';
        popcont.innerHTML = '' +
            '<div id="popupInner">' +
                '<div id="popupTitleBar">' +
                    '<div id="popupTitle"></div>' +
                    '<div id="popupControls">' +
                        '<img src="/plugin_assets/substruct/images/close.gif" onclick="hidePopWin(false);" id="popCloseBox" />' +
                    '</div>' +
                '</div>' +
                '<iframe src="'+ gDefaultPage +'" style="width:100%;height:100%;background-color:transparent;" scrolling="auto" frameborder="0" allowtransparency="true" id="popupFrame" name="popupFrame" width="100%" height="100%"></iframe>' +
            '</div>';
        theBody.appendChild(popmask);
        theBody.appendChild(popcont);
        
        gPopupMask = document.getElementById("popupMask");
        gPopupContainer = document.getElementById("popupContainer");
        gPopFrame = document.getElementById("popupFrame");	
        
        // check to see if this is IE version 6 or lower. hide select boxes if so
        // maybe they'll fix this in version 7?
        var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10);
        if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE") > -1) {
            gHideSelects = true;
        }
        
        // Add onclick handlers to 'a' elements of class submodal or submodal-width-height
        var elms = document.getElementsByTagName('a');
        for (i = 0; i < elms.length; i++) {
            if (elms[i].className.indexOf("submodal") == 0) { 
                // var onclick = 'function (){showPopWin(\''+elms[i].href+'\','+width+', '+height+', null);return false;};';
                // elms[i].onclick = eval(onclick);
                elms[i].onclick = function(){
                    // default width and height
                    var width = 400;
                    var height = 200;
                    // Parse out optional width and height from className
                    params = this.className.split('-');
                    if (params.length == 3) {
                        width = parseInt(params[1]);
                        height = parseInt(params[2]);
                    }
                    showPopWin(this.href,width,height,null); return false;
                }
            }
        }
    }
    catch (e)
    {
        alert(e.message);
    }
    
}
addEvent(window, "load", initPopUp);

 /**
	* @argument width - int in pixels
	* @argument height - int in pixels
	* @argument url - url to display
	* @argument returnFunc - function to call when returning true from the window.
	* @argument showCloseBox - show the close box - default true
	*/

function showPopWin(url, width, height, returnFunc, showCloseBox) {
	// show or hide the window close widget
	if (showCloseBox == null || showCloseBox == true) {
		document.getElementById("popCloseBox").style.display = "block";
	} else {
		document.getElementById("popCloseBox").style.display = "none";
	}
    
    gPopupIsShown = true;
    disableTabIndexes();
    gPopupMask.style.display = "block";
    gPopupContainer.style.display = "block";
    // calculate where to place the window on screen
    centerPopWin(width, height);
    
    var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);


    gPopupContainer.style.width = width + "px";
    gPopupContainer.style.height = (height+titleBarHeight) + "px";
    
    setMaskSize();

    // need to set the width of the iframe to the title bar width because of the dropshadow
    // some oddness was occuring and causing the frame to poke outside the border in IE6
    gPopFrame.style.width = parseInt(document.getElementById("popupTitleBar").offsetWidth, 10) + "px";
    gPopFrame.style.height = (height) + "px";
    
    // set the url
    gPopFrame.src = url;
    
    gReturnFunc = returnFunc;
    // for IE
    if (gHideSelects == true) {
        hideSelectBoxes();
    }
    
    window.setTimeout("setPopTitle();", 600);
   
}

//
var gi = 0;
function centerPopWin(width, height) {
	if (gPopupIsShown == true) {
		if (width == null || isNaN(width)) {
			width = gPopupContainer.offsetWidth;
		}
		if (height == null) {
			height = gPopupContainer.offsetHeight;
		}
		
		//var theBody = document.documentElement;
		var theBody = document.getElementsByTagName("BODY")[0];
		//theBody.style.overflow = "hidden";
		var scTop = parseInt(getScrollTop(),10);
		var scLeft = parseInt(theBody.scrollLeft,10);
	
		setMaskSize();
		
		//window.status = gPopupMask.style.top + " " + gPopupMask.style.left + " " + gi++;
		
		var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);
		
		var fullHeight = getViewportHeight();
		var fullWidth = getViewportWidth();
		
		gPopupContainer.style.top = (scTop + ((fullHeight - (height+titleBarHeight)) / 2)) + "px";
		gPopupContainer.style.left =  (scLeft + ((fullWidth - width) / 2)) + "px";
		
	}
}
addEvent(window, "resize", centerPopWin);
addEvent(window, "scroll", centerPopWin);
window.onscroll = centerPopWin;


/**
 * Sets the size of the popup mask.
 *
 */
function setMaskSize() {
	var theBody = document.getElementsByTagName("BODY")[0];
			
	var fullHeight = getViewportHeight();
	var fullWidth = getViewportWidth();
	
	// Determine what's bigger, scrollHeight or fullHeight / width
	if (fullHeight > theBody.scrollHeight) {
		popHeight = fullHeight;
	} else {
		popHeight = theBody.scrollHeight;
	}
	
	if (fullWidth > theBody.scrollWidth) {
		popWidth = fullWidth;
	} else {
		popWidth = theBody.scrollWidth;
	}
	
	gPopupMask.style.height = popHeight + "px";
	gPopupMask.style.width = popWidth + "px";
}

/**
 * @argument callReturnFunc - bool - determines if we call the return function specified
 * @argument returnVal - anything - return value 
 */
function hidePopWin(callReturnFunc) {
	gPopupIsShown = false;
	var theBody = document.getElementsByTagName("BODY")[0];
	theBody.style.overflow = "";
	restoreTabIndexes();
	if (gPopupMask == null) {
		return;
	}
	gPopupMask.style.display = "none";
	gPopupContainer.style.display = "none";
	if ((callReturnFunc == true || gCallReturnFunc == true) && gReturnFunc != null) {
		// Set the return code to run in a timeout.
		// Was having issues using with an Ajax.Request();
		gReturnVal = window.frames["popupFrame"].returnVal;
		window.setTimeout('gReturnFunc(gReturnVal);', 1);
		// Reset global return function boolean.
		gCallReturnFunc = false;
	}
	gPopFrame.src = gDefaultPage;
	// display all select boxes
	if (gHideSelects == true) {
		displaySelectBoxes();
	}
}

/**
 * Sets the popup title based on the title of the html document it contains.
 * Uses a timeout to keep checking until the title is valid.
 */
function setPopTitle() {
	return;
	if (window.frames["popupFrame"].document.title == null) {
		window.setTimeout("setPopTitle();", 10);
	} else {
		document.getElementById("popupTitle").innerHTML = window.frames["popupFrame"].document.title;
	}
}

// Tab key trap. iff popup is shown and key was [TAB], suppress it.
// @argument e - event - keyboard event that caused this function to be called.
function keyDownHandler(e) {
    if (gPopupIsShown && e.keyCode == 9)  return false;
}

// For IE.  Go through predefined tags and disable tabbing into them.
function disableTabIndexes() {
	if (document.all) {
		var i = 0;
		for (var j = 0; j < gTabbableTags.length; j++) {
			var tagElements = document.getElementsByTagName(gTabbableTags[j]);
			for (var k = 0 ; k < tagElements.length; k++) {
				gTabIndexes[i] = tagElements[k].tabIndex;
				tagElements[k].tabIndex="-1";
				i++;
			}
		}
	}
}

// For IE. Restore tab-indexes.
function restoreTabIndexes() {
	if (document.all) {
		var i = 0;
		for (var j = 0; j < gTabbableTags.length; j++) {
			var tagElements = document.getElementsByTagName(gTabbableTags[j]);
			for (var k = 0 ; k < tagElements.length; k++) {
				tagElements[k].tabIndex = gTabIndexes[i];
				tagElements[k].tabEnabled = true;
				i++;
			}
		}
	}
}


/**
* Hides all drop down form select boxes on the screen so they do not appear above the mask layer.
* IE has a problem with wanted select form tags to always be the topmost z-index or layer
*
* Thanks for the code Scott!
*/
function hideSelectBoxes() {
	for(var i = 0; i < document.forms.length; i++) {
		for(var e = 0; e < document.forms[i].length; e++){
			if(document.forms[i].elements[e].tagName == "SELECT") {
				document.forms[i].elements[e].style.visibility="hidden";
			}
		}
	}
}

/**
* Makes all drop down form select boxes on the screen visible so they do not reappear after the dialog is closed.
* IE has a problem with wanted select form tags to always be the topmost z-index or layer
*/
function displaySelectBoxes() {
	for(var i = 0; i < document.forms.length; i++) {
		for(var e = 0; e < document.forms[i].length; e++){
			if(document.forms[i].elements[e].tagName == "SELECT") {
			document.forms[i].elements[e].style.visibility="visible";
			}
		}
	}
}

/*
 * Conversation Utility Class (Module)
 * 
 */
var ConvUtil = function () {
    var current_notice_div = "";
    var t_out = null;
    return {
        /*
         * Function to extract conversation id from the response
         * @param {Object} response
         */
        getConvId : function (response) {
            var conv_id = null;
            
            if(response.conv_id) {
                conv_id = response.conv_id;
            }else if(response.data && response.data.CID) {
                conv_id = response.data.CID;
            }else if(response.conversation_id) {
                conv_id = response.conversation_id;
            }
            return conv_id;
        },
        
        getConv : function (conv_id) {
            //get conversation rooms from conv_manager
            var conv_obj = null;
            
            if(conv_obj == null)
                conv_obj = EventManager.getConv(conv_id);
            
            return conv_obj;            
        },
        
        /*
         * Function to extract message from response object
         * @param {Object} response
         */
        getMsg : function (response) {
            var msg = null;
            
            if (response.data && response.data["MSG"]) {
                msg = response.data["MSG"];
            }else if(response.message) {
                msg = response.message;
            }
            
            return msg;
        },
        
        /**
         * Returns the presence icon according to the specified presence text
         * @param {String} presence
         */
        getPresenceIcon : function (presence) {
            if(!presence) return "";

            var img_tpl = "<img src='{src}' alt='' title='{title}'/>"

            return YAHOO.lang.substitute(img_tpl, {src : imgPath + presence.toLowerCase() + ".gif", title : presence.capitalize()});
        },
        
        /**
         * Function to check for the validity of the conv id so that junk values r not set as the conv_id
         * @param {Number} id
         */
        isValidConvId : function (id) {
            //check if blank
            if(id == "") return false;
            //check if number or not
            if(isNaN(id)) return false;
            // check if zero only string
            if(parseInt(id) == 0) return false;
            
            return true;
        },
        
        /**
         * Function to create system message object for displaying system notification
         */
        createSystemMessage : function (msg) {
            var message = {};
             //add timestamp property
            message.timestamp = msg.timestamp;
            message.type      = "SYSTEM";           
            
            //get category property of the "msg"
            var prop = msg.data["MTY"];
            var data = msg.data["MEX"];
            //get user name from MEX
            var user = ConvUtil.parseMEX(msg).user_name;
            var user_id = ConvUtil.parseMEX(msg).user_id;

            message.message = msg.data["MSG"];
            //message.data.user  = user;
            message.conv_id = msg.data["CID"];
            message.sub_type = prop.trim().toUpperCase();
            message.user    = user;
            message.email   = user;
            message.user_id = user_id;
            message.created_at = msg.data["MCA"];
            return message;
        },
        /**
         * Function to determine whether the message object is a system message or not
         */
        isSystemMessage : function (msg) {
            if(msg.data && msg.data["MTY"] && msg.data["MTY"] == "S") return true;
            
            return false;
        },
        
        isUserMessage : function (msg) {
            if(msg.data && msg.data["MTY"] && msg.data["MTY"] == "U") return true;
            
            return false;
        },
        
        /**
         * Function to remove the conv_id from the specified conv_list
         * and returns the modified list
         * 
         * @param {Object} conv_list
         * @param {Number} conv_id
         */
        removeItem : function (list, id){           
            for (var i = 0, len = list.length; i < len; ++i) {
                if(list[i].getId() == id) {
                    list.splice(i, 1);
                    break;
                }
            }           
            return list;
        },
        
        /**
         * Function to publish message to comet server that the user has closed the conversation
         * @param {Number} conv_id
         */
        unpublish : function (conv_id) {
            CometRouter.publish({"user-id" : g_user_id, "conversation_id" : conv_id, join : false, "chat" : g_user_id + " has left the conversation..."});
        },
        
        genRandomNum : function (limit, start) {
            if(!limit) return Math.random();
            
            if(start == null || typeof start == "undefined") start = 0; 
            
            return Math.floor((Math.random() * (limit - start) + 1) + start);
        },
        
        /**
         * Function to make ajax call and do the necessary processing
         * @param {String} href     the URL to make the request
         * @param {Object} options  The options object to contains several properties
         */
        ajaxCall : function (href, options) {
            options = options || {};
            var obj = {
                method : "post",
                asynchronous : true,
                evalScripts : true,
                onSuccess : function () {
                    ConvUtil.fireEvent("onHideError", "");
                }
            };
            //make the call the ajax call
            return new Ajax.Request(href, Object.extend(obj, options));
        },
        
        /**
         * Function to create a tab window
         * @param {String} cont_id  The Container Id
         * @param {Object} options  Options object
         */
        createTab : function (cont_id, options) {
            var o = Object.extend({
                classPrefix : "conv",
                height      : "100%",               
                caption     : "Opening",
                onFocus     : 0, // -1 to not bring it in focus
                href        : "#",
                reload      : false,
                callback    : function (){},
                closable    : false,
                popable     : false,
                onClose     : function (){}
            }, options || {});
            
            //create the tab
            var tab = FelixTabMgr.create(cont_id, [o.caption],[o], o.onFocus, o.classPrefix, o, options);
            
            return tab;
        },
        
        /**
         * Function to display messages in the board
         * @param {String/Object} msg
         * @param {Number} conv_id
         */
        formatMessage : function (msg, conv_id) {
             var mType = "";
             //options = Object.clone(options);

             if(msg.type && msg.type == "SYSTEM") { 
                 mType = "SYSTEM";
             }else if (msg.type && msg.type == "LOCAL") {
                 mType = "LOCAL";
             }else {
                 mType = "REMOTE";
             }

             var CM = MS.Core.ConvManager; // shorthand to convmanager
             //conversation object             
             var conv_obj = CM.getConv(conv_id); 

             try {
             
                 switch (mType) {
                     case 'SYSTEM':                         
                         var data = {                            
                            "class" : "system-msg",
                            timestamp: conv_obj.getCivilianTime(new Date())
                         };
                         
                         conv_obj.updateLastSender("", "");
                         return Object.extend(data, msg);
                     case 'LOCAL':
                         var data = Object.clone(msg);

                         var user_email = conv_obj.getOwner();

                         Object.extend(data, {
                            "user"  : "",
                            "email" : user_email,
                            "felix_user_id" : conv_obj.getFelixUserId(),
                            "class" : "you",
                            "timestamp" : "",
                            "type"  : "LOCAL"
                         });
                                                  
                         //if not same user then add user name
                         if(conv_obj.getLastSender() != user_email) {
                             data.user = ConvUtil.getNameFromEmail(conv_obj.getOwnerName());      
                         }
                                                 
                         //update the sender field
                         conv_obj.updateLastSender(user_email, data.user);
                         //update timestamp    
                         data.timestamp = conv_obj.printTime();

                         //write message
                         return data;                         
                     case 'REMOTE':
                         
                         //if(msg.data["USR"] == "undefined") return;
                         if(msg.data == "undefined") return;
                         
                         //get user name from MEX
                         var user  = ConvUtil.parseMEX(msg).user_name; 
                         var email = msg.data["USR"];

                         var data = Object.clone(msg);
                                          
                         Object.extend(data, {
                            user     : "",
                            message  : ConvUtil.getMsg(msg),
                            email    : email,
                            felix_user_id : ConvUtil.parseMEX(msg).user_id,
                            timestamp: "",
                            created_at : msg.data["MCA"],
                            user_medium : msg.data["UME"],
                            type : "REMOTE"
                         });
                         
                         if(conv_obj.getLastSender() != email || user != conv_obj.getLastSenderName()) {     
                             data.user = ConvUtil.getNameFromEmail(user);
                         }
                         
                         //update the sender email and name
                         conv_obj.updateLastSender(email, user);
                                                  
                         //update timestamp    
                         data.timestamp = conv_obj.printTime();
                         
                         return data                
                 }       
             }catch(e){}      
        },
        /**
         * Blinks title of the window when new msg arrives and the window is not in focus
         * @param {String} title
         * @param {Number} delay - optional
         */
        blinkTitle : function (title, delay) {
            clearTimeout(window.globalTimeout);
            if (!isWindowOnFocus) {
                delay = delay || 1000;
                if(document.title == window.defaultTitle) document.title = title;
                else document.title = window.defaultTitle;
                window.globalTimeout = window.setTimeout(function () {
                    ConvUtil.blinkTitle(title, delay);
                }, delay);
            }else document.title = window.defaultTitle;
        },
        
        /**
         * Functoion creates REPLY link in chat trail for organizers tab
         * @param {Object} data
         */
        createReplyLink : function (data) {
            var user_id = data.to_user_id || data.user_id;
            return MS.Dom.create("span", {"class" : "font_m blue bold hand", "value" : "reply", "to_user_id" : user_id, "to_id" : data.felix_user_id});
        },
        
        /**
         * returns the name from either name or email, if email then returns the only the portion before "@"
         * and if name-surname then returs the portion before " ", otherwise returns the string as it is
         * @param {String} email
         */
        getNameFromEmail : function (email) {
            if(!email || email == "") return "";
            var pos = -1;
            var n = ""; 
            if((pos = email.indexOf('@')) == -1)
                n = ((pos = email.indexOf(" ")) != -1) ? email.substring(0, pos) : email;
            else
                n = email.substring(0, pos);
            return n;
        },
        
        /**
         * Returns the last msg time that has come from comet server
         */
        getCometMsgTime : function () {
            //return last_comet_msg_timestamp;
            return //last_msg_sent_at;
        },
        /**
         * Updates the last msg time everytime a msg comes from comet server
         */
        updateCometMsgTime : function (msg_created_at) {
            //last_comet_msg_timestamp = msg_created_at;
            if(msg_created_at != undefined) 
              {
                //if(last_msg_sent_at < msg_created_at)
                  //  last_msg_sent_at = msg_created_at; // global variable updating time
              }      
        },
        
        /**
         * Function to send chat messages to the server
         * @param {Number} conv_id
         * @param {String} message
         */
        sendMessage : function (data, options) {            
            //sends message to the server
            /*ConvUtil.ajaxCall(location.protocol + "//" + location.host + "/imps/send_message", Object.extend({
                postBody        : $H(data).toQueryString()              
            }, options || {}));    */
            CallQueue.push(Object.extend({
                href     : location.protocol + "//" + location.host + "/ce/imps/send_message",
                postBody : $H(data).toQueryString()              
            }, options || {}));
        },
        
        /**
         * Function to highlight any element
         */
        highlight : function (id, options) {
            options = options || {};                    
            new Effect.Highlight(id, options);
        },
        
        /**
         * Performs previous chat fetching operation in chat window
         * @param {String} obj
         */
        getPreviousChat : function (obj) {
            try {
                show_loading("Loading history...", obj.alignObj || null);
                href = obj.href;
                
                delete obj.href;
                delete obj.alignObj;
                
                ConvUtil.ajaxCall(href, {
                    parameters : $H(obj).toQueryString(),
                    onComplete : hide_loading
                });                       
            }catch(e){}
        },
        
        /**
         * Returns the MEX property from the push server response object
         * @param {Object} obj
         */
        getMEX : function (obj) {
            if(obj.data && obj.data["MEX"]) {
                return obj.data["MEX"];
            }
            return "";
        },
        
        /**
         * Function that will fire on every system notification to perform some tasks
         * should be fired using apply()
         * @param {Object} response
         */
        onSysNotify : function (response) {
            var type = response.data["MST"]; //sub-type
            switch (type.toUpperCase()) {
                case 'CCN' : //change conversation name
                    this.fireEvent("onCCN", response);               
                    break;
                case 'CTN' : //change topic name
                    this.fireEvent("onCTN", response);
                    break;                          
            }
        },
        
        /**
         * Checks for any sub-types of the messages and return the output according to it
         * @param {Object} msg_obj
         */
        hasSubTypes : function (msg_obj) {
            var sub_types = ["ANC", "RPL", "ANE", "ANS"];
            var type = ConvUtil.getSubType(msg_obj);

            if(type == "") return false;
            
            return (sub_types.indexOf(type.toUpperCase().trim()) > -1);
        },
        
        /**
         * Function to return the msg sub-types or MST property of the message object
         * @param {Object} msg_obj
         */
        getSubType : function (msg_obj) {
            if(typeof msg_obj != "object") return "";
            var type = "";
            if(msg_obj["MST"]) type = msg_obj["MST"];
            else if (msg_obj.data && msg_obj.data["MST"]) type = msg_obj.data["MST"];
            
            return type.toUpperCase();
        },
        
        parseSubTypes : function (src_obj, dest_obj) {
            var type = ConvUtil.getSubType(src_obj);
            switch (type.toUpperCase()) {
                case "ANC" : //anounces it
                    Object.extend(dest_obj, Object.extend(ConvUtil.parseMEX(src_obj), {"MST" : "ANC"}));
                    break;
                case "RPL" : //reply to
                    Object.extend(dest_obj, Object.extend(ConvUtil.parseMEX(src_obj), {"MST" : "RPL"}));
                    break;
                case "ANE" : //send over email
                    Object.extend(dest_obj, Object.extend(ConvUtil.parseMEX(src_obj), {"MST" : "ANE"}));
                    break;
                case "ANS" : //send over sms
                    Object.extend(dest_obj, Object.extend(ConvUtil.parseMEX(src_obj), {"MST" : "ANS"}));
                    break;
            }
        },
        
        getMTP : function (resp) {
            if (resp && resp.data && resp.data.MTP) {
                return resp.data.MTP;
            }
            return null;
        },
        
        /**
         * Function to parse VID from comet response and returns
         * @param {Object} obj
         */
        getVID : function (obj) {
            if(obj.data && obj.data["VID"]) {
                return obj.data["VID"];
            }
            return null;
        },
        
        /**
         * Parses the MEX property of the comet message object and returns and object
         */
        parseMEX : function (msg_obj) {
            var mex  = ConvUtil.getMEX(msg_obj);
            mex = mex.split(",");
            var len = mex.length;
            var output = {};

            if (len > 1 && len < 3) {
                YAHOO.lang.augmentObject(output, {
                    "user_id"   : mex[0],
                    "user_name" : mex[1]
                }, true);
                
            }else if(len > 2 && len < 4) {
                YAHOO.lang.augmentObject(output, {
                    "user_id"   : mex[0],
                    "user_name" : mex[1],
                    "conv_id"   : mex[2] //always the public conv Id
                }, true);
            }else if(len >= 5) {                
                YAHOO.lang.augmentObject(output, {
                        "user_id"           : mex[0],
                        "user_name"         : mex[1],
                        "conv_id"           : mex[2], //always the public conv Id
                        "to_user_id"        : mex[3],
                        "to_user_name"      : mex[4]
                }, true);
            }
           
            return output;
        },
        
        formatAsSubType : function (sub_type, to_user) {
            if(!sub_type) return "";
            to_user = ConvUtil.getNameFromEmail(to_user);
            var output = "";
            switch(sub_type.toUpperCase()) {
                case "ANC":
                    if(to_user != "") {
                        output = "<strong class='black bold'>&nbsp;[For " + to_user + "] </strong>" + "<img align='absmiddle' src='/images/default/icon_megaphone.gif' height='16' width='16' alt='' title='Announced Message'/>";   
                    }else {
                        output = " <img src='/images/default/icon_megaphone.gif' align='absmiddle' height='16' width='16' alt='' title='Announced Message'/>";
                    }
                    break;
                case "RPL":
                    output = "<strong class='black bold'>&nbsp;[" + to_user + "'s Thread] </strong>";
                    break;
                case "ANE":
                    output = " <img src='/images/default/mail_off.png' align='absmiddle' height='16' width='16' alt='' title='Send over Email'/>"
                    break;
                case "ANS":
                    output = " <img src='/images/default/mobile_option.gif' align='absmiddle' height='16' width='16' alt='' title='Send over SMS'/>"
                    break;
            }
            return output;
        },
        
        /**
         * Function to trap enter key on specified element, binds the callback() with the element specified
         * @param {Object} elem
         * @param {Object} callback
         */
        trapEnterKey : function (elem, callback) {
            elem = $(elem);
            
            if(!elem) return;
            if(typeof callback != "function") return;
            
            MS.Event.add(elem, "keypress", function (event){
                var elem = event.srcElement || event.target;
        
                var key = event.keyCode || event.which;
            
                if(key == 13) {                 
                    // apply the callback function on the elem 
                    callback.apply(elem, [event]);
                    MS.Event.cancel(event);
                }
            });
        },
        
        /**
         * Function to show notice/error messages from server
         * @param {String} notice
         * @param {Object/String} div --optional
         * @param {Object/String} time --optional
         */
        showNotice : function (notice, div /* optional */,time) {
            if(notice.trim() == "") return;
            clearTimeout(t_out);
            current_notice_div = div;
            var time_val = (time != null)? time : 300000;
            var closeStr = '<a href="javascript:show_hide_simple(\'' + div +  '\')" style="float:right;vertical-align:top"><img alt="close" border="0" src="/images/default/cross.gif"></a>';
            var msgStr = '<span style="padding-right:25px">' + notice + '</span>'
            if((elem = $(current_notice_div)) != null) {
                Element.show(elem);
                elem.innerHTML = closeStr + msgStr;                
                this.highlight(elem);
                t_out = setTimeout(function () {
                    ConvUtil.hideNotice(elem);
                }, time_val);
            }
        },
        
        /* Alias to showNotice but only shows some special errors in global cont */
        showError : function (notice) {
            Element.show($("global_error_cont_parent"));// For showing the global error's parent container
            ConvUtil.showNotice(notice, "global_error_cont");
        },
        
        hideError : function () {
            var div = $("global_error_cont");
            if(div) {
                Element.update(div, "");
                Element.hide(div);
                Element.hide($("global_error_cont_parent"));// For hiding the global error's parent container
            }
        },
        
        /**
         * Function hide to notice 
         * @param {Object/String} div
         */
        hideNotice : function () {
            var div = $(current_notice_div);
            if(div) {
                Element.update(div, "");
                Element.hide(div);
                Element.hide($("global_error_cont_parent"));
            }
        },

        /**
         * Function to flip the input msg box in the chat window
         * @param {Number} suffix
         * @param {String} mode
         */
        flipChatBox : function (suffix, mode) {
            //chat box is the base box
            //will move only the inputbox above and underneath the chat box
            var base_el = $("input_box_container" + suffix);
            var obj2move = $("chatPane" + suffix);
            var pl = base_el.parentNode;
            mode = mode.toUpperCase();
                        
            var flip = Element.readAttribute(obj2move, "flip");
            flip = flip.toUpperCase();
            
            if(flip === mode) return false;
            
            obj2move = Element.remove(obj2move);
            
            switch (mode) {
                case "U":
                    pl.insertBefore(obj2move, base_el);
                    obj2move.setAttribute("flip", "U");
                    break;
                case "D":
                    pl.insertBefore(obj2move, pl.lastChild);
                    obj2move.setAttribute("flip", "D");
            }
            
            return true;
        },
        
        /**
         * Returns the announce_it check box value if present checked = Y, not checked = N
         * @param {Number} conv_id
         */
        getAnnounceIt : function (conv_id) {
            var announce_it = $("announce_it" + conv_id);
            if (announce_it) {
                if (announce_it.checked) {
                    this.resetAnnounceIt(announce_it);
                    return "Y";
                }
            }
            return "N";
        },
        
        /**
         * Resets the announce it check box after every get (getAnnounceIt call) 
         * @param {Object} announce_it
         */
        resetAnnounceIt : function (announce_it) {
            if (announce_it) {
                announce_it.checked = false;
            }
        },
        
        playSound : function () {
            try {
                $(player_id).play();
            }catch(e) {
                $(player_id).doPlay();
            }
        },
        
        /**
         * Function to display the list of avatars and also the upload link to upload photo
         * @param {Object} obj
         * @param {Object} params - Json 
         */
        showPhotoList : function (obj, params) {
            
            var options = Object.extend({
                width: 60,
                height: 60,
                cols : 3,                                
                list : [],
                action : "/user_photos/upload_photo",
                onchange : function () {},
                onclik : function () {}
            }, params);
            
            var is_ie = !!document.uniqueID;
            //hide photo list if present
            ConvUtil.hidePhotoList();
            var topHeight = MS.Dom.Element.getHeight(obj,true);
            //position of the clicked element
            var coords = [MS.Position.getPosX(obj), MS.Position.getPosY(obj)];            
            
            if(is_ie) {
                var total_spacing = (3 * (options.cols + 1)) + (options.cols * 4); 
                var i_height =  (options.width * options.cols) + total_spacing + 34;
                var i_width  = (options.width * options.cols) + total_spacing;
                var ifr = MS.Dom.create("iframe", {
                    "id" : "photo_list_frame",                  
                    "height" : i_height, 
                    "width" :i_width,
                    "style" : "position:absolute;z-index:254;background-color:#fff;border:0px"
                });
                
                ifr.style.left = coords[0] - 1 + "px";
                ifr.style.top = coords[1] + topHeight + 8 + "px";
                document.body.appendChild(ifr);
            }
            
            var cont = MS.Dom.create("div", {
                "id"    : "photo_list_container",
                "style" : "position:absolute;z-index:280;width:auto;",
                "class" : "left"
            });
            
            MS.Dom.addStyle(cont, "top:" + (coords[1] + topHeight ) + "px;left:" + coords[0] + "px");
            
            var dv = MS.Dom.create("div", {"style" : "font-size:7px;padding:0px;margin:0px;text-align:right"});
            dv.innerHTML = "<img src='/images/default/cross_small1.gif' height=8 width=8 alt='' class='hand three-border' title='Close'/>";
            cont.appendChild(dv);
            
            MS.Event.add(dv.firstChild, "mousedown", ConvUtil.hidePhotoList);
            
            var t = MS.Table.create({"cellspacing" : 3, "cellpadding" : 2, "style" : "border:1px #808080 solid;background-color:#fff"});
			var tr = MS.Table.addRow(t);
			
			for (var i = 0, len = Math.pow(options.cols, 2); i < len; ++i) {
			    if(i != 0 && (i % options.cols) == 0) tr = MS.Table.addRow(t);			    
			    var td = MS.Table.addCell(tr, {"align" : "center", 
			       "style" : "width:" + options.width + "px;height:" + options.height + "px;border:1px solid #ccc",
			       "href"  : options.list[i]
			    });
			    //height=\"" + options.height + "\" width=\"" + options.height + "\"
				Element.update(td, "<img src=\"" + options.list[i] + "\" alt=\"\">");
				
				MS.Event.add(td, "click", function (e) {
				    ConvUtil.hidePhotoList();
				    options.onclik.apply(this, [this, e, false]);
				});
								
				MS.Event.add(td, "mouseover", function () {
				    MS.Dom.addStyle(this, "cursor:pointer;border-color:#84D7FF");
				});
				MS.Event.add(td, "mouseout", function (){
				    MS.Dom.addStyle(this, "border-color:#ccc");
				});
			}
			cont.appendChild(t);
			
			tr = MS.Table.addRow(t);
			td = MS.Table.addCell(tr, {"colspan" : options.cols});
			
			var div2 = MS.Dom.create("div", {"style" : "position:relative"});
			
			MS.Upload.remote({
				"holder" 	 : div2,
				"fileClass"  : "upload_field",
				"fileId"	 : "photo_upload",
				"fileName"   : "photo[uploaded_data]",
				"action" 	 : options.action,
				onchange	 : ConvUtil.submitUploadPhoto,
				callback     : options.onchange,
				"custom" 	 : obj.id
			});
			
			var spn = MS.Dom.create("span", {"style" : "position:relative;z-index:1;left:3px", "class" : "hand font_s bold blue", "value" : "More..."})
					
			div2.appendChild(spn);			
			td.appendChild(div2);
			document.body.appendChild(cont);   
        },
        
        submitUploadPhoto : function (elem, form_obj, callback, e) {
            //hide notice if any
            ConvUtil.hideNotice();
            
            form_obj = $(form_obj);
			var attrib = Element.readAttribute(form_obj, "custom") || form_obj["custom"];
			
			if(attrib != null && $(attrib)) {
				show_loading("Uploading...", $(attrib));
			}
			$(form_obj).submit();
			if(typeof callback == "function") callback(form_obj, attrib);
			
			ConvUtil.hidePhotoList();			
		},
		
		hidePhotoList : function () {
		    var ph_list = $("photo_list_container");
		    var ph_frame = $("photo_list_frame");
		    
		    if(ph_list) {
				Element.remove(ph_list);
                if(ph_frame) Element.remove(ph_frame);
			}
		},
        
        createPrevLink : function (option) {
            var prev_tpl = new Template('<table id="recent_chat_tbl#{conv_id}" cellspacing="0" cellpadding="2" width="100%" class="font_m" style="margin-bottom:5px;">' + 
                                 '<tr><td id="recent_chat_bar#{conv_id}" class="light_green_row right">' + 
                                 '<img src="/images/default/grey-arrow-down.gif" align="absmiddle">&nbsp;' +
                                 '<span id="recent_chat_link#{conv_id}" class="green font_s bold hand underline" ' +
                                 'onclick="EventManager.showPrevChat(this, {conv_id : #{conv_id}})">Recent Chats</span></td></tr></table>' +
                                 '<div id="recent_chat_holder#{conv_id}"></div>'
                               );
            
            if(!$("recent_chat_bar" + option.conv_id)) {
                new Insertion.Top(Element.down($("chatPane" + option.conv_id)), prev_tpl.evaluate({"conv_id" : option.conv_id}));
            }
        },
		
		/**
		 * Function to initialize file upload when called
		 * @param {Object} props
		 */
     initUpload : function (props) {
        var up_options = {
				clickTarget : "", // the link or span id
                form : "", //form id
                input : "", //input field's ID
				url : "", //where to submit
                callback : function(){}, // callback to be executed after receiving server response
                event : "change" //whether to fire the event on "change/click" default = change
		    };
            Object.extend(up_options, props);
            
            //shorthand variables
            var Ajax = YAHOO.util.Connect,
                Event = YAHOO.util.Event,
                Dom = YAHOO.util.Dom;

            var onUpload = function (e) {
                //the second argument of setForm is crucial,
                //which tells Connection Manager this is a file upload form
                Ajax.setForm(up_options.form, true);

                var uploadHandler = {
                    upload : up_options.callback
                };
                
                if(props.url) {
                    if(detect_browser != "IE") ConvUtil.showLoading("Uploading data, Please wait.");
                    Ajax.asyncRequest('POST', up_options.url, uploadHandler);
                }
            };
            
            if(up_options.input) {
                Event.on(up_options.input, up_options.event, onUpload);
            }

            if(up_options.clikTarget) {
                Event.on(up_options.input, 'mouseout', function(){
                    Dom.removeClass(up_options.clikTarget, "underline");
                });
                Event.on(up_options.input, 'mouseover', function (){
                    Dom.addClass(up_options.clikTarget, "underline");
                });
            }
		 },
        /**
         * Handles file upload result parsing, compatible with YUI file upload only
         * @param {String} text
         */
         parseUploadResult : function (text) {
            var rgx = /^<pre>/;
            var rgx2 = /<\/pre>$/;
            var resp = text.replace(rgx, "").replace(rgx2, "");
            return resp;
         },

        /**
         * Function to write HTML in the page
         * @param {String/Object} id
         * @param {String} html
         */
        render : function (id, html) {
            try {
                MS.Dom.replaceHtml(id, html);
                /* use prototype's evalScripts to run any scripts the html text has */
                setTimeout(function (){
                    if($(id) !== null) {
                        html.evalScripts(); 
                    }
                }, 10);                
            }
            catch (e){
               // alert(e.message);
            }
            
        },
        
        /* function to create RTE box */
        createRTE : function (props) {
            props = props || {};
            
            var Dom = YAHOO.util.Dom,
                Event = YAHOO.util.Event,
                editing = null;
          
            var rte_config = { 
               height: props.height || '150px', 
               width: props.width || '460px',
               focusAtStart : props.focusAtStart || true,
               handleSubmit : props.handleSubmit || false,
               toolbar: { 
                   collapse: false,
                   buttons: [ 
                       { group: 'textstyle', label: ' ', 
                            buttons: [ 
                                { type: 'push', label: 'Bold', value: 'bold' }, 
                                { type: 'push', label: 'Italic', value: 'italic' }, 
                                { type: 'push', label: 'Underline', value: 'underline' }	                    
                            ]
                       },
                        
                       { type : 'separator'},
                        
                       { group: 'fontstyle', label: ' ', 
                            buttons: [ 
                                { type: 'color', label: 'Font Color', value: 'forecolor'},
                                { type: 'select', label: 'Arial', value: 'fontname', 
                                    menu: [ 
                                        { text: 'Arial', checked: true }, 
                                        { text: 'Comic Sans MS' }, 
                                        { text: 'Courier New' }, 
                                        { text: 'Tahoma' }, 
                                        { text: 'Times New Roman' }, 
                                        { text: 'Verdana' } 
                                    ] 
                                }, 
                                { type: 'spin', label: '13', value: 'fontsize', range: [ 9, 75 ] }
                            ]
                        }
                    ] 
                 } 
            };
              
            if(props && props.id != "") {
  	           return new YAHOO.widget.Editor(props.id, rte_config);
            }
            
            return null;
        },
        
        initLoading : function (txt) {     
            txt = txt || "Loading, please wait...";
            YAHOO.ms.panel.loading =  new YAHOO.widget.Panel("wait", { 
                width:"240px",  
                fixedcenter:true,  
                close:false,  
                draggable:false,  
                zindex:4, 
                modal:true, 
                visible:true 
	        }); 
	 
        	YAHOO.ms.panel.loading.setHeader(txt); 
        	YAHOO.ms.panel.loading.setBody('<img src="http://us.i1.yimg.com/us.yimg.com/i/us/per/gr/gp/rel_interstitial_loading.gif" />'); 
        	YAHOO.ms.panel.loading.render(document.body);
        },
        
        showLoading : function (txt) {
            txt = txt || "Loading, please wait...";
            if (!YAHOO.ms.panel.loading) {
                YAHOO.ms.panel.loading =  new YAHOO.widget.Panel("wait", { 
                    width:"240px",  
                    fixedcenter:true,  
                    close:false,  
                    draggable:false,  
                    zIndex:240, 
                    modal:true, 
                    visible:true 
    	        }); 
    	        YAHOO.ms.panel.loading.setHeader(txt);
    	        YAHOO.ms.panel.loading.setBody('<img src="http://us.i1.yimg.com/us.yimg.com/i/us/per/gr/gp/rel_interstitial_loading.gif" />'); 
        	    YAHOO.ms.panel.loading.render(document.body);
            }
        	
            YAHOO.ms.panel.loading.show();
        },
        
        hideLoading : function (reset) {
            YAHOO.ms.panel.loading.destroy();
            YAHOO.ms.panel.loading = null;
        },
        
        /**
         * scrolls the window to up
         */
        scrollUp : function () {			
            window.scrollTo(0, 0);
        },
        
        /**
         * scrolls the window to up
         */
        scrollDown : function () {			
            var down = parseInt(document.body.scrollHeight || document.documentElement.scrollHeight);
            window.scrollTo(0, down);
        },
        
        /**
         * Function clears default text of the textbox or textarea
         * @param {HTMLElement} el
         */
        clearDefaultText : function (el) {
            if(!el) return;
            if (el.value == el.defaultValue)  el.value = "";
        },
        
        /**
         * Function to create YUI alert, confirm and prompt dialog box
         * @param {String} type [CONFIRM, ALERT, PROMPT]
         * @param {Object} options
         */
        createSimpleDialog : function (type, options) {
            var $D = YAHOO.util.Dom,
		        $E = YAHOO.util.Event,
                $L = YAHOO.lang,
		        $W = YAHOO.widget;

            // default configure options
            var data = {
                width : "30em",
                zIndex : 256,
                fixedcenter : true,
                visible : false,
                draggable : false,
                modal : true
            };
            
            var title = "<div class='left'>" + options.title + "</div>";
            var message = options.message;
            var but_captions = options.button_captions || [];            
            var handleYes, handleNo = null;
            
            //now delete these two properties from options
            delete options.title;
            delete options.message;
            delete options.button_captions;
            
            if (but_captions.length == 0) {
                but_captions = ["Ok", "Cancel"];
            }

            /**
             * callbacks fired on clicking the buttons
             */
            if(typeof options.handleYes == "function") {
                handleYes = options.handleYes;
                delete options.handleYes;
            }else {
                handleYes = function () {
                    handleNo();
                }
            }

            if(typeof options.handleNo == "function") {
                handleNo = options.handleNo;
            }else {
                handleNo = function () {
                    this.destroy();
                }
            }
            
            //augment the specified object with the default object
            $L.augmentObject(data, options, true);
            //now create the dialog
            var simple_dialog = new $W.SimpleDialog("ms_simple_dialog", data);
            simple_dialog.setHeader(title);
            simple_dialog.setBody(message);
            
            //override default hide method if no handleNo provided
            if(typeof options.handleNo != "function") {
                simple_dialog.hide = handleNo;
            }
            simple_dialog.CSS_FOOTER = "ft center";
                                    
            var buttons = [{text : but_captions[0], handler : handleYes, isDefault : true}]; 
            if (type.toUpperCase() == "CONFIRM" || type.toUpperCase() == "PROMPT") {
                buttons.push( {text : but_captions[1], handler : handleNo, idDefault : true} );
            }
            simple_dialog.cfg.queueProperty("buttons", buttons);

            simple_dialog.render(document.body);

            return simple_dialog;
        },
        /**
         * Function to remove starting and tralling BR's
         * @param {Object} s
         */
       	removeTrailingBRs : function(s) {
            //regular expressions to remove trailing BRs
            var starts_with = /^(<\/?br>)+/gi, ends_with = /(<\/?br>)+$/gi;
            
            var temp = s.replace(starts_with, "").replace(ends_with, "");
            return temp;
        },
        
        /**
         * Returns the civilian time format at the interval of every 5 messages
         * it maintains the internal private counter for determining 5 msg interval
         */
        printTime : function () {       
            //get time
            var time = new Date().getTime();          
            var dt = new Date();  
            dt.setTime(time);
            //display civilian time format      
            return this._getCivilianTime(dt);
        },
        
        /**
         * Returns the civilian time format
         * @param {Date} date_obj
         */
        _getCivilianTime : function (date_obj) {
            var str = [];
            var hour = date_obj.getHours();
            var min = date_obj.getMinutes();
            var suffix = (hour >= 12) ? "PM" : "AM";
            
            if(hour > 12) {
                hour = hour - 12;
            }
            
            if(hour < 10) {
                hour = "0" + hour;
            }
            
            if(min < 10) {
                min = "0" + min;
            }
            
            return hour + "-" + min + " " + suffix;
        }
    };
}();


/**
 * The CallQueue class maintains a "Queue/List" of pending calls
 * and execute them sequentially, each queue item is an object of Queue class.
 * The pattern of this class is Singleton
 */
 var CallQueue = function () {
     var q = []; // queue elements list     
     var limit = 100; //queue max limit 
     var isRunning = false; // determines whether the shift operation is running or not
     var debug = false;
     var current_call = null;
     
     return {
         /**
          * Accepts a call object consists of href, id (both required) and options property
          */
         push : function (options) {
             if(!options.href) return;
             
             this.debug("Queue Push got called....." + options.href);
             
             //if(this.hasExceeded()) return;
             
             this.addToQueue(Object.clone(options));
         },
         
         /**
          * Checks whether the limit has exceeded it's maximum limit or not
          */
         hasExceeded : function () {
             if(q.length >= limit) return true;
             return false;
         },
         
         /**
          * Function to add queue object in the array and also ensures that the "q" doesn't 
          * exceed it's limit
          * @param {Object} obj
          */
         addToQueue : function (obj) {
             //create a queue object
             var q_elem = new Queue(obj);
             q.push(q_elem);

             this.debug("Added to Queue...." + q_elem.href + "   Length is :: " + q.length);

             if(!isRunning) {
                 this.debug("starting fire from addToQueue...." + q_elem.href);
                 this.fire();
             }
         },
         
         /**
          * Fires the AJAX request on every queue element
          */
         fire : function () {
             if(q.length == 0) {
                 this.debug("setting q length to 0");
                 isRunning = false;
                 return;
             }
             
             isRunning = true;
             
             var q_obj = q[0]; //first item always
             this.debug("Firing URL :: " + q_obj.href + "   Length is :: " + q.length);
             
             var on_complete = q_obj.options.onComplete || Prototype.emptyFunction;

             q_obj.options.onComplete = function (req) {
                 CallQueue.debug("complete called for URL :: " + q_obj.href);
                 on_complete.apply(q_obj, []);
                 q_obj.isDone = true;
                 CallQueue.complete();
             };

             if(!q_obj.options.onException) {
                 //may be because of connection loss
                 q_obj.options.onException = this.notConnected;
             }

             var current_call = ConvUtil.ajaxCall(q_obj.href, q_obj.options);
         },
         
         /**
          * Function to be executed on any exception while connecting to server
          */
         notConnected : function (req, exception) {
             alert("Unable to connect to server! Please wait for few minutes before trying again!");
         },
         
         /**
          * Function to be called after each call is made
          */
         complete : function () {
             this.debug("complete fired.....");
             this.shift();
         },
         
         /**
          * Always removes alement from the start of the 'queue'
          */
         shift : function () {
             var q_obj = q[0]; //first element always
             this.debug("In shift trying to remove URL :: " + q_obj.href);

             if (q_obj.isDone) {                 
                 var item = q.shift();
                 this.debug("Queue length is :: " + q.length);
                 this.debug(q_obj.href + " == " + item.href);
                 CallQueue.fire();
             }
         },
         
         /** 
          * Can abort only the current call (unreliable, works only in that point of time, cannot discard pending queue calls )
          */
         abort : function () {
             //calls abort method on the global request hashMap
             if(current_call) {
                 if(current_call.transport.readyState != 4) {
                     current_call.transport.abort(); //abort the call and
                 }
             }
         },
         /**
          * Debug helper (FireBug Dependant)
          */
         debug : function (str) {
             if(!debug || !console) return;
             
             console.debug(str);
         }
         
     }
 }();
 
 /**
  * This class works as a data structure for making Ajax calls
  * @param {Number} id      (Optional)
  * @param {String} href    (Required)
  * @param {Object} options (Optional)
  */
 function Queue (obj) {     
     this.href = obj.href;
     this.id = obj.id || "";
     delete obj.href;

     this.options = Object.clone(obj);
 }
 
 /* dependant is going to be added later*/
 Queue.prototype = {     
     isDone : false
 };
 
 /* -------------------------------- End of Queue -------------------------- */
