Foros del Web » Programando para Internet » Javascript »

Ayuda con Drag & Drop

Estas en el tema de Ayuda con Drag & Drop en el foro de Javascript en Foros del Web. Hola a todos. Ante todo disculparme si esta no es la sección adecuada donde postear esto. Ahora mi problema: me es necesario poder mover objetos ...
  #1 (permalink)  
Antiguo 10/12/2008, 04:30
 
Fecha de Ingreso: diciembre-2008
Mensajes: 5
Antigüedad: 15 años, 4 meses
Puntos: 0
Ayuda con Drag & Drop

Hola a todos.

Ante todo disculparme si esta no es la sección adecuada donde postear esto.

Ahora mi problema: me es necesario poder mover objetos por mi página, he estado buscando información al respecto hasta que dí con una función que hace lo que yo quiero.

Este es el código que encontré:

Esta parte va dentro del head
Código:
<style type="text/css">
  .objMovible { position:absolute; cursor:pointer }
</style>

Esto lo meto todo dentro de un javascript

Código:
//Si el navegador del cliente es Mozilla la variable siguiente valdrá true
var moz = document.getElementById && !document.all;
//Flag que indica si estamos o no en proceso de arrastrar el ratón
var estoyArrastrando = false;
//Variable para almacenar un puntero al objeto que estamos moviendo
var dobj;
function presionarBoton(e) {
  //Obtenemos el elemento sobre el que se ha presionado el botón del ratón
  var fobj = moz ? e.target : event.srcElement;

  // Buscamos el primer elemento en la que esté contenido aquel sobre el que se ha pulsado
  // que pertenezca a la clase objMovible. Esto es necesario por si hemos pinchando sobre
  // un elemento contenido dentro de otro pero este último es el que pertenece a la clase
  // objmovible
  while (fobj.tagName.toLowerCase() != "html" && fobj.className != "objMovible") {
    fobj = moz ? fobj.parentNode : fobj.parentElement;
  }

  // Si hemos obtenido un objeto movible...			
  if (fobj.className == "objMovible") {
    // Activamos el flag para indicar que se empieza a arrastrar
    estoyArrastrando = true;
    // Guardamos un puntero al objeto que se está moviendo en la variable global
    dobj = fobj;
    // Devolvemos false para no realizar ninguna acción posterior
    return false;
  }
}
//Asociamos la función al evento onmousedown
document.onmousedown = presionarBoton;
function arrastrarRaton(e){
  if (estoyArrastrando) {
    // Obtenemos las coordenadas X e Y del ratón (de forma diferente dependiendo del navegador del cliente)
    newLeft = moz ? e.clientX : event.clientX;
    newTop = moz ? e.clientY : event.clientY;

    // Posicionamos el objeto en las nuevas coordenadas y aplicamos unas desviaciones
    // horizontal y vertical correspondientes a la mitad del ancho y alto del elemento
    // que movemos para colocar el puntero en el centro de la capa movible.
    dobj.style.left = newLeft - parseInt(dobj.style.width)/2;
    dobj.style.top = newTop - parseInt(dobj.style.height)/2;

    // Devolvemos false para no realizar ninguna acción posterior
    return false;
  }
}
//Asociamos la función al evento onmousemove
document.onmousemove = arrastrarRaton;
function soltarBoton(e) {	
  estoyArrastrando = false;
}
//Asociamos la función al evento onmouseup
document.onmouseup = soltarBoton;
Y esto es lo que quiero poder mover por la página.

Código:
<div class="objMovible" style="width:20px;height:20px;background-color:#CC0000"></div>
http://www.locualo.net/rcs/moverjs.htm Aquí ejemplo funcional

Como podeis ver en el ejemplo parece que la función es correcta, pero a la hora de aplicarlo a mi página no funciona. Tan sólo me aparece el cuadradito y me deja arrastrarlo levemente hacia la izquierda (justo hasta toparse con el borde de la página) pero no me deja moverlo ni hacia abajo ni hacia la derecha, ni siquiera para recuperar su posición original.

Agradecería que me ayudaran a corregir el error o me proporcionasen otra idea para llevarlo a cabo. Gracias de antemano.
  #2 (permalink)  
Antiguo 10/12/2008, 04:37
Avatar de caricatos
Moderador
 
Fecha de Ingreso: abril-2002
Ubicación: Torremolinos (Málaga)
Mensajes: 19.607
Antigüedad: 22 años
Puntos: 1284
Respuesta: Ayuda con Drag & Drop

Hola:

A bote pronto, te faltan las medidas:

dobj.style.left = newLeft - parseInt(dobj.style.width)/2 + "px";
dobj.style.top = newTop - parseInt(dobj.style.height)/2 + "px";

