/****************************************************************
** Licensed Materials - Property of IBM
**
** IBM Cognos Products: mdsrv
**
** (C) Copyright IBM Corp. 2008, 2015
**
** US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*****************************************************************/
//***********************************************************************************************
// Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved.
// Cognos (R) is a trademark of Cognos ULC, (formerly Cognos Incorporated).
//
// Component:	Utility - helper objects and functions
//***********************************************************************************************

if ( ! UTIL )
	var UTIL = {};

UTIL.bDebugMode = false;

// The Key codes being passed down in the onkeydown event

UTIL.KEYCODE_TAB			= 9;
UTIL.KEYCODE_ENTER			= 13;
UTIL.KEYCODE_ARROW_LEFT		= 37;
UTIL.KEYCODE_ARROW_RIGHT	= 39;
UTIL.KEYCODE_ARROW_UP		= 38;
UTIL.KEYCODE_ARROW_DOWN		= 40;

//========================================================================
// Augment Javascript basic types
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Inheritance support
//------------------------------------------------------------------------

Function.prototype.method = function ( name, func )
{
	if ( ! this.prototype[name] )
	{
		this.prototype[name] = func;
	}
	return this;
};

Function.method( 'inherits', function ( Parent )
{
	this.prototype = new Parent();
	return this;
});

//------------------------------------------------------------------------
// String support
//------------------------------------------------------------------------

String.method( 'trim', function() {
	return this.replace(/^\s+|\s+$/g, '');
});

//========================================================================
//------------------------------------------------------------------------

function GetScreenResolution()
{
	var size = new CSize();

	var size = { width: screen.width , height: screen.height };

	return size;
}

function getPropertyName( object, propValue )
{
	var propName = "";

	for ( var i in object )
	{
		if ( object[ i ] === propValue )
		{
			propName = i;
			break;
		}
	}

	return propName;
}

//----------------------------------------------------------
// addMethod - Method Overloading
// Examples:
/*----------------------------------------------------------
function Users()
{
	addMethod(this, "find", function(name)
	{
		// Find a user by name
	});
	addMethod(this, "find", function(first, last)
	{
		// Find a user by first and last name
	});
}

Or, if you wanted to use it with an object prototype:

function Users(){}

addMethod(Users.prototype, "find", function(name)
{
	// Find a user by name
});
addMethod(Users.prototype, "find", function(first, last)
{
	// Find a user by first and last name
});
-----------------------------------------------------------*/

function addMethod(object, name, fn)
{
	var old = object[ name ];

	object[ name ] = function()
	{
		if ( fn.length === arguments.length )
			return fn.apply( this, arguments );
		else if ( typeof old === 'function' )
			return old.apply( this, arguments );
	};
}

//------------------------------------------------------------------------

function CElementStyleHelper ( elem )
{
	this.setElem ( elem );

	return this;
}

CElementStyleHelper.prototype.getElem		= function ()
{
	return this.m_elem;
}

CElementStyleHelper.prototype.setElem		= function ( elem )
{
	ASSERT ( elem, "CElementStyleHelper: elem is NOT valid !!!" );

	if ( typeof elem === "string" )
	{
		this.m_elemId	= elem;
		this.m_elem		= document.getElementById( this.m_elemId );
	}
	else
	{
		this.m_elemId	= elem.id;
		this.m_elem		= elem;
	}

	ASSERT ( this.m_elem, "CElementStyleHelper: element " + this.m_elemId + " is NOT found !!!" );

	return this;
}

CElementStyleHelper.prototype.show			= function ( bShow )
{
	// One way - via the visibility property (does NOT seem to affect children's state !!!)

//		this.m_elem.style.visibility = bShow ? "visible" : "hidden";

	// Alternative way - via display property

	this.m_elem.style.display	 = bShow ? "block" : "none";
}

CElementStyleHelper.prototype.isShown		= function ()
{
	var bHidden = typeof this.m_elem.style.display !== "undefined" && this.m_elem.style.display === "none";

	return ! bHidden;
}

CElementStyleHelper.prototype.setZIndex		= function ( zOrder )
{
	this.m_elem.style.zIndex	= zOrder;
}

CElementStyleHelper.prototype.setTextDecoration	= function ( sDecoration )
{
	this.m_elem.style.textDecoration	= sDecoration;
}

CElementStyleHelper.prototype.setText		= function ( sText )
{
	this.m_elem.innerHTML = sText;
}

CElementStyleHelper.prototype.setTextBold	= function ()
{
	var sText = this.m_elem.innerHTML;

	this.m_elem.innerHTML = "<b>" + sText + "</b>";
}

CElementStyleHelper.prototype.setFontWeight	= function ( sFontWeight )
{
	this.m_elem.style.fontWeight = sFontWeight;
}

CElementStyleHelper.prototype.setFontStyle	= function ( sFontStyle )
{
	this.m_elem.style.fontStyle = sFontStyle;
}

