Forums Développement Multimédia

Aller au contenu

ahref, button et fonction js situé dans un objet

CODE Ajax JQuery EaseJs

9 réponses à ce sujet

#1 tlecoz

  • Honoris
  • PipPipPipPipPipPipPipPip
  • 3485 messages

Posté 01 August 2013 - 00:07 AM

Bonjour,

je débute en html/js ; j'aimerais faire quelque chose qui me parait assez simple mais je n'obtiens pas le résultat que je veux (à cause d'un problème de ciblage qui m'échappe un peu...)


J'ai une "classe" javascript qui se présente comme ça

var MaClasse = function(){
          this.truc = "machin";
}
MaClasse.prototype.callFromLink= function(data){
          alert(data);
}
MaClasse.prototype.callFromButton= function(data){
          alert(data);
}
MaClasse.prototype.createElement = function(phpData){
   //...
}
 

Dans la fonction 'createElement', j'aimerais piloter un objet HTMLTableElement et y insérer dans une boucle plusieurs lignes contenant chacune deux champs :
- le premier champs contient un texte cliquable (un lien quoi)
- le deuxieme contient un bouton

J'aimerais que lorsqu'on clic sur un lien, la fonction 'callFromLink' soit appelé avec le texte du lien en paramètre.

Idem pour le bouton, j'aimerais que lorsqu'on clic dessus, la fonction 'callFromButton' soit appelé avec aussi le texte du lien en paramètre.

J'ai essayé d'utiliser quelques ruses sioux que j'utilisais en AS1 pour résoudre les problèmes de ciblages, mais ça ne suffit pas - dans le sens, ca ne fonctionne pas du tout -

Voila le code actuel contenu dans ma fonction createElement

   var th = this;
        var elements = phpData.split(",");
        var table = document.getElementById("liste");
        alert("onPhpGetRubriques "+table);
        var i,len = elements.length;
        var row,cell;

        if(table.rows.length > 0){
                while(table.rows.length>0) table.deleteRow(0);
        }
        for(i=0;i<len;i++){

                alert("> "+elements[i]);

                row = table.insertRow(i);
                cell = row.insertCell(0);
                cell.rubName = elements[i];
                cell.innerHTML = '<a href="#" onclick="callFromLink('+elements[i]+');">'+elements[i]+'</a>' ;

                cell = row.insertCell(1);
                var btn = document.createElement("input");
                btn.type = "button";
                btn.value = "supprimer la rubrique";
                btn.rubName = elements[i];

                btn.onclick = function(){
                        th.callFromButton(this.rubName);
                   // th.phpLoader.sendDatas("removeRubrique.php","removeRubrique",[this.rubName],th.onPhpRemoveRubrique)
                }

                cell.appendChild(btn);
        }
 

Evidemment, ça marche pas...


Une idée ? Image IPB

EDIT : Désolé pour le multipost, je voulais modifier le titre et cela a créé un nouveau sujet...

#2 tlecoz

  • Honoris
  • PipPipPipPipPipPipPipPip
  • 3485 messages

Posté 01 August 2013 - 01:57 AM

Ok j'ai trouvé la solution, mais je trouve ça nul...

Si dans mon code principale, je garde en mémoire la référence de l'instance de MaClasse dont je me sers

var maClasse = new MaClasse();
 

Je peux ensuite me re-servir de cette référence dans les rouage de la classe MaClasse et faire

        var elements = phpData.split(",");
        var table = document.getElementById("liste");
        var i,len = elements.length;
        var row,cell;
        if(table.rows.length > 0){
                while(table.rows.length>0) table.deleteRow(0);
        }
        for(i=0;i<len;i++){
                row = table.insertRow(i);
                cell = row.insertCell(0);
                cell.innerHTML = '<a href="#" onclick="maClasse.callFromLink('+"'"+elements[i]+"'"+');">'+elements[i]+'</a>';;
                cell = row.insertCell(1);

                var btn = document.createElement("input");
                btn.type = "button";
                btn.value = "supprimer la rubrique";
                btn.rubName = elements[i];
                btn.callback = th.callFromButton;
                btn.onclick = function(e){
                        maClasse.callFromButton(this.rubName);
                }
                cell.appendChild(btn);
        }
 

Alors ok, ca marche, chouette ... Mais ce n'est pas du tout universel...
Quelle est la bonne méthode ?

Merci d'avance !

#3 Nelchaël

  • Members
  • PipPipPipPipPipPipPipPip
  • 1900 messages

Posté 01 August 2013 - 10:56 AM

Tu peux toujours coder le clic en dehors comme pour le bouton.
Tu retires la fonction clic dans le innerHTML.
Ensuite, tu cibles l'élément. Il y a plusieurs façons : tu peux utiliser getElementsByTagName ou mettre un id temporaire que tu effaces juste après.
var th=this;
cell.innerHTML = '<a href="#">'+elements[i]+'</a>';
var lien=cell.getElementsByTagName("a")[0];
lien.element=elements[i];
lien.onclick=function(){th.callFromLink(this.element);}
Ce n'est pas forcément la bonne méthode, mais bon, c'est déjà plus relatif. :)
nelchael.fr freelance flash CS6

#4 tlecoz

  • Honoris
  • PipPipPipPipPipPipPipPip
  • 3485 messages

Posté 01 August 2013 - 11:55 AM

Hello Nelchael !

Merci pour ton message mais en fait ta solution est la première que j'ai essayé (en utilisant une variable 'th' egalement :) ), et ça ne fonctionnait pas, du fait que les évenements "sont placés au niveau du code principal" et plus au niveau de mon objet maClasse.

C'est d'ailleurs pour cette raison que je suis "obligé" (j'espère que non en fait) de me servir du nom de l'instance qui fait bien référence à mon objet au niveau du code principal

#5 dcz.switcher

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 2530 messages

Posté 01 August 2013 - 12:31 PM

Salut,

Si je comprend bien, la classe MaClasse, va créer le tableau puis doit réagir aux click sur les liens ou boutons qui s'y trouvent ?

Si c'est bien ça, voici comment j'aborderai le problème :

MaClasse, après avoir créé les lignes, pose un écouteur sur le tableau puis teste à l'aide de la class (css), si on a cliqué sur un lien ou un bouton de suppression

Si tel est le cas, je récupère la référence à l'ID de la ligne à supprimer


Pour commencer, dans la construction du tableau en JS, je supprime les écouteurs onClick( ) et ajoute un attribut nommé data-id

cell.innerHTML = '<a href="#" data-id="'+elements[i]+'">'+elements[i]+'</a>' ;
 

Le HTML ressemble à ça (simplifié)

<table id="liste">
  <thead></thead>
  <tbody>
   <tr>
        <td>ligne 1</td>
        <td>
         <a href="#" class="delete-link" data-id="row1">supprimer</a>
        </td>
   </tr>
   <tr>
        <td>ligne 2</td>
        <td>
         <button class="delete-btn" data-id="row2">Supprimer</button>
        </td>
   </tr>
  </tbody>
</table>
 


Ensuite, je pose mes écouteurs depuis mon objet maClasse, ou plutôt, je pose un seul écouteur

(function (){

  var MaClasse = function ( ) {
   // reference à la liste
   this.el = document.querySelector('#liste');
   this.initialize();
  }
  MaClasse.prototype = {
   initialize: function () {
        this.createElement();
        this.addListeners();
   },
   addListeners: function () {
        var that = this;
        this.el.addEventListener('click', function (e) {
         switch (e.target.className) {
          case 'delete-link':
        e.preventDefault();
           that.callFromLink(e.target.getAttribute('data-id'));
          break;
          case 'delete-btn':
           that.callFromButton(e.target.getAttribute('data-id'));
          break;
          default:
           // rien
         }
        });
   },
   callFromLink: function (dataId) {
        alert('call from link : ' + dataId);
   },
   callFromButton: function (dataId) {
        alert('call from button : ' + dataId);
   },
   createElement: function (phpData) {
        // cell.innerHTML = '<a href="#" data-id="'+elements[i]+'">'+elements[i]+'</a>' ;
   }
  }
  var maClass = new MaClasse();
}());
 

edit : j'ai oublié d'empêcher le lien de fonctionner : e.preventDefault();
"Ce que l'on conçoit bien s'énonce clairement et les mots pour le dire arrivent aisément"

embryon de site

#6 Nelchaël

  • Members
  • PipPipPipPipPipPipPipPip
  • 1900 messages

Posté 01 August 2013 - 13:28 PM

Je n'ai pas regardé de près la réponse de dcz.switcher.
Je reviens juste sur ce que me répondait tlecoz :

Voir le messagetlecoz, le 01 August 2013 - 11:55 AM, dit :

Hello Nelchael !

Merci pour ton message mais en fait ta solution est la première que j'ai essayé (en utilisant une variable 'th' egalement Image IPB ), et ça ne fonctionnait pas, du fait que les évenements "sont placés au niveau du code principal" et plus au niveau de mon objet maClasse.

C'est d'ailleurs pour cette raison que je suis "obligé" (j'espère que non en fait) de me servir du nom de l'instance qui fait bien référence à mon objet au niveau du code principal
Il était logique que le lien ne fonctionne pas dans le premier code, par contre je ne vois pas trop pourquoi le bouton ne fonctionnait pas également (du moins dans l'idée car j'avais seulement survolé le code ;)).

Par exemple, pour reprendre le bout de code en simplifié :
<div id="idDiv1"></div>
<div id="idDiv2"></div>
<script>
function MaClasse(){}
MaClasse.prototype.callFromLink=function(){alert((this===objet1)+", "+(this===objet2));}
MaClasse.prototype.createElement=function(id)
        {
        var th=this;
        var cell=document.getElementById(id);
        cell.innerHTML='<a href="#">lien</a>';
        cell.getElementsByTagName("a")[0].onclick=function(){th.callFromLink();}
        }
var objet1=new MaClasse();
var objet2=new MaClasse();
objet1.createElement("idDiv1");
objet2.createElement("idDiv2");
</script>
Chaque lien se réfère bien à l'objet qui l'a créé.

Variante équivalente :
<div id="idDiv1"></div>
<div id="idDiv2"></div>
<script>
function MaClasse(){}
MaClasse.prototype.callFromLink=function(){alert((this===objet1)+", "+(this===objet2));}
MaClasse.prototype.createElement=function(id)
        {
        var cell=document.getElementById(id);
        cell.innerHTML='<a href="#">lien</a>';
        var lien=cell.getElementsByTagName("a")[0];
        lien.objet=this;
        lien.onclick=function(){this.objet.callFromLink();}
        }
var objet1=new MaClasse();
var objet2=new MaClasse();
objet1.createElement("idDiv1");
objet2.createElement("idDiv2");
</script>

Même si tu changes ta méthode par celle de dcz.switcher, il serait bien de vérifier auparavant que ta méthode était quand même correcte. ;)
nelchael.fr freelance flash CS6

