11540 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous,

Je rencontre un souci que certains ont déjà du avoir mais pour lequel je n'ai pas trouvé de réponse claire.

Je fais apparaitre un formulaire dans un pop fancybox. Dans ce formulaire, j'ai inclus un script JS de façon à ce qu'il puisse être exécuté lorsque je clique sur le submit.

Mon effet m'envoi le contenu du formulaire via une méthode POST vers un script php et ce dernier me retourne une réponse json après laquelle j'exécute la fermeture du pop et le refresh d'un div se situant sur ma page principale.

Tout fonctionne bien la première fois. Lors que je refait apparaitre mon formulaire pour la 2nd fois sans avoir rafraichie la page globale, mes fonctions JS ne s'exécutent plus dans mon pop alors que le fichier appelé dans le pop inclu non seulement ma fonction mais également mon fichier jquery.

Je me pose donc 3 questions :

1. Comment faire pour que ma librairie JQuery que j'utilise pour le contenu de mon pop (fichier php appelé via load ) puisse être utilisée sans être systématiquement inclue dans le contenu du pop ? Et surtout est-ce possible ?

2. Pourquoi mon script JS qui est pourtant inclu dans mon pop (avec en plus la librairie JQuery que je recharge en même temps), ne fonctionne que la première fois et plus la seconde ? Je précise que ni la librairie JQuery, ni mon script ne sont chargés par ma page principale, mais uniquement dans le contenu de mon pop, donc si ça marche 1 fois, ça devrait marcher tout le temps... Smiley decu

3. De manière générale, n'est-il pas possible de faire en sorte que JQuery puisse être appelé n'importe quand sans être obligé de charger son js dans chaque fichier externe appelé ?
Modifié par Klesk (13 Sep 2012 - 16:18)
Salut,

1. C'est possible si ta fancybox inclus le contenu directement dans la page, c'est à dire via un appel ajax. A ce moment là, jQuery est disponible. Si c'est une iframe, non.

2. L deuxième fois que ton script JS est inclus, les fonctions ont déjà été incluses donc peut-etre qu'elle ne peuvent pas être redéclarées.

3. Si. Fancybox a des fonctions callbacks qui peuvent être définis et exécutées une fois le popup chargé, ou quand il est fermé, au redimensionnement, etc. Il y a la liste sur le site de fancybox. Je ne sais pas quelle version tu utilises. Si c'est la v2: http://fancyapps.com/fancybox/. Mets ton JS dans une callback au lieu de le mettre dans la page chargée. Je dis ça mais cela ne fonctionnera pas si ta fancybox charge une iframe, il faut qu'il charge en mode "ajax" pour ton cas je pense.

Tanguy
Merci Martint. J'utilise bien Fancybox 2.Le contenu est effectivement chargé via ajax et non en iframe. Peux-tu m'expliquer un peu plus en détail le principe de callback et la manière de l'utiliser ?
Modifié par Klesk (05 Sep 2012 - 15:15)
Quelque chose comme ça devrait faire l'affaire:

$('...').fancybox({
    // ... autre options..,
    afterLoad: function() {
       // ton code js ici
   }
});
Oui je suis allé voir la doc Fancybox. Donc ce script est a charger sur ma page principale, en prenant soin d'y renseigner l'id de mon conteneur afin que la fonction s'execute lorsque fancybox s'ouvre ou fini de se charger selon le callback choisi, c'est ça ?
Oui, l'id de ton conteneur ou n'importe quel autre selecteur css. Tu charge ta pop-up comment pour le moment?

Tu peux mettre des appels à console.log() dans le callback pour bien être sur qu'elle est appelée.
Fancybox est appelé en indiquant une class sur le lien cliqué. Ca charge la cible du lien dans un pop automatiquement. Après je n'ai pas regardé en détail comment ça fonctionne.

Tout ce que je sais c'est que j'appelle le contenu via ajax avec la class "fancybox.ajax".

En revanche est-ce que tu crois que si je charge ma librairie JQuery une seule fois sur ma page principale, ma fonction également avec le callback, ça fonctionnera malgré le fait que ni l'un ni l'autre ne soit chargé avec le contenu lors de l'appel ajax ??
Oui car ton contenu html rappatrié avec ajax est inséré dans ton balisage donc ta lib jQuery sera toujours accessible, et ta fonction sera automatiquement appelée par fancybox en tant que callback
J'ai mis ça :


