IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

[JS + AJAX] Gestion de groupe avec un nombre important d'utilisateurs


Sujet :

JavaScript

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 61
    Points : 36
    Points
    36
    Par défaut [JS + AJAX] Gestion de groupe avec un nombre important d'utilisateurs
    Bonjour à tous,

    Pour vous expliquer le contexte, voici une capture d'écran du rendu.
    On a donc la liste des groupes déjà créé chargé en AJAX avec la liste des utilisateurs vide dans un premier temps.
    Lorsque l'administrateur ouvre un groupe, ça charge la liste des utilisateurs avec leur checkbox cochés si ils font partie du groupe.

    Nom : gestion_groupes.jpg
Affichages : 205
Taille : 303,2 Ko

    Je me retrouve devant un cas d'optimisation de temps de chargement au vue du nombre d'utilisateurs possible dans chaque groupe.
    Jusqu'à présent pour ce genre d'utilisation j'utilisais de l'AJAX basique, j'appelle une fonction PHP avec l'id du groupe qui génère le tableau HTML des utilisateurs, qui est récupéré en JS et mis dans le conteneur du groupe correspondant par un simple innerHTML.

    Mais voilà, lorsque le retour contient beaucoup d'utilisateurs, ça devient long, environ 6 à 7 secondes pour charger les utilisateurs d'un groupe (dans cet exemple 3379).

    J'ai essayé de charger qu'une seule fois le tableau HTML des utilisateurs dans une DIV masquée, puis de cloner ce tableau dans le conteneur du groupe lors de son ouverture.
    Ensuite je fais un petit appel AJAX qui récupère les id des utilisateurs appartenant au groupe et ça sélectionne les checkbox correspondantes à l'aide de leur valeur (correspondant à l'id).
    Le clonage du tableau et l'appel AJAX se fait rapidement (environ 2s), pas de soucis si il y a peu de case cochés mais si tout est coché par exemple là ça remet environ 6-7s donc retour à la case départ !

    Voici la fonction qui clone le tableau et sélectionne les checkbox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    function cloneUtilisateurs(id) { // id du groupe
    	var newslettersUsersListing = document.getElementById('newslettersUsersListing'); // la div masquée contenant la liste des utilisateurs
    	var cible = document.getElementById('newslettersgroups_dest'+id); // le conteneur du groupe
    	InnerCMSLoading("newslettersgroupsDestList"+id, 'visible', 'fff');
    	removeAllChild(cible);
     
    	var table = firstChildDiv(newslettersUsersListing); // récup du tableau HTML
     
    	var new_table = table.cloneNode(true); // clonage
     
    	cible.appendChild(new_table); // placement
     
     
     
    	action = "get_users";
    	get_Xhr();
    	xhr.onreadystatechange = function() {
    		if(xhr.readyState == 4 && xhr.status == 200) {
    			retour = xhr.responseText;
     
    			var tab_id = new Array();
    			if(retour != '0') tab_id = retour.split('-+-'); // récup des id des utilisateurs
     
    			var all_checkbox = cible.getElementsByTagName('input'); // récup des input checkbox
     
    			for(var i = 0; i < all_checkbox.length; i++) { // parcours les input
    				var checkbox = all_checkbox[i];
    				if(checkbox.name = "newslettersgroups_inscrits[]") { // si c'est le bon nom
    					if(in_array(checkbox.value, tab_id)) { // si la valeur de l'input est dans le tableau des id d'utilisateur
    						checkbox.checked = true;
    					} else checkbox.checked = false;
     
    					checkbox.id = "newslettersgroups_inscrits"+id+"_"+i;
     
    					var tr = checkbox.parentNode.parentNode; // la ligne TR
    					var all_label = tr.getElementsByTagName('label'); // récup tous les label de la ligne
    					for(var j = 0; j < all_label.length; j++) {
    						all_label[j].htmlFor = "newslettersgroups_inscrits"+id+"_"+i; // changement du for pour qu'ils soient cliquable
    					}
    				}
    			}
     
    		}
    	}
    	xhr.open("POST","ajax_groups.php",true);
    	xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded Charset=iso-8859-1');	
     
    	xhr.send("action="+action+"&idgroup="+id);
     
    }
    Voila, je ne vois pas comment gagner du temps sur cette procédure.
    Je suis ouvert à toute autre méthode ou critique des miennes, et n'hésitez pas à me dire si il n'y pas de solution miracle

    Merci d'avance.

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Le premier truc qui me vient à l'esprit: une pagination ?

    Ça sert vraiment à quelqu'un d'afficher une liste de 3000 personnes ?
    One Web to rule them all

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 61
    Points : 36
    Points
    36
    Par défaut
    J'y ai pensé mais vu que ce sont des checkbox comment savoir ce qui est coché en page 1 quand on valide en page 2 par exemple.

    Le formulaire ne va soumettre que les checkbox de la page 2 ...

  4. #4
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Pas si tu les gardes en mémoire en JavaScript. Ce qui bouffe les perfs ici ce n'est pas stocker 3000 ID dans une variable, c'est récupérer et charger les infos de 3000 utilisateurs.
    One Web to rule them all

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 61
    Points : 36
    Points
    36
    Par défaut
    Pour être sûr de comprendre ...

    J'appelle ma fonction PHP qui me renvoi une chaine avec juste les id et si ils doivent être cochés ou non, que je récupère en JS dans un tableau par exemple (appelé uniquement à l'ouverture du groupe).
    Puis un autre appel qui renvoie mon HTML contenant uniquement les utilisateurs de la page voulu.

    Après je joue avec les checkbox pour qu'elles agissent sur mon tableau et je "submit" le tableau plutôt que les inputs du coup.

    C'est bien ça ?

    Merci

  6. #6
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Non, une seule requête suffit. C'est envoyer les infos de tous les utilisateurs qui prend du temps. Et l'utilisateur en consultera peut-être maximum 30 avant de se décourager et changer sa recherche / sa méthode.

    Donc tu pourrais par exemple charger les 30 premiers utilisateurs du groupe (avec un simple LIMIT dans ta requête SQL), et renvoyer les infos au client. S'il passe à la page suivante, même chose avec un offset, enfin j'imagine que tu sais comment on fait de la pagination.

    S'il coche décoche des utilisateurs, il suffit de recenser les changements dans un tableau. Ce tableau contiendra donc uniquement les ID qui ont été coché/décoché et leur valeur finale. Ainsi on soumet uniquement que ce qui a changé : travailler de manière différentielle permet aussi d'alléger la soumission, car ce sera toujours plus court que de renvoyer la liste complète et leur état.

    En tout cas, c'est comme ça que je ferais
    One Web to rule them all

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 61
    Points : 36
    Points
    36
    Par défaut
    Que dire de plus que mais bien sûr !

    J'aime bien ta méthode !!
    Déjà rien qu'avec ta première explication (que j'avais compris de travers en plus), en faisant quelques tests vite fait je suis descendu à moins d'1s.

    De toute façon j'avais prévu de mettre un champ de recherche, ça ira très bien avec ta méthode !

    Juste une question du coup, si une case est coché en page 1 (non coché à la base), l'admin passe en page 2 puis revient en page 1, ce qui viendra du PHP ne saura pas qu'une case à été coché en page 1 vu que ça n'aura pas encore été enregistré dans la BD.
    Tu parcourrais le tableau JS contenant les id modifiées pour voir si il y a un input avec le même id pour agir dessus ?

    Merci beaucoup !!

  8. #8
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Oui par exemple, ce n'est pas très compliqué de merger les infos à chaque fois que tu reçois une réponse PHP, il suffit de se baser sur les ID.

    Une autre idée serait d'envoyer une requête directement à chaque fois qu'on coche/décoche quelqu'un. Mais ça fait plus de requêtes et certains utilisateurs trouvent ça pas très intuitif quand il n'y a plus de bouton Enregistrer.
    One Web to rule them all

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 61
    Points : 36
    Points
    36
    Par défaut
    Ok merci pour ta confirmation.

    Ta seconde idée est pas mal aussi, je l'utilise dans certains cas mais sans bouton enregistrer, j'envoi la requête au cochage/décochage directement, avec un masque loading par dessus pendant l'enregistrement pour éviter un double appel AJAX.

    Mais dans ce cas je craint que ça devienne inconfortable pour l'admin si il doit en cocher beaucoup à la suite.

Discussions similaires

  1. Gestion des groupes avec J2EE
    Par aminepidev dans le forum Composants
    Réponses: 2
    Dernier message: 17/10/2013, 22h56
  2. Gestion de données avec grand nombre d'accès
    Par olivier21c dans le forum C++
    Réponses: 6
    Dernier message: 14/04/2010, 13h37
  3. Réponses: 1
    Dernier message: 25/07/2007, 15h45
  4. [LDAP] Gestion de groupe avec alias
    Par Azanael dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 13/10/2006, 14h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo