var ISNSC_EFFECTS_DEBUG = true;

var ISNSC_MESSAGES_LIMIT = 0;

var ISNSC_BROWSER_DETECTED = false;
var ISNSC_BROWSER_TYPE = null;
var ISNSC_BROWSER_VERSION = null;
var ISNSC_BROWSER_APP_CODE_NAME = null;
var ISNSC_PLATFORM = null;
var ISNSC_COOKIES_ENABLED = null;
var ISNSC_USERAGENT = null;

// Animation options
var ISNSC_ANIMATION_SHOW_FADING_STEP = 0.1;
var ISNSC_ANIMATION_HIDE_FADING_STEP = 0.02;
var ISNSC_ANIMATION_EXPAND_STEP = 8;
var ISNSC_ANIMATION_COLLAPSE_STEP = 4;
var ISNSC_ANIMATION_SETP_TIMEOUT_MILLIS = 30;
//var ISNSC_ANIMATION_SCROLL_SETP = 4;

/*
 * Alignment
 */
var ISNSC_ALIGNMENT_TOP_LEFT = 0;
var ISNSC_ALIGNMENT_TOP_RIGHT = 1;
var ISNSC_ALIGNMENT_BOTTOM_LEFT = 2;
var ISNSC_ALIGNMENT_BOTTOM_RIGHT = 3;

// Directions

// Horizontal
var ISNSC_DIRECTION_LEFT = 0;
var ISNSC_DIRECTION_RIGHT = 1;
// Vertical
var ISNSC_DIRECTION_UP = 2;
var ISNSC_DIRECTION_DOWN = 3;

/*Useful JavaScript string functions*/
String.prototype.trim = function()
{
  return this.replace( /^\s+|\s+$/g , "" );
}

String.prototype.ltrim = function()
{
  return this.replace( /^\s+/ , "" );
}

String.prototype.rtrim = function()
{
  return this.replace( /\s+$/ , "" );
}

function isnscAlert( message )
{
  if( ISNSC_MESSAGES_LIMIT >= 1 )
  {
    ISNSC_MESSAGES_LIMIT--;
    window.alert( message );
  }
}

/*
 * Browser detection functions
 */

function isnscDetectBrowser()
{
  if( ISNSC_BROWSER_DETECTED )
    return;

  if( navigator )
  {
    ISNSC_BROWSER_TYPE = navigator.appName;
    ISNSC_BROWSER_VERSION = navigator.appVersion;
    ISNSC_BROWSER_APP_CODE_NAME = navigator.appCodeName;
    ISNSC_PLATFORM = navigator.platform;
    ISNSC_COOKIES_ENABLED = navigator.cookieEnabled;
    ISNSC_USERAGENT = navigator.userAgent;
  }

  if( ISNSC_EFFECTS_DEBUG )
  {
    isnscAlert( "Browser type (" + ISNSC_BROWSER_TYPE + ")\n\n" +
        "Browser version (" + ISNSC_BROWSER_VERSION + ")\n\n" +
        "App Code Name (" + ISNSC_BROWSER_APP_CODE_NAME + ")\n\n" +
        "Platform (" + ISNSC_PLATFORM + ")\n\n" +
        "Cookies enabled (" + ISNSC_COOKIES_ENABLED + ")\n\n" +
        "HTTP User agent (" + ISNSC_USERAGENT + ")\n\n" );
  }
  ISNSC_BROWSER_DETECTED = true;
}

function isInternetExplorer()
{
  return ISNSC_BROWSER_VERSION.indexOf( "MSIE" ) != -1;
}

function isFirefox()
{
  // Contains only Firefox string and not Navigator string in the user agent string
  return ISNSC_USERAGENT.indexOf( "Firefox" ) != -1 && ISNSC_USERAGENT.indexOf( "Navigator" ) == -1;
}

function isNetscape()
{
  // Contains both Firefox and Navigator in the user agent string
  return ISNSC_USERAGENT.indexOf( "Firefox" ) != -1 && ISNSC_USERAGENT.indexOf( "Navigator" ) != -1;
}

function isOpera()
{
  return ISNSC_BROWSER_TYPE.indexOf( "Opera" ) != -1;
}

