Bonjour,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Je cherche à faire un accordeon en utilisant jQuery et en programmation orienté objet
(POO = voie ô combien compliqué pour le petit scarabée que je suis) :

HTML

<h2 class="section-title">Un titre</h2>
<section>...</section>
<h2>Un autre titre</h2
<section>...</section>

Jquery

$('document').ready(function(){
    var Accordeon = {
        init : function() {
            var titre = $('.section-title');
            var cache = $(this).next($('section'));

            titre.on('click', function(){
                $(this).disparition(cache);
            });
        },

        disparition : function(cible) {
            if (cible.hasClass('hidden')) {
                cible.removeClass('bounceInDown');
                cible.addClass('bounceInUp');
                cible.removeClass('hidden');
            }
            else {
                cible.removeClass('bounceInUp');
                cible.addClass('bounceInDown');
                cible.addClass('hidden');
            }
        }

    };

    var accordeon =  Object.create(Accordeon);
    accordeon.init();
});

Ce que je veux

J'aimerais quand je clique sur le h2.section-title fasse disparaître la section frère uniquement avec une classe .hidden { display : none } avec une animation honteusement pompé sur animation.css.

Ce que j'obtiens

Quand je clique sur mon lien h2, dans la console j'obtien un joli " $(...).disparition is not a function ". Je me doute que j'utilise mal le mot-clé this. Mais je ne comprends pas mon erreur...

Je remercie d'avance, à ceux qui pris le temps de lire mon post.

7 réponses


betaWeb
Réponse acceptée

Salut,

C'est tout simplement un problème et de contexte et de compréhension. Ensuite, tu ne peux pas instancier un objet jQuery depuis un objet JS.

$('document').ready(function(){
    var Accordeon = {
        init : function() {
            var self = this;
            var titre = $('.section-title');

            titre.on('click', function () {
                self.disparition($(this).next($('section')));
            });
        },

        disparition : function(cible) {
            if (cible.hasClass('hidden')) {
                cible.removeClass('bounceInDown');
                cible.addClass('bounceInUp');
                cible.removeClass('hidden');
            }
            else {
                cible.removeClass('bounceInUp');
                cible.addClass('bounceInDown');
                cible.addClass('hidden');
            }
        }

    };

    Accordeon.init();
});

Ah et ce que tu as fait j'ai pas du tout du "jQuery POO", d'ailleurs jQuery n'est pas un langage mais une libraire, c'est de JS POO dont il est question.

reuno92
Auteur

Merci de vos réponses à tout les deux, je résume ce que j'ai compris.

Dans mon code, le contexte c'est :
this = qui va me permettre de naviguer dans mon objet javascript.
$(this) = qui va me permettre de naviguer dans le DOM.

Je pose mon code final pour montrer ce que ça m'a permis de faire (et si ça peut aider quelqu'un :p) :

$('document').ready(function(){
    var Accordeon = {
        init : function() {
            var self = this;
            var titre = $('.section-title');

            titre.each(function(){
                console.log($(this));
                $(this).on('click', function(){
                    self.disparition($(this));
                });
            });

        },

        disparition : function(e) {
            var cache = e.next();
            if (cache.hasClass('hidden')) {
                cache.removeClass('hidden');
            }
            else {
                cache.addClass('hidden');
            }
        }

    };

    var accordeon =  Object.create(Accordeon);
    accordeon.init();
});

pas facile de jouer à Houdini avec Javascript et jQuery en même temps ^^.

C'est déjà mieux, mais pourquoi tu met un var accordeon = Object.create(Accordeon); ??

reuno92
Auteur

Tout bêtement j'ai appris comme ça.
Quand je crée une objet :

var Objet = {...}

Fallait toujours l'instancier pour le faire l'exécuter

var monObjet = Object.create(Objet);

Pour pouvoir lancer par la suite mon constructeur

monObjet.init();

Et pour le coup lancer mon script. Y a t'il plus simple ?

En écrivant, ce reply, je me recompte qu'utilisé l'objet n'a peu d'utilité en l'état... Peut être que je devrais changer la propriété titre :

$(document).ready(function() {
...
titre : this.titre
...
});
var accordeon = Object.create(Accordeon);
accordeon.init(titre : $('section-title');

Et pour le coup, dans mon doc si j'ai besoin de faire la même chose avec des h3 ou h4. j'ai peut être pas besoin de recommencer tout le script.

Beh oui, tu n'as pas besoin de faire comme ça ! Un Objet JS n'est pas censé être instanciable.

// Objet
var monObj = {
    init: function () {
        // init
    }

    // Code
};

monObj.init();

// Class
var MaClasse = function (prop) {
    this.prop = prop;

    this.init(); // par exemple
};

MaClasse.prototype.init = function () {
    // ton initialisation ici
};

MaClasse.prototype.demo = function () {
    alert(this.prop);
};

var maClasse = new MaClasse('Salut la planète');

maClasse.demo(); // alert 'Salut la planète'
reuno92
Auteur

Je suis paumé là :p Je crois que je mélange un objet et une classe... En tout cas, merci ça me donne une piste pour améliorer la conception de mon code.

C'est normal, c'est un peu chiant à comprendre au début ;)