Drag and Drop

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Drag and Drop

par Rei Itchido » 09 juil. 2008, 10:22

Je découvre ce topic et je tiens à saluer sadeq pour sa pédagogie :pouce:

par orgerix » 03 sept. 2007, 14:32

C'est bon, j'ai trouvé ce qui buggais. Comme je me sert d'une barre de défilement interne, document.body.scrollLeft et document.body.scrollTop restaient fixe.

Je pense que maintenant tout va bien. Merci beaucoup Sadeq, j'ai beaucoup progressé dans le javascript (faut dire, je suis parti de pas grand chose...)

par sadeq » 03 sept. 2007, 09:06

Tu peux voir du côté des coordonnées de la barre de défilement (document.body.scrollLeft et document.body.scrollTop) pour ajuster tes points x,y

Par exemple dans la fonction de déplacement onmousemove:

Code : Tout sélectionner

//fonction événementielle pour déplacer le membre selon les XY de la souris en mouvement = milieu du drag&drop document.onmousemove = function deplaceMembre(e) { //XY de la souris var x, y; //IE if (window.event){ x = window.event.x; y = window.event.y;} //FF else { x = e.clientX; y = e.clientY; } //Corriger xy par rapport à la barre de défilement de la page x += parseInt(document.body.scrollLeft ||0); y += parseInt(document.body.scrollTop ||0); //Déplacer le membre sélectionné aux XY if (membre_select && x && y){ membre_select.style.position = "absolute"; membre_select.style.top = y - 5; membre_select.style.left = x - 5; membre_select.style.zIndex = 1; } }

par orgerix » 01 sept. 2007, 14:44

Non, c'est pas ca...

J'ai le même problème.

EDIT : Je ne comprend aps pourquoi, maintenant ca marche avec FF.

J'ai maintenant un autre problème. J'ai l'impression que FF encode les variables envoyés en uft8 et pas IE. Commetn faire pour gérer ce problème ?

EDT 2 :

J'ai réglé le problème en envoyant les données par POST

D'autre part, si on essaye de mettre des formulaire dans la même page, on ne pourra pas les selectionner sous FF. J'ai réglé le problème en mettant OnClick="this.focus();"

IL me reste tout de même un problème. SI on fait défiler la page, les coordonnées sont en fonction de la page et non de l'écran. Comment prendre en compte le défilement ?

par sadeq » 01 sept. 2007, 13:48

Je pense que c'est clientWidth qui cause le problème sous FF car le width du div contener est fixé par un style. Vaut mieux vider le width du style avant d'appeler clientWidth :

Code : Tout sélectionner

function adjust(){ document.getElementById('contener').style.left = ''; var width=document.body.clientWidth; document.getElementById('contener').style.left=width/2-395; }

par orgerix » 01 sept. 2007, 11:12

Mon contener est déclaré comme ca :

Code : Tout sélectionner

<div id="contener" style="overflow:auto; position:absolute; left:0px ; top:0px; width:790px; height:580px; z-index:10; padding-right: 10px; text-align:left;">
Et le plus étrange, c'est que l'erreur ne viens pas lors du déplacement mais lorsqu'on dépose dans une zone, et ce, sans message d'erreur.

De plus, je modifie la veleur de left par javascript pour ajuster le contener en fonciton de la résolution du navigateur.

Code : Tout sélectionner

function adjust() {var width=document.body.clientWidth; document.getElementById('contener').style.left=width/2-395; }
EDIT : En fait, ca marche sur IE mais pas sur FF

par sadeq » 01 sept. 2007, 01:45

C'est bizare, ça marche bien le parseInt() moi j'ai ça dans le div conteneur principal:

Code : Tout sélectionner

<div id="contener" style="position:absolute; top:10px; left:10px;">
et même avec les "px" parseInt() fonctionne et retourne top=10 et left=10

Par contre si on met les coordonnées left et top dans un style hors la balise ça ne fonctionne pas car javascript ne récupère pas les positions du style.

par orgerix » 01 sept. 2007, 00:23

