/*
	Collexis FingerprintBox ASP.NET WebControl javascript functions
	
	Change log:
	14-04-2005 - Added support for negative concept ranks
	15-02-2005 - Initial release tested in IE 6.0 SP2, Netscape 7.2 and FireFox 1.0
*/

//concept types
var ctExcl = 0;
var ctNorm = 1;
var ctReq = 2;

//concept seperators
var csConc = "|";
var csConcData = "=";
var csConcRank = "X";

//settings
var scaleSize;// = 50;			//the scale is this amount of pixels wide
var scaleUnits = 100;		//the scale is this amount of units wide
var rankSize;// = 20;			//the draggable image is this amount of pixels wide
var scaleOffset = 1;		//the amount of pixels between required/excluded and the scale

//global variables
var oCC=oPos=oRank=null;
var ns=ie=n6=false;

//capture browser
if (document.layers) 
{	// Netscape 4
	ns = true;
} else if (document.all) 
{	// Internet Explorer
	ie = true;
} else if (document.getElementById) 
{	// Netscape 6 / FireFox
	n6 = true;
}

//handles registration of events for the given concept
function ccRegEvents(id)
{
	document.getElementById(id + '_s').onclick = ccScaleClick;
	var cc = document.getElementById(id);
	cc.onmousedown = ccClick;
	cc.onmousemove = ccDrag;
	cc.onmouseup = ccRelease;
}

var ta;
/*  Sets the positions of all the sliders according to their rank and requiredness
  set in the hidden fingerprint concepts field */
function setSliderPositions( id )
{	
	ta = document.getElementById('searchtext');
	var fp = document.getElementById( id + '_concepts' );
	var concepts = fp.value.split( '|' );
	
	for ( var i = 0; i < concepts.length; i++ )
	{
/*		var equalsPos = concepts[i].indexOf( '=' );
		var xPos = concepts[i].indexOf( 'X' );
		var conceptId = concepts[i].substring( 0, equalsPos );
		var conceptReq = concepts[i].substring( equalsPos + 1, xPos );
		var conceptRank = concepts[i].substring( xPos + 1 );*/
		var data = concepts[i].split( '=' );
		var conceptId = data[0];
		var data2 = data[1].split( 'X' );
		var conceptReq = data2[0];
		var conceptRank = data2[1];

		var slider = document.getElementById( id + '_' + conceptId );
/*		slider.onmousedown = ccClick;
		slider.onmousemove = ccDrag;
		slider.onmouseup = ccRelease;
		document.getElementById( id + '_' + conceptId + '_s' ).onclick = ccScaleClick;*/
		
		if ( i == 0 )
		{
			defineSettings( id, conceptId );
		}
		
		if ( slider != null )
		{
			var pos;
			if ( conceptReq == 2 )
				pos = scaleSize + rankSize + 1;
			else if ( conceptReq == 0 )
				pos = -rankSize - 1;
			else
			{
				if ( fp.getAttribute( 'allownegative' ) == 'true' )
					pos = (scaleSize / 2) + conceptRank * scaleSize / 2;
				else
					pos = conceptRank * scaleSize;
			}

			slider.style.left = pos;
		}
	}
}
/* Tries to get the width of the scale and the width of the slider from the CSS
   sheets linked to the current page */
function defineSettings( id, conceptId )
{
	if (document.getElementById(id + '_' + conceptId )) {
		var sliderClass = document.getElementById(id + '_' + conceptId ).className;
		var rs = findProperty( sliderClass, 'width' );
		if (rs != "") {
			if ( rs.length > 2 && rs.substring( rs.length - 2 ) == 'px' )
				rs = rs.substring( 0, rs.length - 2 );
	
			rankSize = parseInt( rs );
		}
	}

	if (document.getElementById( id + '_' + conceptId + '_sp' )) {
		var scaleClass = document.getElementById( id + '_' + conceptId + '_sp' ).className;
		var ss = findProperty( scaleClass, 'width' );

		if (ss != "") {
			if ( ss.length > 2 && ss.substring( ss.length - 2 ) == 'px' )
				ss = ss.substring( 0, ss.length - 2 );

			scaleSize = parseInt( ss ) - rankSize;	
		}
	}
}

/* Finds the given property from the CSS class with the specified name */
function findProperty( className, property )
{
	var sheets = document.styleSheets;
	var result = "";
	for ( i = 0; i < sheets.length; i++ )
	{
		var temp;
		if ( ie )
			temp = scanStyleSheetIE( sheets[i], className, property );
		else if ( n6 )
			temp = scanStyleSheet( sheets[i], className, property );
			
		if ( temp )
			result = temp;
	}
	return result;
}

/* NOTE: this function works only on Internet Explorer
         currently only tested for IE6

   Scans the specified style sheet object for a class with the specified 
   classname and returns the value of the specified property */
function scanStyleSheetIE( sheet, className, property )
{
	var result;
	if( sheet.imports.length > 0 )
	{
		for ( var j = 0; j < sheet.imports.length; j++ )
		{
			var temp = scanStyleSheetIE( sheet.imports[j], className, property );
			if ( temp )
				result = temp;
		}
	}

	for ( var i = 0; i < sheet.rules.length; i++ )
	{
		if ( sheet.rules.item( i ).selectorText == '.' + className )
			result = sheet.rules.item( i ).style[property];
	}

	if ( result )
		return result;
	else
		return false;
}

/* NOTE: this function does NOT work with Internet Explorer.
         current other browsers tested: FireFox 2.0

   Scans the specified style sheet object for a class with the specified 
   classname and returns the value of the specified property */
function scanStyleSheet( sheet, className, property )
{
	var result;
	try
	{
		for( var i = 0; i < sheet.cssRules.length; i++ )
		{
			if( sheet.cssRules.item( i ).type == 3 )
			{
				var temp = scanStyleSheet( sheet.cssRules.item( i ).styleSheet, className, property );
				if ( temp )
					result = temp;
			}
			else
			{
				if ( sheet.cssRules.item( i ).selectorText == '.' + className )
					result = sheet.cssRules.item( i ).style[property];
			}
		}
	
		if ( result )
			return result;
		else
			return false;
	}
	catch( e )
	{
		return false;
	}
}

//handles scale click event
function ccScaleClick(e)
{
	var elem;
	
	if (ie)
		elem = window.event.srcElement;
	else if (ns || n6)
		elem = e.target;
	
	if(elem.id)
	{
		if(elem.id.indexOf('_s') != -1)
		{
			//clicked object is a scale
			var oID = elem.id.substring(0, elem.id.lastIndexOf('_'));
			var obj = document.getElementById(oID);
			
			//determine new concept position								
			var newPos = mouseOffsetX(e) - rankSize / 2; //10 = half of image width
			if(newPos > scaleSize)
				newPos = scaleSize;
			else if(newPos < 0)
				newPos = 0;
				
			//set new concept position
			ccSetRank(obj, newPos);
		}
	}
	
	return true;
}

//handles concept click event
function ccClick(e)
{
	//captures the current object and its x position when clicked
	var elem;
	
	if (ie)
		elem = window.event.srcElement;
	else if (ns || n6)
		elem = e.target;
		
	//store current concept
	oCC = elem;
	
	//store current concept position
	oPos = mousePosX(e);
	
	//store current concept rank	
	oRank = oCC.style.left.substring(0, oCC.style.left.length - 2) - 0; //remove 'px'							
	
	return true;
}

//handles concept drag event
function ccDrag(e)
{
	if(oCC)
	{				
		//get pixels to move
		moveX = mousePosX(e) - oPos;
		
		//out of boundaries?
		if(oRank + moveX < 0)
		{
			//new position beyond 0%
			moveX = 0 - oRank;
		}
		else if(oRank + moveX > scaleSize)
		{
			//new position beyond 100%
			moveX = scaleSize - oRank;
		}

		//calculate new position
		oRank += moveX;
			
		//set new position
		ccSetRank(oCC, oRank);
		
		//update current position
		oPos += moveX;
	}
		
	return false;
}

//sets current concept state to excluded
function ccExcl(obj)
{
	var oID = obj.id.substring(0, obj.id.lastIndexOf('_'));
	ccSetRank(document.getElementById(oID), 0 - rankSize - scaleOffset);
	
	return true;
}

//sets current concept state to required
function ccReq(obj)
{
	var oID = obj.id.substring(0, obj.id.lastIndexOf('_'));
	ccSetRank(document.getElementById(oID), rankSize + scaleSize + scaleOffset);
	
	return true;
}

//releases the current concept
function ccRelease() 
{ 
	oCC = null;
}

//sets the rank of the given concept to the given value
function ccSetRank(cc, rankPos) 
{	
	//update concept rank
	cc.style.left = rankPos;
	
	//update fingerprintbox viewstate
	var excluded = rankPos < 0;
	var required = rankPos > scaleSize;
	var strRank, newRank, newClass;
	var intType;
	
	//update concept status
	if (excluded)
	{
		//excluded
		intType = ctExcl;
		newRank = 0;
		strRank = '';
		newClass = 'ccExcl';
	}
	else
	{
		if (required)
		{
			//required
			intType = ctReq;
			newRank = 100;
			strRank = '';
			newClass = 'ccReq';
		}
		else
		{
			//reqular rank
			intType = ctNorm;

			var fpID = cc.id.substring(0, cc.id.lastIndexOf('_'));
			var fp = document.getElementById(fpID+"_concepts");
			
			if(fp.getAttribute("allownegative") == "true")
				newRank = Math.round( (rankPos - scaleSize / 2) * (scaleUnits * 2) / scaleSize );
			else
				newRank = Math.round( rankPos * scaleUnits / scaleSize );

			strRank = newRank;
			newClass = 'ccNorm';
		}
	}
	
	document.getElementById(cc.id + '_r').innerHTML = "<nobr>" + strRank + "</nobr>";
	document.getElementById(cc.id + '_n').className = newClass;
	ccUpdateCC(cc, newRank, intType);
}

//sets the rank of the given concept to the given value
function ccSetRankSimple(cc, rankPos) 
{	
	//update fingerprintbox viewstate
	var excluded = rankPos < 0;
	var required = rankPos > 100;
	var strRank, newRank, newClass;
	var intType;
	
	//update concept status
	if (excluded)
	{
		//excluded
		intType = ctExcl;
		newRank = 0;
		strRank = '';
		newClass = 'ccExcl';
	}
	else
	{
		if (required)
		{
			//required
			intType = ctReq;
			newRank = 100;
			strRank = '';
			newClass = 'ccReq';
		}
		else
		{
			//reqular rank
			intType = ctNorm;

			var fpID = cc.id.substring(0, cc.id.lastIndexOf('_'));
			var fp = document.getElementById(fpID+"_concepts");

			if (scaleSize) {
				if(fp.getAttribute("allownegative") == "true")
					newRank = Math.round( (rankPos - scaleSize / 2) * (scaleUnits * 2) / scaleSize );
				else
					newRank = Math.round( rankPos * scaleUnits / scaleSize );
			} else {
				newRank = rankPos;
			}

			strRank = newRank;
			newClass = 'ccNorm';
		}
	}

	if (document.getElementById(cc.id + '_r'))
		document.getElementById(cc.id + '_r').innerHTML = "<nobr>" + strRank + "</nobr>";
		
	document.getElementById(cc.id + '_n').className = newClass;
	ccUpdateCC(cc, newRank, intType);
}

function ccUpdateCC(cc, rank, type)
{	
	var fpID = cc.id.substring(0, cc.id.lastIndexOf('_'));
	var cID = cc.id.split('_');
	var concID = cID[cID.length - 1];
	var fp = document.getElementById(fpID+"_concepts");
	var concepts = fp.value.split(csConc);
	var newValue = "";
	
	for(i = 0; i < concepts.length; i++)
	{
		var concept = concepts[i].split(csConcData);
		
		//add seperator
		if(newValue.length > 0)
			newValue += csConc;
		
		if(concept[0] == concID)
		{
			//this is the concept we need to change
			newValue += concept[0] + csConcData + type + csConcRank + (rank / 100);
		}
		else
			newValue += concepts[i];
	}
	
	fp.value = newValue;
	
	return true;
}

/* 
	Mouse helper functions from here 
*/

//returns the mouse X position relative to the document
function mousePosX(e)
{
	var posX = 0;
	
	if (ie) 
		posX = event.clientX + document.body.scrollLeft;
	else if (ns || n6) 
		posX = e.pageX;

	return posX;
}

//returns the X offset of the mouse to the object the mouse is over
function mouseOffsetX(e)
{			
	var offsetX = 0;
	
	if (ie)
		offsetX = window.event.offsetX;
	else if (ns || n6)
		offsetX = e.pageX - e.target.offsetLeft;
	
	return offsetX;
}