//list_control.class.js

var s_listControlHash;
s_listControlHash = new CHash();

function FindListControl( strBlockId)
{
	return s_listControlHash.Item( strBlockId);
}

function CListControl( strBlockId, bVisible, bFixedPosition)
{
	// What is rasion for these var declaration?
  //var m_strBlockId;
  //var m_nLineId;
  //var m_strNextFunction;
  //var m_strPreviousFunction;
  //var m_bPreviousExists;
  //var m_bNextExists;
  //var m_block;
  //var m_ul;
  //var m_nMaxLineId;
  //var m_insideDiv;
  //var m_strOnSelectFunction;
  //var m_focusKeeper;
  //var m_bBlockButtons;
  //var m_timeOut;
  //var m_hashSelectedLines;
  //var m_nPixelsForLineVisible;
	////var m_nInnerBlockHeight;
  
  this.m_nMaxLineId = 0;
  this.m_strBlockId = strBlockId;
  this.m_strNextFunction = '';
  this.m_strPreviousFunction = '';
  this.m_bPreviousExists = false;
  this.m_bNextExists = false;
  this.m_nActiveLineId = -1;
  this.m_block = document.getElementById( this.m_strBlockId);
  this.m_ul = null;
  this.m_insideDiv = null;
  this.m_bMousePressed = false;
  this.m_strOnSelectFunction = '';
  this.m_focusKeeper = null;
  this.m_bBlockButtons = false;
  //this.m_hashSelectedLines = new CIdHash();
  this.m_hashSelectedLines = new CHash();
  this.m_nPixelsForLineVisible = 10;
	//this.m_nInnerBlockHeight = 0;
	this.m_bSingleSelection = false

	this.m_strDblClickFunction = false;
	this.m_strReturnFunction = false;

	this.m_bVisible = false;
	this.m_bFixedPosition = false;

	this.m_nScrollTopPosition = -1;

	this.IsSingleSelection = function()
	{
		return this.m_bSingleSelection;
	}

	this.SetSingleSelection = function( bIs)
	{
		this.m_bSingleSelection = bIs;
	}

	this.IsFixedPosition = function()
	{
		return this.m_bFixedPosition;
	}

	this.IsVisible = function()
	{
		return this.m_bVisible;
	}

	this.SetVisible = function()
	{
		this.m_bVisible = true;
		this.m_block.style.display = 'block';
		this.ResizeInnerDiv();
		this.CreateFocusKeeper();
		this.ShowState();
		if ( this.m_nScrollTopPosition >= 0)
			this.m_insideDiv.scrollTop = this.m_nScrollTopPosition;
	}

	this.SetNotVisible = function()
	{
		this.m_bVisible = false;
		this.m_nScrollTopPosition = this.m_insideDiv.scrollTop;
		this.m_block.style.display = 'none';
	}

	this.GetScrollTopPosition = function()
	{
		var nPosition = this.m_nScrollTopPosition;
		if ( this.IsVisible())
		{
			nPosition = this.m_insideDiv.scrollTop;
		}
		return nPosition;
	}

	this.SetScrollTopPosition = function( nScrollTopPosition)
	{
		this.m_nScrollTopPosition = nScrollTopPosition;
		if ( this.IsVisible())
		{
			this.m_insideDiv.scrollTop = nScrollTopPosition;
		}
	}

   
  this.Init = function( bVisible, bFixedPosition)
  {
		this.m_bVisible = bVisible;

		if ( !IsOldIE())
			this.m_bFixedPosition = bFixedPosition;

    var nInnerDivLength; 
    var nInnerDivHeight;
    
    this.m_insideDiv = document.createElement( 'div');
    this.m_bMousePressed = false;
    
    //if ( window.opera )  
    //{
    //  this.m_focusKeeper = document.createElement( 'textarea');
    //  this.m_focusKeeper.setAttribute( 'rows', 0);
    //  this.m_focusKeeper.setAttribute( 'cols', 0);
    //}
    //else
    //{
    //  this.m_focusKeeper = document.createElement( 'input');
    //  this.m_focusKeeper.setAttribute( 'type', 'text');
    //}
    
    this.ResizeInnerDiv();
     
    if ( document.all && ( ! window.opera))
    {
      //Dumb IE
      this.m_insideDiv.attachEvent( 'onclick',  ListControlIEFocusElement);
      this.m_insideDiv.attachEvent( 'onmouseout',  ListControlIEMouseOut);
      //this.m_focusKeeper.attachEvent( 'onkeydown',  ListControlIEKeyDown);
      //this.m_focusKeeper.attachEvent( 'onkeyup',  ListControlIEKeyUp);
     }
    else
    {
      this.m_insideDiv.setAttribute( 'onmouseout', 'ListControlNotIEMouseOut( "'+this.m_strBlockId+'", event)');
      //this.m_focusKeeper.setAttribute( 'onkeyup', 'ListControlKeyUp( "' +this.m_strBlockId+'"); return false;');
      //if ( window.opera || ( navigator.platform != 'Win32'))
      //{
      //  this.m_focusKeeper.setAttribute( 'onkeypress', 'ListControlKeyPressed( "' +this.m_strBlockId+'", event); return false;');
      //}
      //else
      //{
      //  this.m_focusKeeper.setAttribute( 'onkeydown', 'ListControlKeyPressed( "' +this.m_strBlockId+'", event); return false;');
      //}
    }
    
    this.m_block.appendChild( this.m_insideDiv);
		this.CreateFocusKeeper();

		//var arInnerBlockPostion = FindPosition( this.m_insideDiv, false);

    //this.m_focusKeeper.style.position = 'absolute';
    //this.m_focusKeeper.style.left = arInnerBlockPostion[ 0]+'px';
    //this.m_focusKeeper.style.top = arInnerBlockPostion[ 1]+'px';
    //this.m_focusKeeper.className = 'list_control_keeper';
    //this.m_block.appendChild( this.m_focusKeeper);
  }

	this.CreateFocusKeeper = function()
	{
		if ( this.m_focusKeeper)
		{
		}
		else
		if ( this.IsVisible())
		{
			if ( IsOldOpera() || IsChrome())  
			{
				this.m_focusKeeper = document.createElement( 'textarea');
				this.m_focusKeeper.setAttribute( 'rows', 0);
				this.m_focusKeeper.setAttribute( 'cols', 0);
			}
			else
			{
				this.m_focusKeeper = document.createElement( 'input');
				this.m_focusKeeper.setAttribute( 'type', 'text');
			}

			if ( document.all && ( ! window.opera))
			{
				//Dumb IE
				this.m_focusKeeper.attachEvent( 'onkeydown',  ListControlIEKeyDown);
				this.m_focusKeeper.attachEvent( 'onkeyup',  ListControlIEKeyUp);
			 }
			else
			{
				this.m_focusKeeper.setAttribute( 'onkeyup', 'ListControlKeyUp( "' +this.m_strBlockId+'"); return false;');
				if ( window.opera || ( navigator.platform != 'Win32'))
				{
					this.m_focusKeeper.setAttribute( 'onkeypress', 'ListControlKeyPressed( "' +this.m_strBlockId+'", event); return false;');
				}
				else
				{
					this.m_focusKeeper.setAttribute( 'onkeydown', 'ListControlKeyPressed( "' +this.m_strBlockId+'", event); return false;');
				}
			}

			var arInnerBlockPostion = FindPosition( this.m_insideDiv, false);

			if (this.IsFixedPosition())
				this.m_focusKeeper.style.position = 'fixed';
			else
				this.m_focusKeeper.style.position = 'absolute';
			this.m_focusKeeper.style.left = arInnerBlockPostion[ 0] + 'px';
			
			var nTopOffsetFocusKeeper = 0;
			if ( window.opera)
				nTopOffsetFocusKeeper = 10;

			this.m_focusKeeper.style.top = nTopOffsetFocusKeeper + arInnerBlockPostion[ 1] + 'px';
			this.m_focusKeeper.className = 'list_control_keeper';

			//if ( document.all && ( ! window.opera))
				this.m_block.parentNode.insertBefore( this.m_focusKeeper, this.m_block);
			//else
			//	this.m_block.appendChild( this.m_focusKeeper);
		}
	}

	this.SetOnDblClickFunction = function( strDblClickFunction)
	{
		this.m_strDblClickFunction = strDblClickFunction;
	}
	this.SetOnReturnFunction = function( strReturnFunction)
	{
		this.m_strReturnFunction = strReturnFunction;
	}

	this.OnDblClick = function()
	{
		if ( this.m_strDblClickFunction)
		{
			eval( this.m_strDblClickFunction+"( '"+this.m_strBlockId+"')");
		}
	}
	this.OnReturn = function()
	{
		//alert( 'OnReturn');
		if ( this.m_strReturnFunction)
		{
			eval( this.m_strReturnFunction+"( '"+this.m_strBlockId+"')");
		}
	}
  
  this.ListSize = function()
  {
    return this.m_nMaxLineId;
  }
    
  this.SetOnSelectFunction = function( strFunction)
  {
     this.m_strOnSelectFunction = strFunction;
  }
	this.OnSelect = function()
	{
		if ( this.m_strOnSelectFunction)
			eval( this.m_strOnSelectFunction);
	}
  
  this.ResizeInnerDiv = function()
  {
		var ieBug;
		try
		{
			//if ( this.m_nInnerBlockHeight > 0 )
			//{
			//	this.m_insideDiv.style.height = this.m_nInnerBlockHeight + 'px';  
			//}
			//else
			//{
				if ( this.IsVisible())
					this.m_insideDiv.style.height =  this.m_block.offsetHeight - 2 + 'px';  
			//}	
		}
		catch ( ieBug)
		{

		}
  }

	//this.SetInnerBlockHeight = function( nInnerBlockHeight)
	//{
	//	////Should be called only if "ResizeInnerDiv" unable to determine this size automatically
	//	//this.m_nInnerBlockHeight = nInnerBlockHeight;
	//  //this.ResizeInnerDiv();
	//}
  
  this.CreateUl = function()
  {
    var elements = this.m_insideDiv.getElementsByTagName( 'ul');
    if ( elements.length > 0)
    {
      this.m_insideDiv.removeChild( elements[ 0]);
    }
       
    this.m_ul = document.createElement( 'ul'); 
    this.m_ul.setAttribute( 'id', 'ul_' + this.m_strBlockId);
    this.m_insideDiv.appendChild( this.m_ul);
    if ( ! document.all)
    {
      this.m_ul.setAttribute( 'style', '-moz-user-select: none;');
    }
		this.m_nMaxLineId = 0;
		this.m_bPreviousExists = false;
		this.m_bNextExists = false;
  }

	this.ClearControl = function()
  {
    var arElements = this.m_ul.childNodes;
    var nLength = this.m_ul.childNodes.length;
    var i;
    
    for ( i = 0; i < nLength; i++)
    {
      this.m_ul.removeChild( this.m_ul.childNodes[ 0]);
    }
		this.m_nMaxLineId = 0;
		this.m_bPreviousExists = false;
		this.m_bNextExists = false;
  }
  
  this.AddNext = function( strFunction)
  {
    var ul = this.m_ul;
    var li = document.createElement( 'li');
    li.setAttribute( 'class', 'arrow_href');
    if ( document.all && ( ! window.opera))
    {
     li.attachEvent( 'onclick', ListControlIENextFunction);
    }
    else
    {
      li.setAttribute( 'onclick', strFunction + '; return false;');
    }
    
    li.innerHTML = ' &darr; Next &darr; ';
    
    if ( window.opera)
    {
      li.setAttribute( 'onfocus', 'ListControlOperaFocusBug( "'+this.m_strBlockId+'", event);' );
    }
    
    li.setAttribute( 'id', this.GetLiId( this.m_nMaxLineId));
    
    ul.appendChild( li);
    this.m_bNextExists = true;
    this.m_strNextFunction = strFunction;
  }

	this.CallNext = function()
	{
		if ( this.m_bNextExists)
			eval( this.m_strNextFunction);
	}

  
  this.AddPrevious = function( strFunction)
  {
    var ul = this.m_ul;
    var li = document.createElement( 'li');
    li.setAttribute( 'class', 'arrow_href');
    if ( document.all && ( ! window.opera))
    {
     li.attachEvent( 'onclick', ListControlIEPreviousFunction);
    }
    else
    {
      li.setAttribute( 'onclick', strFunction + '; return false;');
    }
    li.setAttribute( 'id', this.GetLiId( '-1'));
    li.innerHTML = ' &uarr; Previous &uarr; ';
    if ( window.opera)
    {
      li.setAttribute( 'onfocus', 'ListControlOperaFocusBug( "'+this.m_strBlockId+'", event);' );
    }
    ul.insertBefore( li, ul.getElementsByTagName( 'li')[ 0]);
    this.m_strPreviousFunction = strFunction;
    this.m_bPreviousExists = true;
  }

	this.CallPrevious = function()
	{
		if ( this.m_bPreviousExists)
			eval( this.m_strPreviousFunction);
	}
  
  
  this.AddLine = function( strKey, strValue)
  {
    var li = document.createElement( 'li');
    var input = document.createElement( 'input');
    
    li.setAttribute( 'id', this.GetLiId( this.m_nMaxLineId));
    
    li.innerHTML = strValue;
    
    input.setAttribute( 'type', 'hidden');
    input.setAttribute( 'name', this.m_strBlockId + '_hiddens[ ' + strKey + ']');
    input.setAttribute( 'id',  this.GetHiddenId( this.m_nMaxLineId));
    input.setAttribute( 'value', 0);
    
    if ( document.all && ( ! window.opera))
    {
      //Dumb IE
      //li.attachEvent( 'onclick',  ListControlIELineClicked);
      li.attachEvent( 'onselectstart', ListControlIEDisableSelect);
      li.attachEvent( 'onmouseover',  ListControlIEMouseOver);
      li.attachEvent( 'onmousedown',  ListControlIEMouseDown);
      li.attachEvent( 'onmouseup',  ListControlIEMouseUp);
      li.attachEvent( 'ondblclick',  ListControlIEDblClick);
    }
    else
    {
      //li.setAttribute( 'onclick', 'ListControlLineClicked( "'+this.m_strBlockId+'", '+this.m_nMaxLineId+', event)' );
      li.setAttribute( 'onmouseover', 'ListControlMouseOver( "'+this.m_strBlockId+'", '+this.m_nMaxLineId+', event)');
      li.setAttribute( 'onmousedown',  'ListControlMouseDown( "'+this.m_strBlockId+'", '+this.m_nMaxLineId+', event)');
      li.setAttribute( 'onmouseup',  'ListControlMouseUp( "'+this.m_strBlockId+'")');
      li.setAttribute( 'ondblclick', 'ListControlDblClick( "' +this.m_strBlockId+'")');
    }
    
    //Dumb Opera bug work-around
    if ( window.opera)
    {
      li.setAttribute( 'onfocus', 'ListControlOperaFocusBug( "'+this.m_strBlockId+'", event); return false;' );
      li.setAttribute( 'onkeyup', 'ListControlKeyUp( "'+this.m_strBlockId+'"); ListControlFocusElement( "'+this.m_strBlockId+'"); return false;');
    }
    
    li.appendChild( input);
    
    
    this.m_ul.appendChild( li);
 
    this.m_nMaxLineId++;
  }
  
  this.LineClicked = function( nLineId, event)
  {
    var bSelectLine = true;
    if ( event.ctrlKey || event.metaKey)
    {
      if ( this.m_hashSelectedLines.Item( nLineId)) // don't use IsLineSelected() here
      {
        bSelectLine = false;
      }
    }
    else if ( event.shiftKey)
    {
      this.SelectSlice( nLineId);
    }
    else
    {
      this.UnselectAll();
    }
    if ( bSelectLine)
    {
      this.SelectLine( nLineId);
    }
    else
    {
      this.UnselectLine( nLineId);
    }
    this.ActivateLine( nLineId);
    this.ShowState();
  }
  
  this.SelectSlice = function( nLineId)
  {
    var i;
    var nActiveLineId = parseInt( this.m_nActiveLineId);
    nLineId = parseInt( nLineId);
    
    if ( nActiveLineId == -1)
    {
     return false; 
    }
    
    if ( parseInt( nLineId) > parseInt( nActiveLineId))
    {
      
      for ( i = nLineId; i > nActiveLineId; i--)
      {
        this.SelectLine( i);
      }
    }
    else if ( parseInt( nLineId) < parseInt( nActiveLineId))
    {
      
      for ( i = nLineId; i < nActiveLineId; i++)
      {
        this.SelectLine( i);
      }
    }
		return true;
  }
  
  this.SelectLine = function( nLineId)
  {
		if ( !this.IsSingleSelection())
		{
			//alert( 'SelectLine( '+nLineId+')');
			//this.m_hashSelectedLines.Mem( nLineId);
			this.m_hashSelectedLines.Set( nLineId, true);
			this.OnSelect();
			//eval( this.m_strOnSelectFunction);
		}
  }

	this.IsLineSelected = function( nLineId)
	{
		var bSelected = false;
		if ( this.IsSingleSelection())
		{
			if ( nLineId == this.m_nActiveLineId)
				bSelected = true;
		}
		else
		{
			if ( this.m_hashSelectedLines.Item( nLineId))
				bSelected = true;
		}
		return bSelected;
	}

  this.GetActiveLine = function()
	{
		return this.m_nActiveLineId;
	}

  this.ActivateLine = function( nLineId)
  {
		//alert( 'ActivateLine( '+nLineId+')');
    this.m_bBlockButtons = false;
    this.m_nActiveLineId = parseInt( nLineId);
		if ( this.IsSingleSelection())
		{
			this.OnSelect();
			//eval( this.m_strOnSelectFunction);
		}
  }
  
  this.UnselectLine = function( nLineId)
  {
		if ( !this.IsSingleSelection())
		{
			//this.m_hashSelectedLines.Remove( nLineId);
			this.m_hashSelectedLines.Del( nLineId);
			{
				this.OnSelect();
				//eval( this.m_strOnSelectFunction);
			}
		}
  }
  
  this.UnselectAll = function()
  {
		if ( !this.IsSingleSelection())
		{
			//this.m_hashSelectedLines = new CIdHash();
			this.m_hashSelectedLines.Clear();
			this.OnSelect();
			//eval( this.m_strOnSelectFunction);
		}
  }
  
  this.ShowState = function( bNoScrollBlock)
  {
    var i;
    //var classNames = new CMultipleClassNames( );
    
    for ( i = 0; i < this.m_nMaxLineId; i++)
    {
			var itemLi = GetIdItem( this.GetLiId( i));
			if ( itemLi)
			{
				var idHashClassName = FillMultiNameIdHash( GetClassName( itemLi));
				//classNames.Load( this.GetLiId( i));  
				if ( this.m_nActiveLineId == i)
				{
					idHashClassName.Mem( 'active');
					//classNames.Mem( 'active');
				}
				else
				{
					idHashClassName.Remove( 'active');
					//classNames.Remove( 'active');
				}
				
				if ( this.IsLineSelected( i))
				{
					idHashClassName.Mem( 'selected');
					//classNames.Mem( 'selected');
					document.getElementById( this.GetHiddenId( i)).value = 1;
				}
				else
				{
					idHashClassName.Remove( 'selected');
					//classNames.Remove( 'selected');
					document.getElementById( this.GetHiddenId( i)).value = 0;
				}
				SetClassName( itemLi, idHashClassName.Value());
			}
      
      //classNames.Save();
    }
		if ( !bNoScrollBlock)
	    this.ScrollBlock();
  }
    
  this.GetHiddenId = function( nLineId)
  {
    return 'hidden_' + this.m_strBlockId + '_' + nLineId;
  }
  
  this.GetLiId = function( nLineId)
  {
    return 'li_' + this.m_strBlockId + '_N_' + nLineId;
  }
  
  this.KeyPressed = function( event)
  {
    if ( !this.m_bBlockButtons)
    {
			var nEventCode = event.keyCode;
			
			var nLineId;
			var nNextLine;
				
			var nUp = 38;
			var nDown = 40;
			var nPgUp = 33;
			var nPgDown = 34;
			// Safary has different value for these codes
			//alert( 'Code = '+nEventCode);
			
			nCurrentLineId = this.m_nActiveLineId;
			
			var bNavigationKey = true;
			switch ( nEventCode)
			{
				case 63232:
				case nUp:
				{
					nNextLine = this.GetLineUp();
					break;
				}
				case 63233:
				case nDown:
				{
					nNextLine = this.GetLineDown();
					break;
				}
				case 63276:
				case nPgUp:
				{
					nNextLine = this.GetPageUp();
					break;
				}
				case 63277:
				case nPgDown:
				{
					nNextLine = this.GetPageDown();
					break;
				}
				default :
				{
					bNavigationKey = false;
				}
			}

			if ( bNavigationKey)
			{
				if ( nNextLine >= this.m_nMaxLineId )
				{
					if ( this.m_bNextExists)
					{
						nNextLine = this.m_nMaxLineId;
						//alert( 'Next: nCurrentLineId = '+nCurrentLineId+' nNextLine = '+nNextLine);
						if ( nCurrentLineId < nNextLine)
							this.CallNext();
							//eval( this.m_strNextFunction);
						//return false;    
					}
					else
					{
						nNextLine = ( this.m_nMaxLineId - 1);
					}
				}
				
				if ( nNextLine <= -1 )
				{
					if ( this.m_bPreviousExists)
					{
						nNextLine = -1;
						//alert( 'Prev: nCurrentLineId = '+nCurrentLineId+' nNextLine = '+nNextLine);
						if ( nCurrentLineId > nNextLine)
							this.CallPrevious();
							//eval( this.m_strPreviousFunction);
						//return false;    
					}
					else
					{
						nNextLine = 0;
					}
				}
				
				if ( event.shiftKey)
				{
					this.SelectSlice( nNextLine);
				}
				else if ( event.ctrlKey || event.metaKey)
				{
					//Do nothing
				}
				else
				{
					 this.UnselectAll();
					 this.SelectLine( nNextLine);
				}
					
				this.ActivateLine( nNextLine);
				this.ShowState();
			}
			else
			{
				if ( nEventCode == 13)
				{
					this.OnReturn();
				}
			}
		}
    return false;
  }
  
	this.GoToLine = function( nLineIndex, bSetForcus)
	{
		if ( nLineIndex < 0)
			nLineIndex = this.m_nMaxLineId -1;
		this.ActivateLine( nLineIndex);
		this.SelectLine( nLineIndex);
		this.ShowState();
		this.ScrollBlock();
		if ( bSetForcus)
			this.SetFocus();
	}

	this.GoToFirstElement = function()
  {
		this.GoToLine( 0, true);
  }
  
  this.GoToLastElement = function()
  {
		this.GoToLine( -1, true);
  }
 
  this.OperaFocusBug = function( event)
  {
    this.SetFocus();
    this.KeyPressed( event);
    
  }

	this.ScrollBlock = function()
  {
    var nBlockTop = TopPosition( this.m_insideDiv) + this.m_insideDiv.scrollTop;
    var nBlockHeight = this.m_insideDiv.offsetHeight;
    var nBlockBottom = ( nBlockTop + nBlockHeight);

    if( this.m_insideDiv.scrollHeight <= this.m_insideDiv.offsetHeight)
    {
      //If there is no scroll..
      return false;
    }
    
    //Dumb opera fix
    this.m_nActiveLineId = parseInt( this.m_nActiveLineId);
    
    var nNearnessToNeibor = 1;
    var topNeibor = document.getElementById( this.GetLiId( this.m_nActiveLineId - nNearnessToNeibor));
    var bottomNeibor = document.getElementById( this.GetLiId( this.m_nActiveLineId + nNearnessToNeibor));
    
    if ( topNeibor)
    {
      var nTopNeiborTop = TopPosition( topNeibor);
      var nTopNeiborHeight = topNeibor.offsetHeight;
      var nTopNeiborBottom = ( nTopNeiborTop + nTopNeiborHeight);
    }
    
    
    if ( bottomNeibor)
    {
      var nBottomNeiborTop = TopPosition( bottomNeibor);
      var nBottomNeiborHeight = bottomNeibor.offsetHeight;
      var nBottomNeiborBottom = ( nBottomNeiborTop + nBottomNeiborHeight);
    }
    
    if (( topNeibor) && ( ( nTopNeiborTop + this.m_nPixelsForLineVisible) < nBlockTop ))
    {
      this.m_insideDiv.scrollTop = ( nTopNeiborBottom - TopPosition( this.m_insideDiv));
    }
    else if ( ! topNeibor)
    {
      this.m_insideDiv.scrollTop = 0;
    }
    
    if (( bottomNeibor) && ( ( nBottomNeiborTop + this.m_nPixelsForLineVisible) > nBlockBottom ))
    {
      this.m_insideDiv.scrollTop = (nBottomNeiborTop -  nBlockHeight - TopPosition( this.m_insideDiv));
    }
    else if ( ! bottomNeibor)
    {
      this.m_insideDiv.scrollTop = TopPosition( this.m_ul) + this.m_ul.offsetHeight;
    }
		return true;
  }
  
  this.SelectAll = function()
  {
     var i;
     for ( i = 0; i < this.m_nMaxLineId; i++)  
     {
       this.SelectLine( i);
     }
     this.ShowState();
  }
  
  this.GetFirstElementNum = function( bShowLast)
  {
    var i;
    var nLineId;
    var nTop = TopPosition( this.m_insideDiv) + this.m_insideDiv.scrollTop;
    var nCurrent = this.m_nActiveLineId;
    for ( i = 1; i < this.m_nMaxLineId; i++)
    {
      var element = document.getElementById( this.GetLiId( i));
      if ( TopPosition( element) > nTop)
      { 
        nLineId = i;
        break;
      }
    }
    if (( nLineId >= this.m_nActiveLineId) || ( bShowLast))
    {
      if ( ! this.m_bNextExists)
      {
        return 0;
      }
      else
      {
        return -1;
      }
    }
    return nLineId;
  }
  
  this.GetLineUp = function()
  {
  	return ( this.m_nActiveLineId - 1);
  }
  
  this.GetLineDown = function()
  {
  	return ( this.m_nActiveLineId + 1);
  }
  
  this.GetPageUp = function()
  {
  	 //Scrolling to make current line at the bottom
    this.ScrollToElementBottom( document.getElementById( this.GetLiId( this.m_nActiveLineId)));
    return this.GetTopLineId();
  }
    
  this.GetPageDown = function()
  {
  	//Scrolling to make current line at the top
  	this.ScrollToElementTop( document.getElementById( this.GetLiId( this.m_nActiveLineId)));
  	return this.GetBottomLineId();
  }
   
   this.GetTopLineId = function()
   {
    //return top element id
    var i;
    var nBlockTop = (TopPosition( this.m_insideDiv) + this.m_insideDiv.scrollTop - this.m_nPixelsForLineVisible);
    for ( i = this.GetMinLineIdForLoops(); i < this.m_nMaxLineId; i++ )
    {
    	var element = document.getElementById( this.GetLiId( i));
    	if ((TopPosition( element)) >= nBlockTop)
    	{
    		break;
    	}
    }
    return i;
   }
   
   
   this.GetBottomLineId = function()
   {
      var i;
      var nBlockBottomLine = (parseInt( TopPosition( this.m_insideDiv)) + this.m_insideDiv.offsetHeight + this.m_insideDiv.scrollTop - this.m_nPixelsForLineVisible);
      
      for ( i = this.GetMaxLineIdForLoops(); i > 0; i--)
      {
        var element = document.getElementById( this.GetLiId( i));
        if ( (TopPosition( element)) <= nBlockBottomLine)
        {
         break;
        }
      }
      return i;
   }
  
  this.ScrollToElementBottom = function ( element)
  {
  	var nDivOffsetBottom = TopPosition( this.m_insideDiv) + this.m_insideDiv.offsetHeight;
    var nCurrentScroll = this.m_insideDiv.scrollTop;
    var i;
    
    for ( i = nCurrentScroll; i > 0; i--)
    {
    	this.m_insideDiv.scrollTop = i;
      if (( TopPosition( element) + element.offsetHeight) >= ( nDivOffsetBottom + i))
      {
      	break;
      }
    }
  }
   
  this.ScrollToElementTop = function ( element)
  {
    var nDivOffset = TopPosition( this.m_insideDiv);
    var nElementOffset = TopPosition( element);
    this.m_insideDiv.scrollTop = ( nElementOffset - nDivOffset);
  }
  
  this.GetMaxLineIdForLoops = function()
  {
  	if ( this.m_bNextExists)
  	{
  		return this.m_nMaxLineId;
  	}
  	else
  	{
  		return (this.m_nMaxLineId - 1);
  	}
  }
  
  this.GetMinLineIdForLoops = function()
  {
  	if ( this.m_bPreviousExists)
  	{
  		return -1;
  	}
  	else
  	{
  		return 0;
  	}
  }
  
  this.GetListOfSelectedItems = function( bFullInfo)
  {
    var arData;
    var arResult;
    var reg = /^(.+)<input[^>]+>$/i;
    var arReturn = new Array();
    
    var list = this.m_ul.getElementsByTagName( 'input');
    
    for ( i = 0; i < list.length; i++)
    {
      if ( list[ i].getAttribute( 'value') == 1)
      {
        if ( bFullInfo)
        {
          arData = new Array();
          arData[ 'key'] = this.GetKeyByLineId( i);
          arResult = reg.exec( document.getElementById( this.GetLiId( i)).innerHTML);
          arData[ 'value'] = arResult[ 1];
          arReturn.push( arData); 
        }
        else
        {
          arReturn.push( this.GetKeyByLineId( i)); 
        }
      }
    }
    return arReturn;
  }
  
 this.GetKeyByLineId = function( nLineId)
  {
    var reg = /_hiddens\[ (.+)\]/i;
    var arResult = reg.exec( document.getElementById( this.GetHiddenId( nLineId)).getAttribute( 'name'));
    return arResult[ 1];
  }
  
  this.MouseMovedOver = function( nLineId)
  {
    if ( this.m_bMousePressed)
    {
     this.SelectSlice( nLineId);
     this.ShowState();
    }
  }
  
  this.SetFocus = function()
  {
		if ( this.IsVisible())
		{
			this.m_focusKeeper.focus();
			return true;
		}
		return false;
  }
  
  this.MouseOut = function ( element, x, y)
  {
    if ( element == this.m_insideDiv)
    {
       this.m_bMousePressed = false;
    }
		else
		if ( !this.IsOverInsideDiv( x, y))
		{
      this.m_bMousePressed = false;
		}
  }

	this.IsOverInsideDiv = function( x, y)
	{
		var bOver = false;
		var arPos = FindPosition( this.m_insideDiv, !this.IsFixedPosition());
		var nLeftReserv = 5;
		var nRightReserv = 0;
		var nTopReserv = 5;
		var nBottomReserv = 1;
		if ( arPos[0] + nLeftReserv < x)
		if ( arPos[0] + this.m_insideDiv.offsetWidth - nRightReserv > x)
		if ( arPos[1] + nTopReserv < y)
		if ( arPos[1] + this.m_insideDiv.offsetHeight - nBottomReserv > y)
		{
			bOver = true;
		}
		return bOver;
	}
  
  this.MousePressed = function( nLineId, event)
  {
   this.m_bMousePressed = true; 
   this.LineClicked( nLineId, event);
  }
  
  this.MouseReleased = function()
  {
   this.SetFocus();
   this.m_bMousePressed = false; 
  }
  
  this.KeyUp = function()
  {
    /*if ( this.m_strOnSelectFunction != '')
    {
      eval( this.m_strOnSelectFunction);
    }
    */
  }
  
  this.Init( bVisible, bFixedPosition);
  s_listControlHash.Set( this.m_strBlockId, this);
  this.CreateUl();
}