Saludos
__________________
Por favor:
No hagan preguntas de temas de foros en mensajes privados... no las respondo
  #3 (permalink)  
Antiguo 10/12/2008, 04:52
 
Fecha de Ingreso: diciembre-2008
Mensajes: 5
Antigüedad: 15 años, 4 meses
Puntos: 0
Respuesta: Ayuda con Drag & Drop

Cita:
Iniciado por caricatos Ver Mensaje
Hola:

A bote pronto, te faltan las medidas:

dobj.style.left = newLeft - parseInt(dobj.style.width)/2 + "px";
dobj.style.top = newTop - parseInt(dobj.style.height)/2 + "px";

Saludos
Gracias!! Ahora funciona a la perfección. Tenía entendido que el "px" sólo era necesario pasarlo en iexplorer, veo que no es así.
  #4 (permalink)  
Antiguo 10/12/2008, 06:45
 
Fecha de Ingreso: diciembre-2008
Mensajes: 5
Antigüedad: 15 años, 4 meses
Puntos: 0
Respuesta: Ayuda con Drag & Drop

Tengo más dudas sobre este tema.

Os explico lo que ha de hacer mi aplicación.

Necesito tener 3 objetos con un texto que se puedan mover por la pantalla arrastrándolos tal y como sucede con la función anterior.

A parte, necesito tres cuadraditos en blanco, en principio los tengo definidos como tres inputs de texto.

Los tres cuadraditos movibles deben ser arrastrados y soltados en los tres cuadrados fijos de forma que estos cuadrados fijos recogan el valor de texto del objeto movible que hay en su interior. Al mismo tiempo necesitaría que si el objeto que se mueve no se suelta dentro de uno de esos 3 cuadrados, debería retornar a su posición original.

Espero haberme explicado bien. Agradezco cualquier ayuda al respecto.
  #5 (permalink)  
Antiguo 10/12/2008, 12:24
 
Fecha de Ingreso: diciembre-2008
Mensajes: 5
Antigüedad: 15 años, 4 meses
Puntos: 0
Respuesta: Ayuda con Drag & Drop

Saludos de nuevo.

Buscando por ahí he encontrado un código mejor para mi aplicación. En este caso los elementos DIV movibles sólo se pueden mover encima de elemento DIV movible haciendo que intercambien posiciones.

Como creo que el valor de los DIV no se puede recoger en un formulario, lo que he ideado es meter un input oculto dentro de estos DIV movibles de manera que, al mover el DIV, el input también se mueva junto con su valor.

Es decir, tendríamos algo así:
<form>
<div id="movible1"><input value="te"/></div>
<div id="movible2"><input value="hola"/></div>
<div id="movible3"><input value="como"/></div>
<div id="movible4"><input value="va"/></div>
</form>

Y se podría mover de manera que quedase:

<form>
<div id="movible2"><input value="hola"/></div>
<div id="movible3"><input value="como"/></div>
<div id="movible1"><input value="te"/></div>
<div id="movible4"><input value="va"/></div>
</form>

Mi pregunta es como podría recoger los valores de esos input en el orden en que el usuario los establezca, en este caso movible2,movible3,movible1,movible4), para poder introducirlos a una bbdd en ese orden.

Os dejo el código para complementar un poco

Este es el javascript para mover los elementos y reordenarlos
Código:
<script type="text/javascript">
// Variables globales
var indiceZ=0; 
var posElInicial=new Array();
var posElFinal=new Array();
var posEls=new Array();
var posMouseInicial=new Array();
var elEnMov=null;

// Cargo las posiciones de las capas en el documento
onload=posElsAbs;
onresize=posElsAbs;

// Detecto el navegadoregador
if(navigator.userAgent.indexOf("MSIE")>=0) navegador=0; // IE
else navegador=1; // Otros

function delay() 
{ 
	/* 
	En IE sin un pequeño delay parece haber problemas con la captura de las posiciones de las capas. Lo extraño es que no siempre sucede por lo que este
	retraso puede no ser necesario.
	*/
}

function posElsAbs()
{
	/*
	funcion: almacenar las posiciones absolutas de los elementos movibles de la pagina
	parametros:
	retorno:
	*/
	setTimeout("delay()", 200);
	var el=document.getElementsByTagName("div");
	var i=0;
	while(el[i])
	{
		if(el[i].id.substr(0, 4)=="drag")
		{
			el[i].onmousedown=inicioMov;
			posEls[el[i].id]=posElAbs(el[i].id);
		}
		i++;
	}
}

function noEventos(event)
{
	if(navegador==0)
	{
		window.event.cancelBubble=true;
		window.event.returnValue=false;
	}
	if(navegador==1) event.preventDefault();
}