CElementStyleHelper.prototype.setFontSize	= function ( sFontSize )
{
	this.m_elem.style.fontSize = sFontSize;
}

CElementStyleHelper.prototype.setColors		= function ( color, bkColor )
{
	if ( color )
		this.m_elem.style.color				= color;

	if ( bkColor )
		this.m_elem.style.backgroundColor	= bkColor;
}

CElementStyleHelper.prototype.getCursor		= function ()
{
	return this.m_elem.style.cursor;
}

CElementStyleHelper.prototype.setCursor		= function ( sCursor )
{
	this.m_elem.style.cursor = sCursor;
}

CElementStyleHelper.prototype.setOpacity	= function ( elemOpacity )
{
	this.m_elem.style.opacity	= elemOpacity;

//		if ( this.m_elem.style.filter )
//			this.m_elem.style.filter	= 'alpha(opacity=' elemOpacity + ')';
}

CElementStyleHelper.prototype.move			= function ( left, top )
{
	if ( left !== -1 )
		this.m_elem.style.left		= left;
	if ( top  !== -1 )
		this.m_elem.style.top		= top;
}

CElementStyleHelper.prototype.moveToPos		= function ( pos )
{
	this.m_elem.style.left		= pos.x;
	this.m_elem.style.top		= pos.y;
}

CElementStyleHelper.prototype.resize		= function ( width, height )
{
	if ( width  !== -1 )
		this.m_elem.style.width		= width;
	if ( height !== -1 )
		this.m_elem.style.height	= height;
}

CElementStyleHelper.prototype.setBorderStyle= function ( sStyle )
{
	this.m_elem.style.borderStyle = sStyle;
}

CElementStyleHelper.prototype.addEvent		= function ( evType, callback, useCapture )
{
	addEvent	( this.m_elem, evType, callback, useCapture );
}

CElementStyleHelper.prototype.removeEvent	= function ( evType, callback, useCapture )
{
	removeEvent	( this.m_elem, evType, callback, useCapture );
}

CElementStyleHelper.prototype.setClass		= function ( sNewClass )
{
	this.m_elem.className = sNewClass;
}

CElementStyleHelper.prototype.addClass		= function ( sNewClass )
{
	if ( ! this.m_elem.className )
	{
		this.m_elem.className = sNewClass;
	}
	else
	{
		newClassName = this.m_elem.className;
		newClassName += " ";
		newClassName += sNewClass;

		this.m_elem.className = newClassName;
	}
}

CElementStyleHelper.prototype.getClientSize	= function ()
{
	var sizeClient	= new CSize();

	var sizeScreen = { width: this.m_elem.clientWidth , height: this.m_elem.clientHeight };

	sizeClient.SetSize ( this.m_elem.clientWidth, this.m_elem.clientHeight );

	return sizeClient;
}

CElementStyleHelper.prototype.getScreenSize	= function ()
{
	var sizeScreen	= this.getClientSize();

	sizeScreen.x	= this.m_elem.offsetLeft;
	sizeScreen.y	= this.m_elem.offsetTop;

	return sizeScreen;
}

CElementStyleHelper.prototype.getAbsPos		= function ()
{
	var left	= 0;
	var top		= 0;
	var obj		= this.m_elem;

	if ( obj.offsetParent )
	{
		left	= obj.offsetLeft;
		top		= obj.offsetTop;

		while ( obj = obj.offsetParent )
		{
			left	+= obj.offsetLeft;
			top		+= obj.offsetTop;
		}
	}

	var pos = new CPosition ( left, top );

	return pos;
}

//======================================================================

function ASSERT( condition, sErrorMessage )
{
	if ( UTIL.bDebugMode )
	{
		if ( typeof condition === "undefined" || ! condition )
			alert( sErrorMessage );
	}
}

function alertTimeDiff ( timeStart, sFunctionName )
{
	var timeCurr = new Date().getTime();
	var timediff = ( timeCurr - timeStart ) + " ms";
	alert ( sFunctionName + " : " + timediff );
}

//--------------------------------------------------------------------------------
// EVENT functionality
//--------------------------------------------------------------------------------

function addEvent( elem, evType, callback, useCapture )
{
	ASSERT( elem, 'addEvent: element is NOT valid !!!!' )

	// cross-browser event handling for IE5+ NS6+, Mozilla

	if ( elem )
	{
		if ( elem.addEventListener )
		{
			elem.addEventListener( evType, callback, useCapture );
			return true;
		}
		else
		if ( elem.attachEvent )
		{
			var r = elem.attachEvent( 'on' + evType, callback );
			return r;
		}
		else
		{
			elem[ 'on' + evType ] = callback;
		}
	}
}

function removeEvent ( elem, evType, callback, useCapture )
{
	ASSERT( elem, 'removeEvent: element is NOT valid !!!!' )

	// cross-browser event handling for IE5+ NS6+, Mozilla

	if ( elem )
	{
		if ( elem.removeEventListener )
		{
			elem.removeEventListener( evType, callback, useCapture );
		}
		else
		if ( elem.detachEvent )
		{
			elem.detachEvent( "on" + evType, callback );
		}
		else
		{
			elem[ 'on' + evType ] = null;
		}
	}
}

