11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous,

J'expose mon problème:
J'ai un tableau classique avec un libellé, une petite flèche montante et une autre descendante.
En gros:

<tr>
     <td>
           Lib1
     </td>
     <td>
           +
     </td>
     <td>
           -
     </td>
</tr>

Je voudrais que lorsqu'on clique sur le + par exemple ce tr passe au dessus de l'autre.
J'utilise la librairie prototype.

Je cherche quelque chose le plus simple possible.
Après moult recherche, je n'ai rien trouvé de concrès ou qui me plaisait.

Merci de votre aide.
Modifié par rob44 (02 Jul 2009 - 17:08)
Bonjour,

Si Prototype propose des fonctionnalités d'aide à la manipulation du DOM, il doit bien y avoir une méthode pour récupérer un noeud DOM (le TR à déplacer), le supprimer de l'arbre DOM, et le placer avant le TR précédent ou après le TR suivant. Je vois à peu près comment ça peut se faire avec jQuery, mais pour Prototype j'avoue mon ignorance.

À tout hasard, je rappelle que la documentation qui va bien est par là:
http://www.prototypejs.org/api/element

Si quelqu'un qui a une bonne expérience de Prototype passe par ici, il pourra te guider d'avantage.

(Sinon ça se fait sans doute bien en DOM pur, sans passer par une bibliothèque de fonctions.)
Merci de ta réponse.
J'ai déjà regardé la doc et sur le principe de comment faire, j'ai un peu compris.
Le problème est que je suis totalement débutant en javascript et si j'arrive à le comprendre à la lecture, en faire moi-même devient plus difficile.

Ça allait jusqu'à présent mais là ça devient un peu trop compliqué pour moi et mes délais sont trop courts.

Sans demander une source complète, si quelqu'un pouvait m'aider d'avantage, ça serait le bonheur.

Là je patauge malheureusement mais bon je vais quand même retenter des choses avec la doc, de toute façon, j'ai pas le choix, il faut que j'y arrive.
Salut,

