Usando a Prototype – passo 1 – escondendo selects debaixo de uma popup

Vamos lá, falar de usos práticos da biblioteca Prototype. Okey, aqui no And After há alguns posts a respeito já, mas estou pensando em criar uma série deles.
Nesse primeiro, amos ver como criar uma função que esconde determinados elementos do html se outro estiver por cima.

Não entendeu? Vamos lá, vou explicar de onde veio a idéia – acho que fica mais fácil.
Uma coisa que aparece em qualquer projeto de web ultimamente é a necessidade de se fazer caixas (normalmente divs) que abrem por cima de outras. Normalmente para mostrar conteúdos oriundos de requisições ajax (ok, sei que o termo não está correto, mas não consegui pensar em outro).
Aí, o que normalmente se faz? Tem-se uma div com display:none e no retorno da requisição (callback), dá-se um display:block nela mostrando o conteúdo da forma adequada.
O grande problema é quando essa div abre por cima de um select ou um flash, por exemplo. O IE6 mostra o select ou o swf por cima da div (não ocorre no Firefox nem IE7), acabando com o layout e dificultando tudo. Para isso fiz essa função aqui, genérica, que recebe dois parâmetros: o id do seu elemento html que estará por cima, e o id de um elemento html que contém elementos do tipo select.

Usando o objeto Position (veja a documentação aqui) da Prototype, é possível acessar o método cumulativeOffset(element) que retorna um array com as posições das coordenadas x e y do elemento, independente do local no código em que esteja (posição relativa dos pais, absoluta, floats, etc…)
Com isso, o que é feito: pega-se a posição da div de popup e suas dimensões, e se varre a lista de selects presentes no outro elemento. A cada select que é encontrado, pega-se também as coordenadas desse select e suas dimensões, e através de uma lógica simples faz a comparação nos eixos x e y se a popup está por cima do select. Se sim, deixa o select como invisível.
Segue o código:

function escondeNoOver(id_popup, id_area) {
        //define qual a popup
        var popup = $(id_popup);
        //pega todas os selects de um determinado elemento
        var selects = $(id_area).getElementsByTagName("select");
        //pega coordenadas X/Y da popup (topo do lado esquerdo) e dimensões da mesma
        var posX = Position.cumulativeOffset(popup)[0];
        var posY = Position.cumulativeOffset(popup)[1];
        var width = popup.clientWidth;
        var height = popup.clientHeight;
       
        //percorre a lista de selects
        for(i=0; i<selects.length; i++) {
           
            //pega coordenadas X/Y do select (topo do lado esquerdo) e dimensões do mesmo
            var selX = Position.cumulativeOffset(selects[i])[0];
            var selY = Position.cumulativeOffset(selects[i])[1];
            var widthS = selects[i].clientWidth;
            var heightS = selects[i].clientHeight;
           
            var onX = false;
            //verifica se no eixo X (horizontal), a popup está entre o início e o final do select
            if(posX<selX+widthS) {
                if(posX+width>selX)
                    onX = true;
            } else {
                if(selX+widthS>posX+width)
                    onX = true;
            }
           
           
            //verifica se no eixo Y (vertical), a popup está entre o início e o final do select
            var onY = false;
            if(posY<selY+heightS) {
           
                if(posY+height>selY)
                    onY = true;
            } else {
                if(selY+heightS>posY+height)
                    onY = true;
            }
           
            //tem que estar dentro de X e Y para esconder a popup
            if(onX && onY){
                selects[i].style.visibility = "hidden";
            }
        }
    }

Abaixo segue o código funcional de um html com essa função, onde ao clicar no link do final da página sera chamada a função e ela verificará se há campos do tipo select por baixo daquela div de popup que possui um fundo acinzentado.
Vale notar que essa função pode ser alterada para verificar outros tipos de objetos e não precisa ser usada apenas para essa questão de retorno de requisições ajax – muitas vezes precisamos esconder algumas coisas, independente do motivo, não? 🙂
 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<style type="text/css">
* {margin:0; padding:0; border:0;}
body {font-family:Verdana, Arial, Helvetica, sans-serif;}
input, select, textarea {border:1px solid #000000;}
form {margin:50px;}
p {margin:10px;}
div#popup{padding:20px; border:3px solid #000000; position:absolute; left:80px; top:350px; background-color:#F0F0F0; width:200px;}
</style>
<script type="text/javascript" src="http://www.prototypejs.org/assets/2008/1/25/prototype-1.6.0.2.js"></script>
<script type="text/javascript">
    function escondeNoOver(id_popup, id_area) {
        //define qual a popup
        var popup = $(id_popup);
        //pega todas os selects de um determinado elemento
        var selects = $(id_area).getElementsByTagName("select");
        //pega coordenadas X/Y da popup (topo do lado esquerdo) e dimensões da mesma
        var posX = Position.cumulativeOffset(popup)[0];
        var posY = Position.cumulativeOffset(popup)[1];
        var width = popup.clientWidth;
        var height = popup.clientHeight;
        //percorre a lista de selects
        for(i=0; i<selects.length; i++) {
            //pega coordenadas X/Y do select (topo do lado esquerdo) e dimensões do mesmo
            var selX = Position.cumulativeOffset(selects[i])[0];
            var selY = Position.cumulativeOffset(selects[i])[1];
            var widthS = selects[i].clientWidth;
            var heightS = selects[i].clientHeight;
            var onX = false;
            //verifica se no eixo X (horizontal), a popup está entre o início e o final do select
            if(posX<selX+widthS) {
                if(posX+width>selX)
                    onX = true;
            } else {
                if(selX+widthS>posX+width)
                    onX = true;
            }
            //verifica se no eixo Y (vertical), a popup está entre o início e o final do select
            var onY = false;
            if(posY<selY+heightS) {
           
                if(posY+height>selY)
                    onY = true;
            } else {
                if(selY+heightS>posY+height)
                    onY = true;
            }
            //tem que estar dentro de X e Y para esconder a popup
            if(onX && onY){
                selects[i].style.visibility = "hidden";
            }
        }
    }
</script>
</head>
<body>
<div id="popup">sua div de popup</div>
<form action="entreemcontato.php" method="post" id="form">
<div>
    <p>Nome:</p>
    <p><input type="text" name="nome" value="Seu Nome"/></p>
    <p>Comentários:</p>
    <p><textarea name="comentários" rows="5" cols="20">
    Seus comentários
    </textarea></p>
    <p>Você é:</p>
    <p><input type="radio" name="vocee" value="homem" checked="checked"/>
    Homem
    </p>
    <p><input type="radio" name="vocee" value="mulher"/>
    Mulher
    </p>
    <p><input type="checkbox" name="cefet" checked="checked"/>Estudo no Cefet</p>
    <p>O que você achou desse minicurso?</p>
    <select>
    <option value="bom">Bom</option>
    <option value="regular" selected="selected">Regular</option>
    <option value="ruim">Ruim</option>
    </select>
    <p>Você repetiria esse curso?</p>
    <select>
    <option value="bom">Sim</option>
    <option value="regular" selected="selected">Sempre</option>
    </select>
    <p><input type="submit" value="Enviar"/></p>
    <p><input type="reset" value="Limpar"/></p>
</div>
</form>
<a href="#" onclick="escondeNoOver(´popup´, ´form´);" title="checar popup">checar popup</a>
</body>
</html>
 

Em breve, outros exemplos usando a Prototype 🙂

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *