//Conjuto de javascripts para fazer o tratamento de objetos select com multiplas seleções (listas)

//Verifica se um determinado option já existe na lista. A verificação é feita pelo value do option
function contains(lista,newvalue)
{
	var contem = -1;

	//Pesquisa sequencial.
	for(var i = 0 ; i < lista.length ; i++)
	{
		if(lista.options[i].value == newvalue)
		{
			contem = i;
			break;	
		}	
	}
	
	return contem;
}

//Adiciona um option como no final da lista. Permite duplicação de options
function additem(lista,newvalue,newlabel)
{
	additem(lista,newvalue,newlabel,true,false);
}

//Adiciona um option como no final da lista. Permite duplicação de options
function additemselected(lista,newvalue,newlabel)
{
	additem(lista,newvalue,newlabel,false,true);
}


//Adiciona um option como no final da lista. É informado de deve-se permitir ou não a duplicacao
function additem(lista,newvalue,newlabel,permiteDuplicacao,selectItem)
{
	//somente é inserido o item se o objeto lista for realmente um select e os newvalue e newlabel sejam direntes de nulo
	if(lista != null && (lista.type == "select-one" || lista.type == "select-multiple") && newvalue != null && newlabel != null && newvalue != "" && newlabel != "")
	{
		//Verifica se precisa testar existencia. Se precisar, o objeto já não deve estar na lista
		if(permiteDuplicacao || (!permiteDuplicacao && contains(lista,newvalue) == -1))
		{			
			//Incrementa um elemento na lista
			lista.length = lista.length+1;
			lista.options[lista.length-1].text = newlabel;
			lista.options[lista.length-1].value = newvalue;
			if(selectItem){
				lista.options[lista.length-1].selected = true;
			}
		}	
	}
}

//Adiciona um array de itens na lista. Somente adiciona se o lista for um select-multiple e se os valores forem um array e do mesmo tamanho.
//Um array é do tipo undefined
function addarray(lista,newarrayvalue,newarraylabel)
{
	if(lista != null && lista.type == "select-multiple" && newarrayvalue != null && newarraylabel != null && newarrayvalue.type == "undefined" && newarraylabe.type == "undefined"  && newarrayvalue.length == newarraylabel.length)
	{
		for(var i = 0 ; i < newarrayvalue.length ; i++)
			additem(lista,newarrayvalue[i],newarraylabel[i]);
	}
}

//Remove um item seleciondo em uma lista, remove o 1º selecionando. Faz um if porque pode ser usado por fora
function remitemsel(lista)
{
	if(lista.selectedIndex > -1)	
		remitem(lista,lista.selectedIndex);
}

//Remove um item de uma lista na posição informada.
function remitem(lista,index)
{
	lista.options[index] = null;
}

//Remove os itens selecionandos em uma lista
function remitems(lista)
{
	//Verificando a lista, removendo somente se for uma lista
	if(lista != null && (lista.type == "select-one" || lista.type == "select-multiple"))
	{	
		//Looping percorrendo os itens da lista e removendo os selecionados
		//Enquanto existirem itens selecionados
		while(lista.selectedIndex > -1)
		{
			remitemsel(lista);			
		}	
	}	
}

//Limpa uma lista por completo
function clearlista(lista)
{
	if(lista != null && (lista.type == "select-one" || lista.type == "select-multiple"))	
	{
		while(lista.options.length > 0)
			remitem(lista,0);
	}
}

//Move os elementos selecionandos na lista uma posição para cima
//Numeros é o numero de paços a subir
function movecima(lista)
{
	deslocaelementos(lista,"c");
}

//Move os elementos selecionandos na lista uma posição para baixo
//Numeros é o numero de paços a subir
function movebaixo(lista,numero)
{
	deslocaelementos(lista,"b");
}