function isSafari()
{
  return ISNSC_BROWSER_VERSION.indexOf( "Safari" ) != -1 && ISNSC_BROWSER_VERSION.indexOf( "Chrome" ) == -1;
}

function isChrome()
{
  return ISNSC_BROWSER_VERSION.indexOf( "Chrome" ) != -1;
}

function isOtherBrowser()
{
  // TODO
  return false;
}

/*
 * DOM Functions
 */

function getMaximumHTMLElementOpacity() 
{
  if( isInternetExplorer() )
    return 100;
  return 1;
}

function showElement( htmlElement )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari() || isChrome() )
  {
    htmlElement.style.display = "block";
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );

    if( style.display )
      htmlElementStyle.display = "block";
    else
      htmlElementStyle.setProrperty( "display" , "block" );
  }
}

function hideElement( htmlElement )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari() || isChrome() )
  {
    htmlElement.style.display = "none";
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( style.display )
      htmlElementStyle.display = "none";
    else
      htmlElementStyle.setProrperty( "display" , "none" );
  }
}

function setElementOpacity( htmlElement , htmlElementOpacity )
{
  if( isInternetExplorer() )
  {
    htmlElement.style.filter = "alpha(opacity=" + htmlElementOpacity + ")";
  }
  else if( isFirefox() || isNetscape() || isOpera() || isSafari() )
  {
    htmlElement.style.opacity = htmlElementOpacity;
  }
  else
  {
    var htmlElementStyle = null;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );

    if( htmlElementStyle.setProperty )
      htmlElementStyle.setProperty( "opacity" , htmlElementOpacity );
    else
      htmlElementStyle.opacity = htmlElementOpacity;
  }
}

function getElementOpacity( htmlElement )
{
  if( isInternetExplorer() )
  {
    var ieOpacityString = htmlElement.style.filter;
    var ieOpacity = 0;
    if( ieOpacityString.indexOf( "alpha\(opacity=" ) != -1 )
    {
      ieOpacityString = ieOpacityString.substring( 'alpha(opacity='.length );
      if( ieOpacityString.indexOf( "\)" ) )
      {
        ieOpacity = parseInt( ieOpacityString );
      }
    }
    return ieOpacity;
  }
  else if( isFirefox() || isNetscape() || isOpera() || isSafari() )
  {
    return parseFloat( htmlElement.style.opacity );
  }
  else
  {
    var htmlElementStyle = null;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );

    if( htmlElementStyle.opacity )
      htmlElementOpacity = parseFloat( htmlElementStyle.opacity );
    else
      htmlElementOpacity = parseFloat( htmlElementStyle.getProperty( "opacity" ) );
    return htmlElementOpacity;
  }
  return null;
}

function setElementHeight( htmlElement , pixelHeight )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
  {
    htmlElement.style.height = pixelHeight + "px";
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( htmlElementStyle.height )
      htmlElementStyle.height = pixelHeight + "px";
    else
      htmlElementStyle.setProrperty( "height" , pixelHeight + "px" );
  }
}

function getElementHeight( htmlElement )
{
  var htmlElementHeight = -1;
  try
  {
    if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
    {
      htmlElementHeight = parseInt( htmlElement.style.height );
    }
    else
    {
      var htmlElementStyle;
      if( htmlElement.style )
        htmlElementStyle = htmlElement.style;
      else
        htmlElementStyle = htmlElement.getAttribute( "style" );
      
      if( htmlElementStyle.height )
        htmlElementHeight = parseInt( htmlElementStyle.height );
      else
        htmlElementHeight = parseInt( htmlElementStyle.getProrperty( "height" ) );
    }
  }
  catch( e )
  {
    htmlElementHeight = -1;
  }

  if( typeof( htmlElementHeight ) != "number" || ( typeof( htmlElementHeight ) == "number" && isNaN( htmlElementHeight ) ) )
    htmlElementHeight = 0;
  return htmlElementHeight;
}

function setElementWidth( htmlElement , pixelWidth )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
  {
    htmlElement.style.width = pixelWidth + "px";
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( htmlElementStyle.height )
      htmlElementStyle.height = pixelWidth + "px";
    else
      htmlElementStyle.setProrperty( "width" , pixelWidth + "px" );
  }
}

