12 de agosto de 2007
25Interface drag and drop com jQuery
Customização é um dos principais conceitos da web 2.0 — deixar o usuário participar ativamente em seu website, seja com conteúdo ou com um visual personalizado. Neste artigo você confere como montar uma interface drag and drop (arrastar & soltar) utilizando a biblioteca javascript jQuery, permitindo ao usuário montar uma página a seu gosto, escolhendo a disposição dos boxes de conteúdo disponíveis no site.
Este artigo está desatualizado. Confira a nova versão deste tutorial em
http://www.daviferreira.com/blog/post/5/interface-drag-and-drop-com-jquery-atualizado.html.
Este tutorial é voltado para quem domina HTML e CSS e tem, pelo menos, uma relativa noção de javascript.
jQuery
Antes de começar, vamos falar um pouco da jQuery. Trata-se de um framework que visa facilitar a programação em javascript, tornando o código mais simples, flexível e infinitamente mais elegante. Além de ser bem leve, a jQuery conta ainda com uma comunidade bastante ativa e uma vasta gama de plugins (seu ponto forte).
Veja a seguir um exemplo de código escrito em javascript convencional e uma versão do mesmo código com jQuery.
javascript:
document.getElementById(box).style.backgroundColor = '#ff0000';
jQuery
$('#box').css('backgroundColor', '#ff0000');
Notaram a diferença? Vamos entender o código jQuery, por partes:
$('#box') — o símbolo do dólar, seguido por parênteses, é o construtor da jQuery. Graças a ele você não precisa mais perder tempo digitando document.getElementById toda vez que precisar capturar um objeto HTML pelo id. O seletor $('#box') representa o elemento HTML de id box. Alguns outros exemplos de seletores são:
- $('a') — pega todos os elementos a do documento html;
- $('div.caixa') — pega todos os elementos div que possuem a classe caixa;
- $('a[@title]') — todos os elementos a que possuem o atributo title declarado;
- $('input[@type=checkbox]') — todos os inputs do tipo checkbox.
.css() — a propriedade .css funciona para exibir ou atribuir um valor CSS de um elemento HTML. No exemplo acima, atribuímos a cor "#ff0000" à propriedade background-color do nosso elemento de id box. Para exibir a propriedade ao invés de atribuir um valor, basta omitir o segundo parâmetro, por exemplo:
$('#box').css('backgroundColor')
Confira algumas outras propriedades dos seletores jQuery:
- .attr() — retorna/manipula os atributos de um elemento, como title, src, rel, href etc.;
- .val() — retorna/manipula o campo value de elementos input;
- .html() — semelhante à propriedade innerHTML do javascript convencional;
- .text() — retorna somente o texto, sem as tags HTML, de um elemento.
É claro que isso não cobre quase nada do que a jQuery tem a oferecer. Para conferir a lista completa de seletores, comandos, propriedades e métodos visite o wiki do projeto em docs.jquery.com.
Arquivos necessários
A interface drag an drop que iremos desenvolver aqui utiliza os plugins de interface disponíveis neste link e nosso código será baseado no módulo Sortables.
O primeiro passo é declarar os arquivos javascript no head de nosso documento HTML.
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="interface.js"></script>
Observação: neste exemplo, estamos utilizando uma versão completa do arquivo interface.js, com todos os seus módulos, mas nada impede (e eu até recomendo) que você utilize no seu projeto final uma versão compactada apenas com os módulos necessários. Você pode conferir a lista de dependências do Sortables acessando este link.
Downloads:
Elementos da interface
Agora vejamos o que é necessário, esquecendo um pouco a parte de javascript, para a construção de uma interface drag and drop. Que elementos vamos utilizar?
- No mínimo uma área para soltar os elementos arrastados;
- Alguns elementos que serão arrastados e soltos nas áreas disponíveis no site;
- Uma área temporária de ajuda, para indicar onde o elemento que está sendo arrastado pode ser solto;
- Todo elemento arrastável deve possuir um handle, ou seja, alguma área dentro do próprio elemento onde o usuário irá clicar para arrastá-lo.
Sendo assim, definiremos as seguintes classes CSS para identificar os elementos de nossa interface:
- recebeDrag
- itemDrag
- dragAjuda
No caso do handle não utilizaremos uma classe, mas sim um elemento específico: a tag h2.
Todos os elementos com a classe recebeDrag servirão de base para os elementos arrastáveis. Estes, por sua vez, virão acompanhados da classe itemDrag. O elemento de ajuda (dragAjuda) não precisa ser declarado no documento HTML — o plugin de interface da jQuery se encarrega de fazer isso, apenas o CSS precisa ser criado. Todo itemDrag deve ainda possuir um elemento H2 para arrastá-lo. Nossa estrutura ficou assim:

E o CSS:
div.recebeDrag {
min-height: 50px;
}
div.itemDrag {
margin: 7px;
border: 1px solid #ccc;
padding: 7px;
}
div.itemDrag h2 {
cursor: move;
background-color: #ff3300;
color: #fff;
padding: 3px;
}
.dragAjuda {
border: 3px dashed #0066cc;
width: auto !important;
}
Monte um documento HTML com o CSS acima e inclua quantas áreas e ítens quiser para efetuarmos nosso teste.
document.ready
Com nosso HTML pronto, agora resta apenas instanciar o elemento Sortable da jQuery. Ao invés de utilizar o bom e velho onload no body, vamos adotar uma abordagem mais elegante e garantida, já que espera todo o DOM ser carregado antes de ser executada. Ao final de nosso HTML, antes de fecharmos o
, utilizaremos o seguinte código javascript:
$(document).ready(
function () {
$('div.recebeDrag').Sortable(
{
accept : 'itemDrag',
helperclass : 'dragAjuda',
activeclass : 'dragAtivo',
hoverclass : 'dragHover',
opacity : 0.7,
handle : 'h2',
onChange : function()
{
serialEsq = $.SortSerialize('drop-esquerda');
serialDir = $.SortSerialize('drop-direita');
},
onStart : function()
{
$.iAutoscroller.start(this, $('body'));
},
onStop : function()
{
$.iAutoscroller.stop();
}
}
);
}
);
O comando/seletor $(document).ready funciona, de certa forma, como o
. Estamos solicitando que, ao carregar o documento, os elementos div com a classe recebeDrag sejam inicializados como objetos Sortables. Logo em seguida declaramos os parâmetros aceitos na nossa interface drag and drop, bem como as ações a serem executadas quando o elemento é mudado de lugar, quando tem início a ação de arrastar e quanto termina esta mesma ação.O bloco dos parâmetros é bem simples. Primeiro, utilizando o parâmetro accept, definimos que os divs com a classe recebeDrag aceitarão apenas elementos com a classe itemDrag arrastados dentro deles. Os quatro parâmetros seguintes são referentes às classes e estilos CSS. helperclass define a classe do elemento que demarca áreas em que os divs itemDrag podem ser soltos. hoverclass e activeclass são as classes de estado active e hover para o elemento recebeDrag. Já o parâmetro opacity define o nível de transparência de um elemento, podendo variar de 0 a 1.
handle, conforme explicado anteriormente, define o elemento HTML que servirá como "link" para arrastar os divs itemDrag.
E, por fim, as ações:
- onChange — qualquer função declarada neste parâmetro será executada quando um elemento for arrastado e solto, e sua posição inicial for alterada. É ideal para executar comandos AJAX para gravar a posição em banco de dados ou arquivo, ou simplesmente setar um cookie ou uma variável de sessão. No nosso exemplo estamos apenas executando a função nativa $.SortSerialize, que retorna as posições de cada elemento do recebeDrag, sem gravar nada.
- onStart — é executada quando tem início o movimento de arrastar o div. Em nossa interface estamos executando o plugin de autoscroll da jQuery, para que o movimento de arrastar e soltar não fique limitado a área visível do navegador.
- onStop — executada quando o movimento de arrastar é interrompido.
Interface em ação
Clique aqui para conferir um exemplo bem simples da nossa interface drag and drop. O CSS e o javascript foram todos declarados no arquivo, basta exibir o código-fonte para entender melhor o funcionamento do nosso exemplo.
Para visualizar a versão final deste teste, visite o site beta do Democracia.
Sugestões de funcionalidades
- Opção para fechar e minimizar as janelas arrastáveis;
- Possibilidade para adicionar ou remover boxes de conteúdo da interface.
Referências
Atualização [06/12/2008]
Muita gente me pergunta sobre isso, então aí vai um exemplo utilizando cookies para salvar o posicionamento e ordenação definidos pelo usuário.
Os cookies estão sendo gerenciados diretamente via javascript, através do plugin jCookie: http://plugins.jquery.com/project/cookie.
Confira o que mudou no código. Na propriedade onchange do elemento sortable adicionamos o método $.cookie() para criar um cookie relacionado à cada coluna:
onChange : function()
{
serialEsq = $.SortSerialize('drop-esquerda');
serialDir = $.SortSerialize('drop-direita');
// salva cookie com posicionamento
$.cookie('coluna1', serialEsq.hash, {expires: 7});
$.cookie('coluna2', serialDir.hash, {expires: 7});
}
E, após carregar o documento, verificamos se o cookie existe e definimos o posicionamento dos boxes nas colunas:
$(document).ready(
function () {
if ($.cookie('coluna1') != null) {
// formata string do cookie
var coluna1 = $.cookie('coluna1').replace(/drop-esquerda[]=/g, '');
var coluna1 = coluna1.split('&');
var div_id = '';
for (var x = 0; x < = coluna1.length; x++) {
div_id = coluna1[x];
$('#drop-esquerda').append($('#'+div_id));
}
}
if ($.cookie('coluna2') != null) {
// formata string do cookie
var coluna2 = $.cookie('coluna2').replace(/drop-direita[]=/g, '');
var coluna2 = coluna2.split('&');
var div_id = '';
for (var x = 0; x <= coluna2.length; x++) {
div_id = coluna2[x];
$('#drop-direita').append($('#'+div_id));
}
}
}
);
Simples, não? :)
25 leitores comentaram este artigo
13/12/2007
22:09
Daniel escreveu:
Olá!
Consegui seguir os passos acima. Porém, seria importante salvar essas alterações, tipo cookies temporários.. mas não entendo nada de JS.. Jquerry.. teria algum tutorial explicando como fazer esta integração com este código do tutorial?
abs!
Responder
16/12/2007
23:26
Davi Ferreira escreveu:
E aí, Daniel. Estou preparando um post com essa segunda etapa. Mas o segredo está na propriedade onChange do Sortable, é ali que você deve salvar o cookie.
O próprio jquery tem um plugin para cookies:
http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/
Abraços!
Responder
03/01/2008
21:59
Eduardo Ferreira Leite escreveu:
Ola Davi estou precisando de alguém que faça um código deste p/ que eu possa implementar em um site,com 14 box destes tipo somente 2 colunas uma maior e outra menor.Sou webdesigner...preciso do valor que vc cobraria p/ desenvolver ou se tem alguém para indicar...valeu
Responder
30/01/2008
19:05
Ramon escreveu:
Valeu cara, era disso que eu tava precisando!! Eu to tentando adaptar isso pro joomla e to conseguindo =D VALEU MESMO!!!
PS: Como colocar uma opção pra desaparecer a div e outra pra ocultar e só deixar o h2?
Responder
12/11/2008
10:37
rodrigo escreveu:
Olá amigo, muito bom o post, só que to tendo alguns problemas, veja esse site aqui como exemplo: http://beta.democracia.com.br/# , as divs simplesmente depois de movimentar-se 2 vezes no IE7, não movimenta mais, enquanto no FF funfa na boa... eu estou implementando a jquery e o interface em um site e está dando o mesmo problema, será que poderia me ajudar a ver o erro??? Obrigado desde já
Responder
13/11/2008
00:08
Davi Ferreira escreveu:
@rodrigo
Realmente tá com esse bug no democracia no IE7, valeu o toque, vou dar uma conferida e depois te falo. Talvez seja porque lá usa uma versão antiga ainda do jquery. O próprio drag and drop já tem uma versão mais atual do que a deste post, no http://ui.jquery.com.
O exemplo do artigo funciona na boa no IE7. Tem um link ali no último parágrafo. Se quiser me mandar uma URL de teste do teu site pra eu dar uma conferida, fique a vontade, manda ali pelo form de contato.
Responder
11/12/2008
11:33
rodrigo escreveu:
opa. eu aki denovo, conseguiu ver ql o problema? eu ja tentei usar a versão mais nova da jquery e msm assim naum to conseguindo, não tenho o link pois o site ainda não está no ar.
Responder
12/12/2008
02:41
Davi Ferreira escreveu:
@Rodrigo: é problema de versão do jQuery sim, só não pode ser a mais nova mesmo :( Só consegui fazer funfar no IE7 com a 1.1.2. Se quiser baixa daqui, usei no exemplo dos cookies: http://www.daviferreira.com/blog/exemplos/draganddrop/jquery.js.
Vou ver depois se consigo fazer com a versão mais nova, mas provavelmente vou ter que migrar tudo pro interface.js novo.
Responder
12/12/2008
14:16
Rodrigo escreveu:
Vlw cara. Funcionou na boa!!! Mas acho q naum vai funfar na versão nova não pq era com ela q eu tava, e o interface tb... :S
Qlqr coisa me dá um tok.
Forte abraço!
Responder
16/12/2008
10:17
Rodrigo escreveu:
Olha eu aqui denovo, ¬¬ ^^, é q no site do democracia eu achei interessante tb o fato de poder minimizar e maximizar as divs, até to tentando implementar isso, mas gostaria de saber se tem um idéia de como ficaria o script para o estado inicial dela ser display none, tipo so abre qnd o usuario clicar... tem alguma idéia??? vlw! Abraço!
Responder
18/12/2008
23:54
Davi Ferreira escreveu:
Fala Rodrigo!
Não sei bem se entendi sua dúvida, mas não seria só colocar o CSS inicial do elemento com 'display:none;'?
Responder
30/12/2008
17:47
kirotawa escreveu:
Opa, gostei do teu tutorial. Mas tipo eu fiz um controlC, controlV aqui e funfou legal, mas não to conseguindo salvar as posições com o cookie. to fazendo algo errado:
$(document).ready(
function () {
if ($.cookie('coluna1') != null) {
// formata string do cookie
var coluna1 = $.cookie('coluna1').replace(/drop-esquerda[]=/g, '');
var coluna1 = coluna1.split('&');
var div_id = '';
for (var x = 0; x < = coluna1.length; x++) {
div_id = coluna1[x];
$('#drop-esquerda').append($('#'+div_id));
}
}
if ($.cookie('coluna2') != null) {
// formata string do cookie
var coluna2 = $.cookie('coluna2').replace(/drop-direita[]=/g, '');
var coluna2 = coluna2.split('&');
var div_id = '';
for (var x = 0; x <= coluna2.length; x++) {
div_id = coluna2[x];
$('#drop-direita').append($('#'+div_id));
}
}
}
$('div.recebeDrag').Sortable(
{
accept : 'itemDrag',
helperclass : 'dragAjuda',
activeclass : 'dragAtivo',
hoverclass : 'dragHover',
handle : 'h2',
opacity : 0.7,
onChange : function()
{
serialEsq = $.SortSerialize('drop-esquerda');
serialDir = $.SortSerialize('drop-direita');
$.cookie('coluna1', serialEsq.hash, {expires: 7});
$.cookie('coluna2', serialDir.hash, {expires: 7});
$('#ser-e').val(serialEsq.hash);
$('#ser-d').val(serialDir.hash);
},
onStart : function()
{
$.iAutoscroller.start(this, document.getElementsByTagName('body'));
},
onStop : function()
{
$.iAutoscroller.stop();
}
}
);
}
);
Responder
30/12/2008
18:08
kirotawa escreveu:
Opa eu denovo, esquece aí. Nesse negócio de ControlC controlV, esqueci do jquery.cookie.js :P. Agora funfou, vlws.
Responder
03/03/2009
13:16
Reginaldo escreveu:
Opa, muito bom seu tutorial cara
Só estou com um problema na hora de criar o cookie e armazenar as posições. Ele cria o cookie, porem cria vazio...nao armazena nada.
Sabe me dizer o pq ou desconfia de algo??
Grato
Responder
04/04/2009
19:19
Eder Santana escreveu:
Excelente tutorial! Só tô com uma dúvida: como eu faço para aumentar a quantidade de colunas? Gostaria de utilizar 4 colunas. Obrigado!
Responder
08/05/2009
15:25
Ezequiel escreveu:
Parabéns pela extensão, porém eu não sei se o problema é com a versão que acabei de baixar ou se é no meu css, pois quando eu arrasto o item ele não se posiciona no lugar que o .dragAjuda marcou, ele fica posicionado no lugar que arrastei, ou seja ele fica desalinhado se eu jogar mais pra esquerda, ele vai, se colocar mais pra direita, também.
Responder
08/05/2009
16:20
Ezequiel escreveu:
eu consegui arrumar aplicando
position: static !important;
no item. Porém creio que não seja a forma certa de arrumar. Abraço.
Responder
08/05/2009
16:27
Ezequiel escreveu:
Não tem como disponibilizar uma versão descriptografada, porque estou tendo uma incompatibilidade com o plugin scrollTo do jQuery. Se eu pudesse verificar o código poderia tentar contornar essa incompatibilidade. Abraço.
Responder
08/05/2009
17:23
Ezequiel escreveu:
o endereço do plugin é:
http://plugins.jquery.com/project/ScrollTo
Ele não ta mais dando scroll quando coloco o js de interface.
Responder
09/05/2009
00:15
Ezequiel escreveu:
Eu experimentei usar o sortable do jQuery UI porém tive melhor flexibilidade com o seu, o único problema que tive com o interface é mesmo o já citado problema do IE e a incompatibilidade com o scrollTo. Consertando isso seu plugin estaria 100% ;). Abraço.
Responder
15/05/2009
12:06
Phillipp M. Oliveira escreveu:
Foi um excelente post, muito bom mesmo. Só tive um problema... quando eu coloco as 4 divs em apenas um lado, ao dar F5 não consigo mais movimentá-las (com e sem cookies).
Abrços =)
Responder
03/06/2009
18:46
Drag and Drop com jQuery | Links Web escreveu:
[...] Site: http://www.daviferreira.com/blog/2007/08/12/interface-drag-and-drop-com-jquery.html [...]
Responder
02/07/2009
17:26
Daniel Schultz escreveu:
Gostei. No momento estou desenvolvendo um sistema de assentos para onibus que usará o conceito de drag'n drop com jquery.
Responder
31/08/2009
21:32
Beto escreveu:
Estou usando com 3 colunas a inicial, mais 2 que vão receber, não teria como eu arrastar um ter outro embaixo escondido? tipo "Item 1"... arrasto ele para a coluna 1, e já ficaria outro "Item 1" no mesmo lugar que eu puxei o primeiro para eu poder arrastar para a coluna 2, e uma opção para excluir se necessário
Responder
28/09/2009
20:40
Interface drag and drop com jQuery (atualizado) | Davi Ferreira blog! escreveu:
[...] por "drag and drop". Em respeito a esses leitores resolvi dar uma atualizada no meu primeiro artigo sobre o tema. Na época em que foi publicado, ainda não existia a parte de interface oficial do [...]
Responder
Deixe seu comentário