//Realiza o tratamento interno do deslocamento dos elementos na lista
function deslocainterno(lista,acao)
{
	//Variavel string que irá conter, via concatenação, a listagem de elementos selecionados.
	//O caracter separador é -
	var opcSelecionados = "";
	
	//Variavel auxiliar para armazenar o valor
	var auxvalue = "";
	
	//Variavel auxiliar para armazenar o label
	var auxlabel = "";	
	
	//Variavel auxiliar para percorrer os indices em casos de movimentacao para baixo e itens em seguida. Esta variavel é utilizada para trocar elementos, definir qual deverá ser desmarcado, etc...
	var auxindicebaixo = -1;

	//inicializando auxindicebaixo com o indice selecionado
	auxindicebaixo = lista.selectedIndex;
			
	//Armazenando os valores atuais temporáriamente.
	auxvalue = lista.options[lista.selectedIndex].value;
	auxlabel = lista.options[lista.selectedIndex].text;				

	//Verificando o tipo de deslocamento
	//Deslocar para cima. Verifica se o elemento selecionado não é o 1º
	if(acao == "c" && lista.selectedIndex != 0)
	{
		//Setando os valores e texto da anterior na atual e na anterior os valores da atual armazenados nas variaveis auxiliares
		setaValores(lista,auxvalue,auxlabel,lista.selectedIndex,lista.selectedIndex-1);
				
		//Setando na lista de index o index anterior agora como sendo o selecionado.
		opcSelecionados = opcSelecionados + (lista.selectedIndex-1) + "-";										

		//Setando a variavel auxiliar com o selectecindex				
		auxindicebaixo = lista.selectedIndex;
	}
	//Deslocar para baixo. Verifica se o elemento selecionado não é o ultimo
	else if(acao == "b" && lista.selectedIndex != lista.length-1) 
	{
		//Verificando se o proximo indice está marcado ou não. Caso esteja ele é quem deverá ser movido com o abaixo dele.				
		//O looping acontece até encontrar um cujo proximo não esteja amrcado ou não exista próximo.				
		//Verificando se não é o ultimo e se não for se o proximo está marcado
		if(lista.selectedIndex < lista.length-1 && lista.options[lista.selectedIndex+1].selected)
		{
			//Obtendo o indice para controle				
			auxindicebaixo = lista.selectedIndex+1;
					
			//Enquanto não for o final da lista ou o proximo não estiver selecionando, procura até chegar no ultimo selecionado.
			while(auxindicebaixo < lista.length-1 && lista.options[auxindicebaixo+1].selected)				
			{
				auxindicebaixo = auxindicebaixo+1;						
			}					

			//Redefindo os valores porque neste caso não é o 1º objeto selecionado o que deve se trocar o valor, mas sim o ultimo obtido no looping
			auxvalue = lista.options[auxindicebaixo].value;					
			auxlabel = lista.options[auxindicebaixo].text;				
					
			//Setando os valores e texto do posterior na atual e no posterior os valores da atual armazenados nas variaveis auxiliares, nesta caso, se o proximo não for maior que o tamanho da lista
			if(auxindicebaixo < lista.length-1)
				setaValores(lista,auxvalue,auxlabel,auxindicebaixo,auxindicebaixo+1);
			
			//Setando na lista de index o index posterior agora como sendo o selecionado.
			if(auxindicebaixo < lista.length-1)
				opcSelecionados = opcSelecionados + (auxindicebaixo+1) + "-";																												
			else
			   opcSelecionados = opcSelecionados + (auxindicebaixo) + "-";																													
					
			//Não é necessário seta o auxindexbaixo já que no caso tratado acima ele já estará setado corretamente.
		}
		//Não existem itens em sequencia, trada de outra forma.
		else
		{
			//Setando os valores e texto do posterior na atual e no posterior os valores da atual armazenados nas variaveis auxiliares
			setaValores(lista,auxvalue,auxlabel,lista.selectedIndex,lista.selectedIndex+1);
			
			//Setando na lista de index o index posterior agora como sendo o selecionado.
			opcSelecionados = opcSelecionados + (lista.selectedIndex+1) + "-";																	
					
			//Setando a variavel auxiliar com o selectecindex				
			auxindicebaixo = lista.selectedIndex;										
		}	
	}									
	//Descelecionando o item.
	lista.options[auxindicebaixo].selected = false;										

	//Retornando a lista de selecionados	
	return opcSelecionados;
}