function getElementWidth( htmlElement )
{
  var htmlElementWidth = -1;
  try
  {
    if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
    {
      htmlElementWidth = parseInt( htmlElement.style.width );
    }
    else
    {
      var htmlElementStyle;
      if( htmlElement.style )
        htmlElementStyle = htmlElement.style;
      else
        htmlElementStyle = htmlElement.getAttribute( "style" );
      
      if( htmlElementStyle.width )
        htmlElementWidth = parseInt( htmlElementStyle.width );
      else
        htmlElementWidth = parseInt( htmlElementStyle.getProrperty( "width" ) );
    }
  }
  catch( e )
  {
    htmlElementWidth = -1;
  }
  
  if( typeof( htmlElementWidth ) != "number" || ( typeof( htmlElementWidth ) == "number" && isNaN( htmlElementWidth ) ) )
    htmlElementWidth = 0;
  return htmlElementWidth;
}

function setElementLeft( htmlElement , pixelLeft )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
  {
    htmlElement.style.left = pixelLeft + "px";
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( htmlElementStyle.left )
      htmlElementStyle.left = pixelLeft + "px";
    else
      htmlElementStyle.setProrperty( "left" , pixelLeft + "px" );
  }
}

function setElementRight( htmlElement , pixelRight )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
  {
    htmlElement.style.right = pixelRight + "px";
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( htmlElementStyle.right )
      htmlElementStyle.right = pixelRight + "px";
    else
      htmlElementStyle.setProrperty( "right" , pixelRight + "px" );
  }
}

function getElementLeft( htmlElement )
{
  var htmlElementLeft = -1;
  try
  {
    if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
    {
      htmlElementLeft = parseInt( htmlElement.style.left );
    }
    else
    {
      var htmlElementStyle;
      if( htmlElement.style )
        htmlElementStyle = htmlElement.style;
      else
        htmlElementStyle = htmlElement.getAttribute( "style" );
      
      if( htmlElementStyle.left )
        htmlElementLeft = parseInt( htmlElementStyle.left );
      else
        htmlElementLeft = parseInt( htmlElementStyle.getProrperty( "left" ) );
    }
  }
  catch( e )
  {
    htmlElementLeft = -1;
  }
  
  if( typeof( htmlElementLeft ) != "number" || ( typeof( htmlElementLeft ) == "number" && isNaN( htmlElementLeft ) ) )
    htmlElementLeft = 0;
  return htmlElementLeft;
}

function setElementTop( htmlElement , pixelLeft )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
  {
    htmlElement.style.top = pixelLeft + "px";
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( htmlElementStyle.top )
      htmlElementStyle.top = pixelLeft + "px";
    else
      htmlElementStyle.setProrperty( "top" , pixelLeft + "px" );
  }
}

function getElementTop( htmlElement )
{
  var htmlElementTop = -1;
  try
  {
    if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
    {
      htmlElementTop = parseInt( htmlElement.style.top );
    }
    else
    {
      var htmlElementStyle;
      if( htmlElement.style )
        htmlElementStyle = htmlElement.style;
      else
        htmlElementStyle = htmlElement.getAttribute( "style" );
      
      if( htmlElementStyle.top )
        htmlElementTop = parseInt( htmlElementStyle.top );
      else
        htmlElementTop = parseInt( htmlElementStyle.getProrperty( "top" ) );
    }
  }
  catch( e )
  {
    htmlElementTop = -1;
  }
  
  if( typeof( htmlElementTop ) != "number" || ( typeof( htmlElementTop ) == "number" && isNaN( htmlElementTop ) ) )
    htmlElementTop = 0;
  return htmlElementTop;
}

function setElementPosition( htmlElement , positionType )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
  {
    htmlElement.style.position = positionType;
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( htmlElementStyle.position )
      htmlElementStyle.position = positionType;
    else
      htmlElementStyle.setProrperty( "position" , positionType );
  }
}