//Wrappers
function ListControlKeyPressed( strBlockId, event)
{
  var listControl = FindListControl( strBlockId);
  if ( window.opera)
  {
    listControl.SetFocus();
  }
  listControl.KeyPressed( event);
}

function ListControlLineClicked(  strBlockId, nLineId, event)
{
  var listControl = FindListControl( strBlockId);
  listControl.LineClicked( nLineId, event)
}

function ListControlKeyUp( strBlockId)
{
  var listControl = FindListControl( strBlockId);
  listControl.KeyUp();
}


function ListControlMouseOver( strBlockId, nLineId, event)
{
  var listControl = FindListControl( strBlockId);
  listControl.MouseMovedOver( nLineId);
}

function ListControlMouseUp( strBlockId)
{
  var listControl = FindListControl( strBlockId);
  listControl.MouseReleased();
  listControl.KeyUp();
}

function ListControlMouseDown(  strBlockId, nLineId, event)
{
  var listControl = FindListControl( strBlockId);
  listControl.MousePressed(  nLineId, event);
}

function ListControlFocusElement( strBlockId)
{
  var listControl = FindListControl( strBlockId);
  listControl.SetFocus();
}



//IE wrappers
function ListControlIsIdPrefix( obj, strPrefix)
{
	var bIs = false;
	if ( obj)
	if ( obj.getAttribute)
	{
		var strId = obj.getAttribute( 'id');
		if ( strId)
		{
			if ( strId.substring( 0, strPrefix.length) == strPrefix)
				bIs = true;
		}
	}
	return bIs;
}

