Forms = 
{
	NeedCheck: function (Form)
	{
		if(Forms.GetHidden(Form, '__NoCheck') )
		{
			if(Forms.GetHidden(Form, '__NoCheck').val() == 1)
			{
				return false;
			}
		}
		return true;
	}
	,
	NeedUniqueCheck: function (Form)
	{
		if(Forms.GetHidden(Form, '__NoUniqueCheck') )
		{
			if(Forms.GetHidden(Form, '__NoUniqueCheck').val() == 1)
			{
				return false;
			}
		}
		return true;
	}
	,
	FillHidden: function(Form, Name, Value) 
	{
		$('form#' + Form + ' #' + Name + '.field[type=hidden]').val(Value);
	}
	, 
	FillHiddens: function(Form, Hiddens) 
	{
		for (var i in Hiddens)
		{
			Forms.FillHidden(Form, i, Hiddens[i]);
		}
	}
	, 
	GetElement: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name);
	}
	, 
	GetHidden: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name + '.field[type=hidden]');
	}
	, 
	GetField: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name + '.field[type!=hidden]');
	}
	, 
	GetFieldRow: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name + 'Row');
	}
	, 
	GetFieldNameContainer: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name + 'NameContainer');
	}
	, 
	GetFieldRequiredContainer: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name + 'RequiredContainer');
	}
	, 
	GetFieldCommentContainer: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name + 'CommentContainer');
	}
	, 
	GetFieldInputContainer: function(Form, Name) 
	{
		return $('form#' + Form + ' #' + Name + 'InputContainer');
	}
	, 
	GetButton: function(Form, Name) 
	{
		return $('form#' + Form + ' input#' + Name + '.button');
	}
	, 
	ShowTab: function(Form, Name)
	{
		$('form#' + Form + ' tr.field_row[tab!=' + Name + '][hidden!=hidden]').hide();
		$('form#' + Form + ' tr.field_row[tab=' + Name + '][hidden!=hidden]').show();
		
		$('form#' + Form + ' a[tab!=' + Name + ']').removeClass('active');
		$('form#' + Form + ' a[tab=' + Name + ']').addClass('active');
		
		Forms.ColorFields(Form);
	}
	, 
	SimpleShowTab: function(Form, Name)
	{
		$('form#' + Form + ' tr.field_row[tab!=' + Name + '][hidden!=hidden]').hide();
		$('form#' + Form + ' tr.field_row[tab=' + Name + '][hidden!=hidden]').show();
		
		$('form#' + Form + ' tr#btnRow input[tab!=' + Name + ']').hide();
		$('form#' + Form + ' tr#btnRow input[tab=' + Name + ']').show();
	}
	,
	SwitchTab: function(Form, Name)
	{
		Forms.ShowTab(Form, Forms.GetFieldRow(Form, Name).attr('tab'));
	}
	, 
	ColorFields: function(Form)
	{
		$('form#' + Form + ' tr.field_row:visible:odd').removeClass('form_odd');
		$('form#' + Form + ' tr.field_row:visible:odd').addClass('form_even');
		
		$('form#' + Form + ' tr.field_row:visible:even').removeClass('form_even');
		$('form#' + Form + ' tr.field_row:visible:even').addClass('form_odd');
	}
	, 
	HideField: function(Form, Name) 
	{
		Forms.GetFieldRow(Form, Name).hide();
		Forms.GetFieldRow(Form, Name).attr('hidden', 'hidden');
	}
	, 
	HideFields: function(Form, Fields) 
	{
		for (var i in Fields)
		{
			Forms.HideField(Form, Fields[i]);
		}
		
		Forms.ColorFields(Form);
	}
	, 
	ShowField: function(Form, Name) 
	{
		Forms.GetFieldRow(Form, Name).show();
		Forms.GetFieldRow(Form, Name).attr('hidden');
	}
	, 
	ShowFields: function(Form, Fields) 
	{
		for (var i in Fields)
		{
			Forms.ShowField(Form, Fields[i]);
		}
		
		Forms.ColorFields(Form);
	}
	, 
	FillField: function(Form, Name, Value) 
	{
		if (Forms.GetField(Form, Name).attr('type') == 'checkbox')
		{
			Forms.GetField(Form, Name).attr('checked', Value);
		}
		else
		{
			Forms.GetField(Form, Name).val(Value);
		}
	}
	, 
	FillFields: function(Form, Fields) 
	{
		for (var i in Fields)
		{
			Forms.FillField(Form, i, Fields[i]);
		}
	}
	, 
	DisableField: function(Form, Name) 
	{
		Forms.GetField(Form, Name).attr('disabled', true);
	}
	, 
	DisableFields: function(Form, Fields)
	{
		if (Fields)
		{
			for (var i in Fields)
			{
				Forms.DisableField(Form, Fields[i]);
			}
		}
		else
		{
			$('form#' + Form + ' .field[type!=hidden]').attr('disabled', true);
		}
	}
	, 
	DisableFieldSaveState: function(Form, Name) 
	{
		Forms.GetField(Form, Name).attr('was_disabled', Forms.GetField(Form, Name).attr('disabled') );
		Forms.GetField(Form, Name).attr('disabled', true);
	}
	, 
	DisableFieldsSaveState: function(Form, Fields)
	{
		if (Fields)
		{
			for (var i in Fields)
			{
				Forms.DisableFieldSaveState(Form, Fields[i]);
			}
		}
		else
		{
			$('form#' + Form + ' .field[type!=hidden]').each(function(){
				$(this).attr('was_disabled', $(this).attr('disabled') );
				$(this).attr('disabled', true);
			});
		}
	}
	, 
	EnableField: function(Form, Name) 
	{
		Forms.GetField(Form, Name).attr('disabled', false);
	}
	, 
	EnableFields: function(Form, Fields) 
	{
		if (Fields)
		{
			for (var i in Fields)
			{
				Forms.EnableField(Form, Fields[i]);
			}
		}
		else
		{
			$('form#' + Form + ' .field[type!=hidden]').attr('disabled', false);
		}
	}
	,
	EnableFieldRestoreState: function(Form, Name) 
	{
		if( Forms.GetField(Form, Name).attr('was_disabled') == 'false' )
		{
			Forms.GetField(Form, Name).attr('disabled', false);
		}
		else
		{
			Forms.GetField(Form, Name).attr('disabled', true);
		}
		Forms.GetField(Form, Name).removeAttr('was_disabled');
	}
	, 
	EnableFieldsRestoreState: function(Form, Fields) 
	{
		if (Fields)
		{
			for (var i in Fields)
			{
				Forms.EnableFieldRestoreState(Form, Fields[i]);
			}
		}
		else
		{
			$('form#' + Form + ' .field[type!=hidden]').each(function(){
				if($(this).attr('was_disabled') == 'false')
				{
					$(this).attr('disabled', false );
				}
				else
				{
					$(this).attr('disabled', true );
				}
				$(this).removeAttr('was_disabled');
			});
		}
	}
	, 
	RequireField: function(Form, Name) 
	{
		Forms.GetField(Form, Name).attr('required', 'required');
		Forms.GetFieldRequiredContainer(Form, Name).html('*');
	}
	, 
	RequireFields: function(Form, Fields) 
	{
		for (var i in Fields)
		{
			Forms.RequireField(Form, Fields[i]);
		}
	}
	, 
	UnRequireField: function(Form, Name) 
	{
		Forms.GetField(Form, Name).removeAttr('required');
		Forms.GetFieldRequiredContainer(Form, Name).html('');
	}
	, 
	UnRequireFields: function(Form, Fields) 
	{
		for (var i in Fields)
		{
			Forms.UnRequireField(Form, Fields[i]);
		}
	}
	, 
	ReadonlyField: function(Form, Name) 
	{
		Forms.GetField(Form, Name).attr('readonly', 'readonly');
		Forms.GetField(Form, Name).addClass('readonly');
	}
	, 
	ReadonlyFields: function(Form, Fields) 
	{
		for (var i in Fields)
		{
			Forms.ReadonlyField(Form, Fields[i]);
		}
	}
	, 
	UnReadonlyField: function(Form, Name) 
	{
		Forms.GetField(Form, Name).removeAttr('readonly');
		Forms.GetField(Form, Name).removeClass('readonly');
	}
	, 
	UnReadonlyFields: function(Form, Fields) 
	{
		for (var i in Fields)
		{
			Forms.UnReadonlyField(Form, Fields[i]);
		}
	}
	, 
	DisableButtons: function(Form) 
	{
		$('form#' + Form + ' input.button').attr('disabled', true);
	}
	,
	EnableButtons: function(Form) 
	{
		$('form#' + Form + ' input.button').attr('disabled', false);
	}
	, 
	SaveReturnValue: function(Form, Return) 
	{
		if (Return != null)
		{
			ReturnValue = $('form#' + Form + ' #Return').val();
			
			$('form#' + Form + ' #Return').val(Return);
		}
	}
	, 
	RestoreReturnValue: function(Form, ReturnValue) 
	{
		if (ReturnValue != null)
		{
			$('form#' + Form + ' #Return').val(ReturnValue);
		}
	}
	, 
	ValidateField: function(Form, Name, Type) 
	{
		if (Type == 'email')
		{
			return Forms.ValidEmail(Forms.GetField(Form, Name).val());
		}
		if (Type == 'password')
		{
			return Forms.ValidPassword(Forms.GetField(Form, Name).val());
		}
		if (Type == 'file')
		{
			return Forms.ValidFileExt(Forms.GetField(Form, Name).val(), Forms.GetField(Form, Name).attr('exts'));
		}
		
		return true;
	}
	, 
	ValidEmail: function(Email)
	{
		var reg = /^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/;

		return reg.test(Email);
	}
	,
	ValidPassword: function(Password)
	{
		var reg = /^([a-zA-Z0-9]*)$/;
		return ( (reg.test(Password)) && (Password.length > 5) );
	}
	, 
	ValidFileExt: function(FileName, SerializedExts)
	{
		if(SerializedExts)
		{
			arExts = SerializedExts.split('|');
			ext = ZFile.GetExt(FileName);
			return ZArray.InArray(arExts, ext);
		}

		return true;
	}
	, 
	ReplaceField: function(Form, Name) // Замена шаблонных вставок в значении поля
	{
		var reg = /{Form\.(\w+)}/g;

		Forms.GetField(Form, Name).val(Forms.GetHidden(Form, Name + 'Cache').val().replace(reg, function(value, $1){ 
			return Forms.GetField(Form, $1).val();
		}));
	}	
	, 
	ReplaceFields: function(Form, Fields) // Замена шаблонных вставок в значениях полей
	{
		for (var i in Fields)
		{         
			Forms.ReplaceField(Form, Fields[i]);
		}
	}	
	,
	CheckRequired: function(Form) // Проверка заполненности обязательных полей формы
	{
		var ErrorCount = 0;
		
		$('form#' + Form + ' .field[type!=hidden][required]').each(function(i){
			if ($(this).val() == '') 
			{
				if (!ErrorCount)
				{
					Forms.SwitchTab(Form, $(this).attr('name'));
				}
				
				$(this).addClass('error');
				
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});	
		
		$('form#' + Form + ' .textarea[required]').each(function(i){
			if ($(this).val() == '') 
			{
				if (!ErrorCount)
				{
					Forms.SwitchTab(Form, $(this).attr('name'));
				}
				
				$(this).addClass('error');
				
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});	
		
		return ErrorCount;
	}
	, 
	SimpleCheckRequired: function(Form) // Проверка заполненности обязательных полей формы
	{
		var ErrorCount = 0;
		
		$('form#' + Form + ' input[type!=hidden][required]').each(function(i){
			if ($(this).val() == '') 
			{
				$(this).addClass('error');
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});	

		$('form#' + Form + ' textarea[required]').each(function(i){
			if ($(this).val() == '') 
			{
				$(this).addClass('error');
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});	
		
		return ErrorCount;
	}
	,
	SimpleCheckTabRequired: function(Form, Tab) // Проверка заполненности обязательных полей формы
	{
		var ErrorCount = 0;
		
		$('form#' + Form + ' tr.field_row[tab='+Tab+'] input[type!=hidden][required]').each(function(i){
			if ($(this).val() == '') 
			{
				$(this).addClass('error');
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});	

		$('form#' + Form + ' tr.field_row[tab='+Tab+'] textarea[required]').each(function(i){
			if ($(this).val() == '') 
			{
				$(this).addClass('error');
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});	
		
		return ErrorCount;
	}
	, 
	CheckValid: function(Form) // Валидация заполнения полей формы
	{
		var ErrorCount = 0;
		
		$('form#' + Form + ' .field[type!=hidden][validate][validate!=]').each(function(i){
			if ($(this).val() && !Forms.ValidateField(Form, this.id, $(this).attr('validate'))) 
			{
				if (!ErrorCount)
				{
					Forms.SwitchTab(Form, $(this).attr('name'));
				}
				
				$(this).addClass('error');
				
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});
		
		return ErrorCount;
	}
	, 
	SimpleCheckValid: function(Form) // Валидация заполнения полей формы
	{
		var ErrorCount = 0;
		$('form#' + Form + ' input[type!=hidden][validate][validate!=]').each(function(i){
			if ($(this).val() && !Forms.ValidateField(Form, this.id, $(this).attr('validate'))) 
			{
				$(this).addClass('error');
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});
		
		return ErrorCount;
	}
	, 
	SimpleCheckTabValid: function(Form, Tab) // Валидация заполнения полей формы
	{
		var ErrorCount = 0;
		$('form#' + Form + ' tr.field_row[tab='+Tab+'] input[type!=hidden][validate][validate!=]').each(function(i){
			if ($(this).val() && !Forms.ValidateField(Form, this.id, $(this).attr('validate'))) 
			{
				$(this).addClass('error');
				ErrorCount++;
			} 
			else 
			{
				$(this).removeClass('error');
			}
		});
		
		return ErrorCount;
	}
	,
	Serialize: function(Form) // Сериализация значений сложных полей формы
	{
		$('form#' + Form + ' .field.selectextended').each(function(i){
			$(this).attr('multiple', 'multiple');
			$(this).selectOptions(/./);
			Forms.FillHidden(Form, this.id + 'Serialized', $(this).serialize());
		});
	}
	, 
	CheckUnique: function(Form, Submit, PostCode) // Проверка уникльности заполнения полей
	{
		var Field, BeanID;
		Field = $('form#' + Form + ' .field[type!=hidden][unique=unique][disabled!=disabled]:first');
		
		// when copiing we need to check uniqueness for new bean
		if(ActionName == 'Copy')
		{
			BeanID = 0;
		}
		else
		{
			BeanID = $('form#' + Form + ' #' + ControllerName + 'ID').size() ? $('form#' + Form + ' #' + ControllerName + 'ID').val() : 0;
		}

		$.AJAX('Main/Unique', {
			'Type': ControllerName, 
			'ID': BeanID, 
			'Name': Field.attr('id'), 
			'Value': Field.val()
		},
		function (result, errors)
		{
			if (result)
			{
				if (result.Unique == 1)
				{
					if (PostCode)
					{
						eval(PostCode);
					}
					
					if (Submit)
					{
						Forms.SubmitForm(Form);
					}
				}
				else
				{
					//if (!ErrorCount)
					//{
						Forms.SwitchTab(Form, Field.attr('name'));
					//}
				
					Field.addClass('error');
					
					alert('Некоторые поля в форме должны содержать уникальные значения (то есть в базе данных не должно быть объектов с таким же значением этого поля). Измените, пожалуйста, значения всех полей, подсвеченных красным цветом.');
					
					Forms.RestoreReturnValue(Form, Return);
					Forms.EnableButtons(Form); 
				}
			}
			
			Forms.RestoreReturnValue(Form);
		});
	}
	, 
	SubmitForm: function(Form, Confirm, Action) // Отправка формы
	{
		if (Confirm)
		{
			if (!confirm('Вы уверены, что хотите совершить выбранное действие?')) 
			{
				return;
			}
		}
		
		if (Action)
		{
			$('form#' + Form + ':first').attr('action', Action);
		}

		$('form#' + Form + ':first').submit();
	}
	, 
	CheckForm: function(Form, Return, Submit, PreCode, PostCode) // Полная проверка заполнения формы
	{
		// if form marked as unchecked - no checks, just submit
		var CheckNeeded = Forms.NeedCheck(Form);
		// should we check uniqueness (for filters - we shouldn't)
		var UniqueCheckNeeded = Forms.NeedUniqueCheck(Form);
		
		Forms.DisableButtons(Form);
		Forms.SaveReturnValue(Form, Return);

		if (PreCode)
		{
			eval(PreCode);
		}
		
		if(CheckNeeded)
		{
			var ErrorCount = 0;
		
			ErrorCount = Forms.CheckRequired(Form);
		
			if (ErrorCount)
			{
				alert('Не все обязательные поля в форме заполнены. Заполните, пожалуйста, все поля, подсвеченные красным цветом.');
			
				Forms.RestoreReturnValue(Form, Return);
				Forms.EnableButtons(Form);
			
				return;
			}
		
			ErrorCount = Forms.CheckValid(Form);
		
			if (ErrorCount)
			{
				alert('Не все поля в форме заполнены корректно. Заполните, пожалуйста, корректно все поля, подсвеченные красным цветом.');
			
				Forms.RestoreReturnValue(Form, Return);
				Forms.EnableButtons(Form);
			
				return;
			}
		}
		
		Forms.Serialize(Form);
		
		if ($('form#' + Form + ' .field[type!=hidden][unique=unique]').size() && CheckNeeded && UniqueCheckNeeded)
		{
			Forms.CheckUnique(Form, Submit, PostCode);
		}
		else
		{
			if (PostCode)
			{
				eval(PostCode);
			}
			
			if (Submit)
			{
				Forms.SubmitForm(Form);
			}
		}
	}
	,
	SimpleCheckForm: function(Form, Messages) // Полная проверка заполнения формы
	{
		var ErrorCount = 0;
		
		ErrorCount = Forms.SimpleCheckRequired(Form);
		if (ErrorCount)
		{
			alert(Messages.Required);
			Forms.EnableButtons(Form);
			return false;
		}
		
		ErrorCount = Forms.SimpleCheckValid(Form);
		if (ErrorCount)
		{
			alert(Messages.Valid);
			Forms.EnableButtons(Form);
			return false;
		}

		return true;
	}
	, 
	SimpleCheckTab: function(Form, Messages, Tab, NextTab) // Полная проверка заполнения формы
	{
		var ErrorCount = 0;
		
		ErrorCount = Forms.SimpleCheckTabRequired(Form, Tab);
		if (ErrorCount)
		{
			alert(Messages.Required);
			return false;
		}
		
		ErrorCount = Forms.SimpleCheckTabValid(Form, Tab);
		if (ErrorCount)
		{
			alert(Messages.Valid);
			return false;
		}
		Forms.SimpleShowTab(Form, NextTab);
		return true;
	}
	, 
	HistoryChange: function(Form) // Получение версии объекта
	{
		if (Forms.GetField(Form, 'HistoryID').val())
		{
			Forms.DisableButtons(Form);
			Forms.DisableFieldsSaveState(Form); 
			
			$.AJAX('Main/History', {
				'HistoryID': Forms.GetField(Form, 'HistoryID').val()
			},
			function (result, errors) 
			{
				if (result) 
				{
					Forms.FillFields(Form, result.Item);
					
					Forms.EnableFieldsRestoreState(Form);
					Forms.EnableButtons(Form);
				}
			});
		}
	}	
}

PHP = 
{
	/* 
	 * More info at: http://kevin.vanzonneveld.net/techblog/article/phpjs_licensing/
	 * 
	 * This is version: 1.76
	 * php.js is copyright 2008 Kevin van Zonneveld.
	 * 
	 * Portions copyright Onno Marsman, Michael White (http://getsprink.com),
	 * _argos, Jack, Jonas Raoni Soares Silva (http://www.jsfromhell.com), Philip
	 * Peterson, Legaev Andrey, Ates Goral (http://magnetiq.com), Martijn
	 * Wieringa, Philippe Baumann, Webtoolkit.info (http://www.webtoolkit.info/),
	 * Carlos R. L. Rodrigues (http://www.jsfromhell.com), Enrique Gonzalez, Ash
	 * Searle (http://hexmen.com/blog/), Erkekjetter, GeekFG
	 * (http://geekfg.blogspot.com), Johnny Mast (http://www.phpvrouwen.nl), d3x,
	 * marrtins, AJ, Alex, Alfonso Jimenez (http://www.alfonsojimenez.com), Aman
	 * Gupta, Arpad Ray (mailto:arpad@php.net), Karol Kowalski, Mirek Slugen,
	 * Nate, Sakimori, Thunder.m, Tyler Akins (http://rumkin.com), mdsjack
	 * (http://www.mdsjack.bo.it), Alexander Ermolaev
	 * (http://snippets.dzone.com/user/AlexanderErmolaev), Allan Jensen
	 * (http://www.winternet.no), Andrea Giammarchi
	 * (http://webreflection.blogspot.com), Anton Ongson, Arno, Atli У?УГr, Bayron
	 * Guevara, Ben Bryan, Benjamin Lupton, Brad Touesnard, Brett Zamir, Cagri
	 * Ekin, Christian Doebler, Cord, David, David James, Dino, DxGx, FGFEmperor,
	 * Felix Geisendoerfer (http://www.debuggable.com/felix), Francois,
	 * FremyCompany, Gabriel Paderni, Howard Yeend, J A R, Kirk Strobeck, LH,
	 * Leslie Hoare, Lincoln Ramsay, Luke Godfrey, Mateusz "loonquawl" Zalega,
	 * MeEtc (http://yass.meetcweb.com), Mick@el, Nathan, Nick Callen, Norman
	 * "zEh" Fuchs, Ozh, Pedro Tainha (http://www.pedrotainha.com), Peter-Paul
	 * Koch (http://www.quirksmode.org/js/beat.html), Pul, Pyerre, ReverseSyntax,
	 * Robin, Sanjoy Roy, Saulo Vallory, Scott Cariss, Simon Willison
	 * (http://simonwillison.net), Slawomir Kaniecki, Steve Clay, Steve Hilder,
	 * Steven Levithan (http://blog.stevenlevithan.com), T.Wild, T0bsn, Thiago
	 * Mata (http://thiagomata.blog.com), Tim Wiel, XoraX (http://www.xorax.info),
	 * Yannoo, baris ozdil, booeyOH, djmix, dptr1988, duncan, echo is bad, gabriel
	 * paderni, ger, gorthaur, hitwork, jakes, john (http://www.jd-tech.net),
	 * johnrembo, kenneth, marc andreu, metjay, nobbler, penutbutterjelly, sankai,
	 * sowberry, stensi
	 * 
	 * Dual licensed under the MIT (MIT-LICENSE.txt)
	 * and GPL (GPL-LICENSE.txt) licenses.
	 * 
	 * Permission is hereby granted, free of charge, to any person obtaining a
	 * copy of this software and associated documentation files (the
	 * "Software"), to deal in the Software without restriction, including
	 * without limitation the rights to use, copy, modify, merge, publish,
	 * distribute, sublicense, and/or sell copies of the Software, and to
	 * permit persons to whom the Software is furnished to do so, subject to
	 * the following conditions:
	 * 
	 * The above copyright notice and this permission notice shall be included
	 * in all copies or substantial portions of the Software.
	 * 
	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
	 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
	 * IN NO EVENT SHALL KEVIN VAN ZONNEVELD BE LIABLE FOR ANY CLAIM, DAMAGES
	 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
	 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	 * OTHER DEALINGS IN THE SOFTWARE.
	 */ 

	// {{{ urlencode
	urlencode: function ( str ) {
	    // URL-encodes string
	    // 
	    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_urlencode/
	    // +       version: 809.1713
	    // +   original by: Philip Peterson
	    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +      input by: AJ
	    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // %          note: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/
	    // *     example 1: urlencode('Kevin van Zonneveld!');
	    // *     returns 1: 'Kevin+van+Zonneveld%21'
	    // *     example 2: urlencode('http://kevin.vanzonneveld.net/');
	    // *     returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F'
	    // *     example 3: urlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a');
	    // *     returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'
					     
	    var histogram = {}, histogram_r = {}, code = 0, tmp_arr = [];
	    var ret = str.toString();
	    
	    var replacer = function(search, replace, str) {
		var tmp_arr = [];
		tmp_arr = str.split(search);
		return tmp_arr.join(replace);
	    };
	    
	    // The histogram is identical to the one in urldecode.
	    histogram['!']   = '%21';
	    histogram['%20'] = '+';
	    
	    // Begin with encodeURIComponent, which most resembles PHP's encoding functions
	    ret = encodeURIComponent(ret);
	    
	    for (search in histogram) {
		replace = histogram[search];
		ret = replacer(search, replace, ret) // Custom replace. No regexing
	    }
	    
	    // Uppercase for full PHP compatibility
	    return ret.replace(/(\%([a-z0-9]{2}))/g, function(full, m1, m2) {
		return "%"+m2.toUpperCase();
	    });
	    
	    return ret;
	}// }}}
	, 
	// {{{ number_format
	number_format: function( number, decimals, dec_point, thousands_sep ) {
	    // Format a number with grouped thousands
	    // 
	    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/
	    // +       version: 809.2411
	    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
	    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +     bugfix by: Michael White (http://getsprink.com)
	    // +     bugfix by: Benjamin Lupton
	    // +     bugfix by: Allan Jensen (http://www.winternet.no)
	    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
	    // +     bugfix by: Howard Yeend
	    // *     example 1: number_format(1234.5678, 2, '.', '');
	    // *     returns 1: 1234.57     

	    var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals;
	    var d = dec_point == undefined ? "." : dec_point;
	    var t = thousands_sep == undefined ? "" : thousands_sep, s = n < 0 ? "-" : "";
	    var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
	    
	    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
	}// }}}
}


ZArray = 
{
	InArray: function (arr, val)
	{
		for(var i = 0; i < arr.length; i++)
		{
			if(arr[i] == val)
			{
				return true;
			}
		}
		return false;
	}
}

ZFile = 
{
	GetExt: function (filename)
	{
		var parts = new Array;
		if(filename.indexOf('.') > 0 )
		{
			parts = filename.split('.');
			return parts[parts.length - 1];
		}
		return '';
	}
}

ZNumeric =
{
	StrToInt: function (str)
	{
		var str = str.replace(",", ".");
		if( str == '' || isNaN(str) )
		{
			return '';
		}
		else
		{
			return parseInt(Number(str, 10));
		}
	},
	StrToDecimal: function (str)
	{
		var str = str.replace(",", ".");
		if( str == '' || isNaN(str) )
		{
			return '';
		}
		else
		{
			return PHP.number_format(str, 2, '.', '');
		}
	}
}

ZDate = 
{
	StrToDate: function (str)
	{
		var datearray, dt;
		dt = new Date();
		datearray = str.split('-');
		dt.setFullYear(Number(datearray[0]));
		dt.setMonth(Number(datearray[1]) - 1);
		dt.setDate(Number(datearray[2]));
		return dt;
	}
	,
	StrToTimestamp: function(str)
	{
		var dt = ZDate.StrToDate(str);
		return dt.getTime();
	}
}