function getElementPosition( htmlElement )
{
  var htmlElementPosition = null;
  try
  {
    if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
    {
      htmlElementPosition = htmlElement.style.position;
    }
    else
    {
      var htmlElementStyle;
      if( htmlElement.style )
        htmlElementStyle = htmlElement.style;
      else
        htmlElementStyle = htmlElement.getAttribute( "style" );
      
      if( htmlElementStyle.top )
        htmlElementPosition = htmlElementStyle.position;
      else
        htmlElementPosition = htmlElementStyle.getProrperty( "position" );
    }
  }
  catch( e )
  {
    htmlElementPosition = null;
  }
  
  return htmlElementPosition;
}

function setElementCursor( htmlElement , cursorType )
{
  if( isInternetExplorer() || isFirefox() || isNetscape() || isOpera() || isSafari()|| isChrome() )
  {
    htmlElement.style.cursor = cursorType;
  }
  else
  {
    var htmlElementStyle;
    if( htmlElement.style )
      htmlElementStyle = htmlElement.style;
    else
      htmlElementStyle = htmlElement.getAttribute( "style" );
    
    if( htmlElementStyle.cursor )
      htmlElementStyle.cursor = cursorType;
    else
      htmlElementStyle.setProrperty( "cursor" , cursorType );
  }
}

function isMaximumHTMLElementOpacity( htmlElementOpacity )
{
  return ( !isInternetExplorer() && htmlElementOpacity >= 1 ) ||
    ( isInternetExplorer() && htmlElementOpacity >= 100 );
}

function increaseHTMLElementOpcity( htmlElementOpacity , change )
{
  if( isInternetExplorer() )
    return htmlElementOpacity + (change*100);
  return htmlElementOpacity + change;
}

function decreaseHTMLElementOpcity( htmlElementOpacity , change )
{
  if( isInternetExplorer() )
    return htmlElementOpacity - (change*100);
  return htmlElementOpacity - change;
}

function detectScrollingChildDIV( htmlElementID )
{
  htmlElement = document.getElementById( htmlElementID );
  if( htmlElement != null )
  {
    var htmlElementChilds = htmlElement.childNodes;
    
    //
    if( htmlElementChilds != null )
    {
      var firstDivElement = null
      for( var i=0 ; i<htmlElementChilds.length ; i++ )
      {
        if( htmlElementChilds[i].nodeValue != null && htmlElementChilds[i].nodeValue.trim() != "" )
          return null;
        if( htmlElementChilds[i].tagName && htmlElementChilds[i].tagName != null &&
            htmlElementChilds[i].tagName.toLowerCase() == "div" )
        {
          if( firstDivElement == null )
            firstDivElement = htmlElementChilds[i];
          else
            return null;
        }
      }

      return firstDivElement;
    }
  }
  return null;
}

/*
 * Animation functions 
 */

var isnscAnimationThreads = new Array();

var currentRunningThreadID = -1;

function isnscGetNextThreadID()
{
  return currentRunningThreadID + 1;
}