Ou tout simplement mettre cette ligne

Code : Tout sélectionner

membre_select.style.position=''; membre_select=null;
Sinon, j'ai remplacé la ligne

membre_select.style.left = x -10; //axe horizontal

par

membre_select.style.left = x -parseInt(document.getElementById('contener').style.left) - 10; //axe horizontal

Et ca me fait planter le script car une fois relaché, le nom reviens automatique à sa place.

par sadeq » 31 août 2007, 23:57

1. la valeur de la propriété Left est en pixel, elle peut contenir l'unité "px" il faut faire un parseInt() pour la convertir avant usage dans un calcul. Comme:

Code : Tout sélectionner

parseInt(document.getElementById('conteneur').style.left)
on écrit souvent aussi:

Code : Tout sélectionner

parseInt(document.getElementById('conteneur').style.left || '0')
pour que le parseInt() retourne 0 si left est "undefined"

2. pour le problème du membre suspendu à la souris tantqu'il n'est pas déposé dans une équipe, c'est normal il faut régler ça, pour respecter l'effet drag&drop. Il faut donc effectivement programmer onMouseUp du conteneur principal pour annuler la sélection du membre (membre_select = null;) après l'avoir redonner sa position fixe.

par orgerix » 31 août 2007, 17:47

J'ai un petit problème a adapter le script.

Comme sur mon arrière plan, j'ai un cadre clair au milieu et des bordures avec des dessins, tout mon site ce situe dans le cadre et est donc contenu dans un div avec comme position absolute.

Mais maintenant, quand je déplace les membre, j'ai l'impression qu'il prend comme point de référence le bors supèrieur gauche du contener. J'ai essayé de modifier la ligne qui règle l'axe des x comme ca :

Code : Tout sélectionner

membre_select.style.left = x - (10+ document.getElementById('conteneur').style.left); //axe horizontal
Mais ca me met comme erreur

Code : Tout sélectionner

Erreur d'analyse de la propriete left. Déclaration abandonnée

D'autre par, j'ai remarqué un "bug". Quand on relache la sourit dans un zone non défini, le membre reste collé à la souris. Pas très grave mais si on pouvais arranger ca.

J'ai d'abord pensé à un evenement générique avec OnMouseUp, mais ca n'entrerai pas en condradiction avec l'evenement OnMouseUp des zones ?

par sadeq » 31 août 2007, 16:15

Le plaisir était pour moi, voici le récap pour toi et nos lecteurs. La solution finale, un peu améliorée, qui affiche les équipes et leurs membres graphiquement selon les données existant dans la base de données et réalise les affectation des membres.

Avec 3 variantes:
1. un groupe des membres sans équipe est affiché aussi pour les membres qui ne sont pas encore affectés
2. les équipes qui n'on pas encore de membres sont affichées vides.
3. les membres affectés à une équipe sont affichés sous forme de table HTML dans leurs divs équipes et le déplacement d'un membre positionne ce dernier automatiquement dans la première céllule libre dans la table HTML. Ce qui permet d'aligner l'affichage des membres dans l'équipe.

Pour réaliser les 2 premières variantes, il faut ajouter une table "equipe" dans la base de données et autoriser les nulls dans le champ equipe de la table membre.

Pour la 3° variante, une fonction javascript est programmée au niveau de l'événement onMouseUp pour insérer l'objet membre à sa place dans la table HTML de l'équipe d'accueil.