function ListControlIeGetLiId( obj)
{
  //while ( obj.getAttribute( 'id').substring(0, 3) != 'li_')
	while ( !ListControlIsIdPrefix( obj, 'li_'))
  {
    obj = obj.parentElement;
    if ( obj.parentElement == null)
    {
     return false;
    }
  }
  return obj.getAttribute( 'id');
}

function ListControlIeGetBlockId( obj)
{
  var classes;
  while ( obj.parentNode != null)
  {
    classes = obj.className.split( ' ');
    if ( classes)
    {
      var i;
      for ( i = 0; i < classes.length; i++)
      {
        if ( classes[ i] == 'list_control')
        {
          return obj.getAttribute( 'id');
        }
      }
    }
    obj = obj.parentNode;
  }
  return '';
}



function ListControlIEFocusElement( event)
{
	var strBlockId = ListControlIeGetBlockId( event.srcElement);
  ListControlFocusElement( strBlockId);
}

function ListControlIEKeyDown( event)
{
  //var strBlockId = event.srcElement.parentElement.getAttribute( 'id');
  var strBlockId = event.srcElement.nextSibling.getAttribute( 'id');
	ListControlKeyPressed( strBlockId, event);
  return false;
}

function ListControlIEKeyUp( event)
{
  //var strBlockId = event.srcElement.parentElement.getAttribute( 'id');
  var strBlockId = event.srcElement.nextSibling.getAttribute( 'id');
  ListControlKeyUp( strBlockId);
}