function antimationWorkingThread( runningTheradID )
{
	if( ( currentRunningThreadID == -1 || currentRunningThreadID == runningTheradID )
	    && isnscAnimationThreads != null && isnscAnimationThreads.length != 0 )
	{
	  currentRunningThreadID = runningTheradID;
		if( ISNSC_EFFECTS_DEBUG )
			isnscAlert( "Animating " + isnscAnimationThreads.length + " objects" );
		
		var finishedThreadItemsIndexes = new Array();
		// Loop over thread items and increase or decrease the fading effect on it
		for( var i=0 ; i<isnscAnimationThreads.length ; i++ )
		{
			var threadItem = isnscAnimationThreads[i];
			
			var htmlElement = threadItem[0];
			var animationType = threadItem[1];
			var animationParameter = threadItem[2];
			var otherInfo = threadItem[3];
			
			// Get element properties
			var htmlElementOpacity = getElementOpacity( htmlElement ) ;
			var htmlElementHeight = getElementHeight( htmlElement );
			var htmlElementWidth = getElementWidth( htmlElement );
			isnscAlert( "Element [" + i + "] opacity is: " + htmlElementOpacity );
			
			try
			{
			  // Animating
				if( animationType == "+-" )
				{
	
					if( otherInfo == "+" )
					{
						//increase element opacity
					  htmlElementOpacity = increaseHTMLElementOpcity( htmlElementOpacity , ISNSC_ANIMATION_SHOW_FADING_STEP );
						
						// Check and validate for end of direction
					  if( isMaximumHTMLElementOpacity( htmlElementOpacity ) )
					  {
					    htmlElementOpacity = getMaximumHTMLElementOpacity();
					    threadItem[3] = "-"
					  }
					  //showElement( htmlElement );
					  setElementOpacity( htmlElement , htmlElementOpacity );
					}
					else if( otherInfo == "-" )
					{
						//decrease element opacity
					  htmlElementOpacity = decreaseHTMLElementOpcity( htmlElementOpacity , ISNSC_ANIMATION_HIDE_FADING_STEP );
						
						// Check and validate for end of direction
						if( htmlElementOpacity <= 0 )
						{
						  //hideElement( htmlElement );

						  htmlElementOpacity = 0;
						  threadItem[3] = "+"
						}

						setElementOpacity( htmlElement , htmlElementOpacity );
					}
					else
					{
						// Handle this case
					}
				}
				// Showing
				else if( animationType == "+" )
				{
				  //increase element opacity
				  htmlElementOpacity = increaseHTMLElementOpcity( htmlElementOpacity , ISNSC_ANIMATION_SHOW_FADING_STEP );
          
          // Check and validate for end of direction
          if( isMaximumHTMLElementOpacity( htmlElementOpacity ) )
          {
            htmlElementOpacity = getMaximumHTMLElementOpacity();

            // Mark item to be deleted
            finishedThreadItemsIndexes[finishedThreadItemsIndexes.length] = i;
          }

          showElement( htmlElement );
          setElementOpacity( htmlElement , htmlElementOpacity );
				}
				// Hiding
				else if( animationType == "-" )
				{
				  //decrease element opacity
				  htmlElementOpacity = decreaseHTMLElementOpcity( htmlElementOpacity , ISNSC_ANIMATION_HIDE_FADING_STEP );

          // Check and validate for end of direction
          if( htmlElementOpacity <= 0 )
          {
            htmlElementOpacity = 0;
            hideElement( htmlElement );

            // Mark item to be deleted
            finishedThreadItemsIndexes[finishedThreadItemsIndexes.length] = i;
          }

          setElementOpacity( htmlElement , htmlElementOpacity );
				}
				else if( animationType == "expand" )
				{
				  showElement( htmlElement );
				  //setElementOpacity( htmlElement , getMaximumHTMLElementOpacity() );

				  // expand element width
				  htmlElementWidth = htmlElementWidth + ISNSC_ANIMATION_EXPAND_STEP;
				  
				  if( htmlElementWidth > animationParameter[0] )
				  {
				    htmlElementWidth = animationParameter[0];
				  }

				  // expand element height
				  htmlElementHeight = htmlElementHeight + ISNSC_ANIMATION_EXPAND_STEP;
				  
				  if( htmlElementHeight > animationParameter[1] )
				  {
				    htmlElementHeight = animationParameter[1];
				  }
				  
				  // Set element properties
				  setElementWidth( htmlElement , htmlElementWidth );
				  setElementHeight( htmlElement , htmlElementHeight );
				  
				  if( htmlElementWidth == animationParameter[0] && htmlElementHeight == animationParameter[1] )
				    finishedThreadItemsIndexes[finishedThreadItemsIndexes.length] = i;
				  
				}
				else if( animationType == "collapse" )
				{
				  // collapse element width
          htmlElementWidth = htmlElementWidth - ISNSC_ANIMATION_COLLAPSE_STEP;
          
          if( htmlElementWidth < animationParameter[0] )
          {
            htmlElementWidth = animationParameter[0];
          }
          
          // collapse element height
          htmlElementHeight = htmlElementHeight - ISNSC_ANIMATION_COLLAPSE_STEP;
          
          if( htmlElementHeight < animationParameter[1] )
          {
            htmlElementHeight = animationParameter[1];
          }
          
          if( htmlElementWidth == animationParameter[0] && htmlElementHeight == animationParameter[1] )
          {
            hideElement( htmlElement );
            finishedThreadItemsIndexes[finishedThreadItemsIndexes.length] = i;
          }

          // Set element properties
          setElementWidth( htmlElement , htmlElementWidth );
          setElementHeight( htmlElement , htmlElementHeight );
				}
				else if( animationType == "rollout" )
				{
          var scrollingDivElement = otherInfo[2];
          var scrollingDivLeft = getElementLeft( scrollingDivElement );
          var scrollingDivTop = getElementTop( scrollingDivElement );
          
          showElement( htmlElement );
          //setElementOpacity( htmlElement , getMaximumHTMLElementOpacity() );
          
          
          // Calculate width expansion step
          var expansionStep = ISNSC_ANIMATION_EXPAND_STEP;
          if( animationParameter[0] - htmlElementWidth < ISNSC_ANIMATION_EXPAND_STEP )
            expansionStep = animationParameter[0] - htmlElementWidth;
          // expand element width
          htmlElementWidth = htmlElementWidth + expansionStep;
          scrollingDivLeft = scrollingDivLeft + expansionStep;
          
          // Calculate height expansion step
          expansionStep = ISNSC_ANIMATION_EXPAND_STEP;
          if( animationParameter[1] - htmlElementHeight < ISNSC_ANIMATION_EXPAND_STEP )
            expansionStep = animationParameter[1] - htmlElementHeight;
          // expand element height
          htmlElementHeight = htmlElementHeight + expansionStep;
          scrollingDivTop = scrollingDivTop + expansionStep;
          
          // Set element properties
          setElementWidth( htmlElement , htmlElementWidth );
          setElementHeight( htmlElement , htmlElementHeight );
          setElementLeft( scrollingDivElement , scrollingDivLeft )
          setElementTop( scrollingDivElement , scrollingDivTop )
          
          if( htmlElementWidth == animationParameter[0] && htmlElementHeight == animationParameter[1] )
            finishedThreadItemsIndexes[finishedThreadItemsIndexes.length] = i;
				}
				else if( animationType == "rollin" )
				{
				  var scrollingDivElement = otherInfo[2];
				  var scrollingDivLeft = getElementLeft( scrollingDivElement );
				  var scrollingDivTop = getElementTop( scrollingDivElement );
				  
				  // Calculate width expansion step
				  var expansionStep = ISNSC_ANIMATION_COLLAPSE_STEP;
				  if( htmlElementWidth - animationParameter[0] < ISNSC_ANIMATION_COLLAPSE_STEP )
				    expansionStep = htmlElementWidth - animationParameter[0];
				  // expand element width
				  htmlElementWidth = htmlElementWidth - expansionStep;
				  scrollingDivLeft = scrollingDivLeft - expansionStep;
				  
				  // Calculate height expansion step
				  expansionStep = ISNSC_ANIMATION_COLLAPSE_STEP;
				  if( htmlElementHeight - animationParameter[1] < ISNSC_ANIMATION_COLLAPSE_STEP )
				    expansionStep = htmlElementHeight - animationParameter[1];
				  // expand element height
				  htmlElementHeight = htmlElementHeight - expansionStep;
				  scrollingDivTop = scrollingDivTop - expansionStep;
				  
				  // Set element properties
				  setElementWidth( htmlElement , htmlElementWidth );
				  setElementHeight( htmlElement , htmlElementHeight );
				  setElementLeft( scrollingDivElement , scrollingDivLeft )
				  setElementTop( scrollingDivElement , scrollingDivTop )
				  
				  if( htmlElementWidth == animationParameter[0] && htmlElementHeight == animationParameter[1] )
				  {
				    hideElement( htmlElement );
				    finishedThreadItemsIndexes[finishedThreadItemsIndexes.length] = i;
				  }
				}
				
			}
			catch( e )
			{
				isnscAlert( e );
			}
		}

		for( var j=finishedThreadItemsIndexes.length-1 ; j>=0 ; j-- )
		{
		  isnscAnimationThreads.splice( finishedThreadItemsIndexes[j] , 1 );
		}
		
		if( isnscAnimationThreads.length == 0 )
		  currentRunningThreadID = -1;
		else
		  setTimeout( "antimationWorkingThread( " + runningTheradID + " )" , ISNSC_ANIMATION_SETP_TIMEOUT_MILLIS );
	}
}