Voici le code final des 2 pages client et serveur:
Page: affecter.membre.client.php
<script>
          /**
         * Moteur Ajax
         */       
         function getXhr(){
            var xhr = null;
            if(window.XMLHttpRequest) // Firefox et autres
               xhr = new XMLHttpRequest();
            else if(window.ActiveXObject){ // Internet Explorer
               try {
                         xhr = new ActiveXObject("Msxml2.XMLHTTP");
                     } catch (e) {
                         xhr = new ActiveXObject("Microsoft.XMLHTTP");
                     }
            }
            else { // XMLHttpRequest non supporté par le navigateur
               alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
               xhr = false;
            }
          return xhr;
         }
         
          /**
         * Méthode qui appelle un script serveur et renvoit sa réponse
         *
         * serveur: l'url du script serveur appelé
         * reponse: objet HTML donné par référence à un conteneur HTML de la page chargée
         * paramètres: liste des paramètres éventuellement passés au script serveur (param1=valeur1&param2=valeur2...)
         **/
         function getByAjax(serveur, reponse, methode, parametres){
           var xhr = getXhr(); //Nouvelle instance Ajax
           if (xhr && serveur){
            // On défini la fonction observant la communication Ajax/serveur
            xhr.onreadystatechange = function(){
               // le code 4/200: détermine que Ajax a reçu une réponse du serveur
               if(xhr.readyState == 4 && xhr.status == 200){
                  reponse.innerHTML = xhr.responseText;  //renvoit la réponse du serveur dans le conteneur reponse
               }
             }

             // Déclenchement de l'appel Ajax/serveur + envoi paramètres POST ou GET
             if (methode == "POST"){
            xhr.open("POST", serveur, true);
               xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
               xhr.send(parametres);
          }
          else {
            xhr.open("GET", serveur+"?"+parametres, true);
               xhr.send(null);             
          }
           }
        }
</script>
<!-- Div de réponse Ajax -->
<div id="div_reponse"></div> 

<?php
//équipes/membres de la base
if (file_exists('../bzw.php')){
    include('../bzw.php');
    $connexion = mysql_connect($host,$user,$password) or die("connexion impossible au serveur");
    mysql_select_db($database,$connexion) or die("la base de donnée n'a pas pu être ouverte");
    //Lister tout: les équipes connues et les membres ayant une équipe ou non
    $requet = " (SELECT equipe.id as equipe, login FROM equipe left join membre on equipe.id=membre.equipe GROUP BY equipe.id, login ORDER BY equipe.id, login)
                UNION 
                (SELECT equipe, login FROM membre WHERE isNull(equipe) or equipe='' GROUP BY equipe, login ORDER BY equipe, login)";
    $result = mysql_query($requet,$connexion);
    //Lire les membres et les grouper par équipe dans un tableau
    while ($result && ($row = mysql_fetch_assoc($result))) {
        $equipe = trim($row["equipe"]);
        $login = trim($row["login"]);
        //Créer un tableau pour des équipes connues même si aucun membre 
        if ($equipe!="") $equipes["$equipe"][] = $login;
        //Créer un tableau pour les membres sans équipe même si aucun membre 
        $equipes["Sans équipe"][] = !$equipe?$login:"";
    }
    //trier le tableau pour que la branche "Sans équipe" soit tassée vers la fin
    array_multisort($equipes);
}
//Lire et afficher le tableau des équipes et leurs membres
if (is_array($equipes)){
  $i=0;
  echo "<table width='100%' border='0'><tr>";
  //Afficher les cadres d'équipes
  foreach($equipes as $equipe=>$membres){
    //Afficher 4 équipes par ligne
    if ($i>0 && $i%4==0) echo "</tr><tr>";
    //Distinguer le groupe des membres sans équipe (id null)
    $equipe_Id = $equipe!="Sans équipe"?$equipe:"null";
    $equipe_Nom = $equipe;
    echo "<th>
        <div id='$equipe_Id' onMouseUp='placeMembre(this);' class='equipe'><b>$equipe_Nom</b>
        <hr><table id='table_$equipe_Id' width='100%' border='0'><tr>";
    $j=0;
    //Afficher le membre de chaque cadre équipe
    foreach ($membres as $membre)
    {
      //Afficher 4 membres par ligne
      if ($j>0 && $j%4==0) echo "</tr><tr>";
      if ($membre){
        $membre_Id = $membre;
        $membre_Nom = $membre;
          echo "<th class='cell'>
              <div id='$membre_Id' onMouseDown='selectMembre(this);' class='membre'>$membre_Nom</div></th>";
      }
      $j++;   
    }
    echo "</tr></table></div></th>";
    $i++;
  }
  echo "</tr></table>";
}
?>