$('#bouton_ajout_terminal').fancybox({
    afterLoad: function() {
		$('#formulaire_ajout_mobiles').on('submit', function() {
				$.ajax({
					url: $(this).attr('action'),
					type: $(this).attr('method'),
					data: $(this).serialize(),
					dataType: 'json',
					success: function(json) {
						if(json.reponse == 'ajout terminal ok') {
							refresh_terminaux();
							$.fancybox.close();
						} else {
							alert('Erreur : '+ json.reponse);
						}
					}
				});
			return false;
		});
   },
});



#bouton_ajout_terminal étant l'id du lien sur lequel je clique et #formulaire_ajout_mobiles l'id du formulaire chargé.

Quand je clique sur mon bouton j'ai ça dans ma console firebug :

GET http://www.monurl.com/emm/utilisateurs/form_ajout_mobile.php Aborted
GET http://www.monurl.com/emm/utilisateurs/form_ajout_mobile.php 200 OK

Ca me sort 2 actions au lieu d'une, dont la première qui est KO. Comme s'il essayait de m'ouvrir mon formulaire avec ma fonction et mon callback, qu'il échouait et du coup me l'ouvrait via la class dans le lien.

Et bien sûr mon formulaire ne tient pas compte de ma fonction mais envoi les données en POST de façon classique.

Je pense que j'ai fais n'importe quoi Smiley smile .

Ca c'est ma fonction d'origine :


<script>
	$(document).ready(function() {
		$('#formulaire_ajout_mobiles').on('submit', function() {
				$.ajax({
					url: $(this).attr('action'),
					type: $(this).attr('method'),
					data: $(this).serialize(),
					dataType: 'json',
					success: function(json) {
						if(json.reponse == 'ajout terminal ok') {
							refresh_terminaux();
							$.fancybox.close(),
						} else {
							alert('Erreur : '+ json.reponse);
						}
					}
				});
			return false;
		});
	});
</script>

Modifié par Klesk (06 Sep 2012 - 11:14)
Non, ça m'a l'air sur la bonne voie, essaie de mettre des console.log() un peu partout pour deboguer et suivre le parcours.

Hmm..essaie d'enlever les attributs fancybox de ton balisage html et rajoute les en tant qu'options passées a l'appel de la method fancybox() sur javascript (type:"ajax" et href:"tonurl").

A mon avis la premier requêtes correspond au lien de ton bouton, la seconde correspond a l'appel ajax fait par fancybox. Et fancybox annulerait un des deux appel, d'où le statut 'Abort'. Ou l'inverse
Tu veux dire supprimer la class du lien et inclure l'url direct dans la fonction avec le callback ?
Genre ça :



$('#bouton_ajout_terminal').fancybox({
	ajax:{
		url: 'http://www.monurl.com/emm/utilisateurs/form_ajout_mobile.php',
		type : 'GET'
	},
	afterLoad: function() {
		$('#formulaire_ajout_mobiles').on('submit', function() {
			$.ajax({
				url: $(this).attr('action'),
				type: $(this).attr('method'),
				data: $(this).serialize(),
				dataType: 'json',
				success: function(json) {
					if(json.reponse == 'ajout terminal ok') {
						refresh_terminaux();
						$.fancybox.close();
					} else {
						alert('Erreur : '+ json.reponse);
					}
				}
			});
			return false;
		});
   },
});


Bon sauf que là ça ne marche pas Smiley decu . Mon formulaire ne se charge pas du tout. J'ai une erreur dans la console lorsque je cliques sur le bouton :

Error: Syntax error, unrecognized expression: http://www.monurl.com/emm/utilisateurs/form_ajout_mobile.php dans le fichier jquery en gros
Modifié par Klesk (06 Sep 2012 - 14:34)
Il y a une option "href" pour mettre l'url. Pas besoin de la mettre dans l'option ajax. Par ailleurs il faut que tu spécifies le "type" de ta fancybox avec type: "ajax".

Peux-tu poster le bout de balisage html correspondant si ça ne fonctionne toujours pas? Ou bien le mettre sur http://jsfiddle.net/
Il y a du nouveau ! J'ai suivi tes indications et formaté ma fonction comme ceci :


