
var Tesla = {};
Ajax = {};
Tesla.Collection = {};
Tesla.Debug = {};
Tesla.UI = {};

function $(ctrlID)
{
	return document.getElementById(ctrlID);
}

function $$( ctrl, attr )
{
	if( ctrl )
	{
		if( ctrl[attr] )
			return ctrl[attr]

		if( ctrl.attributes && ctrl.attributes[attr] )
			return ctrl.attributes[attr].value;
	}
	return null;
}

Function.Empty = function(){};

Function.prototype.GetName = function(obj)
{
	if( this.name )
		return this.name;

	var fn = this.toString();
	
	//Safari ou tipo anonimo
	if( fn == '[function]' )
	{
		var cn = obj.constructor;
		if( cn == String ) this.name = 'String';
		else if( cn == Number ) this.name =  'Number';
		else if( cn == Function ) this.name =  'Function';
		else if( cn == Date ) this.name =  'Date';
		else if( cn == Error ) this.name =  'Error';
		else if( cn == Boolean ) this.name =  'Boolean';
		else if( cn == Array ) this.name =  'Array';
		else this.name =  'Object';

		return this.name;
	}

	var start = fn.indexOf( 'function' ) + 9;
	for(;fn.charAt(start) == ' ';)
		start++;
	var end = start;
	while( fn.charAt(end) != ' ' && fn.charAt(end) != '(' )
		end++;
	this.name = fn.substring( start, end )
	return this.name;
}

Tesla.Debug.ShowProperties = function(obj, showFunctions)
{
	for( var prop in obj )
        if( obj.constructor != Function || (showFunctions && obj.constructor == Function) )
		    alert( String.Format( '{0}: {1}', prop, obj[prop] ) );
}

Tesla.CookieManager = new function()
{
	this.Set = function(name, value, f){ if(!f) value = escape(value); document.cookie = String.Format( '{0}={1};expires=Fri, 31 Dec 2099 23:59:59 GMT;path={2};', name, value, page.ApplicationName.length==0?'/':page.ApplicationName ); }
	this.Get = function(name){ var cookies = document.cookie.split('; '); var rt = null; for (var i=0; i < cookies.length; i++) { var cookie = cookies[i].split('='); if (name == cookie[0])  { rt = unescape(cookies[i].substring(name.length+1)); break; } } return rt; }
	this.Delete = function(name){ document.cookie = name + '=; expires=Fri, 21 Dec 1976 04:31:24 GMT;'; }
	this.SaveObject = function(name, obj){ this.Set( name, obj.Serialize() ); }
	this.LoadObject = function(name){ return eval( '('+this.Get(name)+')' ); }
}

Math.Round = function( valor, casasDecimais )
{
	var v = Math.pow(10, casasDecimais);
	return Math.round(v*valor)/v;
}



function ListAutoComplete(ctrl, jsFeeder)
{
	var value = ctrl.value.Trim();
	if( !value.length )
	{
		$(ctrl.id + '_list').style.display = 'none';
		return;
	}

	if( ctrl.LastValue == value )
		return;

	ListAutoComplete.Control = ctrl;
	ctrl.LastValue = value;
	if(jsFeeder)
		ListAutoCompleteEnd( jsFeeder(ctrl) );
	else
		Ajax.GetAutoCompleteList( $$(ctrl,'TypeName'), value, ListAutoCompleteEnd )
}
function ListAutoCompleteEnd(list)
{
	var ctrl = ListAutoComplete.Control;
	var container = $(ctrl.id + '_list');
	if( !list.length )
	{
		container.style.display = 'none';
		return;
	}
	var p = page.GetPosition( ctrl );

	container.style.top = (p[0] + ctrl.clientHeight + 7) + 'px';
	container.style.left = p[1] + 'px';
	container.style.width = (ctrl.clientWidth+1) + 'px';
	container.style.display = '';

	var sb = new Tesla.StringBuilder();
	for(var i=0; i<list.length; i++)
		sb.Append(String.Format("<div class='autocomplete_item' style='width:{0}px;cursor:pointer;overflow:hidden' onmouseover='this.className=\"autocomplete_item_hover\";' onmouseout='this.className=\"autocomplete_item\";' onclick='AutoCompleteSelect(\"{2}\",\"{1}\")'>{1}</div>", ctrl.clientWidth, list[i], ctrl.id));

	container.innerHTML = sb.toString();
}
function AutoCompleteSelect(id, text)
{
	$(id).value = text;
	$(id+'_list').style.display = 'none';
}

//DefaulJavaScripts


var Validadores = {};

Validadores.ValidaEmail = function(email)
{
	return !email || !email.length || email.match('^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$') != null;
}
Validadores.ValidaNumero = function(st)
{
	for(var i=0; i<st.length; i++)
		if( !Validadores.ValidaDigito(st.charAt(i) ) )
			return false;
	return true;
}
Validadores.ValidaNumeroDecimal = function(st)
{
	for(var i=0; i<st.length; i++)
		if( st.charAt(i) != '.' && !Validadores.ValidaDigito(st.charAt(i) ) )
			return false;
	return true;
}
Validadores.ValidaDigito = function(c)
{
	return ((c >= '0') && (c <= '9'));
}
Validadores.ValidaCPF = function( valor )
{
	return Validadores.ValidaCPF_CNPJ( valor, 1 );
}
Validadores.ValidaCNPJ = function( valor )
{
	return Validadores.ValidaCPF_CNPJ( valor, 2 );
}
Validadores.ValidaCPF_CNPJ = function(campo,pType)
{
	if( campo == null || campo.Trim() == '' )
		return false;

	var campo_filtrado = '', valor_1 = ' ', valor_2 = ' ', ch = '';
	var valido = false;
        
	for (i = 0; i < campo.length; i++)
	{
		ch = campo.substring(i, i + 1);
		if (ch >= '0' && ch <= '9')
		{
			campo_filtrado = campo_filtrado.toString() + ch.toString()
			valor_1 = valor_2;
			valor_2 = ch;
		}
		if ((valor_1 != ' ') && (!valido)) valido = !(valor_1 == valor_2);
	}
	if (!valido) 
		campo_filtrado = '12345678912';

	if (campo_filtrado.length < 11)
	{
		for (i = 1; i <= (11 - campo_filtrado.length); i++){campo_filtrado = '0' + campo_filtrado;}
	}


	if(pType <= 1)
	{
		if ( ( campo_filtrado.substring(9,11) == Validadores.__checkCPF( campo_filtrado.substring(0,9) ) ) && ( campo_filtrado.substring(11,12)=='') )
			return true;
	}

	if((pType == 2) || (pType == 0))
		if (campo_filtrado.length >= 14)
			if ( campo_filtrado.substring(12,14) == Validadores.__checkCNPJ( campo_filtrado.substring(0,12) ) )
				return true;
	return false;
}
Validadores.__checkCNPJ = function(vCNPJ)
{
   var mControle = '';
   var aTabCNPJ = new Array(5,4,3,2,9,8,7,6,5,4,3,2);
   for (i = 1 ; i <= 2 ; i++){
      mSoma = 0;
      for (j = 0 ; j < vCNPJ.length ; j++)
         mSoma = mSoma + (vCNPJ.substring(j,j+1) * aTabCNPJ[j]);
      if (i == 2 ) mSoma = mSoma + ( 2 * mDigito );
      mDigito = ( mSoma * 10 ) % 11;
      if (mDigito == 10 ) mDigito = 0;
      mControle1 = mControle ;
      mControle = mDigito;
      aTabCNPJ = new Array(6,5,4,3,2,9,8,7,6,5,4,3);
   }
   return( (mControle1 * 10) + mControle );
}
Validadores.__checkCPF = function(vCPF)
{
   var mControle = ''
   var mContIni = 2, mContFim = 10, mDigito = 0;
   for (j = 1 ; j <= 2 ; j++){
      mSoma = 0;
      for (i = mContIni ; i <= mContFim ; i++)
         mSoma = mSoma + (vCPF.substring((i-j-1),(i-j)) * (mContFim + 1 + j - i));
      if (j == 2 ) mSoma = mSoma + ( 2 * mDigito );
      mDigito = ( mSoma * 10 ) % 11;
      if (mDigito == 10) mDigito = 0;
      mControle1 = mControle;
      mControle = mDigito;
      mContIni = 3;
      mContFim = 11;
   }
   return( (mControle1 * 10) + mControle );
}
Validadores.ValidaData = function(data)
{
	if( !data || !data.length )
		return null;

	var dataArray = data.Split('/-.');
	if( dataArray.length != 3 )
		return null;

	if( !Validadores.ValidaNumero( (dataArray[0]||'.').TrimStart('0') ) || !Validadores.ValidaNumero( (dataArray[1]||'.').TrimStart('0') ) || !Validadores.ValidaNumero( (dataArray[2]||'.').TrimStart('0') )  )
		return null;

	if( dataArray[2].StartsWith('00') )
		return null;

	var dia = parseInt( dataArray[0].TrimStart('0') );
	var mes = parseInt( dataArray[1].TrimStart('0') );
	var ano = parseInt( dataArray[2].TrimStart('0') );

	if( ano <= 60 )
		ano += 2000;
	else if( ano > 60 && ano <= 99 )
		ano += 1900;
		
	if( dia == 0 || mes == 0 || ano == 0 || mes > 12 )
		return null;		

	if( (ano > 99 && ano < 1900) || (ano > 2099) )
		return null;

	try
	{
		mes--;
		var dt = new Date( ano, mes, dia);
		if( dt.getDate() != dia || dt.getMonth() != mes || dt.getFullYear() != ano )
			return null;
		return dt;
	}
	catch(err)
	{
		return null;
	}
}
Validadores.ValidaDataHora = function( dataHora )
{
	var partes = dataHora.Split(' ');
	if( partes.length != 2 )
		return null;

	var data = Validadores.ValidaData( partes[0] );
	if( !data )
		return null;

	var horaArray = partes[1].Split(':');
	if( horaArray.length < 2 || horaArray.length > 3 )
		return null;

	var hora = 0;
    var minuto = 0;
    var segundo = 0;

	var hora = parseInt( horaArray[0].TrimStart('0') )||0;
	var minuto = parseInt( horaArray[1].TrimStart('0') )||0;
	var segundo = ((horaArray.length==3)?horaArray[2].TrimStart('0'):0)||0;

	if( hora < 0 || hora > 23 ) return null;
	if( minuto < 0 || minuto > 59 ) return null;
	if( segundo < 0 || segundo > 59 ) return null;

	data.setHours(hora);
	data.setMinutes(minuto);
	data.setSeconds(segundo);
	return data;
}

//Validadores


Tesla.UI.ListControl = {};
Tesla.UI.ListControl.Functions = {};

