Aller au menu - Aller au contenu
Inscris-toi au e-camp "Héberge ton jeu Facebook sur Azure" de Microsoft vendredi 25 mai à 13h30 !

[plugin jquery] Envoie de formulaire dynamiquement

Pour accéder à cette section
Connectez-vous !
connexion_rpx
Page 1 
Auteur Message
1 visiteur sur ce sujet (1 Anonyme)
Page 1 
Hors ligne Nek' # Posté le 04/08/2010 à 10:37:37
LPL FTW
Avatar

Ville : Reims
Pays : France métropolitaine
Études : IUT Reims-Châlons-Charleville

Bonjour à tous !
Je viens vous présenter un script que je suis en train de développer pour jquery, il permettra d'envoyer facilement des formulaires dynamiques.

Pourquoi ?


J'ai réalisé qu'il manquait un script sympa et simple pour jquery. Un script qui permet tout simplement de vérifier un formulaire et de l'envoyer du même coup.
Mais ça existe déjà ton truc pourquoi tu fais ça ?

Mon script prend en charge APC uploadprogress (à cause d'un bug d'APC sur mes deux serveurs). C'est à dire qu'il est en mesure de produire une barre de chargement sans flash.
Les scripts prenant en charge uploadprogress sont rarement multi-fonction comme celui-ci, ici les tâches sont vraiment complètement automatisées. Le script fonctionnera sans argument fourni !

Notez cependant que j'intègrerais peut être flash en option étant donné que les uploadeurs flash actuels ne me conviennent pas. Mais ce n'est pas à l'ordre du jour.

Le script


Je viens ici pour vous proposer ce script, mais aussi pour vous demander des conseils puisque je sais qu'un bon nombre de zéro se débrouillent bien en javascript.

Voici donc le code de mon (fabuleux :soleil: ) script.
Code : JavaScript
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
(function($) {
    /**
     * Cette fonction permet d'envoyer un formulaire en ajax simplement
     *
     * @param object options objet contenant les options d'envoie. Rien n'est obligatoire. (nom du fichier APC, barre de chargement etc... doc coming soon :p)
     * @param object verifs objet contenant les noms des champs et ce qu'ils doivent contenir
     *
     */
    $.fn.dynSend = function(options, verifs) {
        this.options = options ? options : {};
        this.uploadLoad = new Array(0,0);

        this.testValeurs = function (verifs) {
            // On vérifie les données
            var probleme = 0, b=0;
            for ( var id in verifs ) {
                if(typeof verifs[id] == 'function'){
                    b = verifs[id]();
                    if(b) probleme++;
                    b = 0;
                } else {
                    if(verifs[id] == 'needed' || verifs[id] == 1)
                        if($('#'+id).val() == '')
                            probleme++;

                }
            }
        };
        this.champsMalRemplis = function() {
            alert('Les champs sont mals remplis !');
        };
        // Fonction qui s'occupe de gérer APC
        this.progressLoad = function() {
            var that = this;
            var url = that.options.url_verif;
            var keyFile = that.options.keyFile;

            $.ajax({
                type: 'POST',
                url: url,
                data: 'keyFile=' + ( keyFile ? $('#'+keyFile).val() : $('#keyFile').val() ),
                success: function(reponse){

                    if(reponse){
                        this.uploadLoad[0] = 1;
                        if(this.options.avanceBarre) this.options.avanceBarre(Math.round(reponse.bytes_uploaded / reponse.bytes_total * 100));
                        else {
                            $('#fileName').html(reponse.filename);
                            this.progressView(Math.round(reponse.bytes_uploaded / reponse.bytes_total * 100));
                        }

                        if(reponse.done != 1)
                            this.progressLoad();
                    } else {
                        if(this.uploadLoad[0]) {
                            this.progressView(100);
                        } else {
                            var date = new Date();
                            if(date.getTime() - this.uploadLoad[1] < 2000)
                                this.progressLoad();
                            else
                                this.progressView(100);

                        }
                    }
                },
                error: function(retour){
                    console.log(retour);
                },
                dataType: 'json',
                context: that
            });
        };
        this.progressView = function(pourcentage, fichier){
            this.avanceBarre(pourcentage);
        };
        this.initBarre = function(){
            $('#progress').append('<div id="formUploadBarre" style="height: 15px; width: 200px; border: #000000 solid 1px;"><div id="formUploadAvancement" style="height: 15px; background: blue; width:0px;"></div></div>');
        };
        this.avanceBarre = function(pourcentage) {
            if($('#formUploadAvancement').is(':not(:animated)'))
                $('#formUploadAvancement').animate({
                    width: (pourcentage * 2) + 'px'
                    }, 'fast');
        //$('#formUploadAvancement').css('width', (pourcentage * 2) + 'px');
        };

        // Si il n'y a pas de champ upload
        if($('input[type=file]').length == 0){
            // Sans upload (donc ajax, c'est plus "logique")
            this.submit(function(){
                var probleme = this.testValeurs(verifs);
                if(!probleme){
                    var data = '';
                    $('#'+this.attr('id')+' input:not([type=file])').each(function(){

                        if(data != '')
                            data += '&';
                        data += $(this).attr('name') + '=' + $(this).val();
                    });
                    $.ajax({
                        data: data,
                        type: $(this).attr('method'),
                        dataType: options.dataType ? options.dataType : 'text',
                        url: options.url ? options.url : $(this).attr('action'),
                        success: options.success,
                        error: options.error ? option.error : function (xhr) {
                            console.log('Erreur à l\'envoie du formulaire: #'+$(this).attr('id'));
                            console.log(xhr.responseText);
                        }
                    });

                } else {
                    this.champsMalRemplis();
                }
                return false;
            });

        } else {
            // Avec Upload (on envoie par iframe, c'est plus chiant)
            var probleme = this.testValeurs(verifs);
            if(!probleme){

                $('#'+this.attr('id')).append('<input type="hidden" name="javascript" value="1" />');
                $('#'+this.attr('id')).after('<iframe id="iframeUpload" name="iframeUpload" src="#" style="display:none"></iframe>');
                $(this).attr('target', 'iframeUpload');
                // Si l'input file n'est pas vide ET si le fichier PHP est renseigné

                var that = this;
                this.submit(function(){
                if(isDefined(that.options.initBarre) && isDefined(that.options.avanceBarre)) that.options.initBarre();
                else {
                    $('#iframeUpload').after('<p id="fileName"></p><p id="progress"></p>');
                    that.initBarre();
                }

                    if(options.url_verif && $('input[type=file]').val() != ''){
                        // Là on doit utiliser un autre fichier pour avoir la progression de l'upload
                        //setTimeout(function(){
                        var date = new Date();
                        that.uploadLoad[1] = date.getTime();
                        that.progressLoad();

                        // Un timeout pour ne pas avoir de conflit avec le démarrage de l'upload
                        setTimeout(function(){
                            $('#iframeUpload').load( function() {
                                var data = $(this).html();
                                if(that.options.dataType == 'script')
                                    $('head:first').append('<script type="text/javascript">' + data + '</script>');
                                if(that.options.dataType == 'json')
                                    data = JSON.parse(data);
                                if(typeof that.options.success == 'function')
                                    that.options.success(data);
                            } );
                        } , '5');
                    }

                });
            } else this.champsMalRemplis();
        }
        return this;
    };
})(jQuery);(function($) {
    /**
     * Cette fonction permet d'envoyer un formulaire en ajax simplement
     *
     * @param object options objet contenant les options d'envoie. Rien n'est obligatoire. (nom du fichier APC, barre de chargement etc... doc coming soon :p)
     * @param object verifs objet contenant les noms des champs et ce qu'ils doivent contenir
     *
     */
    $.fn.dynSend = function(options, verifs) {
        this.options = options ? options : {};
        this.uploadLoad = new Array(0,0);

        this.testValeurs = function (verifs) {
            // On vérifie les données
            var probleme = 0, b=0;
            for ( var id in verifs ) {
                if(typeof verifs[id] == 'function'){
                    b = verifs[id]();
                    if(b) probleme++;
                    b = 0;
                } else {
                    if(verifs[id] == 'needed' || verifs[id] == 1)
                        if($('#'+id).val() == '')
                            probleme++;

                }
            }
        };
        this.champsMalRemplis = function() {
            alert('Les champs sont mals remplis !');
        };
        // Fonction qui s'occupe de gérer APC
        this.progressLoad = function() {
            var that = this;
            var url = that.options.url_verif;
            var keyFile = that.options.keyFile;

            $.ajax({
                type: 'POST',
                url: url,
                data: 'keyFile=' + ( keyFile ? $('#'+keyFile).val() : $('#keyFile').val() ),
                success: function(reponse){

                    if(reponse){
                        this.uploadLoad[0] = 1;
                        if(this.options.avanceBarre) this.options.avanceBarre(Math.round(reponse.bytes_uploaded / reponse.bytes_total * 100));
                        else {
                            $('#fileName').html(reponse.filename);
                            this.progressView(Math.round(reponse.bytes_uploaded / reponse.bytes_total * 100));
                        }

                        if(reponse.done != 1)
                            this.progressLoad();
                    } else {
                        if(this.uploadLoad[0]) {
                            this.progressView(100);
                        } else {
                            var date = new Date();
                            if(date.getTime() - this.uploadLoad[1] < 2000)
                                this.progressLoad();
                            else
                                this.progressView(100);

                        }
                    }
                },
                error: function(retour){
                    console.log(retour);
                },
                dataType: 'json',
                context: that
            });
        };
        this.progressView = function(pourcentage, fichier){
            this.avanceBarre(pourcentage);
        };
        this.initBarre = function(){
            $('#progress').append('<div id="formUploadBarre" style="height: 15px; width: 200px; border: #000000 solid 1px;"><div id="formUploadAvancement" style="height: 15px; background: blue; width:0px;"></div></div>');
        };
        this.avanceBarre = function(pourcentage) {
            if($('#formUploadAvancement').is(':not(:animated)'))
                $('#formUploadAvancement').animate({
                    width: (pourcentage * 2) + 'px'
                    }, 'fast');
        //$('#formUploadAvancement').css('width', (pourcentage * 2) + 'px');
        };

        // Si il n'y a pas de champ upload
        if($('input[type=file]').length == 0){
            // Sans upload (donc ajax, c'est plus "logique")
            this.submit(function(){
                var probleme = this.testValeurs(verifs);
                if(!probleme){
                    var data = '';
                    $('#'+this.attr('id')+' input:not([type=file])').each(function(){

                        if(data != '')
                            data += '&';
                        data += $(this).attr('name') + '=' + $(this).val();
                    });
                    $.ajax({
                        data: data,
                        type: $(this).attr('method'),
                        dataType: options.dataType ? options.dataType : 'text',
                        url: options.url ? options.url : $(this).attr('action'),
                        success: options.success,
                        error: options.error ? option.error : function (xhr) {
                            console.log('Erreur à l\'envoie du formulaire: #'+$(this).attr('id'));
                            console.log(xhr.responseText);
                        }
                    });

                } else {
                    this.champsMalRemplis();
                }
                return false;
            });

        } else {
            // Avec Upload (on envoie par iframe, c'est plus chiant)
            var probleme = this.testValeurs(verifs);
            if(!probleme){

                $('#'+this.attr('id')).append('<input type="hidden" name="javascript" value="1" />');
                $('#'+this.attr('id')).after('<iframe id="iframeUpload" name="iframeUpload" src="#" style="display:none"></iframe>');
                $(this).attr('target', 'iframeUpload');
                // Si l'input file n'est pas vide ET si le fichier PHP est renseigné

                var that = this;
                this.submit(function(){
                if(that.options.initBarre && that.options.avanceBarre) that.options.initBarre();
                else {
                    $('#iframeUpload').after('<p id="fileName"></p><p id="progress"></p>');
                    that.initBarre();
                }

                    if(options.url_verif && $('input[type=file]').val() != ''){
                        // Là on doit utiliser un autre fichier pour avoir la progression de l'upload
                        //setTimeout(function(){
                        var date = new Date();
                        that.uploadLoad[1] = date.getTime();
                        that.progressLoad();

                        // Un timeout pour ne pas avoir de conflit avec le démarrage de l'upload
                        setTimeout(function(){
                            $('#iframeUpload').load( function() {
                                var data = $(this).html();
                                if(that.options.dataType == 'script')
                                    $('head:first').append('<script type="text/javascript">' + data + '</script>');
                                if(that.options.dataType == 'json')
                                    data = JSON.parse(data);
                                if(typeof that.options.success == 'function')
                                    that.options.success(data);
                            } );
                        } , '5');
                    }

                });
            } else this.champsMalRemplis();
        }
        return this;
    };
})(jQuery);


Le code du côté de PHP.
Code : PHP
1
2
3
4
5
6
7
8
9
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
 
if ($_POST['keyFile']) {
	echo json_encode(uploadprogress_get_info($_POST['keyFile']));
	exit();
}
?>

Il faut un serveur compatible ! Très peu d'hébergeurs gratuits fournissent cette option !
Si vous avez un serveur privé il vous faudra installer uploadprogress.
Code : Console
# apt-get install php-pear make php5-dev
# pecl install uploadprogress

Ajoutez la ligne suivante à votre fichier php.ini:
Code : Ini
1
extension=uploadprogress.so

Et enfin rechargez apache.
Code : Console
# /etc/init.d/apache2 restart

N'oubliez pas dans le formulaire de rajouter ceci:
Code : PHP
1
<input type="hidden" id="keyFile" name="UPLOAD_IDENTIFIER" value="<?php echo uniqid(); ?>" />

uploadprogress comporte des bugs, l'un d'eux est que si le champs UPLOAD_IDENTIFIER est après le champ du fichier, alors uploadprogress renverra null: ça ne fonctionnera pas.


Ce script n'est pas terminé, je ferais quelques modifications (notamment sur la vérification des infos, la barre de progression et le retour). J'ai également des tests à faire sur l'envoie « simple ».


Merci d'avance pour vos avis et conseils :) .

Note: je n'ai pas de site et ne partage donc ce script qu'ici, dois-je penser à le partager autre part ?

Je l'avais promise... Voici la mini-doc !

Mini-doc


L'utilisation du script est simple:
Code : JavaScript
1
2
3
4
// On the page's load
	$(document).ready(function() {
		$('#formulaire').dynSend();
	});

Mais évidemment l'utilisation ne s'arrête pas là, on peut aussi charger une barre d'avancement de l'upload, il suffit de préciser quel fichier PHP sera chargé de retourner les informations nécessaires.
Code : JavaScript
1
2
3
4
// On the page's load
	$(document).ready(function() {
		$('#formulaire').dynSend({ url_verif: 'upload.php' });
	});

On peut personnaliser ce que retournera le formulaire, le type de données retournées (comme un bon vieux $.ajax).
Bref, je vous fais un dessin:
Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$('#formulaire').dynSend({
	url_verif: 'upload.php',
	url: '/page.php',		// Par défaut l'url du formulaire sera utilisée
					// Default the form's url
					
	dataType: 'html',		// Le type de données de retour
					// Data type return
					
	initBarre: function(){
		// Personaliser la barre de chargement (initialisation)
		// Personize the loader (init)
	},
	avanceBarre: function(percentage){
		// Personaliser la barre de chargement (avancement)
		// Personize the loader (progression)
	},
	success: function(data) {
		// Fonction qui s'éxécute en cas de succès
		// Success function
	},
	error: function() {
		// Fonction qui s'exécutera si il y a une erreur (ajax)
		// Error function
	}
}, { // Validation du formulaire / form validation
	nameInput: function(){
		// Fonction à appliquer à l'élément en question (vérification du contenu)
		// Function to apply on the element
	},
	//...
});

dataType ne fonctionne pas pour l'instant sur les formulaires avec upload, tout simplement parce que le retour n'est pas géré, idem pour l'erreur, mais bon ça va venir tout ça, patience =).

Bien sûr j'ajouterais de temps en temps de nouvelles fonctionnalités.


C'est le bordel ? C'est normal ! Hé oui c'est ma première « documentation » :').
Édité le 11/08/2010 à 11:48:48 par Nek'

Rejoignez nous sur le chat #siteduzero
J'aide ceux qui codent leurs scripts eux même, inutile de me demander de coder pour vous.
Liens utiles (ou pas): Mon wiki (Symfony2) | JqueryForm | Mon site | Minecraft
 
Publicité # Posté le 04/08/2010 à 10:37:37

Hors ligne Jeremiah # Posté le 04/08/2010 à 10:55:16
what's up ?
Avatar
Flux RSS

Tu crées une démo, tu l'héberges, avec le tuto, et tu l'envoies sur twitter en anglais :)

Image utilisateur
 
Hors ligne Nek' # Posté le 04/08/2010 à 11:59:09
LPL FTW
Avatar

Ville : Reims
Pays : France métropolitaine
Études : IUT Reims-Châlons-Charleville

@Jeremiah: FLEMME. En fait cette question s'adressait plutôt aux modérateurs. Je met mon script à disposition de tout le monde, je ne vais pas courir après une quelconque gloire. (surtout si personne ne trouve ce script intéressant)

Démo: http://jqueryform.nek.fr.nf/

[edit] Bug principal transformé (bah ouais apparemment c'était un bug de javascript !), reste à corriger les petits bugs.

Maintenant c'est un bug PHP. Ça doit être ma configuration qui pose problème mais c'est étrange !
Édité le 04/08/2010 à 13:17:11 par Nek'

Rejoignez nous sur le chat #siteduzero
J'aide ceux qui codent leurs scripts eux même, inutile de me demander de coder pour vous.
Liens utiles (ou pas): Mon wiki (Symfony2) | JqueryForm | Mon site | Minecraft
 
Hors ligne Nek' # Posté le 09/08/2010 à 11:53:51
LPL FTW
Avatar

Ville : Reims
Pays : France métropolitaine
Études : IUT Reims-Châlons-Charleville

Le script est fonctionnel ! \o/.

J'ai mis à jour le premier post du topic.

Have fun !

Mini-doc coming soon.
Édité le 09/08/2010 à 12:01:19 par Nek'

Rejoignez nous sur le chat #siteduzero
J'aide ceux qui codent leurs scripts eux même, inutile de me demander de coder pour vous.
Liens utiles (ou pas): Mon wiki (Symfony2) | JqueryForm | Mon site | Minecraft
 
Hors ligne Nek' # Posté le 11/08/2010 à 11:40:24
LPL FTW
Avatar

Ville : Reims
Pays : France métropolitaine
Études : IUT Reims-Châlons-Charleville

À priori j'ai fini de débug le script, si vous avez des bugs avec, n'hésitez pas a les signaler, je me ferais un plaisir de les corriger.

J'utilise actuellement le script en production (en utilisant simplement $.dynSend()) c'est assez plaisant faut avouer :D .

Rejoignez nous sur le chat #siteduzero
J'aide ceux qui codent leurs scripts eux même, inutile de me demander de coder pour vous.
Liens utiles (ou pas): Mon wiki (Symfony2) | JqueryForm | Mon site | Minecraft
 
Hors ligne anonyme # Posté le 07/09/2010 à 16:58:24

Est il possible d'avoir la barre d'upload sans la validation en JS j'ai deja la mienne en php.
Hors ligne Nek' # Posté le 07/09/2010 à 18:21:10
LPL FTW
Avatar

Ville : Reims
Pays : France métropolitaine
Études : IUT Reims-Châlons-Charleville

Ce que tu dis ne veut rien dire :lol: .

Mais si tu parles d'utiliser une barre d'upload déjà en dur dans le html (ce qui n'est pas une bonne idée :p ), oui tu peux.
Il suffit de passer une fonction vide à l'initialisation de la barre, pour l'avancement de la barre il faudra quand même coder la fonction ;) .

Mais pouvoir utiliser une barre déjà existante n'est pas une mauvaise idée, je verrais pour implémenter un sélecteur de barre dans les options !

Rejoignez nous sur le chat #siteduzero
J'aide ceux qui codent leurs scripts eux même, inutile de me demander de coder pour vous.
Liens utiles (ou pas): Mon wiki (Symfony2) | JqueryForm | Mon site | Minecraft
 
Hors ligne J-C Bubbendorf # Posté le 23/10/2010 à 12:46:58
Aider est une de mes passion
Avatar
Flux RSS

Pour le sélecteur de barre, tu peut utiliser jQuery UI Progressbar.
 
Hors ligne Nek' # Posté le 23/10/2010 à 13:12:13
LPL FTW
Avatar

Ville : Reims
Pays : France métropolitaine
Études : IUT Reims-Châlons-Charleville

Bah en fait j'ai déjà ma propre barre a intégrer avec des infos sympa mais bon j'ai d'autres trucs à développer donc je ne l'ai toujours pas intégré (shame on me).

Euh sinon ça veut dire quoi sélecteur de barre ? ( o_O )

Rejoignez nous sur le chat #siteduzero
J'aide ceux qui codent leurs scripts eux même, inutile de me demander de coder pour vous.
Liens utiles (ou pas): Mon wiki (Symfony2) | JqueryForm | Mon site | Minecraft
 
Hors ligne J-C Bubbendorf # Posté le 23/10/2010 à 18:25:33
Aider est une de mes passion
Avatar
Flux RSS

Citation : Nek'
Mais pouvoir utiliser une barre déjà existante n'est pas une mauvaise idée, je verrais pour implémenter un sélecteur de barre dans les options !

Tu en parles toi-même.

En gros, au lieu de faire définir une fonction à l'utilisateur, tu donne le choix de :
  • Choisir une barre x préfabriquée ;
  • Choisir une barre y préfabriquée ;
  • Ou implémenter une fonction (comme actuellement).
Édité le 23/10/2010 à 18:27:39 par J-C Bubbendorf
 

Retour au forum "Présentation de vos projets" ou à la liste des forums

Pour accéder à cette section
Connectez-vous !
connexion_rpx


Lire aussi