function isnscAdjustHTMLElement( htmlElementID , parentElement , alignment )
{
  if( parentElement && parentElement != null )
  {
    if( typeof( alignment ) == "undefined" || alignment == null )
      alignment = ISNSC_ALIGNMENT_BOTTOM_LEFT;
      
    var htmlElement = document.getElementById( htmlElementID );

    // TODO generalize code to work on all browsers
    var currentElement = parentElement;
    var calculatedTop = 0;
    var calculatedLeft = 0;
    
    if( alignment == ISNSC_ALIGNMENT_BOTTOM_LEFT || alignment == ISNSC_ALIGNMENT_BOTTOM_RIGHT )
      calculatedTop = parentElement.offsetHeight;
    
    if( alignment == ISNSC_ALIGNMENT_BOTTOM_RIGHT || alignment == ISNSC_ALIGNMENT_TOP_RIGHT )
      calculatedLeft = parentElement.offsetWidth;
    
    while( currentElement )
    {
      if( currentElement.offsetTop )
      {
        calculatedTop = calculatedTop + currentElement.offsetTop - getElementTop( currentElement );
      }
      
      if( currentElement.offsetLeft )
      {
        calculatedLeft = calculatedLeft + currentElement.offsetLeft - getElementLeft( currentElement );
      }

      currentElement = currentElement.offsetParent;
    }

    setElementTop( htmlElement , calculatedTop );
    
    if( alignment == ISNSC_ALIGNMENT_BOTTOM_RIGHT )
      setElementRight( htmlElement , document.body.offsetWidth - calculatedLeft);
    else
      setElementLeft( htmlElement , calculatedLeft );
  }
}

