11540 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous !

Je viens à vous car me voilà face à un problème de taille pour mes pauvres connaissances en Javascript.

Les bases :
La partie HTML avec : un formulaire simple (un input text, un bouton submit), le formulaire possédant la classe "ajax" (!important!).
Dessous, une liste (<ul><li>..) construite a l'affichage de la page via une boucle for traité par Django (framework MVT qui donc alimente le template). Cette liste contiens un formulaire par <li></li> possédant lui aussi la classe "ajax".


<form action="/search-music/" method="post" class="input-group ajax">
    <input type="text" name="url" class="form-control video-id" style="text-align:right" placeholder="Titre">
    <span class="input-group-btn">
        <button id="btn-search" class="btn btn-default" type="submit" title="Chercher sur Youtube" alt="Chercher sur Youtube"><i class="fa fa-youtube-play"></i></span> Youtube-moi</button></span>
</form>
<ul class="list-group">
    {% for music in list_musics %}
        <li class="list-group-item item-lib list-music">   
            <form action="/add-music/" method="post" class="pull-right ajax">
                <input type="hidden" value="{{ music.video_id }}" name="url" class="video-id">
                <button class="btn btn-default btn-lg" type="submit" alt="Ajouter à la playlist" title="Ajouter à la playlist"><span class="glyphicon glyphicon-headphones"></span>
                </button>
            </form>
            {{ music.name }}
        </li>
    {% endfor %}
</ul>


(J'ai omis quelques <div> de design inutile);
Ensuite viens le traitement de mes formulaire via un script Jquery et la variable $.ajax :


$(".ajax").submit( function() {
	var urlSubmit = $(this).attr('action');
	var dataSend = 'url=' + $(this).children('.video-id').val();
	$.ajax({
		type: "POST",
		url: urlSubmit,
		data: dataSend,
		dataType: "json",
		success: function(data) {
			if (urlSubmit == '/search-music/') {
				$(".list-music").promise().done(function(){
					$(".list-music").remove();
					$.each(data, function(key, value){
						$(".list-group").append('<li class="list-group-item item-lib list-music" style="display:none;"><form action="/add-music/" method="post" class="pull-right ajax"><input class="video-id" type="hidden" value="'+ value.fields.video_id +'" name="url"><button class="btn btn-default btn-lg" type="submit" alt="Ajouter à la playlist" title="Ajouter à la playlist"><span class="glyphicon glyphicon-headphones"></span></button></form>'+ value.fields.name +'</li>');
					});
				});
			}
		});
		return false;
	});


(Encore une fois, j'ai retiré toutes les instructions de design inutile).

Le problème :

Lorsque je charge page, tout s'affiche correctement, lorsque j'effectue une recherche via le champ text, la requête Ajax est bien effectué et le traitement des données de retour fonctionne parfaitement.

Rafraîchissons la page afin de repartir sur une version propre de nouveau, si je clique sur le bouton du deuxième formulaire, le formulaire est bien submit, Ajax le catch et le traitement est effectué tout marche bien.

Maintenant le problème viens de la combinaisons de ces deux opérations :
On effectue une recherche via le premier formulaire, cela reconstruit la liste (<li></li>) via un "append" exactement identique à ce qu'il y avais précédemment mais avec les nouvelles données et à partir de la si je soumet le deuxième formulaire, ajax ne catch pas le .Submit sur mon formulaire (qui à pourtant bien la classe "ajax") et donc mon serveur ne reçois pas la requête Ajax.

Quelqu'un à-t-il des idées à propos de la provenance du bug ? Ou même des propositions d'amélioration de mon code ? Car il est vrai je trouve "moche" de supprimer et de réécrire complètement la liste après chaque soumission du premier formulaire...

Merci d'avance à vous !! Smiley cligne

ps : si besoin de détail de fonctionnement sur le script ou l'html n'hésitez pas, j'avoue que tout n'est peut être pas compréhensible au premier coup d’œil et étant habitué à ces quelques lignes depuis plusieurs jours, elles me paraissent évidente ce qui contribue sans doute à mon problème... Smiley bawling )
Modifié par Eirika (14 Oct 2014 - 10:09)
Salut,

Le problème que tu soulèves est, si je puis dire, un grand classique de jQuery.

Lorsque tu appliques la méthode on () de jQuery (ou submit (), qui est un raccourci pour on ('submit')), elle n'ajoute l'événement que pour les nœuds présents dans le DOM à l'instant donné. Pour pouvoir ajouter un événement à un nœud présent ou futur (autrement dit, y compris à un élément qui n'a pas encore été généré), il faut procéder comme suit :
$(document).on ('submit', '.ajax', function ()
{
  // Ici, tes instructions
});

Autrement dit, tu ajoutes la méthode on () à l'objet jQuery sélectionnant le document Web dans son ensemble, et non un sélecteur spécifique. Dans les anciennes versions de jQuery, cela correspondait aux méthodes live () et delegate (), deux méthodes aujourd'hui obsolètes (live () ayant même été supprimée).
Wow, une réponse, une résolution de problème !

Un grand merci à toi pour l'aide et l'explication super clair, j'aurai appris quelque chose aujourd'hui qui, je pense, me resservira dans des développements futur ! Smiley smile

Sur ce, bonne journée à toi et à tout le forum Smiley lol