function ListControlIELineClicked( event)
{
  var strBlockId = ListControlIeGetLiId( event.srcElement);
  var arRes = ListControlGetDataById( strBlockId);
  
  ListControlLineClicked(  arRes[ 1], arRes[ 2], event);
  
}

function ListControlIEPreviousFunction( event)
{
  var strBlockId = event.srcElement.parentElement.parentElement.parentElement.getAttribute( 'id');
  var listControl = FindListControl( strBlockId);
	listControl.CallPrevious();
  //if ( listControl.m_bPreviousExists)
  //{
  //  eval( listControl.m_strPreviousFunction);
  //}
}

function ListControlIENextFunction( event)
{ 
  var strBlockId = event.srcElement.parentElement.parentElement.parentElement.getAttribute( 'id');
  var listControl = FindListControl( strBlockId);
	listControl.CallNext();
  //if ( listControl.m_bNextExists)
  //{
  //  eval( listControl.m_strNextFunction);
  //}
}

function ListControlIEDisableSelect()
{
  return false;
}

function ListControlIEMouseOut( event)
{
  var listControl = FindListControl( ListControlIeGetBlockId( event.srcElement));
  listControl.MouseOut( event.srcElement, event.clientX, event.clientY);
}

function ListControlIEMouseOver( event)
{
  var arResult = ListControlGetDataById( ListControlIeGetLiId( event.srcElement));
  var nLineId = arResult[ 2];
  var strBlockId = ListControlIeGetBlockId( event.srcElement);
  
  ListControlMouseOver( strBlockId, nLineId);
}

