/*
Scroll - classe para criação de barras de rolagem no navegador

	Propriedades:
		- Conteudo: id do conteudo que vai receber o scroll
		- AreaVisivel: id da div com o overflow hidden do scroll
		- SetaCima: id do elemento html que vai ser a seta para cima do scroll
		- SetaBaixo: id do elemento html que vai ser a seta para baixo do scroll
		- BotaoArraste: id do elemento html que vai ser o botão de arraste do scroll
		- AreaArraste: id do elemento html que é a área de arraste do scroll
		- Velocidade: velocidade do scroll ao clicar nas setas
		- [TempoIntervalo]: tempo do intervalo entre o incremento dos passos do menu, para controlar melhor a velocidade caso a propriedade 'velocidade' não seja suficiente. Se for omitido, assume 1ms.
		
	Métodos:
		- Init(): inicia todos os eventos e todos os cálculos do scroll. Deve ser executado após serem atribuídas todas as propriedades do scroll
		- Posicionar(): posiciona o scroll em uma certa posição. Recebe essa posição como parametro.
*/

function Scroll()
{
	//armazena o objeto instânciado
	var obj = this;
	
	//inicia as variaveis que serão utilizadas
	var conteudo, areaVisivel; //variaveis do conteudo
	var setaCima, setaBaixo, botaoArraste; //variaveis dos botões de controle
	var velocidade, evento; // variáveis de configuração
	
	//verifica se o navegador é o IE
	var IE = (navigator.userAgent.indexOf('MSIE') > -1 && navigator.userAgent.toLowerCase().indexOf('opera') == -1);
	
	var relacao; //variável que armazena a proporção do tamanho do conteudo em relação ao tamanho da barra de scroll
	var yMaximo; //variavel que armazena o valor máximo de top que o botão do scroll pode ter
	var intervaloMovimento; // variavel que armazena o intervalo do movimento das setas
	var direcao; //varivável que armazena a direção do movimento do conteudo
	var tempoIntervalo; //variavel que armazena o tempo do intervalo entre o movimento do conteúdo
	var movimentarDiretamente; // flag que indica se deve ir diretamente a algum ponto do scroll[se a pessoa clicar na área de arraste]
	
	//Armazena os eventos anteriores
	var prevMouseMove, prevMouseUp;
	
	//Init(): inicia os eventos do scroll
	this.Init = function()
	{
		//armazena os objetos de acordo com as id's passadas dentro de suas respectivas variáveis
		conteudo = document.getElementById(obj.Conteudo);
		areaVisivel = document.getElementById(obj.AreaVisivel);
		setaCima = document.getElementById(obj.SetaCima);
		setaBaixo = document.getElementById(obj.SetaBaixo);
		
		botaoArraste = document.getElementById(obj.BotaoArraste);
		areaArraste = document.getElementById(obj.AreaArraste);
		
		//verifica se foi passado um tempo para o intervalo. Se não foi, o tempo padrão é 1ms
		tempoIntervalo = (obj.TempoIntervalo)? obj.TempoIntervalo : 1;
		
		//armazena a velocidade
		velocidade = obj.Velocidade;
		
		//Efetua os calculos necessários ao scroll
		Calcular();
		
		//altera o position do botão de arraste e da area de arraste itens para o funcionamento correto
		areaArraste.style.position = 'relative';
		botaoArraste.style.position = 'absolute';
		conteudo.style.position = 'absolute';
		
		/*evento = (obj.Evento)? obj.Evento : 'onmousedown';
		var contraEvento = (evento == 'onmousedown') ? 'onmouseup' : 'onmouseout';*/
		
		movimentarDiretamente = true;
		
		//anula o mousemove do botão de arraste para não gerar bugs
		botaoArraste.onmousemove = function(){return false;};
		
		//caso o conteúdo seja menor que a área visível, esconde o scroll
		if(conteudo.offsetHeight < areaVisivel.offsetHeight)
		{
			setaCima.style.visibility = 'hidden';
			setaBaixo.style.visibility = 'hidden';
			botaoArraste.style.visibility = 'hidden';
			areaArraste.style.visibility = 'hidden';
		}
		
		
		if(botaoArraste != null)
		{
			//atribui o mousedown do botão de arraste
			botaoArraste.onmousedown = function(e)
			{
				movimentarDiretamente = false;
				//armazena o evento
				if(!e) e = event;
				
				//armazena a posição do mouse
				var ymouse = (IE) ? e.clientY + document.documentElement.scrollTop : e.pageY;
				
				//calcula a diferença da posição do botão em relação ao mouse
				var dy = ymouse - botaoArraste.offsetTop;
				
				//armazena os eventos anteriores ao scroll, para evitar problemas
				prevMouseMove = document.onmousemove;
				prevMouseUp = document.onmouseup;
				
				document.onmousemove = function(e)
				{
					//armazena o evento do mousemove
					if(!e) e = event;
					//armazena o y do mouse
					ymouse = (IE) ? e.clientY + document.documentElement.scrollTop : e.pageY;
					
					//verifica se  botão é o 0 [0 = o internauta soltou o mouse fora do browser e depois voltou]
					//	- obs: apenas o IE retorna o botão do mouse dentro do mousemove. os demais browsers retornam apenas no onmousedown
					if(IE)
					{
						//caso o botão estiver solto, para o arraste do botão
						if(e.button == 0) document.onmouseup();
					}
					
					//calcula o y para onde o botão de arraste deve ir
					var yFinal = ymouse - dy;
					
					//verifica se o botão não saiu dos limites
					if(yFinal <= 0) yFinal = 0;
					else if(yFinal > yMaximo) yFinal = yMaximo;
					
					//posiciona o botão da barra de rolagem e o conteúdo
					botaoArraste.style.top = yFinal + 'px';
					conteudo.style.top = (yFinal * relacao * -1) + 'px';
				}
				
				//atribui o mouseup em todo o 'document', pois o internauta pode soltar o mouse em qualquer parte da página
				document.onmouseup = function()
				{
					movimentarDiretamente = true;
					//deleta os eventos
					document.onmousemove = prevMouseMove;
					document.onmouseup = prevMouseUp;
				}
				
				//retorna false para anular os outros efeitos do mousemove no browser
				return false;
			}
		}
		
		if(areaArraste != null)
		{
			areaArraste.onmousedown = function(e)
			{
				if(movimentarDiretamente)
				{
					//armazena o evento do mousemove
					if(!e) e = event;
					
					//armazena o y do mouse
					var ymouse = (IE) ? e.clientY + document.documentElement.scrollTop : e.pageY;
					
					var posicaoFinal = ymouse - (GetPosition(areaArraste).y);
					
					obj.Posicionar(posicaoFinal);
				}
			}
		}
		
		if(setaBaixo != null)
		{
			//atribui a direção das setas
			setaCima.direcao = -1;
			setaBaixo.direcao = 1;
			
			//anula o mousemove dos botões para evitar bugs
			setaBaixo.onmousemove = setaCima.onmousemove = function(){return false;};
			//atribui o onmousedown das setas
			setaBaixo.onmousedown = setaCima.onmousedown = function()
			{
				//altera o valor da variável direção de acordo com ao sentido da seta
				direcao = this.direcao;
				
				//move o conteudo
				Mover();
				
				//atribui o onmouseup do conteúdo
				document.onmouseup = function()
				{
					//limpa o intervalo e o evento
					document.onmouseup = null;
					clearTimeout(intervaloMovimento);
				}
				
				//retorna false para anular os outros efeitos do mousedown no browser
				return false;
			}
		}
	}
	
	//GetPosition(): retorna a posição real de um objeto na tela
	//	- alvo: objeto a retornar a posição
	function GetPosition(alvo){
		var parent = alvo;
		
		for(var ol = alvo.offsetLeft, ot = alvo.offsetTop; parent = parent.offsetParent; )
		{
			ol += parent.offsetLeft;
			ot += parent.offsetTop;
		}
		return {x:parseInt(ol),y:parseInt(ot)};
	}
	
	//Posicionar(): posiciona o scroll em alguma posição
	//	- posicao: posição de destino
	this.Posicionar = function(posicao)
	{
		//armazena a posição final
		var yFinal = posicao;
		
		//caso a posição passada seja maior ou menor do que o tamanho permitido, limita
		if(yFinal <= 0) yFinal = 0;
		else if(yFinal > yMaximo) yFinal = yMaximo;
		
		//posiciona o conteudo e o botão do scroll
		conteudo.style.top = (yFinal * relacao * -1) + 'px';
		botaoArraste.style.top = yFinal + 'px';	
	}
	
	//Calcular(): efetua os cálculos necessários ao scroll, deve ser executada sempre que o tamanho do conteúdo for alterado
	function Calcular()
	{
		//calcula a proporção do tamanho da barra de rolagem em relação ao tamanho do conteudo
		relacao = ((conteudo.offsetHeight - areaVisivel.offsetHeight) / (areaArraste.offsetHeight - botaoArraste.offsetHeight));
		
		//calcula o y máximo que o botão de arraste pode ter
		yMaximo = areaArraste.offsetHeight - botaoArraste.offsetHeight;
	}
	
	//Mover(): função interna que move o conteudo e o botão de scroll, de acordo com o valor da variavel direção [-1 sobe o conteudo, e 1 desce o conteudo]
	function Mover()
	{
		//armazena o y final, de acordo com o passo do menu e a direção
		var yFinal = (botaoArraste.offsetTop + velocidade * direcao);
		
		//limita o valor doy final dentro dos valores permitidos
		if(yFinal <= 0) yFinal = 0;
		else if(yFinal > yMaximo) yFinal = yMaximo;
		
		//posiciona o conteudo e o botão de arraste
		conteudo.style.top = (yFinal * relacao * -1) + 'px';
		botaoArraste.style.top = yFinal + 'px';	
		
		//chama novamente a função depois de um tempo
		intervaloMovimento = setTimeout(Mover, tempoIntervalo);
	}
}