Ver Mensaje Individual
  #18 (permalink)  
Antiguo 28/08/2008, 19:10
Avatar de derkenuke
derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Respuesta: Usar drag & drop con javascript

Hola de nuevo scorm:

Madre mía, vaya programita!

No sé que tenemos los frameworks y yo, que no nos llevamos. He estado peleándome para hacer tu ejemplo más cómodo al usuario. Según lo he probado funciona en IE y en FF; y todo con el ratón. Ya no utilizo botones de borrar ni nada, si uno quiere eliminar una capa de sitio, la arrastra al origen.

Hace falta un código un poco más complicado. Me ha pasado bastantes veces que el framework no funcionaba como esperaba, y cuando la capa tenía que volver a su sitio porque la soltaba volvía a otro sitio. En ese caso cancelaba el revert automático y lo hacía manual (complicado). Guardo las coordenadas actuales, y cuando detecto un onEnd en el drag&drop (cuando se hace drop) entonces fuerzo a la capa a moverse a esas coordenadas origen.

He eliminado algo de CSS, porque ocurrían cosas raras. Si quieres agregarle borde o padding a las cosas creo que se puede sin problemas, pero si las capaz azules no van a donde tienen que ir hay una variable comodín bordeExtra que ajusta la posición de la capa azul.

Lo he ido comentando, aunque es dificil de digerir es "más natural".

Código PHP:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<
html>
<
head>

<
script src="prototype-1.6.0.2.js" type="text/javascript"></script>
<script src="scriptaculous/scriptaculous.js" type="text/javascript"></script> 

<style type="text/css">
body {
    font-family:Georgia, "Times New Roman", Times, serif;
    font-size:12px;
    color:#666666;
    text-align:center; /*aqui mandamos a centrar todo el contenido*/ 
}

#contenedorppal {
    width:100%; /*ancho total de la pagina 77777777777777antes ponia 600*/ 
    border:1px solid #333333; /*encadeno los 3 atributos claves del borde en una sola linea, ahorrando codigo XD*/ 
    background-color:#FFF8F0;
    margin:1px auto; /*10px arriba y abajo, y auto a los lados, para los navegadores nuevos es suficiente para centrar la pagina*/ 
    text-align:left; /*aqui alineamos todo de nuevo a la izquierda, pero dentro del contenedor*/
    overflow: auto;/*se ajusta a firefox para que se vea bien*/
    /*overflow-y:hidden; 
    overflow-y:hidden;overflow-x:hidden;*/
}

#margenDerecho{
    margin: 1px; /*para que no se pegue al borde*/ 
    padding: 1px; /*algo de relleno*/
    width: 230px; /*  este ancho es para que cuadre con el texto*/ 
     /* height:50px; idem*/
    border: 1px solid #333333; /*decoracion*/ 
    background-color: #CC6600; /*more*/ 
    float: right; /*lo flotamos a la izquierda*/ 
    display: inline; /*display:inline;(*)*/ 
}

#margenIzquierdo{
    margin:1px; /*para que no se pegue al borde*/ 
    padding:1px; /*algo de relleno*/
    width:auto; /*240 px cambiado para boton borrar  este ancho es para que cuadre con el texto*/ 
     /* height:50px; idem*/ 
    border:1px solid #333333; /*decoracion*/ 
    background-color:#CC6600; /*more*/ 
    float:left; /*lo flotamos a la izquierda*/ 
    display:inline; /*display:inline;(*)*/ 
}

  .droppable_demo {
    width: 230px;
    height: 40px;
    background: #fff;
    border: 1px solid #ccc;
    margin: 0px 0em 0em 0px;
    text-align: center; 
    }
    
  .droppable_demo.hover {
    border: 1px dashed #aaa;
    background:#efefef; 
    }
    
  .draggable{ 
    cursor:pointer; 
    width:230px; 
    height:40px; 
    background:#7baaed; 
    border:1px solid #333;
    margin: 0 1em 1em 0;
    text-align: center;
    }
   
   #margenDerecho.hover {
    background-color: #FFFF99;
   }
</style>

</head>
 
<body> 
<form ENCTYPE="multipart/form-data" METHOD="post" name="form">

<div id="contenedorppal">
 
<div id="margenDerecho">
        <div class="draggable" id="bloq_1">Texto 1</div>
        <div class="draggable" id="bloq_2" align="center">Texto 2</div>
        <div class="draggable" id="bloq_3" align="center">Texto 3</div>
        <div class="draggable" id="bloq_4" align="center">Texto 4</div>
        <div class="draggable" id="bloq_5" align="center">Texto 5</div>