function getEl(idEl) 
{
	/*
	funcion: devolver el elemento cuyo id se recibe
	parametros: (string) id de elemento
	retorno: (objeto) elemento cuyo id se recibe
	*/
	return document.getElementById(idEl); 
}

function copiaArr(arr) 
{ 
	/*
	funcion: devolver una copia exacta del array que se recibe por parametro
	parametros: (array) array a copiar
	retorno: (array) duplicado del array recibido
	*/
	var tArr=new Array();
	for(var n in arr) tArr[n]=arr[n];
	return tArr;
}

function posMouse(event)
{
	/*
	funcion: devolver la posicion del puntero en un momento determinado
	parametros: (objeto) objeto event
	retorno: (array=>["x"] - ["y"]) posicion del puntero
	*/
	var pos=new Array();
	if(navegador==0)
	{
		/* document.body.clientLeft/clientTop es el tamaño del borde (usualmente 2px) que
		encierra al documento ya que en IE este no empieza en (0,0) */
	 	pos["x"]=window.event.clientX+document.body.clientLeft+document.body.scrollLeft;
		pos["y"]=window.event.clientY+document.body.clientTop+document.body.scrollTop;
	}
	if(navegador==1)
	{
		pos["x"]=event.clientX+window.pageXOffset;
		pos["y"]=event.clientY+window.pageYOffset;
	}
	return pos;
}

function posElAbs(idEl)
{
	/*
	funcion: devolver la posicion del elemento con respecto a los bordes del documento
	parametros: (string) id del elemento
	retorno: (array=>["xInicial"] - ["xFinal"] - ["yInicial"] - ["yFinal"]) posicion del elemento
	*/
	var el=elP=getEl(idEl);
	var pos=new Array();
	pos["xInicial"]=pos["yInicial"]=pos["xFinal"]=pos["yFinal"]=0;
	
	do
	{
		pos["xInicial"]+=elP.offsetLeft;
		pos["yInicial"]+=elP.offsetTop;
		elP=elP.offsetParent;
	} while(elP);

	pos["xFinal"]=el.offsetWidth+pos["xInicial"];
	pos["yFinal"]=el.offsetHeight+pos["yInicial"];

	return pos;
}

function posElRel(idEl)
{
	/*
	funcion: devolver la posicion del elemento con respecto a su contenedor (left y top)
	parametros: (string) id del elemento
	retorno: (array=>["x"] - ["y"]) posicion del elemento
	*/
	var el=getEl(idEl);
	var pos=new Array();
	pos["x"]=parseInt(el.style.left);
	pos["y"]=parseInt(el.style.top);
	return pos;
}

function reOrdena(posMouse)
{
	for(var idEl in posEls)
	{
		if(idEl!=elEnMov.id)
		{
			if(posMouse["x"]>=posEls[idEl]["xInicial"] && posMouse["x"]<=posEls[idEl]["xFinal"] &&
			posMouse["y"]>=posEls[idEl]["yInicial"] && posMouse["y"]<=posEls[idEl]["yFinal"]) 
			{
				// La capa cuyo id es idEl debe posicionarse en la posicion de comienzo de la capa en movimiento
				var el=getEl(idEl);
				
				// Intercambio la posicion de la capa estatica por la posicion final de la capa en movimiento
				var temp=new Array();
				temp["x"]=parseInt(el.style.left);
				temp["y"]=parseInt(el.style.top);
				el.style.left=posElFinal["x"]+"px";
				el.style.top=posElFinal["y"]+"px";
				posElFinal=copiaArr(temp);
				
				// Cambio los valores de posicion de la capa estatica y la capa en movimiento en el array de posiciones
				var temp1=new Array();

				temp1=copiaArr(posEls[elEnMov.id]);
				posEls[elEnMov.id]=copiaArr(posEls[idEl]);
				posEls[idEl]=copiaArr(temp1);
			}
		}
	}
}

function inicioMov(event)
{
	if(navegador==0)
	{
	 	elEnMov=window.event.srcElement;
		
		document.attachEvent("onmousemove", enMov);
		document.attachEvent("onmouseup", finMov);
	}
	if(navegador==1)
	{
		elEnMov=event.target;
		
		document.addEventListener("mousemove", enMov, true);
		document.addEventListener("mouseup", finMov, true);
	}
	
	posElInicial=posElRel(elEnMov.id);
	posMouseInicial=posMouse(event);
	
	posElFinal=copiaArr(posElInicial);
	
	elEnMov.style.zIndex=++indiceZ;
	noEventos(event);
}