<script>
//CODE POUR LE DRAG&DROP

//mémoire globale d'un membre sélectionné
var membre_select = null;

//fonction pour sélectionner le membre pointé = commencement du drag&drop
function selectMembre(membre){    
    membre_select = membre;
}

//fonction pour placer le membre dans une équipe = fin du drag&drop
function placeMembre(equipe){
    if (equipe && membre_select) {
        //Affectation du membre sélectionné dans l'équipe pointé dans la base de données par Ajax
        getByAjax('affecter.membre.serveur.php', document.getElementById('div_reponse'), 'GET', 'equipe='+equipe.id+'&login='+membre_select.id);
        
        //Placement de l'objet membre dans l'objet équipe
        membre_select.style.position = ""; //ancrer sa position
        insertCellToTable("table_"+equipe.id, membre_select, 4); //l'insérer dans la table de destination
        
        //Effacer la sélection en cours = terminé
        membre_select = null;
    }
}

//fonction d'insertion d'une nouvelle céllule dans une table HTML
function insertCellToTable(tableId, contentCell, defaultCols){
    //Propriétés de la table ciblée
    var table = document.getElementById(tableId);
    var rows = table.rows.length;
    var cols = defaultCols;
    //Céllule recherchée pour l'insertion du contenu
    var cell = null;
    //Recherche de la position d'insertion = première céllule libre ou à la fin de la table
    var r=0;
    //Parcourir les lignes
    while (r<rows && cell == null) { 
        var c=0;
        //Et les colonnes 
        while (c<cols && cell == null){
            //si la céllule en cours est la dernière
            if (table.rows[r].cells[c]==null) {
                //en ajouter une nouvelle
                cell = table.rows[r].insertCell(-1);
            }
            //sinon si vide la réutiliser
            else if (table.rows[r].cells[c].innerHTML=="") cell = table.rows[r].cells[c];
            c++;
        }
        r++;
    } 
    //A la fin de la recherche si cell est toujours introuvable, ajouter une nouvelle ligne et céllule
    if (cell == null) {var row = table.insertRow(-1); cell = row.insertCell(-1);}
    //Et finalement placer le contenu dans la céllule cell (existante ou nouvelle)
    cell.appendChild(contentCell);
    //Formater la nouvelle céllule par une classe CSS
    cell.className = "cell";
}

//fonction événementielle pour désactiver la sélection du texte dùe au drag&drop
document.onmousedown = function (){
    document.onselectstart=function() { return false; }; //IE
    return false; //FF
}

//fonction événementielle pour annuler le drag&drop
document.onmouseup = function (){
    membre_select.style.position = "";
	membre_select = null;
}