//Desloca os elementos para posições acima ou abaixo
//acao = c (para cima)  ou b(para baixo)
function deslocaelementos(lista,acao)
{
	//Variavel string que irá conter, via concatenação, a listagem de elementos selecionados.
	//O caracter separador é -
	var opcSelecionados = "";
	
	//Variavel auxiliar para armazenar o indice
	var indice = -1;
	
	//Variavel auxiliar para armazenar o valor
	var auxvalue = "";
	
	//Variavel auxiliar para armazenar o label
	var auxlabel = "";	
	
	//Variavel auxiliar para percorrer os indices em casos de movimentacao para baixo e itens em seguida. Esta variavel é utilizada para trocar elementos, definir qual deverá ser desmarcado, etc...
	var auxindicebaixo = -1;

	//Se for uma lista e tiver pelo menos um elemento selecionado. O selectedIndex deve ser maior que -1, já que se não estiver selecionado nada. É verificado também se existem somente 1 item de opção
	if(lista != null && (lista.type == "select-one" || lista.type == "select-multiple") && lista.selectedIndex > -1 && lista.length > 1)
	{		
	   if(lista.type == "select-multiple")
		{
			while(lista.selectedIndex > -1)		
				opcSelecionados = opcSelecionados + deslocainterno(lista,acao);				
		}
		else
		{
			if(lista.selectedIndex > -1)		
				opcSelecionados = opcSelecionados + deslocainterno(lista,acao);				
		}

		//Reselecionando os elementos.
		while(opcSelecionados != "" && opcSelecionados != "-" && opcSelecionados.indexOf("-") != -1)
		{
			//Obtendo o indice
			indice = parseInt(opcSelecionados.substring(0,opcSelecionados.indexOf("-")));
			
			//Selecionado
			lista.options[indice].selected = true;										

			//Excluindo da lista de selecionados este item
			opcSelecionados = opcSelecionados.substring(opcSelecionados.indexOf("-")+1,opcSelecionados.length);
		}
	}
}

function setaValores(lista,auxvalue,auxlabel,selectedIndex,novoIndice)
{
	//Setando os valores e texto do novoIndice na atual
	lista.options[selectedIndex].value = lista.options[novoIndice].value;			
	lista.options[selectedIndex].text = lista.options[novoIndice].text;			
				
	//Setando no novoIndice os valores da atual armazenados nas variaveis auxiliares
	lista.options[novoIndice].value = auxvalue;
	lista.options[novoIndice].text = auxlabel;
}

//Marca ou desmarca um elementos em uma lista
function selDesElemento(lista,indice,selecionado)
{
	lista.options[indice].selected = selecionado;
}

//Seleciona todos os elementos em uma lista
function selectAll(lista)
{
	if(lista != null && lista.type == "select-multiple")
	{
		for(i = 0 ; i < lista.options.length; i++)
		{
			selDesElemento(lista,i,true);
		}	
	}
}

//Desmarca todos os elementos em uma lista
function desSelectAll(lista)
{
	if(lista != null && lista.type == "select-multiple")
	{
		while(lista.selectedIndex > -1)
		{
			selDesElemento(lista,lista.selectedIndex,false);
		}
	}
}

function encode (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";

		for (var n = 0; n < string.length; n++) {

			var c = string.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;
}
function decode (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;

		while ( i < utftext.length ) {

			c = utftext.charCodeAt(i);

			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}

		}

		return string;
}