Tesla.UI.ListControl.Functions.SetSelectedValue = function(value) 
{ 
	if( String.IsNullOrEmpty(value) )
	{
		this.selectedIndex = 0; 
		return;
	}
	var i =0;
	while( i<this.options.length && this.options[i].value != value )
		i++;

	if( this.options[i].value == value ) 
		this.selectedIndex = i; 
}
Tesla.UI.ListControl.Functions.SetSelectedIndex = function(idx)
{ 
	this.selectedIndex = idx; 
}
Tesla.UI.ListControl.Functions.SelectedValue = function() 
{ 
	if( this.length <= 0 ) 
		return ''; 
	return this.options[this.selectedIndex].value; 
}
Tesla.UI.ListControl.Functions.SelectedText = function() 
{ 
	if( this.length <= 0 || this.selectedIndex<0 ) 
		return ''; 
	return this.options[this.selectedIndex].text; 
}
Tesla.UI.ListControl.Functions.SelectedItem = function() 
{ 
	if( this.length <= 0 ) 
		return null; 
	return this.options[this.selectedIndex]; 
}
Tesla.UI.ListControl.Functions.GetSelectedItemAttribute = function(attr) 
{ 
	var item = this.SelectedItem(); 
	if(!item) 
		return null; 
	var v = item.attributes[attr]; 
	if(!v) 
		return null; 
	return v.value; 
}
Tesla.UI.ListControl.Functions.Clear = function() 
{ 
	this.length = 0; 
}
Tesla.UI.ListControl.Functions.Add = function( value, text ) 
{ 
	this.options[this.options.length] = new Option( text, value ); 
	return this.options[this.options.length-1]; 
}
Tesla.UI.ListControl.Functions.AddAt = function(index, value, text) 
{ 
	if( index < 0 ) 
		index = 0; 
	var lg = this.length; 
	if( index < lg ) 
		for( var i=lg; i>index; i--) 
			this.options[i] = new Option(this.options[i-1].text, this.options[i-1].value); 
	
	this.options[index] = new Option( text, value ); 
	return this.options[index]; 
}
Tesla.UI.ListControl.Functions.Bind = function(dataSource, valueProperty, textProperty, selectOption, preserveItems, p1, p2, p3) 
{ 
	if(!dataSource.GetEnumerator)
		return;

	drop = this;
	if(!preserveItems)
		drop.options.length = 0;

	if( selectOption )
		drop.Add('', selectOption);

	var en = dataSource.GetEnumerator();
	while( en.MoveNext() )
	{
		drop.Add( valueProperty?en.Current[valueProperty]:en.Current, textProperty?en.Current[textProperty]:en.Current );
		if( p1 ) drop.options[drop.options.length-1][p1] = en.Current[p1];
		if( p2 ) drop.options[drop.options.length-1][p2] = en.Current[p2];
		if( p3 ) drop.options[drop.options.length-1][p3] = en.Current[p3];
	}
}
Tesla.UI.ListControl.Functions.DataBind = function(dataSource, textProperty, valueProperty, selectOption, preserveItems, p1, p2, p3)
{
	this.Bind(dataSource, valueProperty, textProperty, selectOption, preserveItems, p1, p2, p3);
}
Tesla.UI.ListControl.Functions.CopyTo = function(drop, onlySelectedItems, copyCallBack)
{  
	for(var i=0; i<this.options.length; i++) 
	{
		if( onlySelectedItems && !this.options[i].selected )
			continue;

		var optSrc = this.options[i];
		var optDest = drop.Add( optSrc.value, optSrc.text );
		if( copyCallBack )
			copyCallBack( optSrc, optDest );
	}
}
Tesla.UI.ListControl.Functions.GetValue = function()
{
	var rt = new Tesla.StringBuilder();
	for( var i=0; i<this.options.length; i++)
	{
		rt.Append( this.options[i].value )
		rt.Append( ',' );
	}
	return rt.ToString();
}
Tesla.UI.ListControl.Functions.SetDisabled = function()
{
	this.disabled = true;
}
Tesla.UI.ListControl.Functions.SetEnabled = function()
{
	this.disabled = false;
}
Tesla.UI.ListControl.Functions.Hide = function()
{
	this.style.display = 'none';
}
Tesla.UI.ListControl.Functions.Show = function()
{
	this.style.display = '';
}
Tesla.UI.ListControl.BindFunctions = function( drop ) 
{ 
	if(!drop) 
		return; 
	for(var prop in Tesla.UI.ListControl.Functions) 
		drop[prop] = Tesla.UI.ListControl.Functions[prop]; 
	return drop; 
}
Tesla.UI.ListControl.GetByID = function(id) 
{ 
	var drop = document.getElementById(id); 
	Tesla.UI.ListControl.BindFunctions(drop); 
	return drop; 
}

//ListControl


function $IE6(value1, value2)
{
	return page.IsIE6 ? value1 : value2
}

function __QueryString()
{
	this.AllKeys = [];
	this.Values = [];

	var subs = window.location.search.substring(1);
	var queries = subs.split("&");
	for (i=0;i<queries.length;i++)
	{
		query = queries[i].split("=");
		this[query[0]] = query[1];
		this.AllKeys.push( query[0] );
		this.Values.push( query[1] );
	}
}

Tesla.UI.Page = function()
{
	this.SelectFromBrowser = function(v1, v2, v3)
	{
		if( this.IsIE && !this.IsIE6 )
			return v1;
		if( !this.IsIE )
			return v2||v1;
		return v3||v1;
	}

	this.IsIE = /MSIE/.test(navigator.userAgent);
	this.IsIE6 = /MSIE 6.0/.test(navigator.userAgent);

	var _historyController = null;
	var _controls = [];
	var _completed = false;
	var _loadCallback = [];
	var _posLoadCallback = [];
	var _controlsToRegister = [];
	var _onClickHandlers = [];
	var self = this;
	var _isListening = false;

	this.Controls = [];
	this.QueryString = new __QueryString();
	

	if( !this.IsIE )
		addEventListener('DOMContentLoaded', function(){ _completed = true; }, false);

	_loadCallback.push( RegisterControls )

	function SetHierarchy( id, value )
	{
		var rt = Tesla.UI.Page.Current;
		id = id.Split('.');
		for(var i=0; i<id.length-1; i++)
			rt = rt[id[i]];
		
		rt[id[id.length-1]] = value;
	}

	function RegisterControls()
	{
		var ctrls = page.ControlsToRegister||[];
		for(var i=0; i<ctrls.length; i++)
		{
			var _ctrls = ctrls[i].Controls;
			for(var j=0; j<_ctrls.length; j++)
			{
                ctrls[i].Prefix = ctrls[i].Prefix || '';
				var name = ctrls[i].Prefix.length?String.Format('{0}_{1}', ctrls[i].Prefix, _ctrls[j].ID):_ctrls[j].ID;
				var id = String.Format('{0}{1}', ctrls[i].ControlPrefix, _ctrls[j].ID);
				if( _ctrls[j].Type == 'L' )
					SetHierarchy( name, Tesla.UI.ListControl.GetByID(id) );
				else
					SetHierarchy( name, $(id) );
			}
		}
	}

	function RaiseOnClick()
	{
		for(var i=0; i<_onClickHandlers.length; i++)
			_onClickHandlers[i]();
	}

	this.AddOnClick = function(fn)
	{
		_onClickHandlers.push( fn );
		if( _onClickHandlers.length > 1 )
			return;
		if( this.IsIE )
		{
			document.onclick = RaiseOnClick;
			return;
		}
		window.captureEvents(Event.Click) 
		window.onclick = RaiseOnClick;
	}
	this.RemoveOnClick = function(fn)
	{
		_onClickHandlers.Remove(fn);
	}

	this.GetEventKeyCode = function(ev)
	{
		if( ev )
			return parseInt(ev.wich||ev.keyCode);
		return parseInt(event.keyCode);
	}
	this.IsNumber = function(e)
	{
		var keynum;
		var keychar;
		var numcheck;
		if(window.event)
			keynum = e.keyCode;
		else if(e.which)
			keynum = e.which;

		keychar = String.fromCharCode(keynum);
		numcheck = /\d/;
		return numcheck.test(keychar);
	}
	this.CheckNumbers = function(e, allowedChars)
	{
        return e.keyCode == 8 || e.keyCode == 9 || this.IsNumber(e);
	}
	
	this.IsLoaded = function()
	{
		if( _completed )
			return true;

		if( document.readyState )
		{
			if( document.readyState == 'complete' || document.readyState == 'loaded' ) 
				_completed = true;
		}
		return _completed;
	}
	this.CreateForm = function( name, action, method, target )
	{
		var frm		= document.createElement('form');
		frm.action	= action;
		frm.method	= method;
		frm.name	= name;
		frm.target	= target;
		document.body.appendChild(frm);
		frm.AddField = function(name, value){ frm.appendChild( page.CreateInput(name, 'text', value) ); };
		return frm;
	}
	this.CreateInput = function( name, type, value )
	{
		var ipt		= document.createElement('input');
		ipt.type	= type;
		ipt.name	= name;
		ipt.value	= value;
		return ipt;
	}
	this.CreateIFrame = function()
	{
		var iframe 	= document.createElement('iframe');
		document.body.appendChild(iframe);
		iframe.style.display = 'none';
		return iframe;
	}
	this.CreateSpan = function(id)
	{
		var rt	= document.createElement('span');
		rt.name	= id;
		rt.id	= id;
		return rt;
	}
	this.GetHistoryControler = function()
	{
		if(!_historyController)
			_historyController = new Tesla.UI.Page.HistoryControler();
		return _historyController;
	}
	this.HideControl = function( controlID )
	{
		_controls[controlID].style.display = 'none';
	}
	this.ShowControl = function(controlID)
	{
		_controls[controlID].style.display = '';
	}
	this.Redirect = function(url)
	{
		window.location.href = this.ResolveUrl(url);
	}
	this.AddControl = function(controlID, name)
	{
		name = name || controlID;
		var ctrl	= {};
		ctrl.ID		= controlID;
		ctrl.Name	= name;
		_controlsToRegister.Add( ctrl );
		if( this.IsLoaded() )
			RegisterControls_Internal();
		else 
			this.__ListenForOnLoad();
	}
	this.__SetLoadCompleted = function()
	{
		if( _completed )
			return;
		_completed = true;
		this.__ListenForOnLoad(1);
	}
	this.__ListenForOnLoad = function(arg)
	{
		if( !arg && _isListening )
			return;

		_isListening = true;
		if( this.IsLoaded() )
		{
			if(this.ListeningTimer)
				clearTimeout( this.ListeningTimer );

			_isListening = false;

			if( _controlsToRegister.length > 0 )
				RegisterControls_Internal();

			for(var i=0; i<_loadCallback.length; i++)
				_loadCallback[i]();

			for(var i=0; i<_posLoadCallback.length; i++)
				_posLoadCallback[i]();

			return;
		}
		this.ListeningTimer = setTimeout( 'Tesla.UI.Page.Current.__ListenForOnLoad(1)', 5 );
	}
	function RegisterControls_Internal()
	{
		for(var i=0; i<_controlsToRegister.length; i++)
		{
			var ctrl = document.getElementById(_controlsToRegister[i].ID);
			if( !ctrl || ctrl.Registered )
				continue;
			
			ctrl.Registered = true;
			if( ctrl.tagName.toUpperCase() == 'SELECT' )
				ctrl = Tesla.UI.ListControl.GetByID(_controlsToRegister[i].ID)

			GetHierarchy(_controlsToRegister[i].ID)[_controlsToRegister[i].Name] = ctrl;
			_controls.Add( ctrl );
		}
	}
	function GetHierarchy( id )
	{
		var rt = Tesla.UI.Page.Current;
		id = id.Split('.');
		for(var i=0; i<id.length-1; i++)
			rt = rt[id[i]];
		return rt;
	}

	this.AddOnLoad = function( onLoadCallback )
	{
		if( GetType(onLoadCallback) == 'String' )
			onLoadCallback = $L( '() =>' + onLoadCallback )

		if( this.IsLoaded() )
		{
			onLoadCallback();
			return;
		}

		_loadCallback.push( onLoadCallback );

		if( _posLoadCallback.length == 0 && _loadCallback.length == 1 )
			this.__ListenForOnLoad();
	}
	this.AddOnPosLoad = function( onLoadCallback )
	{
		if( GetType(onLoadCallback) == 'String' )
			onLoadCallback = $L( '() =>' + onLoadCallback )

		if( this.IsLoaded() )
		{
			onLoadCallback();
			return;
		}

		_posLoadCallback.push( onLoadCallback );

		if( _posLoadCallback.length == 1 && _loadCallback.length == 0 )
			this.__ListenForOnLoad();
	}
	this.ResolveUrl = function(path)
	{
		if( path.charAt(0) == '~' )
		{
			path = path.substr(1);
			if( path.charAt(0) == '/' )
				path = path.substr(1);

			if( page.ApplicationName.length > 0 )
				path = page.ApplicationName + '/' + path;
		}
		else if( path.charAt(0) != '/' )
			path = location.pathname.Left(location.pathname.lastIndexOf('/')+1) + path;
		
		if( path.charAt(0) == '/' )
			path = path.substr(1);

		return String.Format( '{0}//{1}/{2}', location.protocol, location.host, path );
	}
	this.FindControl = function( ctrlPath )
	{
		var arr = ctrlPath.Split('.');
		var rt = page;
		for(var i=0; i<arr.length; i++)
			rt = rt[arr[i]];
		
		return rt;
	}
	this.AjaxUpload = function(ctrl, callBack)
	{
		ctrl.onupload = callBack;
		var frm = document.forms[0];
		frm.oldMethod = frm.method;
		frm.oldTarget = frm.target;
		frm.target = '__AjaxUpload';
		frm.method = 'post';

		var items = (ctrl.Items||'').ToString();
		frm.oldAction = frm.action;
		frm.action = this.ResolveUrl( String.Format('~/AjaxMethod/AjaxFileUpload.ashx?ctrl={0}&ctrlName={1}&ctrlID={2}&{3}', $$( ctrl, 'ControlType'), ctrl.name||ctrl.id, $$( ctrl, 'ControlID'), items ) );
		frm.submit();
		
		frm.method = frm.oldMethod;
		frm.target = frm.oldTarget;
		frm.action = frm.oldAction;
		ctrl.value = null;
	}
    this.ChangeRadioButton = function(rb, setChecked)
	{
        var rt = null;
	    var group = $$( rb, 'groupname' );
	    var ctrlGroup = $(group);

	    ctrlGroup.value = '';
	    for(var i=0; i<page[group].length; i++)
	    {
	        var ctrl = $(page[group][i]);
	        var checked = false;

	        if( ctrl.id == rb.id )
	        {
                if (setChecked !== undefined)
                    checked = setChecked;
                else
	                checked = !(ctrl.checked||false);
                
                rt = checked;
                if (checked)
                    ctrlGroup.value = ctrl.id+'|'+$$(ctrl,'value');
                
                ctrl.checked = checked;
                ctrl.childNodes[0].src = $$(ctrl, (checked?'checkedImage':'uncheckedImage'));
            }
            else
            {
                if (setChecked == undefined || setChecked)
                {
                    ctrl.checked = false;
                    ctrl.childNodes[0].src = $$(ctrl, 'uncheckedImage');
                }
            }
	    }
        page[group].value = ctrlGroup.value; 
        return rt;
	}
    this.ChangeCheckBox = function(cb, checked)
    {
        cb.checked = checked;
        var id = cb.id;
        var img = $(id+'_image');
        img.src = $$(img, checked?'checkedImage':'uncheckedImage');
    }
    this.NoOp = function()
    {
    }

    this.CaptureMouseMove = function(callBack)
	{
		document.onmousemove = function(e){  callBack(event.clientX + document.body.scrollLeft, event.clientY + document.body.scrollTop ) };
	}
	
	this.StopCaptureMouseMove = function()
	{
		document.onmousemove = null;
	}

	this.GetPosition = function(obj) 
    {
	    var curleft = curtop = 0;
	    if( !obj.Top || !obj.Left )
	    {
		    var currObj = obj;
		    if (currObj.offsetParent) 
		    {
			    curleft = currObj.offsetLeft
			    curtop = currObj.offsetTop
			    while (currObj = currObj.offsetParent) 
			    {
				    curleft += currObj.offsetLeft
				    curtop += currObj.offsetTop
			    }
		    }
	    }
	    return [curtop, curleft];
    }
}

function $R( name, id )
{
	id = id || name;
	var ctrl = document.getElementById(name);

	if( !ctrl )
	{
		if( Tesla.Debug.Write )
			Tesla.Debug.Write( name + ': Não Encontrado!' );
		return;
	}

	if( ctrl.Registered)
		return;
	
	ctrl.Registered = true;
	if( ctrl.tagName.toUpperCase() == 'SELECT' )
		ctrl = Tesla.UI.ListControl.GetByID(_controlsToRegister[i].ID)
	
	page[id] = ctrl;
}

window.page = new Tesla.UI.Page();
Tesla.UI.Page.Current = page;

Tesla.UI.Page.HistoryControler = function()
{
	this.IE = /MSIE/.test(navigator.userAgent),
	this.IESupportBack = true,
	this.Hash = document.location.hash,
	this.Initialized = false,
	this.Check = function()
	{
		var h = document.location.hash
		var h2 = this.Hash
		if (h != h2 || !h || h.length == 0)
		{
			this.Hash = h;
			if( this.OnHashChanged )
				this.OnHashChanged( this.GetHash().substr(1) );
		}
	}
	this.Init = function()
	{
		if (this.IE && this.IESupportBack) 
		{
			var frame = document.createElement("iframe");
			frame.id = "state-frame";
			frame.style.display = "none";
			document.body.appendChild(frame);
			this.WriteFrame("");
		}

		var self = this;

		if ("onpropertychange" in document && "attachEvent" in document) 
			document.attachEvent("onpropertychange", function (){ if (event.propertyName == "location") self.Check(); } );
		else 
			window.setInterval(function () { self.Check() }, 100);

		this.Initialized = true;
	}
	this.SetHash = function(s)
	{
		this.Hash = '#'+s;
		
		if(!this.Initialized)
			this.Init();
		
		if (this.IE && this.IESupportBack) 
			this.WriteFrame(s);

		document.location.hash = this.Hash;
	}
	this.GetHash = function()
	{
		return document.location.hash;
	}
	this.WriteFrame = function(s)
	{
		var f = document.getElementById("state-frame");
		var d = f.contentDocument || f.contentWindow.document;
		
		d.open();
		d.write("<script>window._hash = '" + s + "'; window.onload = parent.HistoryControler.SyncHash;<\/script>");
		d.close();
	}
	this.SyncHash = function()
	{
		var s = this._hash;
		if (s != '' && s != document.location.hash)
			document.location.hash = s;
	}
}


//Page


Number.prototype.GetInteger = function() 
{
	return Math.floor(this);
}
Number.prototype.GetDecimal = function() 
{
	return this - Math.floor(this);
}
Number.prototype.ToString = function(formato) 
{
	if( formato.toLowerCase() == 'c' )
	{
		var _int = this.GetInteger().toString();

		var int = '';
		for(var i=_int.length-1;i>=0; i--)
		{
			if( i!=_int.length-1 && (_int.length-i-1)%3 == 0 )
				int = '.' + int;
			int = _int.charAt(i) + int;
		}
		return String.Format('R$ {0},{1}', int, ('0'+Math.round(this.GetDecimal()*100)).Right(2) );
	}
	if( formato == '#.###,##' )
	{
		var _int = this.GetInteger().toString();

		var int = '';
		for(var i=_int.length-1;i>=0; i--)
		{
			if( i!=_int.length-1 && (_int.length-i-1)%3 == 0 )
				int = '.' + int;
			int = _int.charAt(i) + int;
		}
		return String.Format('{0},{1}', int, ('0'+Math.round(this.GetDecimal()*100)).Right(2) );
	}
	return this.toString();
}
Number.ParseInt = function(value, defaultValue)
{
	if( String.IsNullOrEmpty(value) || !Validadores.ValidaNumero( value ) )
		return defaultValue || 0;
	return parseInt(value);
}
Number.ParseFloat = function(value, defaultValue)
{
	if( String.IsNullOrEmpty(value) || !Validadores.ValidaNumeroDecimal( value ) )
		return defaultValue || 0;
	return parseFloat(value);
}
Number.prototype.ToNumber = function()
{
	return this;
}

//Number


Date.Months = [ 'jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez' ];
Date.MonthsLong = [ 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro' ];
Date.prototype.ToString = function(formato)
{
    formato = formato || 'dd/MM/yyyy HH:mm:ss';
	var ano = 1900 + this.getYear(); 
	ano = ano >= 2000?ano-2000:ano-1900;
	if( ano < 0 ) 
		ano = 0;
	ano = ('0'+ano.toString()).Right(2);
	formato = formato.Replace( 'yyyy', this.getFullYear() );
	formato = formato.Replace( 'yy', ano );
	formato = formato.Replace( 'MMMM', Date.MonthsLong[this.getMonth()] );
	formato = formato.Replace( 'MMM', Date.Months[this.getMonth()] );
	formato = formato.Replace( 'MM', ('0'+(this.getMonth()+1)).Right(2) );
	formato = formato.Replace( 'dd', ('0'+this.getDate().toString()).Right(2) );
	formato = formato.Replace( 'hh', ('0'+Math.abs( this.getHours()-12 ).toString()).Right(2) );
	formato = formato.Replace( 'HH', ('0'+this.getHours().toString()).Right(2) );
	formato = formato.Replace( 'mm', ('0'+this.getMinutes().toString()).Right(2) );
	formato = formato.Replace( 'ss', ('0'+this.getSeconds().toString()).Right(2) );
	return formato;
}

Date.prototype.IsBetween = function( start, end )
{
	var d = this;
	return d >= start && d <= end;
}

Date.Parse = function(data)
{
	var rt = Validadores.ValidaDataHora(data);
	if( !rt )
		rt = Validadores.ValidaData(data);

	if( !rt )
		return null;
	
	return rt;
}
Date.GetFirstDayInMonth = function(p1, p2)
{
	if( GetType(p1) === 'Date' )
		return Date.Parse(String.Format('1/{0}/{1}', p1.getMonth()+1, p1.getYear()));
	
	return Date.Parse(String.Format('1/{0}/{1}', p1, p2));
}

Date.DaysInMonth = function(month, year)
{
    if( month == 12 )
    {
        month = 0;
        year++;
    }
    return Date.Parse( String.Format('1/{0}/{1}', month+1, year) ).SubtractDays(1).getDate();
}

Date.IsValidInterval = function(start, end) 
{
	var dStart = start;
	var dEnd = end;

	if( GetType(dStart) != 'Date' )
	{
		var d1 = start.split('/');
		dStart = new Date(d1[2] + '/' + d1[1] + '/' + d1[0]);
	}
	if( GetType(dEnd) != 'Date' )
	{
		var d2 = end.split('/');
		var dEnd = new Date(d2[2] + '/' + d2[1] + '/' + d2[0]);
	}
	return dStart <= dEnd;
}

Date.prototype.SubtractDays = function(days)
{
    days = days||0;
    var date = this;
    return new Date( date - (1000*60*60*24*days) );
}

Date.prototype.AddDays = function(days)
{
    days = days||0;
    var date = this;
    return new Date( date.valueOf() + (1000*60*60*24*days) );
}

Date.prototype.AddMonths = function(months)
{
	var date = this;
	var day = date.getDate();
	var month = date.getMonth()+1;
	var year = date.getFullYear();
    
	for(var i=0; i<months; i++)
	{
		month++;
		if( month == 13 )
		{
			month = 1;
			year++;
		}
	}
	var dt = String.Format('{0}/{1}/{2}', day, month, year);
	return Date.Parse(dt);
}

Date.prototype.SubtractMonths = function(months)
{
    var date = this;
    var day = date.getDate();
    var month = date.getMonth()+1;
    var year = date.getYear();
    
    for(var i=0; i<months; i++)
    {
        month--;
        if( month == 0 )
        {
            month = 12;
            year--;
        }
    }

    return Date.Parse(String.Format('{0}/{1}/{2}', day, month, year));
}

//Date


function AjaxRepeater(id)
{
	var _template = null;
	var self = this;
	var _id = id;
	var _slots = [];
	this.ItemTemplate = null;
	this.AlternateItemTemplate = null;
	this.HeaderTemplate = null;
	this.FooterTemplate = null;
	this.SeparatorTemplate = null;
	this.ContentPlaceHolder = null;
	AjaxRepeater[_id] = self;
	this.constructor.BindMethod = { Sync: 0, Async: 1, Fast:2 };
	this.constructor.BindItem = function(id, idx){ var rpt = AjaxRepeater[id]; rpt.__BindItem(idx||0); }

	this.Bind = function( collection, option, bindMethod, option2, option3 )
	{
		if( collection == null )
			collection = '';

		if( _template != null )
		{
			for( var tpl in _template )
				if( _template[tpl] && _template[tpl].length )
					this[tpl] = new Tesla.UI.Template( _template[tpl] );
			_template = null;
		}

		if( GetType(collection) != 'Array' && collection.GetEnumerator )
		{
			var en = collection.GetEnumerator();
			var c = [];
			while( en.MoveNext() )
				c.push( en.Current );
			
			collection = c;
		}


		if( !bindMethod )
			this.__BindSync( collection, option );
		else if( bindMethod == AjaxRepeater.BindMethod.Async )
			this.__BindAsync( collection, option );
	}

	this.__BindSync = function( collection, preservContent )
	{
		//var start = new Date();
		var content = new Tesla.StringBuilder();
		if( this.HeaderTemplate )
			content.Append(this.HeaderTemplate.Bind( null, null, collection ));
		for(var i=0; i<collection.length; i++)
		{
			if( (i%2) == 0 || !this.AlternateItemTemplate )
				content.Append(this.ItemTemplate.Bind( collection[i], i, collection ));
			else
				content.Append(this.AlternateItemTemplate.Bind( collection[i], i, collection ));

			if( i<collection.length-1 && this.SeparatorTemplate )
				content.Append(this.SeparatorTemplate.Bind( collection[i], i, collection ));
		}
		if( this.FooterTemplate )
			content.Append(this.FooterTemplate.Bind( null, null, collection ));

		//alert( new Date() - start );
		//start = new Date();

		if(	preservContent )
			this.ContentPlaceHolder.innerHTML += content.toString();
		else
			this.ContentPlaceHolder.innerHTML = content.toString();

		//alert( new Date() - start );
		this.ContentPlaceHolder.style.display = '';
	}

	this.__BindAsync = function( collection, itemsPerThreshold )
	{
		if(this.__SyncObject)
		{
			clearTimeout(this.__SyncObject);
			this.__SyncObject = null;
		}

		this.ClearContent();

		for(var i=0; i<_slots.length; i++)
			_slots[i].innerHTML = '';

		this.DataSource = collection;
		this.SlotIndex = 0;
		this.ContentPlaceHolder.style.display = '';
		this.ItemsPerThreshold = itemsPerThreshold || 10;

		if(!this.ContentPlaceHolder.HeaderPH)
		{
			this.ContentPlaceHolder.HeaderPH = document.createElement('span');
			this.ContentPlaceHolder.appendChild( this.ContentPlaceHolder.HeaderPH );
		}
		if(!this.ContentPlaceHolder.ContentPH)
		{
			this.ContentPlaceHolder.ContentPH = document.createElement('span');
			this.ContentPlaceHolder.appendChild( this.ContentPlaceHolder.ContentPH );
		}

		if(!this.ContentPlaceHolder.FooterPH)
		{
			this.ContentPlaceHolder.FooterPH = document.createElement('span');
			this.ContentPlaceHolder.appendChild( this.ContentPlaceHolder.FooterPH );
		}
	
		if( this.HeaderTemplate )
			this.ContentPlaceHolder.HeaderPH.innerHTML = this.HeaderTemplate.Bind( null, null, collection );

		if( this.FooterTemplate )
			this.ContentPlaceHolder.FooterPH.innerHTML = this.FooterTemplate.Bind( null, null, collection );

		this.__SyncObject = setTimeout( String.Format('AjaxRepeater.BindItem("{0}");', _id), 1 );
	}

	this.__BindItem = function(idx)
	{
		if( idx >= this.DataSource.length )
		{
			if( this.OnBindCompleted )
				this.OnBindCompleted();
			this.__SyncObject = null;
			return;
		}

		var content = _slots[this.SlotIndex];
		if( !content )
		{
			content = document.createElement('span');
			_slots[this.SlotIndex] = content;
			this.ContentPlaceHolder.ContentPH.appendChild( content ); 
		}
		var c = new Tesla.StringBuilder();

		for( var i=0; i<this.ItemsPerThreshold && idx+i < this.DataSource.length; i++ )
			c.Append( this.ItemTemplate.Bind( this.DataSource[idx+i], idx+i, this.DataSource ) );
		
		content.innerHTML = c.toString();

		if( this.OnItemDataBound )
			for( var i=0; i<this.ItemsPerThreshold && idx+i < this.DataSource.length; i++ )
				this.OnItemDataBound( content, this.DataSource[idx+i] );

		this.SlotIndex = this.SlotIndex + 1;
		idx = idx + Math.min(this.ItemsPerThreshold, (this.DataSource.length-idx)||1);
		this.__SyncObject = setTimeout( String.Format('AjaxRepeater.BindItem("{0}", {1});', _id, idx), 1 );
		//setTimeout( 'AjaxRepeater.BindItem("'+_id+'", '+this.ItemsPerThreshold+');', 1 );
	}

	this.ClearContent = function()
	{
		if( !_slots.length )
			this.ContentPlaceHolder.innerHTML = '';

		if( this.ContentPlaceHolder.HeaderPH ) this.ContentPlaceHolder.HeaderPH.innerHTML = '';
		if( this.ContentPlaceHolder.FooterPH ) this.ContentPlaceHolder.FooterPH.innerHTML = '';

		this.ContentPlaceHolder.style.display = 'none';
	}

	this.SetTemplate = function(template)
	{
		_template = template;
	}

	this.InnerHTML = function()
	{
		return this.ContentPlaceHolder.innerHTML;
	}

	var span = document.getElementById(id)
	if( span == null )
		return;
	
	this.ContentPlaceHolder = span;
}
AjaxRepeater.Bind = function( id, collection )
{
	var rpt = new AjaxRepeater(id);
	rpt.Bind(collection);
	return rpt;
}
AjaxRepeater.BindTemplate = function( itemTemplate, collection )
{
	var rpt = new AjaxRepeater();
	rpt.ContentPlaceHolder = CreateSpan('ajaxRpt');
	rpt.ItemTemplate = itemTemplate;
	rpt.Bind(collection);
	return rpt.ContentPlaceHolder.innerHTML;
}

//AjaxRepeater


Tesla.UI.Template = function( template )
{
	var _templateInfo = [];
	template = unescape(template);
	var templateIdx = 0;
	var idx = 0;
	for(var i=0; i<template.length; i++)
	{
		i = template.indexOf( '(%', i );
		_templateInfo[templateIdx] = {}
		if( i < 0 )
		{
			_templateInfo[templateIdx].Template = template.substring( idx, template.length );
			_templateInfo[templateIdx].PlaceHolder = null;
			break;
		}
		_templateInfo[templateIdx].Template = template.substring( idx, i );
		_templateInfo[templateIdx].PlaceHolder = template.substring( i+2, template.indexOf( '%)', i ) );
		_templateInfo[templateIdx].SimpleDataBind = VerifySimpleDataBind( _templateInfo[templateIdx].PlaceHolder );
		if( !_templateInfo[templateIdx].SimpleDataBind )
			_templateInfo[templateIdx].PlaceHolder = GetPlaceHolderFunction( _templateInfo[templateIdx].PlaceHolder );

		templateIdx++;
		i = idx = (template.indexOf( '%)', i )+2);
	}

	this.Bind = function( DataItem, Index, Collection )
	{
		var rt = '';
		
		for(var i=0; i<_templateInfo.length; i++)
		{
			rt += _templateInfo[i].Template;
			if( _templateInfo[i].SimpleDataBind )
				rt += DataItem[ _templateInfo[i].SimpleDataBind ];
			else if( _templateInfo[i].PlaceHolder )
				rt += _templateInfo[i].PlaceHolder( DataItem, Index, Collection );
		}
		return rt;
	}
	
	function VerifySimpleDataBind( template )
	{
		var info = template.Trim();
		var t = info.Split('. +-/*()[]%');
		if( t.length == 2 && t[0] == 'DataItem' )
			return t[1];
		return null;
	}
	function GetPlaceHolderFunction( placeHolder )
	{
		return new Function( 'DataItem, Index, Collection', 'return '+placeHolder  );
	}
}
Tesla.UI.Template.Bind = function( template, DataItem )
{
	if( template == null )
		return '';
	else
		template = unescape(template);
	if( DataItem == null )
		DataItem = '';

	var rt = '';
	var idx = 0;
	for(var i=0; i<template.length; i++)
	{
		i = template.indexOf( '(%', i );
		if( i < 0 )
		{
			rt += template.substring( idx, template.length );
			break;
		}
		rt += template.substring( idx, i );
		rt += eval( template.substring( i+2, template.indexOf( '%)', i ) ) );
		i = idx = (template.indexOf( '%)', i )+2);
	}
	return rt;
}
Tesla.UI.TemplateWindow = function( divID, template )
{
	var _template;
	var _div = divID;

	if( divID && GetType(divID) == 'String' ) 
		_div = $( divID );

	if( !_div )
	{
		_div = document.createElement('div')
		document.body.appendChild( _div );
		_div.style.display = 'none';
		_div.innerHTML = template;
		_template = new Tesla.UI.Template(template);	
	}
	else
	{
		template = _div.innerHTML;
		_template = new Tesla.UI.Template(template);
	}
    this.Container = _div;

	this.Show = function(obj, absoluteCenter)
	{
		_div.innerHTML = _template.Bind( obj, null, null );

		if( absoluteCenter )
		{
			_div.style.position = 'absolute';
			_div.style.top = document.body.scrollTop + 210;
			_div.style.left = document.body.scrollLeft + 340;
		}

		_div.style.display = 'block';
		if( this.OnShow )
			this.OnShow();
	}
	this.Hide = function()
	{
		_div.style.display = 'none';
		if( this.OnClose )
			this.OnClose();
	}
	this.SetCenter = function(x, y)
	{
		_div.style.position = 'absolute';
		_div.style.top = x - _div.offsetHeight;
		_div.style.left = y;
	}
}

//Template


Tesla.UI.AjaxWizard = function(id, validateSteps, previousButton, nextButton, finishButton)
{
	var placeHolder = document.getElementById(id);
	var steps = [];
	var stepsName = [];
	var currStep = 0;
	var visible = false;
	var _self = this;

	if(previousButton) 
	{
		previousButton = document.getElementById(previousButton);
		previousButton.style.display = 'none';
		previousButton.onclick = function(){ _self.Previous(); return false; };
	}
	if(nextButton)
	{
		nextButton = document.getElementById(nextButton);
		nextButton.onclick = function(){ _self.Next(); return false; };
	}
	if(finishButton)
	{
		finishButton = document.getElementById(finishButton);
		finishButton.onclick = function(){ _self.Finish(); return false; };
	}

	for(var i=0; i<placeHolder.childNodes.length; i++)
	{
		steps.push( placeHolder.childNodes[i] );
		stepsName.push(  $$(placeHolder.childNodes[i], 'stepName') );
	}

	this.Show = function(stepName)
	{
		if( !steps.length )
			return;

		for(var i=0; stepName&&i<stepsName.length; i++)
			if( stepsName[i] == stepName )
				currStep = i;

		if( previousButton ) previousButton.style.display = (steps.length>1&&currStep>0?'':'none');
		if( nextButton ) nextButton.style.display = (steps.length>1&&currStep<steps.length-1?'':'none');
		if( finishButton ) finishButton.style.display = (currStep==steps.length-1?'':'none');

		visible = true;
		placeHolder.style.display = '';
		for(var i=0; i<steps.length; i++)
			steps[i].style.display = (i==currStep?'':'none');
	}
	this.Hide = function()
	{
		visible = false;
		placeHolder.style.display = 'none';
	}
	this.Previous = function()
	{
		_currStep = Math.max( currStep-1, 0);
		if( this.OnStepChange && !this.OnStepChange( _currStep, stepsName[_currStep] ) )
			return;

		currStep = _currStep;
		if(!currStep && previousButton) previousButton.style.display = 'none';
		if( visible ) this.Show();
	}
	this.Next = function()
	{
		if( validateSteps && !ValidateElement( steps[currStep] ) )
			return;
			
		var _currStep = Math.max(0,Math.min( currStep+1, steps.length-1 ));
		if( this.OnStepChange && !this.OnStepChange( _currStep, stepsName[_currStep] ) )
			return;

		currStep = _currStep;
		if( visible ) this.Show();
	}
	this.CurrentStep = function()
	{
		return currStep;
	}
	this.TotalSteps = function()
	{
		return steps.length;
	}
	this.IsCurrentStepValid = function()
	{
		return ValidateElement( steps[currStep] );
	}
	this.Finish = function()
	{
		if(this.IsCurrentStepValid())
		{ 
			document.getElementById('hd'+id).value = 1;
			var currElem = placeHolder;
			while( !currElem.tagName || currElem.tagName.toLowerCase() != 'form' )
				currElem = currElem.parentNode;
			currElem.submit();
		}
	}
	var ValidateElement = function( elem )
	{
		var attribs = elem.attributes;

		var validationType = GetAttributeValue( attribs, 'ValidationType', true );
		if( validationType )
		{
			var validationProperty = GetAttributeValue( attribs, 'ValidationProperty', true );
			if( !validationProperty ) validationProperty = GetValidationProperty( elem );
			var validationMessage = GetAttributeValue( attribs, 'ValidationMessage', true );

			var rt = true;
			if( validationType.indexOf('|') > 0 )
			{
				var types = validationType.Split('|');

				for(var i = 0; i<types.length; i++)
				{
					if( !Validate( elem[validationProperty], types[i] ) )
					{
						validationMessage = validationMessage.Split('|')[i];
						rt = false;
						break;
					}
				}
			}
			else
				rt = Validate( elem[validationProperty], validationType );
			
			if( !rt )
			{
				if(_self.OnStepError )
					_self.OnStepError( elem, validationMessage );
				return false;
			}
		}

		for(var i=0; i<elem.childNodes.length; i++)
			if(!ValidateElement(elem.childNodes[i]))
				return false;
		return true;
	}
	
	var GetValidationProperty = function( elem )
	{
		switch( elem.tagName.toLowerCase() )
		{
			case 'input': 
			case 'select': 
				return 'value';
		}
		return '';
	}
	var Validate = function( value, type )
	{
		if( type.indexOf(':') > 0 )
			return eval( String.Format('{0}("{1}")', type.substr(7,type.length), value) );

		if( value === undefined )
			value = null;

		switch( type.toLowerCase() )
		{
			case 'number': return Validadores.ValidaNumero( value );
			case 'date': return Validadores.ValidaData( value );
			case 'email': return Validadores.ValidaEmail( value );
			case 'cpf': return Validadores.ValidaCPF( value );
			case 'cnpj': return Validadores.ValidaCNPJ( value );
			case 'required': return (value!=null&&(value||value.toString().length))?true:false;
		}
		return true;
	}

	var GetAttributeValue = function( attributes, name, caseInsensitive )
	{
		if( !attributes || !attributes.length )
				return;

		if( attributes[name] )
			return attributes[name].value;

		if( caseInsensitive )
			name = name.toLowerCase();

		for(var i=0; i<attributes.length; i++)
		{
			if( !attributes[i].name )
				continue;
			if( caseInsensitive && name == attributes[i].name.toLowerCase() )
				return attributes[i].value;
			else if( !caseInsensitive && name == attributes[i].name )
				return attributes[i].value;
		}
		return null;
	}
}

//AjaxWizard


Tesla.Enumerator = function(moveNextFn, currentItemFn)
{
	this._MoveNext = moveNextFn;
	this._CurrentItem = currentItemFn;

	this.MoveNext = function()
	{
		this.Current = this._CurrentItem();
		return this._MoveNext();
	}
	this.GetEnumerator = function()
	{
		return this;
	}
}

Tesla.Collection.Stack = function()
{
	this.Index = 0;
	this.Push = function( item )
	{
		this[this.Index++] = item;
	}
	this.Pop = function()
	{
		var rt = this[--this.Index];
		if( this.Index < 0 )
			this.Index = 0;
		return rt;		
	}
}
Tesla.Collection.Stack.name = 'Tesla.Collection.Stack';

Array.prototype.GetEnumerator = function()
{
	var arr = this;
	var idx = 0;

	var rt = new Tesla.Enumerator( function(){ if(idx >= arr.length) return false; idx++; return true; }, function(){ return arr[idx]; } ); 
	return rt;
}

Array.prototype.Top = function(count)
{
	var size = Math.min( count, this.length );
	var rt = new Array(size);
	for(var i=0; i<size; i++)
		rt[i] = this[i];

	return rt;
}

Array.prototype.Add = function(obj)
{
	var rt = this.length;
	this[this.length] = obj;
	return rt;
}
Array.prototype.IndexOf = function( value )
{
	for(var i=0; i<this.length; i++)
		if( this[i] == value )
			return i;
	return -1;
}
Array.prototype.Contains = function( obj )
{
	if( obj && GetType(obj) == 'Function' )
	{
		for(var i=0; i<this.length; i++)
			if( obj(this[i]) )
				return true;
		return false;
	}
	return this.IndexOf(obj) >= 0;
}
Array.prototype.FindByProperty = function( value, property )
{
	for(var i=0; i<this.length; i++)
		if( this[i][property] == value )
			return this[i];
	return null;
}
Array.prototype.RemoveAt = function(idx)
{
	if( idx >= this.length || idx < 0)
		return;

	for(var i=idx; i<this.length; i++)
		this[i] = this[i+1];

	this.length = this.length-1;
}
Array.prototype.Remove = function( value )
{
	this.RemoveAt( this.IndexOf(value) );
}
Array.prototype.Clear = function()
{
	this.length = 0;
}
Array.prototype.ForEach = function( action, predicate )
{
	if( GetType(action) == 'String' )
		action = $L(action);	

	if( predicate && GetType(predicate) == 'String' )
		predicate = $L(predicate);	

	for(var i=0; i<this.length; i++)
		if( !predicate || predicate(this[i]) )
			action( this[i] );
}
Array.prototype.Search = function( predicate )
{
	var rt = [];
	for(var i=0; i<this.length; i++)
		if( predicate(this[i]) )
			rt.Add( this[i] );
	return rt;	
}
Array.prototype.FindFirst = function( predicate )
{
	for(var i=0; i<this.length; i++)
		if( predicate(this[i]) )
			return this[i];
	return null;
}
Array.prototype.FindFirstIndex = function( predicate )
{
	for(var i=0; i<this.length; i++)
		if( predicate(this[i]) )
			return i;
	return -1;
}
Array.prototype.Clone = function()
{
	var rt = [];
	for(var i=0; i<this.length; i++)
		rt.Add( this[i] );
	return rt;
}

Array.prototype.ListRange = function(start, end)
{
	var idx = start;
	end = Math.min( this.length, end );
	var arr = this;
	var en = new Tesla.Enumerator( function(){ idx++; return idx<=end; }, function(){ return arr[idx]; } );
	return en;
}

Object.CompareTo = function( obj2 )
{
	if(this > obj2)
		return 1;
	else if(this < obj2)
		return -1;
	return 0;
}

String.prototype.CompareTo = Object.CompareTo;
Number.prototype.CompareTo = Object.CompareTo;
Date.prototype.CompareTo = Object.CompareTo;

window.SystemLambdas = {};
function $F(lambda)
{
	if( arguments.length == 1 && window.SystemLambdas[lambda] )
		return window.SystemLambdas[lambda];

	var parts = lambda.split('=>');
	var parameters = parts[0].Trim().TrimStart('(').TrimEnd(')').Trim();
	
	parts.RemoveAt(0);
	parts = parts.join('=>');
	var code = String.Format('{0};', parts);

	if( arguments.length > 1 )
	{
		for(var i=1; i<arguments.length; i++)
			code = 'var p'+i+' = arguments.callee.p'+i+';\r\n' + code;

		var rt = new Function( parameters, code );
		for(var i=1; i<arguments.length; i++)
			rt['p'+i] = arguments[i];
		return rt;
	}
	
	var rt = new Function( parameters, code );
	window.SystemLambdas[lambda] = rt;
	return rt;
}
function $L(lambda)
{
	if( arguments.length == 1 && window.SystemLambdas[lambda] )
		return window.SystemLambdas[lambda];

	var parts = lambda.split('=>');
	var parameters = parts[0].Trim().TrimStart('(').TrimEnd(')').Trim();
	
	parts.RemoveAt(0);
	parts = parts.join('=>');
	var code = String.Format('return {0};', parts);

	if( arguments.length > 1 )
	{
		for(var i=1; i<arguments.length; i++)
			code = 'var p'+i+' = arguments.callee.p'+i+';\r\n' + code;

		var rt = new Function( parameters, code );
		for(var i=1; i<arguments.length; i++)
			rt['p'+i] = arguments[i];
		return rt;
	}
	
	var rt = new Function( parameters, code );
	window.SystemLambdas[lambda] = rt;
	return rt;
}

Array.prototype.SkipWhile = function(whereClause)
{
	if( GetType(whereClause) == 'String' )
		whereClause = $L.apply(null, arguments);

	var rt = [];
	var i = 0;
	for(i=0; i<this.length; i++)
		if( !whereClause( this[i] ) )
			break;
	for(;i<this.length; i++)
		rt.push( this[i] );
	
	return rt;
}

Array.prototype.Where = function(whereClause)
{
	if( GetType(whereClause) == 'String' )
		whereClause = $L.apply(null, arguments);
	
	var rt = [];
	for(var i=0; i<this.length; i++)
		if( whereClause(this[i]) )
			rt.push(this[i]);
	return rt;
}

Array.GetComparator = function(sortClause)
{
	if( !sortClause )
		return $L('i1,i2 => i1.CompareTo(i2)');

	if( GetType(sortClause) == 'Function' )
		return sortClause;
		
	if( sortClause.indexOf('=>') < 0 )
	{
		var sorts = sortClause.Trim().Split(',');
	
		if( sorts.length == 1 )
		{
			var s = sorts[0].Trim().split(' ');

			if( s.length > 1 && s[1].toLowerCase() == 'desc' )
				sortClause = String.Format('i1, i2 => i2.{0}.CompareTo(i1.{0})', s[0]);
			else
				sortClause = String.Format('i1, i2 => i1.{0}.CompareTo(i2.{0})', s[0]);
		}
		else
		{
			var code = 'i1, i2 => ';
			
			for(var i =0; i<sorts.length; i++)
			{
				var s = sorts[i].Trim().split(' ');
				if( s.length > 1 && s[1].toLowerCase() == 'desc' )
					code += String.Format('( i2.{0}.CompareTo(i1.{0}) ? i2.{0}.CompareTo(i1.{0}) : ', s[0]);
				else
					code += String.Format('( i1.{0}.CompareTo(i2.{0}) ? i1.{0}.CompareTo(i2.{0}) : ', s[0]);
			}
			
			code += '0';
			
			for(var i =0; i<sorts.length; i++)
				code += ')';
			
			sortClause = code;
		}
	}
	return $L(sortClause);
}

Array.prototype.OrderBy = function(sortClause)
{
	var rt = [];
	for(var i=0; i<this.length; i++)
		rt.push( this[i] );

	rt.sort(Array.GetComparator(sortClause));
	return rt;
}

Array.prototype.Select = function(selectStatement)
{
	if( !selectStatement )
		selectStatement = $L('i => i');
		
	if( GetType(selectStatement) == 'String' )
	{
		if( selectStatement.indexOf('=>') < 0 )
			selectStatement = String.Format('i => i.{0}', selectStatement);

		selectStatement = $L.apply(null, arguments);
	}
	
	var rt = [];
	for(var i=0; i<this.length; i++)
		rt.push(selectStatement(this[i]));
	return rt;
}

Array.prototype.First = function(whereClause)
{
	if( !this.length )
		return null;

	if( !whereClause )
		return this[0];	

	if( GetType(whereClause) == 'String' )
		whereClause = $L.apply(null, arguments);

	for(var i=0; i<this.length; i++)
		if( whereClause(this[i]) )
			return this[i];

	return null;
}

Array.prototype.Last = function(whereClause)
{
	if( !this.length )
		return null;

	if( !whereClause )
		return this[this.length-1];	

	if( GetType(whereClause) == 'String' )
		whereClause = $L.apply(null, arguments);

	for(var i=this.length-1; i>=0; i--)
		if( whereClause(this[i]) )
			return this[i];

	return null;
}

Array.prototype.Count = function(whereClause)
{
	if( !this.length )
		return 0;

	if( !whereClause )
		return this.length;	

	if( GetType(whereClause) == 'String' )
		whereClause = $L.apply(null, arguments);

	var c = 0;
	for(var i=0; i<this.length; i++)
		if( whereClause(this[i]) )
			c++;

	return c;
}

Array.prototype.Distinct = function(comparator, sort)
{
	if( !this.length )
		return [];
		
	var arr = this;
	if( sort )
		arr = this.OrderBy(comparator);
		
	var rt = [];
	comparator = Array.GetComparator(comparator);
	
	if( arr.length > 1 )
		if( comparator(arr[0], arr[1]) )
			rt.push( arr[0] );
	
	for(var i=0; i<arr.length; i++)
		if(arr[i+1] && comparator(arr[i], arr[i+1]) != 0 )
			rt.push( arr[i+1] );
	return rt;
}



Tesla.Collection.Dictionary = function()
{
	this.Keys = [];
	this.Values = [];

	this.Add = function(key, value)
	{
		this.Remove( key );
		this.Keys.Add( key );
		this.Values.Add(value);
		this[key] = value;
	};
	this.RemoveAt = function(idx)
	{
		var key = this.Keys[idx];
		this[key] = null;
		this.Keys.RemoveAt(idx);
		this.Values.RemoveAt(idx);
	}
	this.Remove = function(key)
	{
		var idx = this.Keys.IndexOf(key);
		if( idx < 0 )
			return;

		this.RemoveAt(idx);
	}
	this.ToString = function()
	{
		var rt = '';
		for( var i=0; i<this.Keys.length; i++)
			rt += String.Format('{0}={1}&', this.Keys[i], this.Values[i] );

		return rt.substr(0, rt.length-1 );
	}
}
Tesla.Collection.Dictionary.name = 'Tesla.Collection.Dictionary';
Tesla.Collection.Dictionary.Create = function(st)
{
	var rt = new Tesla.Collection.Dictionary();
	if( !st || !st.length )
		return rt;

	var values = st.Split( '&' );
	for(var i=0; i<values.length; i++)
	{
		if( !values[i] || values[i].length == 0 )
			continue;
		var v = values[i].Split('=');
		rt.Add( v[0], v[1] );
	}
	return rt;
}

//Collection


Tesla.StringBuilder = function()
{
	var strings = [];
	var accum = '';
    
	this.AppendFormat = function()
	{
		if( !arguments.length || !arguments[0].length ) return '';
		var format = arguments[0];
		if( String._Formats[ format ] )
		{
			this.Append( String._Formats[ format ]( arguments ) );
			return;
		}
		var l = format.length-1;
		var j = 0;
		var rt = [];
		for(var i=0; i<format.length; i++)
		{
			if( format.charAt(i) == '{' && i < l && format.charAt(i+1) != '{' )
			{
				rt.push( (rt.length?'+"':'"')+format.substring(j, i).Replace('"', '\\"')+'"' );
				j = i;
				while( format.charAt(j) != '}' )
					j++;
				var formats = format.substring( i+1, j ).split(':');
				if( formats.length == 1 ) rt.push( '+args['+(parseInt(formats[0])+1)+']' );
				else rt.push( '+args['+(parseInt(formats[0])+1)+'].ToString("'+formats[1]+'")' );
				j++;
			}
		}
		rt.push( (rt.length?'+"':'"')+format.substring(j, format.length).Replace('"', '\\"')+'"' );
		var script = 'return '+rt.join('')+';';
		String._Formats[ format ] = new Function( 'args', script );
		this.Append( String._Formats[ format ]( arguments ) );
	}
	this.Append = function(value)
	{
		if(value ===null || value === undefined || (GetType(value) == String && !value.length) )
			return;

		value = value.toString();

		accum += value;
		if( accum.length >= 2800 )
		{
			strings.push(accum);
			accum = '';
		}
	}
	this.Clear = function()
	{
		strings.length = 0;
	}
	this.GetLength = function()
	{ 
		return strings.length;
	}
	this.toString = function()
	{
		if( accum.length )
		{
			strings.push( accum );
			accum = '';
		}
		var rt = strings.join('');
		strings = [rt];
		return rt;
	}
}

//StringBuilderJS


Tesla.ImageGallery = function(id, rows, cols, callBackFunction)
{
    var allFiles = window[id+'_ImageGalleryFiles'];
    var files = allFiles;
    var ph = $(id);
    var txtAutoComplete = $(id+'_autocomplete');
    var autoCompleteList = $(id+'_autocomplete_list');

    this.Search = function()
    {
		files = allFiles.Where('i => i.Name.IsEqualsOrStartsWith(p1, 1)', txtAutoComplete.value);
		this.SetPage(0);
    }
    
    this.SetPage = function(page)
    {
		autoCompleteList.style.display = 'none';
        var sb = new Tesla.StringBuilder();
        var start = page * cols * rows;
        var end = Math.min( start + (cols*rows), files.length );
        
        for(var i=start; i<end; i++)
        {
            var div = String.Format('<div style="float:left;width:90px;height:85px;"><div onclick="Tesla.ImageGallery.Select( this, \'{4}\', {1}, \'{2}\')" onmouseover="if(!Tesla.ImageGallery.IsSelected(\'{4}\', this)) this.className=\'tlg_image_hover\';" onmouseout="if(!Tesla.ImageGallery.IsSelected(\'{4}\', this)) this.className=\'tlg_image\';" class="tlg_image" style="cursor:pointer;width:90px;height:65px;background-image:url({0});background-position:center;background-repeat:no-repeat;"></div><div style="width:90px;height:17px;overflow:hidden;text-align:center;font-size:12px">{3}</div></div>', files[i].UrlThumb, callBackFunction, files[i].Url, files[i].Name, id );
            sb.Append(div);
        }
        
        while( ((end) % cols != 0) )
        {
			sb.Append("<div style='float:left;width:90px;height:85px;overflow:hidden'>&nbsp;</div>");
			end++;
		}

        sb.Append( GetPagingHtml(page) );
        ph.innerHTML = sb.toString();
    }

    function GetPagingHtml(page)
    {
    	var totalPages = parseInt(files.length/(cols*rows));
		if( (files.length % (cols*rows)) )
			totalPages++;

        var sb = new Tesla.StringBuilder();
		sb.Append( "<div><div class='tlg_paging_title' style='float:left'>Páginas:</div>" );
	
		var start = Math.max( 0, page - 4 );
		var end = Math.min(start + 9, totalPages);
		
		for(var i=start; i<end; i++)
		{
			if( i == page )
				sb.Append( String.Format( "<div style='float:left' class='tlg_paging_currentpage'>{0}</div>", i+1 ) );
			else
				sb.Append( String.Format( "<div style='float:left;cursor:pointer' class='tlg_paging_page' onclick='page[\"{2}\"].SetPage({1})'>{0}</div>", i+1, i, id ) );
		}
		
		sb.Append("</div>");
		return sb.toString();
    }
    
    this.GetFiles = function(fileNameStart)
    {
		return allFiles.Select('i => i.Name').Search($L('i => i.IsEqualsOrStartsWith(p1, 1)', fileNameStart)).Top(5);
    }
    
    this.SetPage(0);
}
Tesla.ImageGallery.Create = function(id, rows, cols, callback)
{
    page[id] = new Tesla.ImageGallery(id, rows, cols, callback);
	Tesla.ImageGallery[id] = page[id];
}
Tesla.ImageGallery.IsSelected = function( id, div )
{
	return Tesla.ImageGallery[id].SelectedImage && Tesla.ImageGallery[id].SelectedImage.Div == div;
}
Tesla.ImageGallery.Select = function( div, id, callBack, imageName )
{
	if( Tesla.ImageGallery[id].SelectedImage )
		Tesla.ImageGallery[id].SelectedImage.Div.className = 'tlg_image';

	Tesla.ImageGallery[id].SelectedImage = { Div: div, Image: imageName };
	div.className = 'tlg_image_selected';
	callBack(imageName.substr(imageName.lastIndexOf('/')+1));
}
//ImageGallery


Object.CopyProperties = function(source, destination) 
{
	for (var property in source)
	{
		try { if(typeof(source[property])!=='function') destination[property] = source[property]; }
		catch(ex){ }
	}
}
Object.CopyFunctions = function(source, destination) 
{
	for (var property in source)
	{
		try { if(typeof(source[property])=='function') destination[property] = source[property]; }
		catch(ex){ }
	}
	destination.toString = source.toString;
}
function GetType(obj)
{
	if( obj.constructor )
		return obj.constructor.GetName(self);
	return null;
}
function Serialize()
{
	var type = GetType(this);
	if( type === 'String' )
		return "'"+this+"'";
	else if( type === 'Number' )
		return this.toString();
	else if( type === 'Array' )
	{
		var rt = '[ ';
		for(var i=0; i<this.length; i++)
		{
			var j = this[i];
			if( j )
				rt += this[i].Serialize();
			else
				rt += 'null';
			if( i<this.length-1 )
				rt += ', ';
		}
		return rt + ' ]';
	}
	var rt = '{ ';
	for(var prop in this)
	{
		try
		{
			if( !this[prop] || this[prop] instanceof Function )
				continue;
			rt += prop + ':' + this[prop].Serialize() + ', ';
		}
		catch(ex)
		{
		}
	}
	if( rt.length > 2 )
		rt = rt.substring( 0, rt.length-2 );
	return rt+' }';
}

//Object


String.Empty = '';
String.None = 'none';

String.prototype.Capitalize = function()
{
	if( !String.Accents )
		String.InitializeAccents();

	var t = this;
	var rt = '';

	var oldC = null;
	for(var i=0; i<t.length; i++)
	{
		var c = t.charAt(i);
		if( oldC && ( (oldC>='a' && oldC<='z') || ( oldC>='A' && oldC<='Z') || (oldC>='0' && oldC<='9') || String.Accents[oldC] ) )
			rt += c.toLowerCase();
		else
			rt += c.toUpperCase();

		oldC = c;
	}
	return rt;	
}
String.prototype.Equals = function( text, ignoreCase )
{
	var t1 = ignoreCase ? this.toLowerCase() : this;
	var t2 = ignoreCase ? text.toLowerCase() : text;

	return t1 == t2;	
}
String.prototype.IsEqualsOrStartsWith = function( text, ignoreCase )
{
	return this.Equals(text, ignoreCase) || this.StartsWith(text, ignoreCase);
}
String.prototype.Left = function( tamanho, str )
{
	var rt = this;
	if( tamanho < rt.length )
		return rt.substr( 0, tamanho ) + (str||'');

	return rt;
}
String.prototype.Right = function( t )
{
	var rt = this;
	if( rt.length < t )
		return rt;

	return rt.substr( rt.length-t, t );
}
String.prototype.TrimStart = function(c) 
{
    if( !c )
        c = ' ';
	var rt = this;
	while(rt.substring(0,1) == c)
	{
		rt = rt.substring(1, rt.length);
	}
	return rt;
}
String.prototype.TrimEnd = function(c) 
{
    if( !c )
        c = ' ';
	var rt = this;
	while(rt.substring(rt.length-1, rt.length) == c)
	{
		rt = rt.substring(0,rt.length-1);
	}
	return rt;
}
String.prototype.Trim = function(c) 
{
    if( !c )
        c = ' ';
	return this.TrimEnd(c).TrimStart(c);
}
String.prototype.RemoveAccent = function()
{
	if( !String.Accents )
		String.InitializeAccents();

	var _st = this;
	var rt = '';
	for(var idx=0; idx<_st.length; idx++)
	{
		var ch = _st.charAt(idx);
		ch = (String.Accents[ch] || ch);
		rt += ch
	}
	return rt;
}
String.InitializeAccents = function()
{
	var accents = {};
	accents['á'] = accents['à'] = accents['ã'] = accents['â'] = accents['ä'] = 'a';
	accents['Á'] = accents['À'] = accents['Ã'] = accents['Â'] = accents['Ä'] = 'A';
	accents['é'] = accents['è'] = accents['ê'] = accents['ë'] = 'e';
	accents['É'] = accents['È'] = accents['Ê'] = accents['Ë'] = 'E';
	accents['í'] = accents['ì'] = accents['î'] = accents['ï'] = 'i';
	accents['Í'] = accents['Ì'] = accents['Î'] = accents['Ï'] = 'I';
	accents['ó'] = accents['ò'] = accents['ô'] = accents['õ'] = accents['ö'] = 'o';
	accents['Ó'] = accents['Ò'] = accents['Ô'] = accents['Õ'] = accents['Ö'] = 'O';
	accents['ú'] = accents['ù'] = accents['û'] = accents['ü'] = 'u';
	accents['Ú'] = accents['Ù'] = accents['Û'] = accents['Ü'] = 'U';
	accents['ç'] = 'c'; accents['Ç'] = 'C';
	accents['ñ'] = 'n'; accents['Ñ'] = 'N';
	accents['ÿ'] = accents['ý'] = 'y';
	accents['Ý'] = 'Y';
	String.Accents = accents;
}
String.WhenNullOrEmpty = function( text, ifNullValue, notNullFormat )
{
	if( String.IsNullOrEmpty( text ) )
		return ifNullValue;

	if( notNullFormat )
		return String.Format( notNullFormat, text );
	
	return text;
}
String.prototype.ToString = function(formato) 
{
	return this;
}
String.Parse = function(value)
{
	if( value.ToString )
		return value.ToString();
	return value.toString();
}

String.Concat = function()
{
	var rt = '';
	for( var i=0; i<arguments.length; i++ )
	{
		if( arguments[i] == null )
			return null;

		rt += arguments[i];
	}
	return rt;
}

String._Formats = {};
String.Format = function()
{
	if( !arguments.length || !arguments[0].length ) return '';
	var format = arguments[0];
	if( String._Formats[ format ] ) return String._Formats[ format ]( arguments );
	var l = format.length-1;
	var j = 0;
	var rt = [];
	for(var i=0; i<format.length; i++)
	{
		if( format.charAt(i) == '{' && i < l && format.charAt(i+1) != '{' )
		{
			rt.push( (rt.length?'+"':'"')+format.substring(j, i).Replace('"', '\\"')+'"' );
			j = i;
			while( format.charAt(j) != '}' )
				j++;
			var formats = format.substring( i+1, j ).split(':');
			if( formats.length == 1 ) rt.push( '+args['+(parseInt(formats[0])+1)+']' );
			else rt.push( '+args['+(parseInt(formats[0])+1)+'].ToString("'+formats[1]+'")' );
			j++;
		}
	}
	rt.push( (rt.length?'+"':'"')+format.substring(j, format.length).Replace('"', '\\"')+'"' );
	var script = 'return '+rt.join('')+';';
	String._Formats[ format ] = new Function( 'args', script );
	return String._Formats[ format ]( arguments );
}
String.prototype.Split = function(separadores) 
{
	var count = 0;
	var txt = this;
	var last = false;
	for(var i=0; i<txt.length; i++)
	{
		for(var j=0; j<separadores.length; j++)
		{
			if( txt.charAt(i) == separadores.charAt(j) )
			{
				if( i == txt.length-1 )
					last = true;
				count++;
			}
		}
	}
	var rt = new Array(count+1);
	var start = 0;
	var idx = 0;
	for(var i=0; i<txt.length; i++)
	{
		for(var j=0; j<separadores.length; j++)
		{
			if( txt.charAt(i) == separadores.charAt(j) )
			{
				rt[idx] = txt.substr( start, i-start );
				start = i+1;
				idx++;
			}
		}
	}
	if( !last )
		rt[idx] = txt.substr( start, txt.length-start );
	return rt;
}
String.prototype.ToNumber = function(defaultValue)
{
	if( !Validadores.ValidaNumero( this ) )
		return defaultValue || 0;
	return parseInt(this);
}
String.prototype.Replace = function(par1,par2)
{
	par1 = new RegExp(par1, "g");
	var rt = this.replace( par1, par2 );
	return rt;
}
String.Concat = function()
{
	if( arguments.length == 0 )
		return null;
	
	var str = '';
	for(var i=0;i<arguments.length;i++)
		if( arguments[i] == null )
			return null;
		else
			str += arguments[i];

	return str;
}
String.IsNullOrEmpty = function(value, trimmValue) 
{
	if( trimmValue && value != null )
		value = value.Trim();
	return value == null || value.length == 0;
}
String.prototype.StartsWith = function(text, ignoreCase)
{
	var _this = ignoreCase? this.toLowerCase() : this;
	var _str = ignoreCase ? text.toLowerCase() : text;
	
	for(var i=0; i<_str.length; i++)
		if( _this.charAt(i) != _str.charAt(i) )
			return false;
	return true;
}

String.prototype.EndsWith = function(text, ignoreCase)
{
	if( this.length < text.length )
		return false;

	var text1 = (ignoreCase?this.toLowerCase():this);
	var text2 = (ignoreCase?text.toLowerCase():text);

	var j = text1.length - text2.length;
	for(var i=0; i<text2.length; i++)
	{
		if( text1.charAt(j++) != text2.charAt(i) )
			return false;
	}
	return true;
}

String.prototype.IsDigit = function(idx)
{
	idx = idx || 0;
	var c = this.charAt(idx) || ' ';
    return ((c >= '0') && (c <= '9'));
}

String.prototype.IsLetter = function(idx)
{
	idx = idx || 0;
	var c = this.charAt(idx).toLowerCase() || ' ';
    return ((c >= 'a') && (c <= 'z'));
}

String.prototype.IsLetterOrDigit = function(idx)
{
    return this.IsLetter(idx) || this.IsDigit(idx);
}

String.UTF8 = new function()
{
	this.Encode = function (text) 
	{
		text = text.replace(/\r\n/g,'\n');
		var utftext = '';

		for (var n = 0; n < text.length; n++) 
		{
			var c = text.charCodeAt(n);
			if (c < 128) 
				utftext += String.fromCharCode(c);
			else if((c > 127) && (c < 2048)) 
			{
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else 
			{
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
		}

		return utftext;
    }

    this.Decode = function (utftext) 
	{
		var rt = '';
		var i = 0;
		var c = c1 = c2 = 0;

		while ( i < utftext.length ) 
		{
			c = utftext.charCodeAt(i);

			if (c < 128) 
			{
				rt += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) 
			{
				c2 = utftext.charCodeAt(i+1);
				rt += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else 
			{
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				rt += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}

		}

		return rt;
	}
}
//StringFunctions


Tesla.ImageCropper = function(id, height, width, resourcePath)
{
	this.ID = id;
	this.Height			= height;
	this.Width			= width;
	this.ImageControl	= $('__img_'+id);
	this.ImageControl.Parent = this;
	this.ImageControl.onload = function(){ this.Parent.CreateCropArea(); };

	this.SetImage = function(serverPath)
	{
		if( this.ImageControl.src == page.ResolveUrl(serverPath) && this.ImageControl.style.display == String.Empty )
		{
			this.CreateCropArea();
			return;
		}

		this.ServerPath = serverPath;
		this.ImageControl.src = page.ResolveUrl(serverPath);
		this.ImageControl.style.display = String.Empty;
	}
	
	this.UpdatePositionH = function(x, y)
	{
		if( this.Y === null ) this.Y = y;
		var diffY = y - this.Y;
		if( !diffY ) return;
			
		var size1 = this.CurrentHeight + diffY;
		var size2 = this.MaxBorderSize - size1;

		if( size1 > this.MaxBorderSize )
		{
			size1 = this.MaxBorderSize -1;
			size2 = 0;
		}
		else if( size2 > this.MaxBorderSize )
		{
			size2 = this.MaxBorderSize -1;
			size1 = 0;
		}
		this.CropArea1.style.height = size1 + 'px';
		this.CropArea3.style.height = size2 + 'px';
	}
	
	this.UpdatePositionV = function(x, y)
	{
		if( this.X === null ) this.X = x;
		var diffX = x - this.X;
		if( !diffX ) return;
			
		var size1 = this.CurrentWidth + diffX;
		var size2 = this.MaxBorderSize - size1;

		if( size1 > this.MaxBorderSize )
		{
			size1 = this.MaxBorderSize -1;
			size2 = 0;
		}
		else if( size2 > this.MaxBorderSize )
		{
			size2 = this.MaxBorderSize -1;
			size1 = 0;
		}
		this.CropArea1.style.width = size1 + 'px';
		this.CropArea3.style.width = size2 + 'px';
	}
	
	this.CreateCropArea = function()
	{
		var v1 = this.ImageControl.height / this.Height;
		var v2 = this.ImageControl.width / this.Width;
		
		//Não requer crop, imagem perfeita
		if( v1 == v2 )
		{
			this.CropType = 'None';
			return;
		}

		if( this.TestSize && (this.ImageControl.height < this.Height || this.ImageControl.width < this.Width) )
		{
			this.ImageControl.style.display = 'none';
			alert(String.Format('Tamanho insuficiente para crop.\\r\\nA imagem precisa ser maior ou igual a (H:{0},W:{1})', this.Height, this.Width));
			return;
		}

		var vMin = Math.min(v1, v2);
		var vMax = Math.max(v1, v2);

		$(id+'Image').style.height = (this.ImageControl.height/vMin) + 'px';
		$(id+'Image').style.width = (this.ImageControl.width/vMin)  + 'px';
		
		this.ImageControl.width = (this.ImageControl.width/vMin);
		if( vMin == v1 )
			this.CreateCropAreaV();
		else
			this.CreateCropAreaH();
	}
	
	this.CreateCropAreaH = function()
	{
		this.CropType = 'Horizontal';
		var placeHolder = $(id+'PlaceHolder');
		placeHolder.innerHTML = String.Format( "<div id='__{0}' style='z-index:1000;position:absolute;display:none;'><div id='__c1_{0}' style='overflow:hidden;background-color:Black;opacity:0.7;filter:alpha(opacity=70);background-image:url({1}/h.gif);background-repeat: repeat-x;background-position:bottom'></div><div id='__c2_{0}' style='background-color:White;opacity:0.01;filter:alpha(opacity=1);cursor:move;' onmousedown='Tesla.ImageCropper.MouseHook(\"{0}\", 1);' onmouseup='Tesla.ImageCropper.MouseHook(\"{0}\", 0);'></div><div id='__c3_{0}' style='overflow:hidden;background-color:Black;opacity:0.7;filter:alpha(opacity=70);background-image:url({1}/h.gif);background-repeat: repeat-x;background-position:top'></div></div>", id, page.ResolveUrl(resourcePath).TrimEnd('/') );
		this.Container = $('__'+id);
		this.CropArea1 = $('__c1_'+id);
		this.CropArea2 = $('__c2_'+id);
		this.CropArea3 = $('__c3_'+id);

		var size = ((this.ImageControl.clientHeight - this.Height)/2);
		
		this.CropArea1.style.height = size + 'px';
		this.CropArea1.style.width = this.ImageControl.width + 'px';

		this.CropArea2.style.height = (this.ImageControl.clientHeight - ((this.ImageControl.clientHeight - this.Height))) + 'px';
		this.CropArea2.style.width = this.ImageControl.width + 'px';

		this.CropArea3.style.height = size + 'px';
		this.CropArea3.style.width = this.ImageControl.width + 'px';

		this.Container.style.display = String.Empty;
		this.MaxBorderSize = size*2;
		this.UpdatePosition = this.UpdatePositionH;
		
		this.CropArea1.style.float = '';
		this.CropArea2.style.float = '';
		this.CropArea3.style.float = '';
	}
	
	this.CreateCropAreaV = function()
	{
		this.CropType = 'Vertical';
		$(id+'PlaceHolder').innerHTML = String.Format( "<div id='__{0}' style='z-index:1000;position:absolute;display:none'><div id='__c1_{0}' style='float:left;background-color:Black;opacity:0.7;filter:alpha(opacity=70);background-image:url({1}/v.gif);background-repeat: repeat-y;background-position:right'></div><div id='__c2_{0}' style='float:left;background-color:White;opacity:0.01;filter:alpha(opacity=1);cursor:move;' onmousedown='Tesla.ImageCropper.MouseHook(\"{0}\", 1);' onmouseup='Tesla.ImageCropper.MouseHook(\"{0}\", 0);'></div><div id='__c3_{0}' style='float:left;background-color:Black;opacity:0.7;filter:alpha(opacity=70);background-image:url({1}/v.gif);background-repeat: repeat-y;background-position:left'></div></div>", id, page.ResolveUrl(resourcePath).TrimEnd('/') );
		this.Container = $('__'+id);
		this.CropArea1 = $('__c1_'+id);
		this.CropArea2 = $('__c2_'+id);
		this.CropArea3 = $('__c3_'+id);

		var size = ((this.ImageControl.clientWidth - this.Width)/2);
		
		this.CropArea1.style.width = size + 'px';
		this.CropArea1.style.height = this.ImageControl.height + 'px';

		this.CropArea2.style.width = (this.ImageControl.width - (size*2)) + 'px';
		this.CropArea2.style.height = this.ImageControl.height + 'px';

		this.CropArea3.style.width = size + 'px';
		this.CropArea3.style.height = this.ImageControl.height + 'px';

		this.Container.style.display = String.Empty;
		this.MaxBorderSize = size*2;
		this.UpdatePosition = this.UpdatePositionV;
	}
	
	this.GenerateImage = function(serverPath, ErrorCallBack)
	{
		var startAt = 0;
		if( this.CropType == 'Vertical' ) startAt = parseInt(this.CropArea1.style.width);
		else if( this.CropType == 'Horizontal' ) startAt = parseInt(this.CropArea1.style.height);
		Ajax.ImageCropperGenerateImage( this.ServerPath, serverPath, this.CropType, this.Height, this.Width, startAt, ErrorCallBack || EndGenerateImage );
	}
	function EndGenerateImage(ex)
	{
		if(ex) alert( ex );
	}
}

Tesla.ImageCropper.RegisterControl = function(id, height, width, resourcePath)
{
	if( !Tesla.ImageCropper.Controls )
		Tesla.ImageCropper.Controls = {};
	
	var ctrl = new Tesla.ImageCropper(id, height, width, resourcePath);
	page[id] = Tesla.ImageCropper.Controls[id] = ctrl;
}	

Tesla.ImageCropper.MouseHook = function(id, value)
{
	page[id].X = null;
	page[id].Y = null;
	page[id].CurrentHeight = parseInt(page[id].CropArea1.style.height);
	page[id].CurrentWidth = parseInt(page[id].CropArea1.style.width);

	if( value )
		page.CaptureMouseMove( function(x, y){ page[id].UpdatePosition(x,y) } );
	else
		page.StopCaptureMouseMove();
}//ImageCropper

//PriorityAttribute


page.ApplicationName = '';