//fonction événementielle pour déplacer le membre selon les XY de la souris en mouvement = milieu du drag&drop
document.onmousemove = function deplaceMembre(e)
{ 
    //XY de la souris
    var x, y;
    //IE
    if (window.event){ x = window.event.x;  y = window.event.y;}
    //FF
    else { x = e.clientX; y = e.clientY; }
    //Déplacer le membre sélectionné aux XY
    if (membre_select && x && y){
        membre_select.style.position = "absolute"; 
        membre_select.style.top = y - 5; 
        membre_select.style.left = x - 5;
        membre_select.style.zIndex = 1;
    }
}
</script>
<style>
    .equipe {width:200px; height:200px;  border: 1px solid #eeeeee; background-image:url(equipe.gif); background-repeat:no-repeat; cursor:pointer; text-align:center; margin:10}
    .membre {width:30px; height:30px;  line-height:70px; border-style:none; background-image:url(membre.gif); background-repeat:no-repeat; cursor:pointer; ; text-align:center; margin:10; display:table-cell;}
    .cell {border: none}
</style>

<?php
/*
* Base de données utilisée
-- phpMyAdmin SQL Dump
-- version 2.9.2
-- http://www.phpmyadmin.net
-- 
-- Serveur: localhost
-- Généré le : Jeudi 30 Août 2007 à 02:10
-- Version du serveur: 5.0.27
-- Version de PHP: 5.2.1
-- 
-- Base de données: `test`
-- 

-- --------------------------------------------------------

-- 
-- Structure de la table `equipe`
-- 

CREATE TABLE `equipe` (
  `id` varchar(20) collate latin1_general_ci NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

-- 
-- Contenu de la table `equipe`
-- 

INSERT INTO `equipe` (`id`) VALUES 
('e1'),
('e2'),
('e3'),
('e4'),
('e5'),
('e6'),
('e7'),
('e8');

-- --------------------------------------------------------

-- 
-- Structure de la table `membre`
-- 

CREATE TABLE `membre` (
  `login` varchar(20) collate latin1_general_ci NOT NULL,
  `equipe` varchar(20) collate latin1_general_ci default NULL,
  PRIMARY KEY  (`login`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

-- 
-- Contenu de la table `membre`
-- 

INSERT INTO `membre` (`login`, `equipe`) VALUES 
('m1', 'e1'),
('m2', 'e2'),
('m3', 'e3'),
('m4', 'e4'),
('m5', NULL),
('m6', NULL);

*/
?> 
Page: affecter.membre.serveur.php
<?php
//reçoit 2 paramètres: equipe et login du membre
//print_r($_GET);
$equipe = trim(html_entity_decode($_GET['equipe']));
$equipe = $equipe!="null"?$equipe:null;
$login = trim(html_entity_decode($_GET['login']));
if ($login && file_exists('../bzw.php')){
    include('../bzw.php');
    //Affecter le membre à l'équipe 
    $connexion = mysql_connect($host,$user,$password) or die("connexion impossible au serveur");
    mysql_select_db($database,$connexion) or die("la base de donnée n'a pas pu être ouverte");
    $requet = "UPDATE membre SET equipe='".mysql_real_escape_string($equipe,$connexion)."' WHERE login='".mysql_real_escape_string($login,$connexion)."'";
    $result = mysql_query($requet,$connexion);
    //Vérifier si la mise à jour est effectuée
    if ($result) {
        echo utf8_encode('Affectation effectuée');
        exit;
    }
}
//Dans tous les cas d'erreur
echo utf8_encode('Affectation non effectuée');

?> 
<?php
/*
* Base de données utilisée
-- phpMyAdmin SQL Dump
-- version 2.9.2
-- http://www.phpmyadmin.net
-- 
-- Serveur: localhost
-- Généré le : Jeudi 30 Août 2007 à 02:10
-- Version du serveur: 5.0.27
-- Version de PHP: 5.2.1
-- 
-- Base de données: `test`
-- 

-- --------------------------------------------------------

-- 
-- Structure de la table `equipe`
-- 

CREATE TABLE `equipe` (
  `id` varchar(20) collate latin1_general_ci NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

-- 
-- Contenu de la table `equipe`
-- 

INSERT INTO `equipe` (`id`) VALUES 
('e1'),
('e2'),
('e3'),
('e4'),
('e5'),
('e6'),
('e7'),
('e8');

-- --------------------------------------------------------

-- 
-- Structure de la table `membre`
-- 

CREATE TABLE `membre` (
  `login` varchar(20) collate latin1_general_ci NOT NULL,
  `equipe` varchar(20) collate latin1_general_ci default NULL,
  PRIMARY KEY  (`login`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

-- 
-- Contenu de la table `membre`
-- 

INSERT INTO `membre` (`login`, `equipe`) VALUES 
('m1', 'e1'),
('m2', 'e2'),
('m3', 'e3'),
('m4', 'e4'),
('m5', NULL),
('m6', NULL);

*/
?>
:wink:

par orgerix » 31 août 2007, 15:47

Un grand merci à toi Sadeq.

Il y a juste une petit détail qui me gène. Lorsqu'on relache l'objet, il reste la ou on l'a posé, sans revenir à sa place 'normal', ou il aurait été s'il avait été lors du chargement de la page. Je pense qu'il faut modifier l'attribut position, mais je ne sais pas quoi mettre à la place. relative ? inherit ?

EDIT :

Après une petite recherche, j'ai trouvé, il faut mettre fixed.

Et encore merci pour ton aide et ta patience

par sadeq » 31 août 2007, 15:38

C'est parfait, t'as tout compris, c'est effectivement comme ça qu'on va appeler Ajax. Voici le script exact:

Code : Tout sélectionner

//fonction pour placer le membre dans une équipe = fin du drag&drop function placeMembre(equipe){ if (equipe && membre_select) { //Affectation du membre sélectionné dans l'équipe pointé dans la base de données par Ajax getByAjax('affecter.membre.serveur.php', document.getElementById('div_reponse'), 'GET', 'equipe='+equipe.id+'&login='+membre_select.id); //Déplacement DomHTML de l'objet membre dans l'objet équipe equipe.appendChild(membre_select); //Effacer la sélection en cours = terminé membre_select = null; } }
L'effect graphique qui représente le déplacement du membre consiste à faire trainer l'objet membre avec le mouvement de la souris à partir du drag (mousedown) jusqu'à le drop (mouseup)

Cet effet peut être programmé par un événement onMouseMove qui observe le mouvement de la souris. Seulement il faut faire écouter cet événement au niveau de tout le document, car l'utilisateur trainera la souris du point d'origine du membre qui est un cadre équipe vers un point d'arrivée qui est une autre équipe et la souris traversera alors des espaces héterogènes de différents objets existant dans la trajectoire du déplacement.

Placer l'écouteur de l'événement onMouseMove au niveau document s'écrit alors:

Code : Tout sélectionner

//fonction événementielle pour déplacer le membre selon les XY de la souris en mouvement = milieu du drag&drop document.onmousemove = function deplaceMembre(e) { ... }
où la fonction "deplaceMembre(e)" servira à simuler graphiquement le déplacement de l'objet membre sélectionné par le drag.

Simuler le déplacement consiste à positionner l'objet membre sélectionné aux points XY de la souris.

Le paramètre "e" sera renseigné par le système et recevra des propriétés concernant l'objet qui déclenche l'événement et les coordonnées XY de la souris

Sous Internet Explorer on a pas besoin du paramètre "e" car les XY de la souris se trouvent dans l'événement window.event par contre pour les autres navigateurs utiliseront le paramètre "e" de la fonction deplaceMembre.

Voici donc la fonction complète:

Code : Tout sélectionner

//fonction événementielle pour déplacer le membre selon les XY de la souris en mouvement = milieu du drag&drop document.onmousemove = function deplaceMembre(e) { //XY de la souris var x, y; //IE if (window.event){ x = window.event.x; y = window.event.y;} //FF else { x = e.clientX; y = e.clientY; } //Déplacer le membre sélectionné aux XY if (membre_select && x && y){ membre_select.style.position = "absolute"; //libérer l'ancre de l'objet membre_select.style.top = y - 10; //axe vertical membre_select.style.left = x - 10; //axe horizontal membre_select.style.zIndex = 1; //axe Z (premier/arrière-plan) } }
Mais il y a un leger désagrément souvent causé par l'effet mouseDown+mouseMove : c'est la sélection de texte, car le navigateur sélectionne le texte selon ces actions combinées. Il faut donc désactiver la sélection de texte pour améliorer l'affichage du drag&drop.

Et pour ce faire, il faut programmer sous IE l'événement onselectstart qui observe la sélection de texte pour annuler son effet. par contre sous d'autres navigateurs cet événement n'existe pas mais on peut annuler l'effet de mousedown qui est à l'origine de l'action de sélection.

Voici, comment faire:

Code : Tout sélectionner

//fonction événementielle pour désactiver la sélection du texte dùe au drag&drop document.onmousedown = function (){ document.onselectstart=function() { return false; }; //IE return false; //FF }
D'abord on tente d'exécuter l'événement onselectstart pour l'annuler pour IE et si c'est pas IE, on annule l'effet de mousedown.

Voilà je croix qu'on a tout là. :wink:

par orgerix » 31 août 2007, 14:31

C'est bon, pour l'instant je suis.

Et c'est beaucoup plus simple que ce que je pensais. Au départ, j'avais imaginer une fonction sur l'effet Onmouseavor qui assignerait l'équipe à une variable globale puis un controleur d'evenement OnmouseUp qui fait la même chose que placerMembre. POurquoi faire simple quand on peut faire compliquer.

Maintenant il faut ajouter la requete Ajax et les effets graphiques

Pour ajouter la requete ajax, il mesemble qu'il suffit de mettre cette ligne avant de supprimer l'objet membre_select.

Code : Tout sélectionner

getByAjax('affecter.membre.serveur.php' ,getElementById( 'reponse'), 'GET', 'login='+membre_select.id+'&equipe='+equipe.id);


Pour les effet graphiques, ben c'est pas trop mon domaine, je suis plutot dans le traitement de données :P

par sadeq » 31 août 2007, 10:43

D'accord, on continue.
Maintenant que le début du drag&drop est programmé, on va s'intéresser à sa fin (en passant sous silence, son milieu, qui est la trainée de l'objet car ce n'est pas important pour l'instant)

Le drag&drop sera terminé dans notre cas quand l'utilisateur, ayant sélectionné un membre en le pointant et pressant la souris, aura pointé un cadre équipe et relaché le bouton de la souris. Ce qui veut dire qu'on doit observer l'événement onMouseUp (bouton de souris relaché) sur tous les cadres équipes car l'utilisateur peut choisir n'importe lequel.

Ceci peut s'écrire pour le cadre de l'équipe e1 par exemple, comme ça:

Code : Tout sélectionner

<div id='e1' onMouseUp="placeMembre(this);" class="equipe">
où la fonction qu'on a nommé "placeMembre(this)" sera déclenchée par un MouseUp et doit donc effectuer le placement du membre déjà sélectionné (qui se trouve dans la variable globale "membre_select") dans le cadre pointé et représenté par l'objet "this" passé à cette fonction.

Sachant que le membre est un div HTML, le placer dans le cadre équipe pointé qui est un div HTML aussi est une affaire relevant du Dom HTML.

Il s'agit du modèle objet du HTML selon lequel toute balise HTML de type conteneur ou collection comme <html> <head> <body> <p> <div> <table> ...
est une hiérarchie de sous objets comme par exemple les hiérarchies suivantes:
html --> head --> title
html --> body --> table
table --> tr --> td
table --> tr --> th
select --> option
...
On peut alors concevoir tout type d'affiliation entre objets et sous objets dans la limite du possible.
Et dans cette optique on peut trés bien affecter un objet dans un autre objet conteneur en l'affectant à un noeud de sa collection de sous-objets.