function isAnimationConflict( animationThreadItem , animationType )
{
  if( animationThreadItem != null && typeof( animationThreadItem ) == "object" )
  {
    // If the two animations of the same type
    if( animationThreadItem[1] == animationType )
      return true;
    
    // Fade in : Fade out : Flicker 
    if( ( animationThreadItem[1] == "+" || animationThreadItem[1] == "-" || animationThreadItem[1] == "+-" ) &&
        ( animationType == "+" || animationType == "-" || animationType == "+-" ) )
      return true;
    
    // Expand : Collapse : Rollin : Rollout
    if( ( animationThreadItem[1] == "expand" || animationThreadItem[1] == "collapse" || animationThreadItem[1] == "rollout" || animationThreadItem[1] == "rollin" )
        &&
        ( animationType == "expand" || animationType == "collapse" || animationType == "rollout" || animationType == "rollin" ) )
      return true;
  }
  return false;
}

function isnscAnimateElement( htmlElementID , animationType , animationParameter , otherInfo)
{
	if( ISNSC_EFFECTS_DEBUG )
		isnscAlert( "Starting to animate " + htmlElementID );

	var htmlElement = document.getElementById( htmlElementID );
	
	if( htmlElement != null )
	{
	  
	  var threadItem = null;
	  for( var i=0 ; i<isnscAnimationThreads.length ; i++ )
	  {
	    if( isnscAnimationThreads[i][0] == htmlElement && isAnimationConflict( isnscAnimationThreads[i] , animationType ) )
	    {
	      threadItem = isnscAnimationThreads[i];
	      break;
	    }
	  }

	  var newItemCreated = false;

	  // Create a thread item ( element , animation type + or - , animation parameter , other-info )
	  if( threadItem == null )
	  {
	    newItemCreated = true;
	    threadItem = new Array();
	    isnscAnimationThreads[isnscAnimationThreads.length] = threadItem;
	  }
	  
  	threadItem[0] = htmlElement;
  	threadItem[1] = animationType;
  	threadItem[2] = animationParameter;
  	threadItem[3] = otherInfo;
  	
  	if( newItemCreated )
  	  antimationWorkingThread( isnscGetNextThreadID() );
	}
}

function isnscFlickerElement( htmlElementID )
{
  isnscAnimateElement( htmlElementID , "+-" , null  , "-" );
}

function isnscShowElement( htmlElementID , parentElement , alignmenet )
{
  isnscAdjustHTMLElement( htmlElementID , parentElement , alignmenet );
  isnscAnimateElement( htmlElementID , "+" , 1 , null );
}

function isnscHideElement( htmlElementID )
{
  isnscAnimateElement( htmlElementID , "-" , 0 , null );
}

function isnscExpandElement( htmlElementID , parentElement , targetWidth , targetHeight , horizontalDirection , verticalDirection )
{
  isnscAdjustHTMLElement( htmlElementID , parentElement );

  if( typeof( horizontalDirection ) == "undefined" )
    horizontalDirection = ISNSC_DIRECTION_RIGHT;
  if( typeof( verticalDirection ) == "undefined" )
    verticalDirection = ISNSC_DIRECTION_DOWN;
  isnscAnimateElement( htmlElementID , "expand" , [targetWidth,targetHeight] ,
      [horizontalDirection,verticalDirection] );
}

function isnscCollapseElement( htmlElementID , targetWidth , targetHeight , horizontalDirection , verticalDirection )
{
  if( typeof( targetWidth ) == "undefined" )
    targetWidth = 0;
  if( typeof( targetHeight ) == "undefined" )
    targetHeight = 0;
  
  if( typeof( horizontalDirection ) == "undefined" )
    horizontalDirection = ISNSC_DIRECTION_LEFT;
  if( typeof( verticalDirection ) == "undefined" )
    verticalDirection = ISNSC_DIRECTION_UP;

  isnscAnimateElement( htmlElementID , "collapse" , [targetWidth,targetHeight] ,
      [horizontalDirection,verticalDirection] );
}

function isnscRollOutElement( htmlElementID , parentElement , targetWidth , targetHeight , horizontalDirection , verticalDirection )
{
  isnscAdjustHTMLElement( htmlElementID , parentElement );

  // Determine scrolling div
  var scrollingDIV = detectScrollingChildDIV( htmlElementID );
  
  
  if( typeof( horizontalDirection ) == "undefined" )
    horizontalDirection = ISNSC_DIRECTION_RIGHT;
  if( typeof( verticalDirection ) == "undefined" )
    verticalDirection = ISNSC_DIRECTION_DOWN;
  
  if( scrollingDIV == null )
  {
    isnscAnimateElement( htmlElementID , "expand" , [targetWidth,targetHeight] ,
        [horizontalDirection,verticalDirection] );
  }
  else
  {
    isnscAnimateElement( htmlElementID , "rollout" , [targetWidth,targetHeight] ,
        [horizontalDirection,verticalDirection,scrollingDIV] );
  }
}

function isnscRollInElement( htmlElementID , targetWidth , targetHeight , horizontalDirection , verticalDirection )
{
  // Determine scrolling div
  var scrollingDIV = detectScrollingChildDIV( htmlElementID );

  if( typeof( targetWidth ) == "undefined" )
    targetWidth = 0;
  if( typeof( targetHeight ) == "undefined" )
    targetHeight = 0;
  
  if( typeof( horizontalDirection ) == "undefined" )
    horizontalDirection = ISNSC_DIRECTION_LEFT;
  if( typeof( verticalDirection ) == "undefined" )
    verticalDirection = ISNSC_DIRECTION_UP;
  
  if( scrollingDIV == null )
  {
    isnscAnimateElement( htmlElementID , "collapse" , [targetWidth,targetHeight] ,
        [horizontalDirection,verticalDirection] );
  }
  else
  {
    isnscAnimateElement( htmlElementID , "rollin" , [targetWidth,targetHeight] ,
        [horizontalDirection,verticalDirection,scrollingDIV] );
  }
}

/*
 * Detect browser type
 */
isnscDetectBrowser();

/*
 * 0 - Internet Explorer
 * 1 - Firefox
 * 2 - Netscape
 * 3 - Opera
 * 4 - Safari
 * 5 - Chrome
 * 6 - Other (Symbian, IPhone)
 */