Drag and Drop – Parte 1
“Drag and Drop” é aquele conhecido efeito de arrastar e soltar, comum em muitos serviços que encontramos na Internet hoje em dia, e acredito que você já tenha se deparado com muitos desses serviços.
Dividi este tutorial em duas partes, pra não ficar muito cansativo. Nessa primeira parte, vou explicar o básico, como “arrastar”. Na outra, vamos aprender a “soltar” (parece meio óbvio, mas vai ser útil, aguarde).
Capturando Movimentos do Mouse
A primeira coisa que devemos fazer é capturar as coordenadas do mouse quando ele se move. Isso é feito adicionando uma função ao evento document.onmousemove.
document.onmousemove = mouseMove;// Essa não é a melhor maneira de fazer isso// Quando for "de verdade", use addEventfunction mouseMove(ev){ ev = ev || window.event; var mousePos = mouseCoords(ev);}function mouseCoords(ev){ if(ev.pageX || ev.pageY){ return {x:ev.pageX, y:ev.pageY}; } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, y:ev.clientY + document.body.scrollTop - document.body.clientTop };}
Primeiro vamos ao evento. Praticamente tudo que fizemos quando estamos em uma página dispara um evento (um clique, um movimento de mouse, uma tecla pressionada…). No IE, esse evento é global, e fica na variável window.event. Nos browsers de verdade (Firefox, Opera, Safari…), esse evento é passado como argumento para a função que está vinculada a ação.
Sempre diferente, o IE dá um jeito de atrapalhar. Nos browsers (Firefox, Opera, Safari…, IE não é browser), event.pageX e event.pageY representam a posição do mouse em relação ao documento, onde o topo esquerdo é a posição 0×0. Se você rolar a página 100 pixels abaixo, pageY será 100, e assim por diante.
Já se você clicar num ícone com um “E” azul e for testar, a posição do mouse em relação a janela estará armazenada em event.clientX e event.clientY. Assim sendo, mesmo se você rolar a página (e manter o mouse no lugar), a posição será sempre 0×0 (já que a posição é em relação a janela, e não ao documento inteiro). As variáveis scrollTop e scrollLeft nos ajudam a resolver o problema, já que elas armazenam a “quantidade” rolada. Piorando um pouco a situação (e aumentando mais um termo em nossa expressão algébrica “made-for-ie”), o documento não fica na posição 0×0, há uma pequena borda ao redor. document.body.clientLeft e document.body.clientTop contém a largura dessa borda.
Pra não nos preocuparmos com isso, o dito cujo criador da função (que permanece desconhecido pra mim) deixou tudo pronto. Em todos os exemplos, suprimirei essa função, mas ela deve estar lá sempre!
Capturando Cliques do Mouse
Agora precisamos saber quando o botão do mouse é pressionado e quando ele é soltado. Novamente usamos os eventos, agora onmousedown e onmouseup. Note que eles não devem ser vinculados ao documento, e sim ao objeto que queremos arrastar. Assim só eles poderão ser arrastados, e não o documento.
document.onmouseup = mouseUp;var dragObject = null;
function makeClickable(object){ object.onmousedown = function(){ dragObject = this; }}
function mouseUp(ev){ dragObject = null;}
A variável dragObject conterá o objeto que está sendo carregado. Se o objeto for “arrastável”, e clicarmos nele, ele vai pra essa variável. Caso contrário, ela permanece nula. E quando soltamos o botão do mouse, idem. E para tornar um objeto possível de se arrastar (“arrastável”, não sei se isso existe), usamos a função makeClickable, passando o dito objeto como parâmetro.
Movendo um Objeto
Agora na reta final. Primeiro, para podermos arrastar um objeto, precisamos que o estilo position seja absolute, obviamente porque a sua posição é relativa ao topo esquerdo do documento, assim como a posição do mouse.
Uma vez que objeto.style.position = "absolute", tudo que temos que fazer é mudar os estilos top e left. So, voila! Só falta saber como fazer isso:
document.onmousemove = mouseMove;document.onmouseup = mouseUp;
var dragObject = null;var mouseOffset = null;
function mouseMove(ev){ ev = ev || window.event; var mousePos = mouseCoords(ev);}
// mouseCoords(ev)...
function getMouseOffset(target, ev){ ev = ev || window.event;
var docPos = getPosition(target); var mousePos = mouseCoords(ev); return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};}
function getPosition(e){ var left = 0; var top = 0;
while (e.offsetParent){ left += e.offsetLeft; top += e.offsetTop; e = e.offsetParent; }
left += e.offsetLeft; top += e.offsetTop;
return {x:left, y:top};}
function mouseMove(ev){ ev = ev || window.event; var mousePos = mouseCoords(ev);
if(dragObject){ dragObject.style.position = 'absolute'; dragObject.style.top = mousePos.y - mouseOffset.y; dragObject.style.left = mousePos.x - mouseOffset.x;
return false; }}function mouseUp(){ dragObject = null;}
function makeDraggable(item){ if(!item) return; item.onmousedown = function(ev){ dragObject = this; mouseOffset = getMouseOffset(this, ev); return false; }}
Esse “juntão” de códigos (e alguns a mais) nos permite mover livremente um objeto (desde que seja “arrastável” (preciso de um substituto pra essa palavra), através de makeDraggable).
Algo mais que possa interessar: quando clicamos em um item (item = objeto “arrastável”, ufa), guardamos outra variável: mouseOffset. Ela contém o lugar em que clicamos em nosso item. Isso para que possamos posicionar o item abaixo do mouse da mesma maneira quando clicado.
Outra função diferente que usamos: getPosition. Ela retorna a posição de um item relativo ao documento. Como seu offsetLeft e offsetTop são relativos ao seu elemento pai, a função vai somando até chegar ao documento.
Soltando um Objeto
Até agora cumprimos tudo, carregamos o item para qualquer lugar da página. Mas podemos fazer mais que isso, como encaixar o item em um lugar específico, ou carrega-lo para uma lixeira, pasta…
Isso é legal, concorda? E tenho um segredo pra contar: só na parte 2, até!
Não esqueça de ler a parte 2 do artigo!







document.body.scrollTop
isso salvou meu dia, opps, minha noite.
Esse IE realmente é o mocinho bandido
Valeu