function cancelEvent( ev )
{
	if ( ev.preventDefault )
		ev.preventDefault();
	else
	if ( ev.returnValue )
		ev.returnValue = false;
}

function stopEvent( ev )
{
	if ( ev.stopPropagation )
		ev.stopPropagation();
	else
	if ( ev.cancelBubble )
		ev.cancelBubble = true;
}

function getMousePosition ( evt )
{
	// This is the correct script for detecting the mouse coordinates:

	var pos = new CPosition();

	var posx = 0;
	var posy = 0;

	if ( ! evt ) var evt = window.event;

	if ( evt.pageX || evt.pageY )
	{
		posx = evt.pageX;
		posy = evt.pageY;
	}
	else
	if ( evt.clientX || evt.clientY )
	{
	    if (document.documentElement.clientHeight == 0) {
	        posx = evt.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
	        posy = evt.clientY + document.body.scrollTop + document.documentElement.scrollTop;
	    }
	    else {
	        posx = evt.clientX + document.documentElement.scrollLeft + document.documentElement.scrollLeft;
	        posy = evt.clientY + document.documentElement.scrollTop + document.documentElement.scrollTop;
	    }
	}

	// posx and posy now contain the mouse position relative to the document

	pos.Set ( posx, posy );

	return pos;
}

function CKeyboardEvent ( evt )
{
	if ( evt )
		this.evt = evt; 
	else
		this.evt = window.event; 

	if ( this.evt.which )
		this.key = this.evt.which;		// Netscape/Firefox/Opera
	else
		this.key = this.evt.keyCode;	// IE
}

function CMouseEvent ( evt )
{
	if ( evt )
		this.evt = evt; 
	else
		this.evt = window.event; 

	if ( this.evt.pageX )
		this.x = this.evt.pageX; 
	else
		this.x = this.evt.clientX; 

	if ( this.evt.pageY )
		this.y = this.evt.pageY; 
	else
		this.y = this.evt.clientY; 

	if ( this.evt.target )
		this.target = this.evt.target; 
	else
		this.target = this.evt.srcElement;
}

CMouseEvent.prototype.ClientToScreen = function (pos) {
    var posNew = pos;

    if (this.evt.pageX || this.evt.pageY) {
        posNew.x = this.evt.pageX;
        posNew.y = this.evt.pageY;
    }
    else
        if (this.evt.clientX || this.evt.clientY) {
            if (document.documentElement.clientHeight == 0) {
                posNew.x += document.body.scrollLeft + this.target.scrollLeft;
                posNew.y += document.body.scrollTop + this.target.scrollTop;
            }
            else {
                posNew.x += document.documentElement.scrollLeft + this.target.scrollLeft;
                posNew.y += document.documentElement.scrollTop + this.target.scrollTop;
            }
        }

    return posNew;
}

function addListener( elem, type, callback ) 
{
	if ( elem.addEventListener )
	{
		elem.addEventListener( type, callback, false );
	}
	else
	if ( elem.attachEvent )
	{
		elem.attachEvent( "on"+type, callback, false );
	}
}

function removeListener ( elem, type, callback )
{
	if ( elem.removeEventListener )
	{
		elem.removeEventListener( type, callback, false );
	}
	else
	if ( elem.detachEvent )
	{
		elem.detachEvent( "on" + type, callback, false );
	}
}

//---------------------------------------------------------------------
// DEBUG API
//---------------------------------------------------------------------

function getLikeElements ( tagName, attrName, attrValue )
{
	var startSet;
	var endSet = new Array( );

	if ( tagName )
	{
	    startSet = document.getElementsByTagName(tagName);    
	}
	else
	{
	    startSet = (document.all) ? document.all : document.getElementsByTagName("*");
	}

	if ( attrName )
	{
	    for ( var i = 0; i < startSet.length; i++ )
	    {
	        if ( startSet[i].getAttribute(attrName) )
	        {
	            if ( attrValue )
	            {
	                if ( startSet[i].getAttribute(attrName) === attrValue )
	                {
	                    endSet[endSet.length] = startSet[i];
	                }
	            }
	            else
	            {
	                endSet[endSet.length] = startSet[i];
	            }
	        }
	    }
	}
	else
	{
	    endSet = startSet;
	}

	return endSet;
}

function walkChildNodes ( objRef, bAllNodes, n )
{
	var obj;

	if ( objRef )
	{
		if ( typeof objRef === "string" )
		{
		    obj = document.getElementById( objRef );
		}
		else
		{
			obj = objRef;
		}
	}
	else
	{
	    if (document.documentElement.clientHeight == 0)
	        obj = (document.body.parentElement) ? document.body.parentElement : document.body.parentNode;
        else
            obj = (document.documentElement.parentElement) ? document.documentElement.parentElement : document.documentElement.parentNode;
	}

	var output = "";
	var indent = "";
	var i, group, txt;

	if ( n )
	{
		for (i = 0; i < n; i++)
		{
			indent += "+---";
		}
	}
	else
	{
		n = 0;

		output += "Child Nodes of <" + obj.tagName.toLowerCase( );
		output += ">\n=  ==  ==  ==  ==  ==  ==  ==  ==  ==  ==\n";
	}

	group = obj.childNodes;

	for ( i = 0; i < group.length; i++ )
	{
		var elem = group[i];

		output += indent;

		switch ( elem.nodeType )
		{
			case 1:

				if ( bAllNodes || ( elem.id || elem.name ) )
				{
					output += "<" + elem.tagName.toLowerCase( );
					output += (elem.id)		? " ID=" + elem.id : "";
					output += (elem.name)	? " NAME=" + elem.name : "";
					output += ">\n";
				}
				break;
			case 3:

				txt = elem.nodeValue.substr( 0, 25 );

				output += "[ \"" + txt.replace(/[\r\n]/g,"<cr>");

				if ( elem.nodeValue.length > 25 )
				{
					output += "...";
				}

				output += "\" ]\n";
				break;
			case 8:
			    output += "[!COMMENT!]\n";
			    break;
			default:
			    output += "[Node Type = " + elem.nodeType + "]\n";
		}

		if ( elem.childNodes.length > 0 )
		{
		    output += walkChildNodes ( elem, bAllNodes, n+1 );
		}
	}

    return output;
}

//---------------------------------------------------------------------
// TABLE API <W3C DOM>
//---------------------------------------------------------------------

/*
function clearTBody()
{
	var tbodies = this.getElementsByTagName( "tbody" );

	for ( var i = 0; i < tbodies.length; i++ )
	{
		while ( tbodies[ i ].rows.length > 0
			tbodies[ i ].deleteRow( 0 );
	}
}

HTMLTableElement.prototype.clear = clearTBody;
*/

/* escape/encode/decodeHtml() functions are used to deal with the ', ", <, >, and & characters
when dynamic HTML re-writing of form input values. These functions are client-side equivalent
of the Java htmlEncode() method.
Note: The & must be translated first to avoid translating it for other characters */