Voici une solution, à mettre au chargement de ta page bien sûr (Event.observe(window, "load") :
Event.observe("myTable", "click", function(event) {
    var target = Event.element(event);
    if (target.hasClassName('up')) {
        var row = Event.findElement(event, 'tr');
        var previousTr = row.previous('tr');
        if (previousTr) {
            previousTr.insert({'before': row});
        }
    } else if (target.hasClassName('down')) {
        var row = Event.findElement(event, 'tr');
        var nextTr = row.next('tr');
        if (nextTr) {
            nextTr.insert({'after': row});
        }                    
    }
});
Pour que ça marche, il faut que tu mettes les id et classes suivants :
<table id="myTable">
    <tr>
        <td>Lib1</td>
        <td class="up">+</td>
        <td class="down">-</td>
    </tr>
</table>

@modos : la coloration syntaxique [code=js] proposée par le select marche pô (empêche visiblement l'interprétation correcte de la balise [code]).
Modifié par marcv (03 Jul 2009 - 09:41)
Bon je dois être idiot mais je n'arrive pas à faire fonctionner ce script...
Je suis sur que ça vient de moi.

Au niveau du "(Event.observe(window, "load")" quelle est la syntaxe à mettre ?
Car en fait je ne sais pas vraiment.

Dans les autres scripts, il y avait ceci d'utilisé:
document.observe('dom:loaded', function(){


Même utilité ou pas ? Je pensais mais je suis pas sur du tout maintenant.

EDIT: j'ai rien dit, j'ai fait une grosse erreur ailleurs. Je vous redis ça ensuite.

EDIT2: Ca marche, un grand merci de tout coeur. Je n'avais rien trouvé de bien et là rapidement, j'ai quelque chose de simple et fonctionnel.

On peut dire que mon problème est résolu.
Merci pour l'aide
Modifié par rob44 (03 Jul 2009 - 10:43)
a écrit :
document.observe('dom:loaded', function(){
Même utilité ou pas ?
C'est très bien si tu utilises déjà dom:loaded, c'est encore mieux que window.load.
Bon alors je continue le sujet pour ma culture et mon apprentissage.
En quoi est-ce mieux justement, quelle est la différence ?

Merci d'avance.
C'est simple : le code que je t'ai donné se contente de trouver le tableau #myTable et de lui coller un gestionnaire d'événement. Pour ça on a pas besoin d'attendre que la page soit complètement chargée, avec images et ressources externes téléchargées, mais simplement que le DOM (la charpente de la page) soit prêt, ce qui arrive bien sûr avant. Voilà pourquoi on préfère dans ce cas 'dom:loaded' à (window, 'load').
Modifié par marcv (03 Jul 2009 - 13:11)
Ok, j'ai compris la différence.
Ça rentre petit à petit.

Merci de l'explication.
Bon finalement j'ai encore un problème avec ce tableau mais le problème est différent.
Je ne sais pas si je dois créer un nouveau sujet mais comme c'est dans la même partie du code je me suis dit autant poser ma question ici.

Alors voilà dans mon tableau, sur un tr sur deux il y a un "class='fondBleu' pour avoir une ligne sur deux blanche et l'autre bleu.
Mais voilà quand j'intervertis mes lignes, forcément ça ne marche plus.
J'ai essayé quelque chose et je pensais que cela allait fonctionner. Je vous met mon bout de code et j'explique mon problème:

Event.observe("tableValeurs", "click", function(event) {
  	    var target = Event.element(event);
  	    if (target.hasClassName('up')) {
  	        var row = Event.findElement(event, 'tr');
  	        var previousTr = row.previous('tr');
  	        if (previousTr) {
  	            previousTr.insert({'before': row});
  	            if (row.hasClassName('fondBleu')){
					row.className = '';
					previousTr.className='fondBleu';
  	            }
  	            else {
  	            	row.className = 'fondBleu';
					previousTr.className='';
  	            }
  	        }
  	    } else if (target.hasClassName('down')) {
  	        var row = Event.findElement(event, 'tr');
  	        var nextTr = row.next('tr');
  	        if (nextTr) {
  	            nextTr.insert({'after': row});
  	            if (row.hasClassName('fondBleu')){
					row.className = '';
					nextTr.className='fondBleu';
  	            }
  	            else {
  	            	row.className = 'fondBleu';
					nextTr.className='';
  	            }
  	        }
  	    }
  	});


Bon ce code marche une fois. Et oui ça change bien les class de mes tr mais quand je regarde la source, cela n'a pas bougé. Donc au coup suivant, ça déconne puisque le code dit blanc alors qu'on voit à l'écran bleu.
Je ne vois pas comment faire, si quelqu'un a compris et voit une solution, merci d'avance.

EDIT:
Une fois de plus, le problème était l'interface chaise clavier, c'est à dire moi.
Une belle erreur de ma part.

J'ai donc maintenant un beau tableau dans lequel je peux monter ou descendre le tr à l'aide de jolies petite flèches.
Merci pour votre aide.

Ce problème est définitivement résolu.
Modifié par rob44 (03 Jul 2009 - 17:08)
Des lignes comme ça sont problématiques :
row.className = '';
nextTr.className='fondBleu';
En effet, tu effaces/remplaces l'ensemble des classes affectées à ton <tr>. Pour le moment tu n'as peut-être que 'fondBleu', mais si un jour tu dois en ajouter d'autres, pour par exemple styler un peu plus le tableau, ton script les effaceras à chaque clic. Prototype, comme quasiment toutes les autres bibliothèques JS, propose des méthodes qui répondent spécialement à ce besoin (un des plus courants) :
- addClassName() pour ajouter une classe sans toucher aux autres
- removeClassName() pour retirer une classe sans toucher aux autres
- toggleclassName() pour ajouter/retirer une classe en mode "va et vient", sans toucher aux autres.

Autre chose : ça commence à faire pas mal de tâches identiques dans les deux cas (monter/descendre), on peut donc tenter de factoriser un peu le code. Voici une nouvelle version, plus courte mais qui fait la même chose (gestion des "fondBleu" incluse) :
Event.observe("tableValeurs", "click", function(event) {
    var target = Event.element(event);
    var isMoveCell = target.className.match(/(^|\s)(up|down)(\s|$)/);
    if (isMoveCell) {
        var row = Event.findElement(event, 'tr');
        var otherRow = row[isMoveCell[0] == 'up' ? 'previous' : 'next']('tr');
        if (otherRow) {
            otherRow.insert(isMoveCell[0] == 'up' ? {'before':row} : {'after':row});
            [row, otherRow].each(function(tr){
                tr.toggleClassName('fondBleu');
            });
        }
    }
});
C'est bien sûr toujours à mettre dans un gestionnaire dom:loaded.
Modifié par marcv (03 Jul 2009 - 18:04)
Encore merci,
je viens d'apprendre des choses bien utiles grâce à toi et mon code marche nickel.

J'ai rien d'autre à ajouter pour l'instant.