$('#bouton_ajout_terminal').fancybox({
	href: 'http://www.monurl.com/emm/utilisateurs/form_ajout_mobile.php',
	type: 'ajax',
	css: '.fancybox-effects-c',
	afterLoad: function() {
		$('#formulaire_ajout_mobiles').on('submit', function() {
			$.ajax({
				url: $(this).attr('action'),
				type: $(this).attr('method'),
				data: $(this).serialize(),
				dataType: 'json',
				success: function(json) {
					if(json.reponse == 'ajout terminal ok') {
						refresh_terminaux();
						$.fancybox.close();
					} else {
						alert('Erreur : '+ json.reponse);
					}
				}
			});
			return false;
		});
   },
});


Le clic sur le bouton fonctionne et m'affiche mon formulaire !! reste a trouver comment appliquer la class css que je veux parmis celles de fancybox, mais ça c'est du détail. Le " css: '.fancybox-effects-c', " ne marche pas Smiley smile , je feuillette la doc de l'api là.

EDIT : Partie CSS ok Smiley smile .

En revanche, la validation de mon formulaire, et donc la partie callback, ne fonctionne pas. L'envoi des données s'effectue toujours via le POST classique de mon formulaire et non via la partie ajax. Et donc au lieu d'avoir une fermeture de mon pop et un refresh de mon tableau, j'arrive sur la page avec le retour json "{"reponse":"ajout terminal ok"}", ce qui est normal qd js ne fonctionne pas pour cette partie.

Voici mon code coté formulaire :


<form id="formulaire_ajout_mobiles" action='http://www.monurl.com/emm/utilisateurs/form_ajout_mobile.php' method='post' enctype='multipart/form-data'>
	<table id="tableau_formulaires">
		<tr>
			<td style="vertical-align:top;">
				<fieldset>
					<legend>G&eacute;n&eacute;ral</legend>
					<p><label>Constructeur<span style="color:red;">&#149;</span> :</label><select name="marque" id="constructeur">
					<?php $liste_constructeur = $bdd->query('SELECT * FROM constructeur ORDER BY Nom ASC');
					While ($liste_constructeur_exp = $liste_constructeur->fetch())
						{
							$Nom = $liste_constructeur_exp['Nom'];
							echo '<option value="'.$Nom.'">'.$Nom.'</option>';
						}
					?>
					</select></p>
					<p><label>Mod&egrave;le<span style="color:red;">&#149;</span> :</label><input id="modele" type='text' name='modele' required /></p>
					<p><label>IMEI<span style="color:red;">&#149;</span> :</label><input id="imei" type='text' name='imei' placeholder='IMEI &agrave 15 chiffres' pattern='[0-9]{15}' required /></p>
				</fieldset>
				<fieldset>
					<legend>Statut</legend>
					<p><label>Expo :</label><input id="expo" type='checkbox' name='expo' value='oui'/></p>
					<p><label>Simlock&eacute; :</label><input id="simlock" type='checkbox' name='simlocker'  value='0'/></p>
				</fieldset>
				<fieldset>
					<legend>Divers</legend>
					<p><label>Fiche Technique :</label><input id="technique" type='text' name='fiche_Technique' /></p>
				</fieldset>
			</td>
			<td style="vertical-align:top;">
				<fieldset>
					<legend>Accessoires</legend>
					<p><label>SIM :</label><select id="sim" name="sim"><option value="Standard">Standard</option><option value="Micro-Sim">Micro-Sim</option><option value="Aucune">Aucune</option></select></p>
					<p><label>Chargeur :</label><input id="chargeur" type='checkbox' name='chargeur' value='oui'/></p>
					<p><label>Batterie :</label><input id="batterie" type='checkbox' name='batterie' value='oui'/></p>
					<p><label>Kit Main Libre :</label><input id="kit" type='checkbox' name='kit_main_libre' value='oui'/></p>
					<p><label>Adaptateur USB :</label><input id="usb" type='checkbox' name='adaptateur_USB' value='oui'/></p>
				</fieldset>
				<fieldset>
					<legend>Illustration</legend>
					<p style='font-size:11px;color:#A8A8A8;'>Seul les format jpg et png sont autoris&eacute;s, taille maximum 300ko</p>
					<p><input id="image" type='file' name='image' /></p>
					<input type='hidden' name='Url_image' value='<?php $Url_image ?>'/>
				</fieldset>
			</td>
		</tr>
	</table>
	<input type='submit' value='Valider' />
</form>


Comme tu le verras peut-être dans mon formulaire j'ai de l'envoi de fichier qui ne peut fonctionner via ajax apriori, mais ça je verrai pour faire autrement.
Modifié par Klesk (06 Sep 2012 - 16:20)
Encore de l'évolution. Nouveau code :