function escapeHTML ( sInputString )
{
	var sOutputString = "" + sInputString;

	if ((sOutputString === '0') || ((sInputString !== null) && (sInputString !== false)))
	{
		sOutputString = sOutputString.replace(/&/g, "&amp;");
		sOutputString = sOutputString.replace(/</g, "&lt;");
		sOutputString = sOutputString.replace(/>/g, "&gt;");
		sOutputString = sOutputString.replace(/"/g, "&quot;");
		sOutputString = sOutputString.replace(/'/g,  "&#39;");	// the numeric value for "&apos;"
	}
	else if (sInputString === null)
	{
		//return empty string if the value is null or false
		sOutputString = "";
	}

	return sOutputString;
};

function getFormattedPropertyValue ( sValue )
{
	var sStr1 = sValue.replace( /\n/g , "" );
	var sStr2 = sStr1.replace( /&apos;/g , "'" );
	var sStr3 = sStr2.replace( /&quot;/g , "\"" );

	var sFormattedValue = sStr3;

	var strArray = sFormattedValue.split( " " );

	if ( strArray.length > 1 )
	{
		sFormattedValue = "";

		for ( var j = 0; j < strArray.length; j++ )
		{
			if ( strArray[ j ] )
			{
				sFormattedValue += strArray[ j ] + " ";
			}
		}
	}

	return sFormattedValue;
}

function CPropertyTable ( idTable )
{
	this.id	= idTable;
}

CPropertyTable.prototype.Clear			= function ()
{
	var table		= document.getElementById( this.id );
	var tbodies		= table.getElementsByTagName( 'tbody' );

	ASSERT ( tbodies.length === 1, "AppendRow: <TBODY> element is missing in table " + this.id );

	var tbody		= tbodies[0];

	if ( tbody )
	{
		var rows		= tbody.getElementsByTagName( 'tr' );

		var numRows		= rows.length;

		for ( var i = numRows - 1; i >= 0; i-- )
		{
			tbody.removeChild( rows[i] );
		}
	}
}

CPropertyTable.prototype.AppendList		= function ( propertyList )
{
	for ( var i in propertyList )
	{
		var propPair = new PropertyPair( propertyList[i][0], propertyList[i][1] );

		this.AppendRow( propPair );
	}
}

CPropertyTable.prototype.findPropertyValue	= function ( obj, sPropName )
{
	var sPropValue	= "Unknown";
	var cProperties	= this.getPropertyCount();

	for ( var i = 0; i < cProperties; i++ )
	{
		if ( obj.getPropertyName(i) === sPropName )
		{
			sPropValue = obj.getPropertyValue(i);
			break;
		}
	}

	return sPropValue;
}

CPropertyTable.prototype.AppendObjPropList		= function ( obj )
{
	for ( var i = 0; i < obj.getPropertyCount(); i++ )
	{
//		alert ( obj.getPropertyDisplayName(i) + ' = ' + obj.getPropertyValue(i) );

		var sFormattedValue = getFormattedPropertyValue ( obj.getPropertyValue(i) );

		var propPair = new PropertyPair( obj.getPropertyDisplayName(i), sFormattedValue );

		this.AppendRow( propPair );
	}
}

CPropertyTable.prototype.AppendRow		= function ( propertyPair )
{
	// Creating a new table row based on a PropertyPair

	var table		= document.getElementById( this.id );
	var tbodies		= table.getElementsByTagName( 'tbody' );

	ASSERT ( tbodies.length === 1, "AppendRow: <TBODY> element is missing in table " + this.id );

	var tbody = tbodies[0];

	// Re-use API oTR = object.insertRow( [iIndex])
	// Example: myNewRow = document.all.myTable.insertRow()

	var row		= document.createElement( 'tr' );

	var col1	= document.createElement( 'td' );

	var attr11	= document.createAttribute( "width" );
	attr11.value = '20%';
	col1.setAttributeNode( attr11 );

	var attr12	= document.createAttribute( "class" );
	attr12.value = 'Col1';
	col1.setAttributeNode( attr12 );

	var col2	= document.createElement( 'td' );

	var attr21	= document.createAttribute( "width" );
	attr21.value = '80%';
	col2.setAttributeNode( attr21 );

	var attr22	= document.createAttribute( "class" );
	attr22.value = 'Col2';
	col2.setAttributeNode( attr22 );

	// adding text to nodes

	var text1	= document.createTextNode( propertyPair.name );

	col1.appendChild ( text1 );

	var text2	= document.createTextNode( propertyPair.value );

	col2.appendChild ( text2 );

	row.appendChild( col1 );
	row.appendChild( col2 );

	tbody.appendChild( row );
}

//---------------------------------------------------------------------
// Creation helpers of various elements
//---------------------------------------------------------------------

function CreateLink ( elemId, parentId, className, text, left, top, fnOnClick )
{
	var elemLink	= document.createElement ( 'a' );
	var elemParent	= document.getElementById( parentId );

	if ( ! elemLink || ! elemParent )
	{
		ASSERT( elemParent,	'CreateLink: elemParent is NOT valid !' );		
		ASSERT( elemLink,	'CreateLink: elemLink is NOT valid !' );		
		return null;
	}

	var elemText	= document.createTextNode( text );

	elemLink.appendChild ( elemText );

//	elemLink.innerHTML		= text;
	elemLink.id				= elemId;
	elemLink.href			= '#';

	if ( className )
		elemLink.className	= className;

	elemLink.style.left		= left + 'px';
	elemLink.style.top		= top + 'px';

	addEvent( elemLink, 'click', fnOnClick, false );

	elemParent.appendChild ( elemLink );

	//----------------------------------------------------
	// Test the new element

	var AttrId		= elemLink.getAttribute( "id" );
	var AttrClass	= elemLink.getAttribute( "className" ) || "Unknown Class";

//	alert ( "CreateLink: " + AttrId + ", " + AttrClass );

	return elemLink;
}

function CreateDiv ( elemId, parentId, className, left, top, width, height )
{
	var elemDiv		= document.createElement ( 'div' );
	var elemParent	= document.getElementById( parentId );

	if ( ! elemDiv || ! elemParent )
	{
		ASSERT( elemParent,	'CreateDiv: elemParent is NOT valid !' );		
		ASSERT( elemDiv,	'CreateDiv: elemDiv is NOT valid !' );		
		return null;
	}

	elemDiv.setAttribute( "id", elemId );
	elemDiv.id = elemId;	// a hack for IE6 as it's setAttribute works incorrectly

	if ( className )
		elemDiv.className			= className;

	elemDiv.style.left				= left + 'px';
	elemDiv.style.top				= top + 'px';
	if ( width )
		elemDiv.style.width			= width + 'px';
	if ( height )
		elemDiv.style.height		= height + 'px';

	elemParent.appendChild ( elemDiv );

	// Test the new element

	var AttrId		= elemDiv.getAttribute( "id" );
	var AttrClass	= elemDiv.getAttribute( "className" );
	var AttrWidth	= elemDiv.getAttribute( "offsetWidth" );
	var AttrHeight	= elemDiv.getAttribute( "offsetHeight" );

//	alert ( "CreateDIV: " + AttrId + ", " + AttrClass + ", width=" + AttrWidth + ", height=" + AttrHeight);

	return elemDiv;
}

function CreateText ( elemId, parentId, className, text, left, top, width, height )
{
	var elemDiv		= CreateDiv ( elemId, parentId, className, left, top, width, height );

	if ( ! elemDiv )
	{
		ASSERT( elemDiv,	'CreateText: elemDiv is NOT valid !' );		
		return null;
	}

	elemDiv.innerHTML		= text;

	return elemDiv;
}

function CreateImage ( elemId, parentId, sImageName, left, top, width, height )
{
	var elemDiv		= CreateDiv ( elemId, parentId, 'classImageHolder', left, top, width, height );

	var elemImage	= document.createElement ( 'img' );

	if ( ! elemImage || ! elemDiv )
	{
		ASSERT( elemDiv,	'CreateImage: elemDiv is NOT valid !' );		
		ASSERT( elemImage,	'CreateImage: elemImage is NOT valid !' );		
		return null;
	}
/*
	var attr1	= document.createAttribute( "id" );
	attr1.value = elemId;
	elemImage.setAttributeNode( attr1 );
*/
	var attr2	= document.createAttribute( "src" );
	attr2.value = sImageName;
	elemImage.setAttributeNode( attr2 );

	var attr3	= document.createAttribute( "width" );
	attr3.value = width;
	elemImage.setAttributeNode( attr3 );

	var attr4	= document.createAttribute( "height" );
	attr4.value = height;
	elemImage.setAttributeNode( attr4 );

	elemDiv.appendChild ( elemImage );

	// Test the new element

	var AttrId		= elemImage.getAttribute( "id" );
	var AttrSrc		= elemImage.getAttribute( "src" );
	var AttrWidth	= elemImage.getAttribute( "offsetWidth" );
	var AttrHeight	= elemImage.getAttribute( "offsetHeight" );

//	alert ( "CreateImage: " + AttrId + ", " + AttrSrc + ", " + AttrWidth + ", " + AttrHeight );

	return elemDiv;
}

//---------------------------------------------------------------------
// Date / Time API
//---------------------------------------------------------------------

function GetReportTime()
{
	var d, s, t;
	var MinMilli = 1000 * 60;
	var HrMilli = MinMilli * 60;
	var DyMilli = HrMilli * 24;
	d = new Date();
	t = d.getTime();

	var dash = "-";

	s  =  d.getFullYear()   + dash;
	s += (d.getMonth() + 1) + dash;
	s +=  d.getDate() + " ";

	var c = ":";

	s += d.getHours() + c;
	s += d.getMinutes() + c;
	s += d.getSeconds();

	return(s);
}

//----------------------------------------------------------
// CStringBuffer implementation
//----------------------------------------------------------
/* Usage:

 var buf = new CStringBuffer();

 buf.append("hello");
 buf.append("world");

 alert(buf.toString());
----------------------------------------------------------*/

function CStringBuffer ( cStrings )
{
	if ( typeof cStrings !== "undefined" && cStrings > 0 )
		this.buffer = new Array( cStrings );
	else
		this.buffer = new Array();
}

CStringBuffer.prototype.append = function append( string )
{
	this.buffer.push( string );
	return this;
}

CStringBuffer.prototype.toString = function toString()
{
	return this.buffer.join("");
}

CStringBuffer.prototype.cleanUp = function cleanUp()
{
	return this.buffer.length = 0;
}

//----------------------------------------------------------
// Array helpers
//----------------------------------------------------------

function find ( array, searchStr )
{
	var returnArray = false;

	for ( var i = 0; i < array.length; i++ )
	{
		if ( array[i] === searchStr )
		{
			if ( ! returnArray )
			{
				returnArray = new Array();
			}

			returnArray.push(i);
		}
	}

	return returnArray;
}

function indexOf(array, value, startIndex)
{
	var index = -1;

	for ( var i = startIndex || 0; i < array.length; i++ )
	{
		if ( array[i] === value )
		{
			index = i;
			break;
		}
	}

	return index;
}

Array.indexOf	= indexOf;
Array.find		= find;

//-------------------------------------------------------------------------------------
// class CProgressControl
//-------------------------------------------------------------------------------------
// To run it you need to create:
//
// 1) The CSS classes .progressControl & .progressComponent
// 2) the following HTML elements:
/*
	<div id="id_progress_indicator" align=center style="position:relative; width:100%; height:100%;">
	<table width="100%" height=100%>
		<tbody>
			<tr><td align=center>
				<div id="id_progress_ctrl" class="progressControl" style="position:relative; width:105px; height:30px;">
					<div id="id_progress_ctrl_part1" class="progressComponent" style="position:absolute; left:5px;  top:5px; width:20px; height:15px;">
					</div>
					<div id="id_progress_ctrl_part2" class="progressComponent" style="position:absolute; left:30px; top:5px; width:20px; height:15px;">
					</div>
					<div id="id_progress_ctrl_part3" class="progressComponent" style="position:absolute; left:55px; top:5px; width:20px; height:15px;">
					</div>
					<div id="id_progress_ctrl_part4" class="progressComponent" style="position:absolute; left:80px; top:5px; width:20px; height:15px;">
					</div>
				</div>
			</td></tr>
		</tbody>
	</table>
	</div>
*/
//-------------------------------------------------------------------------------------

var idProgressCtrl		= null;
var idProgressTimer		= null;
var nLastProgressPart	= -1;
var cProgressParts		= 4;
var progress_part_ids	= ["id_progress_ctrl_part1", "id_progress_ctrl_part2", "id_progress_ctrl_part3", "id_progress_ctrl_part4"];
var progress_part_elems	= [];

function busyWait( millis )
{
	var stop = new Date().getTime() + millis;

	while( new Date().getTime() < stop )
	{
		// do nothing loop - just to yield control to the browser
		var elem = document.getElementById( idProgressCtrl );
		var html = elem.innerHTML;
	}
}

function runProgressBody ( )
{
	for ( var i = 0; i < cProgressParts; i++ )
	{
		progress_part_elems[ i ].style.backgroundColor = "Lightgrey";
	}

	nLastProgressPart++;
	if ( nLastProgressPart > 3 )
		nLastProgressPart = 0;

	progress_part_elems[ nLastProgressPart ].style.backgroundColor = "blue";
}

function runProgressControl ( idProgressDiv )
{
	idProgressCtrl = idProgressDiv;

	var cssHelper = new CElementStyleHelper ( idProgressCtrl );
	cssHelper.show ( true );

	for ( var i = 0; i < cProgressParts; i++ )
	{
		var elem = document.getElementById( progress_part_ids[ i ] );
		progress_part_elems[ i ] = elem;
	}

//	alert( progress_part_elems.length );

	idProgressTimer = setInterval ( "runProgressBody()", 500 );
}

function stopProgressControl ()
{
	if ( idProgressTimer )
	{
		var cssHelper = new CElementStyleHelper ( idProgressCtrl );
		cssHelper.show ( false );

		clearInterval ( idProgressTimer );

		idProgressTimer = null;
	}
}

//-------------------------------------------------------------------------------------------------
// Display helpers
//-------------------------------------------------------------------------------------------------

function CDisplayHelper()
{}

CDisplayHelper.prototype.hasAnyDigit	= function ( str )
{
	var ret = false;

	for (var i = str.length - 1; i >= 0; i--)
	{
		if (str.charAt(i) >= "0" && str.charAt(i) <= "9")
		{
			ret = true;
			break;
		}
	}

	if ((ret= true) && ((str.indexOf("+") > i) || (str.indexOf("-") > i)))
		ret = false;

	return ret;
}

CDisplayHelper.prototype.isNumber	= function ( str )
{
	var ret = false;

	if ( isNaN(str) || str === null )
	{
		ret = false;
	}
	else
	{
		ret = true;
	}

	return ret;
}

CDisplayHelper.prototype.trimTrailingBlanks	= function ( myStr )
{ 
	var idx;

	// ensure there really is a string to trim 

	if ( myStr !== null && myStr !== "undefined" )
	{ 
		while ( (myStr.length > 0) && ((idx = myStr.indexOf(" ")) === 0) )
		{ 
			myStr = myStr.substring(1); 
		} 

		while ( (myStr.length > 0) && ((idx = myStr.lastIndexOf(" ")) === (myStr.length -1)) )
		{ 
			myStr = myStr.substring(0,idx); 
		} 
	} 

	return myStr; 
}

CDisplayHelper.prototype.printNewLine = function ()
{
	return "\n";
}

CDisplayHelper.prototype.printTabs	= function ( nLevel )
{
	var sPrintXml = "";

	for ( var i = 0; i < nLevel; i++ )
	{
		sPrintXml += "\t";
	}

	return sPrintXml;
}

CDisplayHelper.prototype.printTag	= function ( sTag, nLevel, bPositionTag )
{
	var sPrintXml = "";

	if ( bPositionTag )
	{
		sPrintXml += "\n";
		sPrintXml += this.printTabs( nLevel );
	}

	sPrintXml += sTag;

	return sPrintXml;
}

CDisplayHelper.prototype.printValue	= function ( sValue )
{
	var sPrintXml = "";

	if ( sValue.length > 0 )
	{
		sPrintXml += sValue;
	}

	return sPrintXml;
}

CDisplayHelper.prototype.printNode	= function ( sXml, nLevel )
{
	if ( sXml.length === 0 )
		return "";

	var sPrintXml	= "";
	var tag_name	= ""
	var sTagBegin	= "<";

	var iTagBegin = sXml.indexOf( sTagBegin );

	if ( iTagBegin > -1 )
	{
		var iSelfTagEnd	= sXml.indexOf( "/>" );
		var iTagEnd	= sXml.indexOf( ">" );
		var iSpace	= sXml.indexOf( " " );

		var tag_contents = "";

		if ( ( iSelfTagEnd !== -1 ) && ( iSelfTagEnd < iTagEnd ) )
		{
			tag_contents = sXml.slice( iTagBegin + 1, iSelfTagEnd );

			var sSelfTag = "<" + tag_contents + "/>";

			sPrintXml += this.printTag( sSelfTag, nLevel, true );

			var iNodeEnd = iSelfTagEnd + 1;

			if ( iNodeEnd < sXml.length )
			{
				sXml = sXml.slice( iNodeEnd + 1 );
				sPrintXml += this.printNode ( sXml, nLevel );
			}

			return sPrintXml;
		}

		tag_contents = sXml.slice( iTagBegin + 1, iTagEnd );

		if ( ( iSpace !== -1 ) && ( iSpace < iTagEnd ) )
		{
			tag_name = sXml.slice( iTagBegin + 1, iSpace );
		}
		else
		{
			tag_name = sXml.slice( iTagBegin + 1, iTagEnd );
		}

		// Print the opening tag

		var sOpeningTag = "<" + tag_contents + ">";

		sPrintXml += this.printTag( sOpeningTag, nLevel, true );

		// Find the closing tag

		var sClosingTag = "</" + tag_name + ">";

		var iClosingTag = sXml.indexOf( sClosingTag );

		if ( iClosingTag !== -1 )
		{
			// Continue with the node value

			var sNodeValue = sXml.slice( iTagEnd + 1, iClosingTag );

			var sPrintedValue = this.printNode ( sNodeValue, nLevel + 1 );

			sPrintXml += sPrintedValue;

			// Print the closing tag

			var iTagInside = sPrintedValue.indexOf( "<" );
			var bPositionTag = ( iTagInside === -1 ? false : true );

			sPrintXml += this.printTag( sClosingTag, nLevel, bPositionTag );

			// Print siblings if any

			var iNodeEnd = iClosingTag + tag_name.length + 2;

			if ( iNodeEnd < sXml.length )
			{
				sXml = sXml.slice( iNodeEnd + 1 );
				sPrintXml += this.printNode ( sXml, nLevel );
			}
		}
		else
		{
			// Error: closing tag not found - cut off the start tag and print the text as is !

			var sNodeValue = sXml.slice( iTagEnd + 1 );

			sPrintXml += this.printValue( sNodeValue );
		}
	}
	else
	{
		sPrintXml += this.printValue( sXml );
	}

	return sPrintXml;
}

CDisplayHelper.prototype.prettyPrintXml	= function ( sXml )
{
	var sPrintXml = this.printNode ( sXml, 0 );

	return sPrintXml;
}

//**********************************************************************
// Instantiate global helpers
//**********************************************************************

//----------------------------------------------------------------------
// Instantiate Element helper
//----------------------------------------------------------------------

UTIL.ElementHelper = new CElementStyleHelper ( '' );

//----------------------------------------------------------------------
// Instantiate Display helper
//----------------------------------------------------------------------

UTIL.DisplayHelper = new CDisplayHelper ();

//----------------------------------------------------------------------


//**********************************************************************
// tanko test
//**********************************************************************

function MDSRV_paneCallBack()
{
	this.m_elRootPane	= document.getElementById ( "id_HAL_root_pane_placeholder" );
	this.m_nRootPane	= G_ResManager.F_GetResource ( "id_HAL_root_pane" );

	var heightOffset	= document.getElementById( "id_lineage_view" ).offsetTop;
	
	var width			= 0;
	var height			= 0;
	if (document.documentElement.clientHeight == 0)
	{
		width			= document.body.clientWidth - 10;
		height			= document.body.clientHeight - ( heightOffset + 5 );
	}
	else
	{
		width			= document.documentElement.clientWidth - 10;
		height			= document.documentElement.clientHeight - ( heightOffset + 5 );
	}
	this.m_oPaneManager = new C_PaneManager( this.m_elRootPane, this.m_nRootPane, this, width, height, false );
}

function MDSRV_initPaneMgr()
{
	LNS.MDSRV_paneManager = new MDSRV_paneCallBack( );

	LNS.MDSRV_paneManager.F_PaneManager_OnPaneResize = function( paneMgr, pane, width, heigth, resize)
	{
		var graphCanvasHeight = document.getElementById( "id_canvas_graph" ).offsetHeight;
		var graphHeaderHeight = document.getElementById( "id_graph_header" ).offsetHeight;

		document.getElementById( "id_graph" ).style.height = graphCanvasHeight - graphHeaderHeight;
	}
}

window.onresize = function()
{
	if ( LNS.MDSRV_paneManager )
	{
		var heightOffset	= document.getElementById( "id_lineage_view" ).offsetTop;

		var width			= 0;
		var height			= 0;
		if (document.documentElement.clientHeight == 0)
		{
			width			= document.body.clientWidth - 10;
			height			= document.body.clientHeight - ( heightOffset + 5 );
		}
		else
		{
			width			= document.documentElement.clientWidth - 10;
			height			= document.documentElement.clientHeight - ( heightOffset + 5 );
		}		

		LNS.MDSRV_paneManager.m_oPaneManager.F_SetNewPaneSize( "id_HAL_root_pane", width, height );
	}
}