</div> <!-- fin div margenDerecho -->    
    

 <div id="margenIzquierdo"> 
        <div class="droppable_demo" id="cont_1"></div>
        <div class="droppable_demo" id="cont_2"></div>
        <div class="droppable_demo" id="cont_3"></div>
        <div class="droppable_demo" id="cont_4"></div>
        <div class="droppable_demo" id="cont_5"></div>
        <div class="droppable_demo" id="cont_6"></div>
 </div> <!--  fin div margenIzquierdo  -->  
  
  
  
 <script type="text/javascript">
    var capas=document.getElementById("margenDerecho").getElementsByTagName("div");
    for (i=0;i<capas.length;i++){
        capas[i].elObjDraggable = new Draggable(capas[i].id, {revert: true, zindex:100});
        capas[i].posicionInicial = capas[i].cumulativeOffset();
    }
    
    // Para poder devolver elementos a su posición original
    Droppables.add( "margenDerecho", {
        accept: "draggable",            // sólo acepta con className=="draggable"
        hoverclass: "hover",
        onDrop: function(element, dropon) {
            element.heVuelto = true;                // Para controlar si hemos vuelto desde margenIzquierdo
            element.elObjDraggable.options.revert = false;
            mueve(element, element.posicionInicial[0], element.posicionInicial[1] );
        }
    } );

    var capas_cont=document.getElementById("margenIzquierdo").getElementsByTagName("div");
    for (i=0;i<capas_cont.length;i++){
        Droppables.add(capas_cont[i].id, { 
            accept: 'draggable',
            hoverclass: 'hover',
            onDrop: function(element, dropon) { 
                // dropon es el contenedor al que arrastro el 'div'
                // element es el div que arrastro
                if( !dropon.ocupado ) {            // CASILLA LIBRE

                    // Ahora ya está ocupada
                    dropon.ocupado = true;

                    // Haré que la capa se mueva forzadamente a las coordenadas de dropon
                    var coords = dropon.cumulativeOffset();
                    
                    
                    // el revert no funciona bien. Forcémoslo
                    var bordeExtra = parseInt(dropon.getStyle("border-width") || 0)*2;                // borde para sumar a las coordenadas - borderWidth*2 (anomalías..)
                    element.elObjDraggable.options.revert = false;                                    // el revert ya lo hacemos nosotros
                    element.coordenadasBase = [coords.left+bordeExtra, coords.top+bordeExtra];        // coordenadas para volvera aquí en onEnd
                    element.droponBase = dropon;                                                    // para saber cuál es el dropon a donde pertenece
                    
                    // Lo ajustamos bien al dropon, que quede "dentro"
                    mueve(element, coords.left+bordeExtra, coords.top+bordeExtra, function() {
                        // cuando se acabe de mover, nos aseguramos de que el dropon queda ocupado
                        dropon.ocupado = true;
                        // Si sacamos la capa a pasear (si no la hacemos volver a margenDerecho), cuando la soltemos tiene que volver a coordenadasBase (a su droponBase) y ocuparlo
                        element.elObjDraggable.options.onEnd = function() {
                            if( !element.heVuelto && element.coordenadasBase) {        // si no ha vuelto a su posición inicial
                                mueve(element, element.coordenadasBase[0], element.coordenadasBase[1], function() {
                                    element.droponBase.ocupado = true;        // ha vuelto a su dropon base
                                });
                            }
                        }
                    });

                    // cuando saquemos a la capa de dropon tendrá que desocuparse porque no sabemos a dónde irá.
                    element.elObjDraggable.options.onStart = function() {
                        dropon.ocupado = false;
                    }
               
                 }
                 else {                // CASILLA OCUPADA
                    alert("Esta casilla está ocupada, usa otra por favor.");
                    // Si tenía un droponBase entonces hay que volver a él "de manera forzada"
                    if( element.coordenadasBase ) {
                        element.elObjDraggable.options.revert = false;
                        mueve(element, element.coordenadasBase[0], element.coordenadasBase[1], function() {
                            element.droponBase.ocupado = true;        // al volver al droponBase así, habrá que ocuparlo
                        });
                    }
                }
                
             }
          });
    }


    function mostrarValores(){
        /*var capas_cont=document.getElementById("margenIzquierdo").getElementsByTagName("div");
        for (i=0;i<capas_cont.length;i++){
           alert(capas_cont[i].id);
        }

        var capas_cont=document.getElementById("margenDerecho").getElementsByTagName("div");
        for (i=0;i<capas_cont.length;i++){
           alert(capas_cont[i].id);
        }*/
    }

    function mueve(elemento, x, y, despues) {
        var coords = elemento.cumulativeOffset();
        coords = [parseInt(x-coords.left), parseInt(y-coords.top)];
        new Effect.Move(elemento, { x: parseInt(coords[0]), y: parseInt(coords[1]), duration: 1,
             queue: {scope:'', position:''}, mode:'relative', afterFinish: despues
        })
    }
  </script>
  
  <input type="submit" value="Seleccionar" name="seleccionar" onClick="mostrarValores();">
  
</div> <!-- fin contenedorppal -->
</form>


</body>
</html> 
He sudado bastante para sacarlo. La función mueve() es totamente fortuíta, la he sacado sin querer...


Y he visto que te peleas con el CSS, hay buena gente en el foro de CSS (no se te ocurra postearles este javascript jajaj). De todas maneras si es una duda simple te la sabría responder.

Espero que te guste más es script. No he hecho el mostrarValores(), creo que habría que ir almacenándo las cosas en campos ocultos paralelamente para saber qué ocurre de verdad y poder enviar al servidor algo.


Por cierto, según he leído en algún post, necesito borrar una línea en dragdrop.js (lo que hay que hacer...). Línea 41, es así:
Element.makePositioned(element); // fix IE
Bueno, pues esa a comentarla, que si no pasan cosas raras (además funciona igual..).



Bueno, un saludo.
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.