$('#bouton_ajout_terminal').fancybox({
	href: 'http://www.korx-crew.com/emm/utilisateurs/form_ajout_mobile.php',
	type: 'ajax',
	wrapCSS: 'fancybox-custom',
	closeClick:false,
	openEffect:'elastic',
	openSpeed:200,
	closeEffect:'elastic',
	closeSpeed:200,
	helpers:{
		overlay:{
			css:{'background-color':'#eee'}
		}
	},
	afterShow: function() {
		$('#formulaire_ajout_mobiles').on('submit', function() {
			$.ajax({
				url: $(this).attr('action'),
				type: $(this).attr('method'),
				data: $(this).serialize(),
				dataType: 'json',
				success: function(json) {
					if(json.reponse == 'ajout terminal ok') {
						refresh_terminaux();
						$.fancybox.close();
					} else {
						alert('Erreur : '+ json.reponse);
					}
				}
			});
			return false;
		});
   }
});



J'ai remplacé le afterLoad par afterShow car il semble que afterLoad ne charge pas correctement JQuery (cf:https://github.com/fancyapps/fancyBox/issues/6).

Mon formulaire s'affiche bien, le JS sur le submit fonctionne bien et me refresh bien mon tableau, en revanche la fermeture de la fenêtre Fancybox, que je commande via $.fancybox.close();, ne s'exécute que la première fois et pas les fois suivantes.
Ce que je ne comprends pas, c'est que la fermeture du pop avec la croix fonctionne, le fais de cliquer dans le vide a coté du pop ferme également, et le refresh de mon tableau qui est déclenché par la même fonction s'effectue sans problème en arrière plan. La seule et unique chose qui ne fonctionne qu'après le premier chargement de la page c'est ce satané $.fancybox.close();
Modifié par Klesk (11 Sep 2012 - 17:00)
Absolument aucune erreur Smiley decu . Et le truc étrange est qu'au premier submit tout fonctionne impec, refresh + fermeture fancybox. Sur les submit suivants, seul le refresh fonctionne Smiley decu
Bon j'ai inclus des console.log() après mon refresh de div et après mon code de fermeture de fancybox.

La première fois que j'utilise le formulaire après un chargement de ma page principale, les deux codes console remontent sans souci. La seconde fois le premier remonte mais pas le suivant. J'en ai donc déduis que mon problème pouvait venir de mon script de refresh de div ou du contenu rechargé par le refresh. J'ai viré l'appel à la fonction refresh et cette fois le fancybox.close marche à chaque fois.

Voici donc le code correspondant à mon refresh_terminaux(); :


var refresh_terminaux = function() {
	$('#tableau_terminaux_wrapper').fadeOut('fast').load('admin/tableau_mobiles.php?refresh=ok').fadeIn('normal');
}


Voici ce qui se passe concrètement au chargement de ma page principale :

1. chargement des css
2. chargement du contenu html + include d'un tableau en php
3. chargement de jquery, datatables etc

Après cela, tout fonctionne bien. Voici ce qui se passe quand je refresh mon tableau :

1. envoi des données a un script php pour traitement et retour json
2. rechargement via ajax de mon tableau php avec rechargement de jquery + datatables
3. demande de fermeture de fancybox.

J'ai inclus une condition dans mon script php qui renvoi les jquery+datatables uniquement si j'ai "refresh=ok" dans l'url, ce qui explique que ça ne les charge qu'une fois lors du chargement de la page principale.

Après ce refresh, mon fancybox ne se ferme plus avec fancybox.close(); . Je n'ai pas utilisé de fonction de callback avec datatable car je ne maitrise pas du tout js à la base et je commence tout juste à en comprendre les raouages. Si quelqu'un connait je suis preneur de conseils pour cleaner tout ça.
Modifié par Klesk (13 Sep 2012 - 14:03)
Bon mon problème semble résolu Smiley smile . Pour se faire j'ai dégagé JQuery et Datatables de mon fichier php appelé via l'include. Je les ai mis dans mon header car il est apriori nécessaire de les avoir avant l'execution de ma fonction Datatables sinon cela ne marche pas. Si quelqu'un sait comment faire pour les mettre en footer sans perdre la dépendance je suis preneur.

J'ai laissé ma fonction JS de mise en forme Datatables dans mon fichier php, du coup elle est executée a chaque refresh du tableau Smiley smile .
Modifié par Klesk (13 Sep 2012 - 17:00)