#7 tlecoz

  • Honoris
  • PipPipPipPipPipPipPipPip
  • 3485 messages

Posté 01 August 2013 - 13:53 PM

Merci pour vos réponses !

@Nelchael :

lien.objet=this;
lien.onclick=function(){
        this.objet.callFromLink();}
}
 
j'ai passé ma soirée/nuit à faire ce genre d'essais, sans succés.
si je fais

lien.objet=this;
lien.onclick=function(){
        alert(this.objet) //---> il me trouve bien l'objet
        //mais bizarrement, si je fais
        alert(this.objet.callFromButton) //--> il me trouve 'undefined'  
}
 
Si j'essaye de stocker la fonction directement en propriété de l'objet lien, il me trouve également 'undefined' ...


@ Dcz.Switcher

Ton code est intéressant ! Je ne l'ai pas testé... Il marche ? Image IPB

Il y a des petits points de détails qui m'échappe ceci dit Image IPB

(function (){
//...
}() )
 
A quoi sert cette construction ? Je la vois de temps en temps sur le net, sans trop comprendre l'intérêt

Je ne connaissais pas non plus (désolé je débute vraiment...)

this.el = document.querySelector('#liste');
 
En quoi est ce mieux (si c'est mieux) que ' document.getElementById("liste") ' et pourquoi ?

Idem, je ne savais pas que je pouvais utiliser la syntaxe 'addEventListener'...
Quelle est la différence entre


var that = this;
this.el.addEventListener('click', function (e) {
   switch (e.target.className) {
          case 'delete-link':
                e.preventDefault();
                that.callFromLink(e.target.getAttribute('data-id'));
                break;
          case 'delete-btn':
                that.callFromButton(e.target.getAttribute('data-id'));
                break;
          default:
           // rien
   }
});
 
et

var that = this;
this.el.onclick = function(e){
   switch (e.target.className) {
          case 'delete-link':
                e.preventDefault();
                that.callFromLink(e.target.getAttribute('data-id'));
                break;
          case 'delete-btn':
                that.callFromButton(e.target.getAttribute('data-id'));
                break;
          default:
           // rien
   }
};
 

Merci !

EDIT : querySelector, j'ai compris ce que c'était :)

#8 Nelchaël

  • Members
  • PipPipPipPipPipPipPipPip
  • 1900 messages

Posté 01 August 2013 - 14:54 PM

Encore moi. Image IPB

Ca paraît fou tes tests qui ne marchent pas. Image IPB

En fait, c'est comme si ta fonction n'était pas appelée à partir de ta référence.
Ce serait possible si tu avais défini une variable pointant sur la fonction, exemple :

var maClasse=new MaClasse();
var createElement=maClasse.createElement;
createElement();
Si tu fais ça, ça donnerait le problème que tu dis (alors qu'en AS3, ça marcherait).

Citation

Si j'essaye de stocker la fonction directement en propriété de l'objet lien, il me trouve également 'undefined' ...
Tu avais bien mis le ciblage devant ? "this.callFromButton" et pas seulement "callFromButton" ?
Avec les réflexes de l'AS3, on ne sait jamais ! Image IPB

Enfin, j'imagine que tu as bien testé, mais c'est vraiment étrange tout ça !
En tout cas, mes bouts de code marchent tels quels pour moi...


Pour la construction de dcz.switcher "(function (){//... }() )", je dirais qu'un intérêt est de ne pas garder en mémoire des références qui ne seront plus utilisées ensuite, car les variables déclarées dans cette fonction anonyme seront locales à la fonction (et, par la même occasion, ça permet d'éviter des conflits de noms de variables). J'attends de voir la réponse de dcz.switcher là-dessus.
nelchael.fr freelance flash CS6

#9 dcz.switcher

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 2530 messages

Posté 01 August 2013 - 20:38 PM

Voir le messagetlecoz, le 01 August 2013 - 13:53 PM, dit :

Ton code est intéressant ! Je ne l'ai pas testé... Il marche ? Image IPB
Tu me fends le coeur Image IPB

http://dcz-lab.fr/me...x/forum/180933/

Citation

Il y a des petits points de détails qui m'échappe ceci dit Image IPB

(function (){
//...
}() )
 
A quoi sert cette construction ? Je la vois de temps en temps sur le net, sans trop comprendre l'intérêt

Je rejoins Nelchaël, l'intérêt principal est d'éviter de balancer les variables dans le scope global, il s'agit d'une fonction qui s'appelle elle même.


Citation

Je ne connaissais pas non plus (désolé je débute vraiment...)

this.el = document.querySelector('#liste');
 
En quoi est ce mieux (si c'est mieux) que ' document.getElementById("liste") ' et pourquoi ?
J'ai vu tu avais trouvé la réponse, a priori, il y aurait encore plus efficace :

document.getElementByClassName( )
 

L'avantage de querySelector et querySelectorAll est bien entendu d'utiliser la syntaxe CSS et d'être compatible IE8+ !


Citation

Idem, je ne savais pas que je pouvais utiliser la syntaxe 'addEventListener'...
Quelle est la différence entre


var that = this;
this.el.addEventListener('click', function (e) {
   switch (e.target.className) {
          case 'delete-link':
                e.preventDefault();
                that.callFromLink(e.target.getAttribute('data-id'));
                break;
          case 'delete-btn':
                that.callFromButton(e.target.getAttribute('data-id'));
                break;
          default:
           // rien
   }
});
 
et

var that = this;
this.el.onclick = function(e){
   switch (e.target.className) {
          case 'delete-link':
                e.preventDefault();
                that.callFromLink(e.target.getAttribute('data-id'));
                break;
          case 'delete-btn':
                that.callFromButton(e.target.getAttribute('data-id'));
                break;
          default:
           // rien
   }
};
 

Bon, en fait, addEventListener( ) ne fonctionne pas avecc IE (hasard), il faut utiliser la syntaxe attachEvent( )
https://developer.mo...ternet_Explorer

Pour l'avantage, ça reste personnel mais je trouve ça plus clair

D'une manière globale, je pense que les devs actionscript ont un atout énorme qui est l'optimisation, par exemple, ne poser qu'un seul écouteur plutôt que n en ciblant chaque élément, ça ne vous rappelle rien ?

http://forums.mediab...ielle.pdf#page1

lire page 11+
"Ce que l'on conçoit bien s'énonce clairement et les mots pour le dire arrivent aisément"

embryon de site

#10 tlecoz

  • Honoris
  • PipPipPipPipPipPipPipPip
  • 3485 messages

Posté 01 August 2013 - 21:21 PM

Merci beaucoup pour tes explications !

Citation

L'avantage de querySelector et querySelectorAll est bien entendu d'utiliser la syntaxe CSS et d'être compatible IE8+ !

Tiens, c'est drôle, c'est un aspect des choses qui m'était passé au dessus :)
Le truc qui me paraissait vraiment intéressant avec querySelector, c'était de pouvoir faire des selections au niveau de mes pseudo-DisplayObjectContainer (div) plutôt qu'au niveau du document.



1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)

authorised training centre

Centre de Formation Mediabox - Adobe et Apple Authorised Training Center.

Déclaré auprès de la Direction du Travail et de la Formation Professionnelle

Mediabox : SARL au capital de 62.000€ - Numéro d'activité : 11 75 44555 75 - SIRET : 49371646800035

MEDIABOX, 23, rue de Bruxelles, 75009 PARIS

FFP