function ListControlIEMouseDown( event)
{
  var li = document.getElementById( ListControlIeGetLiId( event.srcElement));
  var strBlockId = li.parentElement.parentElement.parentElement.getAttribute( 'id');
  var arResult = ListControlGetDataById( li.getAttribute( 'id'));
  var nLineId = arResult[ 2];
  
  ListControlMouseDown(  strBlockId, nLineId, event);
}

function ListControlIEMouseUp( event)
{
  var strBlockId = ListControlIeGetBlockId( event.srcElement);
  ListControlMouseUp( strBlockId);
}

function ListControlGetDataById( strId)
{
  var reg = /^li_(.+)_N_(\d+)$/i;
  var arRes = reg.exec( strId);
  return arRes;
}

function ListControlNotIEMouseOut( strBlockId, event)
{
  var listControl = FindListControl( strBlockId);
  listControl.MouseOut( event.target, event.clientX, event.clientY);
}

//Opera bugs

function ListControlOperaFocusBug( strBlockId, event)
{
  var listControl = FindListControl( strBlockId);
  listControl.OperaFocusBug( event);
}


// Additional events
function ListControlIEDblClick( event)
{
  var strBlockId = ListControlIeGetBlockId( event.srcElement);
  ListControlDblClick( strBlockId);
}

function ListControlDblClick( strBlockId)
{
	var listControl = FindListControl( strBlockId);
	listControl.OnDblClick();
}

function ListControlSetFocus( strBlockId)
{
	var listControl = FindListControl( strBlockId);
	if ( listControl)
		return listControl.SetFocus();
	return false;
}