Nos div répondent à ce modèle, on peut donc affecter l'objet div membre dans l'objet div équipe en exploitant les méthodes et propriétés du modèle objet HTML (pour plus d'information voir DOM HTML)

Voici donc la fonction javascript "placeMembre(this)" qui réalise cette acrobatie à notre pauvre petit div membre "membre_select":

Code : Tout sélectionner

//fonction pour placer le membre dans une équipe = fin du drag&drop function placeMembre(equipe){ if (equipe && membre_select) { //Placement de l'objet membre dans l'objet équipe equipe.appendChild(membre_select); //Effacer la sélection en cours = terminé membre_select = null; } }
Voilà, après avoir tester la présence des 2 objets concernés : equipe qui est le parmètre reçu de "this" référençant le cadre équipe déclencheur du onMouseUp et membre_select qui représente l'objet membre sélectionné, la fonction place l'objet membre en tant que fils de l'objet equipe.

En l'occurence, elle ajouté le div membre sélectionné au contenu du div équipe pointé en l'arrachant biensûr de son conteneur d'origine car l'objet membre est manipulé par référence.

Ceci provoque visuallement le déplacement qui illustre le dra&drop.

Le drag&drop étant terminé, la fonction, fait le ménage dans la variable globale et vide donc la sélection du membre traité par l'affectation "membre_select = null;"

Est-ce clair? un petit test s'impose de ce mécanisme avant de poursuivre et voir comment inclure dans notre programme l'appel Ajax au serveur Update.

Voici un récap de ce qu'on a fait jusqu'à maintenant sur le client:
Page: affecter.membre.client.php
<script>
          /**
         * Moteur Ajax
         */       
         function getXhr(){
            var xhr = null;
            if(window.XMLHttpRequest) // Firefox et autres
               xhr = new XMLHttpRequest();
            else if(window.ActiveXObject){ // Internet Explorer
               try {
                         xhr = new ActiveXObject("Msxml2.XMLHTTP");
                     } catch (e) {
                         xhr = new ActiveXObject("Microsoft.XMLHTTP");
                     }
            }
            else { // XMLHttpRequest non supporté par le navigateur
               alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
               xhr = false;
            }
          return xhr;
         }
         
          /**
         * Méthode qui appelle un script serveur et renvoit sa réponse
         *
         * serveur: l'url du script serveur appelé
         * reponse: objet HTML donné par référence à un conteneur HTML de la page chargée
         * paramètres: liste des paramètres éventuellement passés au script serveur (param1=valeur1&param2=valeur2...)
         **/
         function getByAjax(serveur, reponse, methode, parametres){
           var xhr = getXhr(); //Nouvelle instance Ajax
           if (xhr && serveur){
            // On défini la fonction observant la communication Ajax/serveur
            xhr.onreadystatechange = function(){
               // le code 4/200: détermine que Ajax a reçu une réponse du serveur
               if(xhr.readyState == 4 && xhr.status == 200){
                  reponse.innerHTML = xhr.responseText;  //renvoit la réponse du serveur dans le conteneur reponse
               }
             }

             // Déclenchement de l'appel Ajax/serveur + envoi paramètres POST ou GET
             if (methode == "POST"){
            xhr.open("POST", serveur, true);
               xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
               xhr.send(parametres);
          }
          else {
            xhr.open("GET", serveur+"?"+parametres, true);
               xhr.send(null);             
          }
           }
        }
</script>
<!-- Div de réponse Ajax -->
<div id="div_reponse"></div> 

<!-- Une équipe -->
<div id='e1' onMouseUp="placeMembre(this);" class="equipe"><b>e1</b><hr>
	<!-- Un membre -->
	<div id='m1' onMouseDown="selectMembre(this);" class="membre">m1</div>
</div>

<!-- Une équipe -->
<div id='e2' onMouseUp="placeMembre(this);" class="equipe"><b>e2</b><hr>
	<!-- Un membre -->
	<div id='m2' onMouseDown="selectMembre(this);" class="membre">m2</div>
</div>

<script>
//CODE POUR LE DRAG&DROP

//mémoire globale d'un membre sélectionné
var membre_select = null;

//fonction pour sélectionner le membre pointé = commencement du drag&drop
function selectMembre(membre){	
	membre_select = membre;
}

//fonction pour placer le membre dans une équipe = fin du drag&drop
function placeMembre(equipe){
	if (equipe && membre_select) {
	
		//Déplacement DomHTML de l'objet membre dans l'objet équipe
		equipe.appendChild(membre_select);
		
		//Effacer la sélection en cours = terminé
		membre_select = null;
	}
}
</script>
<style>
	.equipe {width:200px; height:200px;  border: 1px solid #eeeeee; background-image:url(equipe.gif); background-repeat:no-repeat; cursor:pointer; text-align:center; margin:10}
	.membre {width:30px; height:30px; line-height:70px; border-style:none; background-image:url(membre.gif); background-repeat:no-repeat; cursor:pointer; ; text-align:center; margin:10}
</style>