function enMov(event)
{	 
	var pos=posMouse(event);
	reOrdena(pos);
	
	elEnMov.style.left=posElInicial["x"]+pos["x"]-posMouseInicial["x"]+"px";
	elEnMov.style.top=posElInicial["y"]+pos["y"]-posMouseInicial["y"]+"px";
	
	
	noEventos(event);
}

function finMov(event)
{
	elEnMov.style.left=posElFinal["x"]+"px";
	elEnMov.style.top=posElFinal["y"]+"px";
	
	if(navegador==0)
	{    
		document.detachEvent("onmousemove", enMov);
		document.detachEvent("onmouseup", finMov);
	}
	if(navegador==1)
	{
		document.removeEventListener("mousemove", enMov, true);
		document.removeEventListener("mouseup", finMov, true); 
	}
}
</script>
El estilo
Código:
<style type="text/css">
#contenedor DIV
{
	height:15px;
	width:29px;
	position:absolute;
	border-color:#000000; border-style:solid; border-width:1px;
	background:#FF2070;
	font-family:Verdana; font-size:12px;
	padding-top:4px;
	margin:5px;
	text-align:center;
	cursor:pointer;
	z-index:2;
}

#contenedor
{
	position:absolute;
	top:189px;
	left:118px;
	margin-left:-75px;
}

</style>
Y estos son los elementos movibles
Código:
<div id="contenedor">
<div id="drag_1" style="top:-151px; left:100px;">cuadrado<input type="hidden" value="cuadrado" /></div>
<div id="drag_2" style="top:-151px; left:150px;">circulo<input type="hidden" value="circulo" /></div>
<div id="drag_3" style="top:-151px; left:200px;">triangulo<input type="hidden" value="triangulo" /></div>
<div id="drag_4" style="top:-151px; left:250px;">rombo<input type="hidden" value="rombo" /></div>
</div>
En este caso los valores a recoger serían cuadrado, circulo, triangulo, rombo. Quiero que al cambiarlos de orden al moverlos se sigan recogiendo en ese orden de arriba a abajo.
Se me ocurre que quizás se podría hacer creando una función para que cuando dos DIV se intercambien (y en este caso también sus respectivos inputs) estos inputs intercambien sus nombres de manera que el input1 siempre quede arriba y sólo sea su valor lo que cambie. Pero no tengo ni idea de como hacer esto.

Gracias por todo y disculpen mi ignorancia

Última edición por Fithos; 10/12/2008 a las 12:40
  #6 (permalink)  
Antiguo 10/12/2008, 14:16
Avatar de Panino5001
Me alejo de Omelas
 
Fecha de Ingreso: mayo-2004
Ubicación: -34.637167,-58.462984
Mensajes: 5.148
Antigüedad: 20 años
Puntos: 834
Respuesta: Ayuda con Drag & Drop

A ver si te sirve de orientación:
Código PHP:
<!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>Documento sin t&iacute;tulo</title>
<
style>
div{position:absolute;}
</
style>
<
script>

function 
verOrden(){
    var 
els=document.getElementById('f1').getElementsByTagName('div');
    var 
orden=[];
    var 
divs=[];
    for(var 
i=0,l=els.length;i<l;i++){
        
orden.push(parseInt(els[i].style.top));
    }
    
orden=orden.sort(function(a,b){return a-b;});
    for(var 
ii=0,ll=orden.length;ii<ll;ii++){
        for(
i=0,l=els.length;i<l;i++){
            if(
parseInt(els[i].style.top)!==orden[ii])continue;
                
divs.push(els[i].id);
            
        }
    }
    return 
divs;
}
</script>
</head>

<body><form id="f1">
<div id="movible2" style="top:0"><input value="hola"/></div>
<div id="movible4" style="top:90px"><input value="va"/></div>
<div id="movible3" style="top:30px"><input value="como"/></div>
<div id="movible1" style="top:60px"><input value="te"/></div>
<br />
<br />
<br />
<br />
<br />
<br />
<input type="button" name="Submit" value="Orden?" onclick="alert(verOrden())" />
</form>
</body>
</html> 
  #7 (permalink)  
Antiguo 10/12/2008, 16:56
 
Fecha de Ingreso: diciembre-2008
Mensajes: 5
Antigüedad: 15 años, 4 meses
Puntos: 0
Respuesta: Ayuda con Drag & Drop

He estado echando un ojo además de incorporarlo a mi aplicación para ver como funciona. Creo entender lo que hace ese código, pero tampoco lo veo muy bien, si pudieras explicarlo con más profundidad...

Tal y como está ahora metido implementado en mi código no funciona bien, al clickar me aparecen los nombres de mis divs, peor muchos de ellos repetidos, sin seguir el orden que yo les ponga.
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 01:43.