/*--------------------------------------------------------------------------
 File      : grid.js
 Summary   : AJAX grid implementation
 Programmer: Sorin Vinatoru

 Revisions :	yyyy-mm-dd	sign		comment
				2006-04-01	sorin		created
				2006-05-01	gabriel		IE compatibility
				2006-06-27	sorin		added options for footer display (has prev, next, last, pageno)
				2006-07-25	gabriel		removed footer in case of: "Page 1 of 1" with option 'FooterWhenNeeded' set to 'true'
				2006-11-15	sorin		converted from XML to JSON

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 to do list
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 Copyright (C) Abroad Software SRL
 Developed by Abroad Software
 --------------------------------------------------------------------------*/
var AbScript =
{
  Version: '0.0.2',
  prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1])
}

function IsFunction(a)
{
    return typeof a == 'function';
}

//extend prototype AJAX object
Ajax.Request.prototype.SetObject = function(AnObject) { this.RefObject = AnObject };
Ajax.Request.prototype.GetObject = function() { return this.RefObject };

AbScript.AbGrid = Class.create();

AbScript.AbGrid.prototype =
{
	initialize: function (TableId, Options)
	{
		eval('Var' + TableId + '=this');

		this.IsIE = navigator.userAgent.toLowerCase().indexOf("msie") >= 0;

		this.Table = $(TableId);
		this.Rows = new Array();


		this.Options = {
			HasHeader: true,
			HasFooter: false,
			FooterWhenNeeded: false,		// If there is only one page "Page 1 of 1 " the footer is not displayed when set to true
			SortAscendImg: 'img/sort_asc.gif',
			SortDescendImg: 'img/sort_desc.gif',
			SortImageWidth: 9,
			SortImageHeight: 5,
			SortURLParms: [],
			TableClass: $(TableId).className,
			OddClass: '',
			EvenClass: '',
			FooterClass: '',
			FooterAClass: '',
			ColumnPrefixClass: '',
			PageScript: '',
			RowsPerPage: 3,
			CallBack: null,
			GlobalCallback: null,
			HasPrev: true,
			HasNext: true,
			HasLast: true,
			HasFirst: true,
			PrevText: 'Prev',
			NextText: 'Next',
			LastText: 'Last',
			FirstText: 'First',
			HasPageNo: true,
			DisableFirstUse: false
		};

		Object.extend(this.Options, Options || {});

		this.CurrentPage = 0;

		//compute and save rows collection with start and end row
		this.TableRows = this.Table.rows;

		this.SortColumn = '';
		this.SortDir = '';

		this.ResetTable();
		if (this.Options.DisableFirstUse)
			this.Options.DisableFirstUse = false;
		else
			this.PopulateTable(this.CurrentPage);

		this.FooterRow = this.TableRows[this.TableRows.length - 1];
	},

	ComputeRowStart: function()
	{
		return this.Options.HasHeader ? 1 : 0;
	},

	ComputeRowEnd: function()
	{
		if (this.Options.HasFooter)
			return this.Options.HasHeader ? 2 : 1;
		else
			return this.Options.HasHeader ? 1 : 0;
	},

	ComputeTableLength: function()
	{
		return this.TableRows.length;
	},

	ResetTable: function ()
	{
		//empty table contents
		var DelRow = this.ComputeRowStart();

		while (this.TableRows.length < (this.ComputeRowEnd() - this.ComputeRowStart()))
			this.Table.deleteRow(DelRow);

		//hook sort columns
		if (this.Options.HasHeader)
		{
			for (var i = 0; i < this.Options.Columns.length; i++)
			{
				if ((this.Options.Columns[i][0] != 'ignore') && (this.Options.Columns[i][1] == true))
				{
					this.TableRows[0].cells[i].setAttribute('SortColumn', this.Options.Columns[i][0]);
					this.TableRows[0].cells[i].setAttribute('SortDir', 'ASC');
					this.TableRows[0].cells[i].setAttribute('TableId', this.Table.id);
					this.TableRows[0].cells[i].style.cursor = 'pointer';
					this.TableRows[0].cells[i].onclick = this.HandleClick;
				}
			}
		}
	},

	HandleClick: function(event)
	{
		// IE doesn't pass event into the parameter
	    if ( !event )
	        event = window.event;

	    // IE doesn't have the property "target".
	    // Use "srcElement" instead.
	    // Not 100% the same, but works in most simple cases
	    var Target = event.target ? event.target : event.srcElement;

		var ParentObj = eval('Var' + Target.attributes['TableId'].value);
		ParentObj.SortColumn = Target.attributes['SortColumn'].value;
		ParentObj.SortDir = Target.attributes['SortDir'].value;
		ParentObj.CurrentPage = 0; //always start from first page when sorting
		ParentObj.PopulateTable(ParentObj.CurrentPage);

		if (Target.attributes['SortDir'].value == 'ASC')
			Target.setAttribute('SortDir', 'DESC');
		else
			Target.setAttribute('SortDir', 'ASC');
	},

	PopulateTable: function(PageNo)
	{
		var PageParams = 'Start=' + (PageNo * this.Options.RowsPerPage ) + '&Rows=' + this.Options.RowsPerPage;
		if (this.SortColumn != '')
		{
			PageParams += '&Sort=' + this.SortColumn;
			if (this.SortDir == 'ASC')
				PageParams += '&Dir=ASC';
			else
				PageParams += '&Dir=DESC';
		}

		if ($('Progress'))
		{
			$('Progress').style.visibility = 'visible';
		}
		var AjaxRequest = new Ajax.Request(this.Options.PageScript, {method: 'get', parameters: PageParams, onSuccess: this.HandlePopulateTable.bindAsEventListener(this)});
	},

	HandlePopulateTable: function(OriginalRequest, AjaxRequest)
	{
		if (!OriginalRequest)
			return;

		// User can set an onFailure option - which will be called by prototype
		if (OriginalRequest.status != 200)
			return;

		var ParentObj = this;

		eval("Response = " + OriginalRequest.responseText);

		if (Response == null)
			return;

		var DelRow = ParentObj.ComputeRowStart();

		var PageLength = Response.Rows.length;

		if (ParentObj.Options.HasFooter)
			PageLength++;
		if (ParentObj.Options.HasHeader)
			PageLength++;

		while (parseInt(PageLength) < ParentObj.ComputeTableLength())
			ParentObj.Table.deleteRow(DelRow);

		//iterate rows
		var RowIndex = ParentObj.ComputeRowStart();
		var Rows = Response.Rows;

		for ( var i = 0 ; i < Rows.length ; i++ )
		{
			var RowElement = Rows[i];

			var AbsoluteRowIndex = RowIndex;
			if (ParentObj.Options.HasHeader)
				AbsoluteRowIndex++;
			if (ParentObj.Options.HasFooter)
				AbsoluteRowIndex++;

			if (AbsoluteRowIndex > ParentObj.ComputeTableLength())
				NewRow = ParentObj.Table.insertRow(RowIndex);
			else
				NewRow = ParentObj.TableRows[RowIndex];

			var ColIndex = 0;

			for ( var j = 0; j < RowElement.length; j++ )
			{
				var ColElement = RowElement[j];

				if (NewRow.cells.length <= ColIndex)
					NewRow.insertCell(-1);

				if ((ColElement != null) && (ColElement.toString().trim() != '' ) && (ColElement.toString().trim() != 'NULL' ))
					NewRow.cells[ColIndex].innerHTML = ColElement.toString();
				else
					NewRow.cells[ColIndex].innerHTML = '&nbsp;';

				var ColumnClass = '';
				if (ParentObj.Options.ColumnPrefixClass != '')
					ColumnClass = ParentObj.Options.ColumnPrefixClass + ColIndex;

				if ((RowIndex % 2) == 0)
				{
					if (ParentObj.Options.EvenClass != '')
					{
						if (ColumnClass != '')
							NewRow.cells[ColIndex].className = ParentObj.Options.EvenClass + ' ' + ColumnClass;
						else
							NewRow.cells[ColIndex].className = ParentObj.Options.EvenClass;
					}
					else
					{
						if (ColumnClass != '')
							NewRow.cells[ColIndex].className = ColumnClass;
					}
				}
				else
				{
					if (ParentObj.Options.OddClass != '')
					{
						if (ColumnClass != '')
							NewRow.cells[ColIndex].className = ParentObj.Options.OddClass + ' ' + ColumnClass;
						else
							NewRow.cells[ColIndex].className = ParentObj.Options.OddClass;
					}
					else
					{
						if (ColumnClass != '')
							NewRow.cells[ColIndex].className = ColumnClass;
					}
				}

				ColIndex++;
			}

			if (IsFunction(ParentObj.Options.CallBack))
			{
				(ParentObj.Options.CallBack)(NewRow, Response, i);
			}

			RowIndex++;
		}
		ParentObj.HandlePopulateFooter(ParentObj, Response.TotalRows);

		if (IsFunction(ParentObj.Options.GlobalCallBack))
		{
			(ParentObj.Options.GlobalCallBack)(ParentObj, Response);
		}
	},

	AppendAnchor: function(ParentObj, Parent, Href, InnerHtml, Page, OnClick)
	{
		var Anch = document.createElement('a');
		Anch.href = Href;
		Anch.innerHTML = InnerHtml;
		Anch.setAttribute('Page', Page);
		Anch.setAttribute('TableId', ParentObj.Table.id);
		Parent.appendChild(Anch);
		Anch.onclick = ParentObj.HandlePage;

		if (ParentObj.Options.FooterAClass != '')
			Anch.className = ParentObj.Options.FooterAClass;

		ParentObj.AppendLabel(Parent, '&nbsp;');
	},

	AppendLabel: function(Parent, InnerHtml)
	{
		var Label = document.createElement('label');
		Label.innerHTML = InnerHtml;
		Parent.appendChild(Label);
	},

	AppendImage: function(Parent, ImageSource)
	{
		var Img = document.createElement('img');
		Img.src = ImageSource;
		Parent.appendChild(Img);
	},

	HandlePopulateFooter: function(ParentObj, TotalRows)
	{
		if (!ParentObj.Options.HasFooter)
			return;

		var MaxPages = Math.ceil(TotalRows / ParentObj.Options.RowsPerPage) - 1;

		// If this is page 1 of 1 don't display the footer at all
		if( (MaxPages <= 0) && ParentObj.Options.FooterWhenNeeded)
			return;

		if (ParentObj.Options.FooterClass != '')
			ParentObj.FooterRow.cells[0].className = ParentObj.Options.FooterClass;

		ParentObj.FooterRow.cells[0].innerHTML = '';
		if ($('Progress'))
		{
			$('Progress').style.visibility = 'hidden';
		}

		if (ParentObj.CurrentPage > 0)
		{
			if (ParentObj.Options.HasFirst)
				ParentObj.AppendAnchor(ParentObj, ParentObj.FooterRow.cells[0], '#', '[<< ' + ParentObj.Options.FirstText + ']', '0', ParentObj.HandlePage);
			if (ParentObj.Options.HasPrev)
				ParentObj.AppendAnchor(ParentObj, ParentObj.FooterRow.cells[0], '#', '[< ' + ParentObj.Options.PrevText + ']', parseInt(ParentObj.CurrentPage) - 1, ParentObj.HandlePage);
		}
		else
		{
			if (ParentObj.Options.HasFirst)
				ParentObj.AppendLabel(ParentObj.FooterRow.cells[0], '[<< ' + ParentObj.Options.FirstText + ']&nbsp;');
			if (ParentObj.Options.HasPrev)
				ParentObj.AppendLabel(ParentObj.FooterRow.cells[0], '[< ' + ParentObj.Options.PrevText + ']&nbsp;');
		}

		if (ParentObj.Options.HasPageNo)
			ParentObj.AppendLabel(ParentObj.FooterRow.cells[0], (parseInt(ParentObj.CurrentPage) + 1) + ' / ' + (parseInt(MaxPages) + 1) + '&nbsp;');

		if (ParentObj.CurrentPage < MaxPages)
		{
			if (ParentObj.Options.HasNext)
				ParentObj.AppendAnchor(ParentObj, ParentObj.FooterRow.cells[0], '#', '[' + ParentObj.Options.NextText + '>]', parseInt(ParentObj.CurrentPage) + 1, ParentObj.HandlePage);
			if (ParentObj.Options.HasLast)
				ParentObj.AppendAnchor(ParentObj, ParentObj.FooterRow.cells[0], '#', '[' + ParentObj.Options.LastText + '>>]', MaxPages, ParentObj.HandlePage);
		}
		else
		{
			if (ParentObj.Options.HasNext)
				ParentObj.AppendLabel(ParentObj.FooterRow.cells[0], '[' + ParentObj.Options.NextText + ' >]&nbsp;');
			if (ParentObj.Options.HasLast)
				ParentObj.AppendLabel(ParentObj.FooterRow.cells[0], '[' + ParentObj.Options.LastText + ' >>]&nbsp;');
		}

	},

	HandlePage: function(event)
	{
		// IE doesn't pass event into the parameter
	    if ( !event )
	        event = window.event;

		// IE doesn't have the property "target".
	    // Use "srcElement" instead.
	    // Not 100% the same, but works in most simple cases
	    var Target = event.target ? event.target : event.srcElement;

		var ParentObj = eval('Var' + Target.attributes['TableId'].value);

		ParentObj.CurrentPage = Target.attributes['Page'].value;
		ParentObj.PopulateTable(ParentObj.CurrentPage);

		return false;
	},

	Reload: function()
	{
		this.PopulateTable(this.CurrentPage);
	}
}
