jQuery(function () {



    try {

        sofad.chemins.serviceQuestionnaire = sofad.info.base_url +  'index.php/services_interactivites/questionnaire';
        sofad.chemins.serviceQuiz    = sofad.info.base_url + 'index.php/services_interactivites/quiz';

        sofad.interactivites = {};
        var widgets    = sofad.interactivites.widgets    = {interactivites: {}};
        var extensions = sofad.interactivites.extensions = {};
        var controleurs = sofad.interactivites.controleurs = {};

        sofad.interactivites.obtientType = function(widget) {
            var classes = widget.noeuds.attr('class').split(' ');
            var matches;
            var type = {type: "", sousType: ""};
            for(var ii=0; ii<classes.length; ++ii) {
                if(matches = classes[ii].match(/^type-(.+)$/)) {
                    type.type = matches[1];
                } else if(matches = classes[ii].match(/^soustype-(.+)$/)) {
                    type.sousType = matches[1];
                }
            }
            return type;
        };

        /* FORMULAIRES */
        widgets.interactivites.Formulaire = (function() {
            var constructeur    = sofad.sousType( sofad.widgets.Widget );
            var proto           = constructeur.prototype;
            proto.requete      = 'body.type-formulaire';
            proto.prefixeAlias = 'alias-de-';
            
            proto.typesEnfants = {sequence: 'sequences.widgets.Sequence', 
                                  questionnaire: 'questionnaires.widgets.Questionnaire'};
            var ext = sofad.sequences.extensions;
            proto.factory( 'sequences.widgets.Sequence',
                           ext.pagination( ext.precSuiv(  sofad.sequences.widgets.Sequence ) ) );
            
            //DEMO Desactiver enregistrements
            var parent_demarre  = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                this.attacheSurveillanceCompletion();
            };


            proto.idClient = function() {
                var classes = this.noeuds.attr('class').split(" ");
                for(var ii=0; ii<classes.length; ++ii) {
                    var classe = classes[ii];
                    if(0 === classe.indexOf(this.prefixeAlias)) {
                        return classe.substr(this.prefixeAlias.length);
                    }
                }
                return this.noeuds.attr('id').substr(5);
            };


            proto.attacheSurveillanceCompletion = function() {
                var questions = [];
                var questions_corrigees = [];
                var that = this;

                for(var ii=0; ii<this.enfants.length; ++ii) {
                    if ("Questionnaire" == this.enfants[ii].nomWidget) {
                        var questionnaire = this.enfants[ii];

                        for(var jj=0; jj<questionnaire.enfants.length; ++jj) {

                            if ("Question" == questionnaire.enfants[jj].nomWidget) {
                                (function (question) {
                                    questions[ questions.length ] = question;
                                    question.events.correction.subscribe(function() {
                                        if(-1 != questions_corrigees.indexOf(question)) return;
                                        questions_corrigees[ questions_corrigees.length ] = question;
                                        if(questions_corrigees.length == questions.length) {
                                            var tableau_points = questionnaire.points();
                                            var points = (tableau_points && 2 == tableau_points.length) ?
                                                tableau_points.join("/") :
                                                "1/1";

                                            jQuery.getJSON(sofad.chemins.serviceQuestionnaire,
                                                           {mode: "insere",
                                                            resultat: points,
                                                            id_client: that.idClient()});
                                        }
                                    }, null, that);
                                })(questionnaire.enfants[jj]);

                            }
                        }
                    }
                }
            };

            return constructeur;
        })();

        /* RESUMER */

        widgets.interactivites.Resumer = (function () {
            //CONSTRUCTEUR
            var parent_constructeur = widgets.interactivites.Formulaire;
            var constructeur = sofad.sousType( parent_constructeur, function() {
                parent_constructeur.apply(this, arguments);
                this.estEnregistre = false;
                for(var ii=0; ii<this.enfants.length; ++ii) {
                    if("Sequence" == this.enfants[ii].nomWidget) {
                        this.sequence = this.enfants[ii];
                    } else if ("Questionnaire" == this.enfants[ii].nomWidget) {
                        this.questionnaire = this.enfants[ii];
                    }
                }
                if(!(('sequence' in this) && ('questionnaire' in this))) {
                    throw sofad.ExceptionAucunSousWidget(this);
                }

                this.controleurs.boutonCorrige    = new (this.factory('interactivites.controleurs.BoutonCorrigeResumer'))   (this.sequence.controleurs.barreNav);
                this.controleurs.boutonReinit     = new (this.factory('interactivites.controleurs.BoutonReinitResumer'))    (this.sequence.controleurs.barreNav);
                this.controleurs.boutonEnregistre = new (this.factory('interactivites.controleurs.BoutonEnregistreResumer'))(this.sequence.controleurs.barreNav);
                this.controleurs.boutonCorrige.noeuds.hide();
                this.controleurs.boutonReinit.noeuds.hide();
                this.controleurs.boutonEnregistre.noeuds.hide();
                var type = sofad.interactivites.obtientType(this);
                if('exercice' == type.sousType) {
                    this.controleurs.boutonEnregistre.noeuds.remove();
                }
            } );
            var proto = constructeur.prototype;
            proto.requete          = 'body.type-resumer:not(.page-demo)';
            proto.classeBtnInactif = 'inactif';

            //METHODES
            proto.attacheSurveillanceCompletion = function() {};
            proto.alert = function(m) { alert(m); };
            proto.index = function() { 
                return this.sequence.index;
            };


            proto.iterChamps = function(question_active_seulement) { 
                return new constIterChamps(this, question_active_seulement);
            };


            proto.changeComportement = function(nom_comportement) {
                this.comportement = new (this.comportements[nom_comportement])(this);
            };


            proto.etat = function(mode, f) { //Gestion d'erreur pourrait être faite
                if(!f) f = function(){};
                jQuery.getJSON(sofad.chemins.serviceQuestionnaire,
                               {mode: mode, id_client: this.idClient()},
                               function(o) { 
                                   f(o);
                               });
            };

                
            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                var that = this;

                //Fonctionnalité du bouton Corrigé. Doit être mise en place avant le démarrage des questions,
                //afin qu'elles sachent qu'elles ne doivent pas instancier leur propre bouton Corrigé.
                for(var ii=0; ii<this.questionnaire.enfants.length; ++ii) {
                    (function() {
                        var question = that.questionnaire.enfants[ii];
                        var index_question = ii;
                        
                        question.inscritDeclencheurEvent('correction', function(f_corrige_q) {
                            that.controleurs.boutonCorrige.noeuds.bind('click', function() {
                                if(!jQuery(this).is(':visible')) return;
                                else if(index_question != that.index()) return;
                                else if(question.estCorrige()) return;
                                else if(jQuery(this).hasClass(that.classeBtnInactif)) that.alert(sofad.lang('{L:interactivites.resumer_interdiction_corrige}'));
                                else f_corrige_q();
                            });
                        });
                    })();
                }

                parent_demarre.apply(this, arguments);

                this.charge();
            };

            proto.charge = function() {
                var that = this;
                this.etat('statusclient', function(o) {
                    that.changeComportement( o.est_enregistre ? "enregistre": "ouvert" );
                });
            };


            //CONSTRUCTEURS DE PROPRIÉTÉS OBJETS

            var constIterChamps = (function() {
                var constructeur = function(resumer, question_active_seulement) {
                    this.resumer                 = resumer;
                    this.questionActiveSeulement = question_active_seulement;
                    this.indexQuestion           = question_active_seulement ? this.resumer.index() : 0;
                    this.indexChamp              = 0;
                };

                constructeur.prototype = {
                    suivant: function() {
                        for(; this.indexQuestion < this.resumer.questionnaire.enfants.length; ++this.indexQuestion) {
                            var question = this.resumer.questionnaire.enfants[ this.indexQuestion ];
                            for(; this.indexChamp < question.enfants.length; ++this.indexChamp) {
                                var champ = question.enfants[ this.indexChamp ];
                                if('TexteCorrige' == champ.nomWidget) {
                                    ++this.indexChamp;
                                    return champ;
                                }
                            }
                            if(this.questionActiveSeulement) return;
                            this.indexChamp = 0;
                        }
                    },
                    courant: function() {
                        if(this.valide()) return this.resumer.questionnaire.enfants[ this.indexQuestion ].enfants[ this.indexChamp ]; 
                    },
                    valide: function() {
                        return this.questionActiveSeulement ?
                            this.indexChamp >= this.resumer.questionnaire.enfants[ this.indexQuestion ].enfants.length :
                            this.indexQuestion >= this.resumer.questionnaire.enfants.length;
                    }
                };

                return constructeur;
            })();



            proto.comportements = {
                ouvert: (function() {
                    var constructeur = function(resumer) {
                        this.resumer = resumer;

                        /* Ne pas utiliser simplement .noeuds.show(), car on veut qqch de plus subtil.
                           Le CSS doit pouvoir décider de l'affichage ou non d'un bouton lorsqu'il est inactif.
                           Si on utilise show, un attribut style="display:inline" est ajouté au bouton,
                           ce qui prend préséance sur un style CSS .inactif{display: none}. */
                        this.resumer.controleurs.boutonCorrige.noeuds.removeAttr("style");
                        this.resumer.controleurs.boutonReinit.noeuds.hide();
                        this.resumer.controleurs.boutonEnregistre.noeuds.removeAttr("style");

                        this.brancheVerificationPermissionCorrige();
                        this.brancheVerificationPermissionEnregistrer();
                        this.brancheBoutonEnregistrer();
                    };
                    
                    constructeur.prototype = {
                        brancheVerificationPermissionCorrige: function() {
                            var champ;
                            var iter = this.resumer.iterChamps();
                            var that = this;
                            var f_verif = function() {
                                that.verifiePermissionCorrige();
                            };
                            while(champ = iter.suivant()) {
                                champ.noeuds.bind('change.ouvert', f_verif);
                            }
                            this.resumer.sequence.controleurs.btnSuiv.noeuds.bind('click.ouvert', f_verif);
                            this.resumer.sequence.controleurs.btnPrec.noeuds.bind('click.ouvert', f_verif);
                            this.resumer.controleurs.boutonCorrige.noeuds.bind('click.ouvert', f_verif);
                            this.verifiePermissionCorrige();
                        },

                        brancheVerificationPermissionEnregistrer: function() {
                            var that = this;
                            this.resumer.controleurs.boutonCorrige.noeuds.bind('click.ouvert', function() {
                                that.verifiePermissionEnregistrer();
                            });
                            this.verifiePermissionEnregistrer();
                        },

                        brancheBoutonEnregistrer: function() {
                            var that = this;
                            this.resumer.controleurs.boutonEnregistre.noeuds.bind('click.ouvert', function() {
                                if(!jQuery(this).is(':visible')) return;
                                if(jQuery(this).hasClass(that.resumer.classeBtnInactif)) {
                                    return that.resumer.alert(sofad.lang("{L:interactivites.resumer_interdiction_enregistre}"));
                                }
                                that.resumer.etat('insere', function() {
                                    that.resumer.alert(sofad.lang("{L:interactivites.resumer_confirmation_enregistre}"));
                                });
                                var iter = that.resumer.iterChamps();
                                var champ;
                                while(champ = iter.suivant()) champ.noeuds.unbind('change.ouvert');
                                that.resumer.controleurs.boutonCorrige.noeuds.unbind('click.ouvert');
                                that.resumer.controleurs.boutonEnregistre.noeuds.unbind('click.ouvert');
                                that.resumer.sequence.controleurs.btnSuiv.noeuds.unbind('click.ouvert');
                                that.resumer.sequence.controleurs.btnPrec.noeuds.unbind('click.ouvert');

                                that.resumer.changeComportement('enregistre');
                            });
                        },

                        verifiePermissionEnregistrer: function() {
                            for(var ii=0; ii<this.resumer.questionnaire.enfants.length; ++ii) {
                                var question = this.resumer.questionnaire.enfants[ ii ];
                                if(!question.estCorrige()) {
                                    return this.resumer.controleurs.boutonEnregistre.noeuds.addClass(this.resumer.classeBtnInactif);
                                }
                            }
                            return this.resumer.controleurs.boutonEnregistre.noeuds.removeClass(this.resumer.classeBtnInactif);
                        },
                        
                        verifiePermissionCorrige: function () {
                            var champ;
                            var iter = this.resumer.iterChamps(true);

                            if(this.resumer.questionnaire.enfants[ this.resumer.index() ].estCorrige()) {
                                return this.resumer.controleurs.boutonCorrige.noeuds.addClass(this.resumer.classeBtnInactif);
                            }

                            while(champ = iter.suivant()) {
                                if(champ.noeuds[0].value) {
                                    return this.resumer.controleurs.boutonCorrige.noeuds.removeClass(this.resumer.classeBtnInactif);
                                }
                            }
                            
                            return this.resumer.controleurs.boutonCorrige.noeuds.addClass(this.resumer.classeBtnInactif);
                        }
                    };

                    return constructeur;
                })(),


                enregistre: (function() {
                    var constructeur = function(resumer) {
                        this.resumer = resumer;
                        this.resumer.controleurs.boutonCorrige.noeuds.hide();
                        this.resumer.controleurs.boutonReinit.noeuds.removeAttr("style");
                        this.resumer.controleurs.boutonEnregistre.noeuds.hide();

                        this.resumer.questionnaire.reset();
                        for(var ii=0; ii<this.resumer.questionnaire.enfants.length; ++ii) {
                            var question = this.resumer.questionnaire.enfants[ii];
                            if(!question.estCorrige()) question.events.correction.fire();
                        }

                        jQuery('.mauvaise-reponse, .espacement-mauvaise-reponse').remove();

                        this.brancheBoutonReinit();
                    };

                    constructeur.prototype = {
                        brancheBoutonReinit: function() {
                            var that = this;
                            this.resumer.controleurs.boutonReinit.noeuds.bind('click.ferme', function() {
                                that.resumer.etat('reinit');
                                that.resumer.controleurs.boutonReinit.noeuds.unbind('click.ferme');
                                that.resumer.questionnaire.reset();
                                that.resumer.sequence.activeSegment(0);
                                that.resumer.changeComportement('ouvert');
                            });
                        }
                    };

                    return constructeur;
                })()
            };




            return constructeur;
        })();


        //Résumer sans enregistrement

        widgets.interactivites.ResumerDemo = (function() {
            var parent_constructeur = widgets.interactivites.Resumer;
            var constructeur = sofad.sousType( parent_constructeur, function() {
                parent_constructeur.apply(this, arguments);

                this.controleurs.boutonReinit.noeuds.remove();
                //this.controleurs.boutonEnregistre.noeuds.remove();
            } );

            var proto = constructeur.prototype;
            proto.requete = 'body.type-resumer.page-demo';

            proto.comportements = {
                ouvert: sofad.sousType(proto.comportements.ouvert)
            };
            
            proto.comportements.ouvert.prototype.verifiePermissionEnregistrer = function() {
                return this.resumer.controleurs.boutonEnregistre.noeuds.addClass(this.resumer.classeBtnInactif);
            };
            
            proto.comportements.ouvert.prototype.brancheBoutonEnregistrer = function() {
                var that = this;
                this.resumer.controleurs.boutonEnregistre.noeuds.bind('click', function() {
                    that.resumer.alert(sofad.lang('{L:interactivites.btn_quiz_demo_inactif}'));
                });
            };

            proto.charge = function() {
                this.changeComportement("ouvert");
            };
           
            return constructeur;
        })();


        /* Client Quiz */

        widgets.RadioQuiz = (function() {
            var constructeur = sofad.sousType( sofad.widgets.Widget );
            var proto = constructeur.prototype;
            proto.requete = 'input:radio';
            proto.images = {
                bon:     sofad.questionnaires.widgets.RadioBon.prototype.imagesCorrige,
                mauvais: sofad.questionnaires.widgets.RadioMauvais.prototype.imagesCorrige
            };
            proto.verrouille = sofad.questionnaires.widgets.RadioBon.prototype.verrouille;

            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                this.parentEvent('correction').subscribe(this.corrige, null, this);
                this.inscritCommeDeclencheurCorrection();
            };


            proto.inscritCommeDeclencheurCorrection = function() {
                if(jQuery('body.sans-correction-immediate').length) return;
                var quiz      = this.widgetParent.widgetParent.widgetParent.widgetParent;
                var type_quiz = sofad.interactivites.obtientType(quiz);
                if('sans-corrige' == type_quiz.sousType) return;
                var that = this;
                this.declencheParentEvent('correction', 
                                          function(fn) {
                                              that.noeuds.bind('click', function() {
                                                  for(var ii = 0; ii < that.widgetParent.enfants.length; ++ii) {
                                                      that.widgetParent.enfants[ii].noeuds.attr("disabled", true);
                                                      //Indicateur de chargement
                                                      if(this == that.widgetParent.enfants[ii].noeuds[0]) {
                                                          jQuery(this).after(sofad.lang(sofad.format(quiz.htmlIndicateurChargement, sofad.chemins.images)));
                                                      }
                                                  }
                                                  //L'effet par defaut du clic sur un bouton radio est de le cocher.
                                                  //Cet effet ne semble cependant pas toujours se realiser avant
                                                  //Les effets personnalises. Je provoque ici l'effet par defaut avant
                                                  //L'execution des effets personnalises.
                                                  this.checked = true;
                                                  //On inscrit le bouton Radio comme provocateur de l'evenement correction,
                                                  //quoiqu'on ne l'invoque pas directement via fn(). On doit passer
                                                  //par la question pour que celle-ci passe la requete au service web et la reponse
                                                  //aux subscribers.
                                                  that.widgetParent.widgetParent.cliqueBoutonCorrige();
                                              });
                                          });
            }


            proto.corrige = function(nom_evenement, corrige) {
                var quiz = this.widgetParent.widgetParent.widgetParent.widgetParent;
                this.noeuds.parent().find(quiz.requeteIndicateurChargement).remove();
                if(this._estCorrige) return;

                var corrige_question = corrige[0].corriges[ this.widgetParent.widgetParent.index() ]; 
                if(undefined === corrige_question) throw "Corrigé non fourni.";
                
                var corrige_radio = corrige_question[ this.noeuds.attr("name") ];
                var images = this.estUneBonneReponse(corrige_radio) ?
                    this.images.bon :
                    this.images.mauvais;

                this.noeuds.before( sofad.lang( sofad.format( 
                    images[ this.noeuds.is(':checked') ? 'coche' : 'nonCoche' ],
                    sofad.chemins.images ) ) );

                if(("feedbackInline" in corrige_radio) && this.noeuds.is(":checked")) {
                    this.widgetParent.afficheFeedbackInline( corrige_radio.feedbackInline );
                }

                this.verrouille();
                this._estCorrige = true;
            };


            proto.estUneBonneReponse = function(corrige_radio) {
                return (corrige_radio.bon && this.noeuds.is(":checked")) ||
                    !corrige_radio.bon && -1 != jQuery.inArray(this.noeuds[0].value, corrige_radio.bonneReponse);
            };

            proto.videChamps = function() {
                this.noeuds[0].checked = false;
            };



            return constructeur;
        })();



        widgets.CaseCocherQuiz = (function () {
            var constructeur = sofad.sousType( widgets.RadioQuiz );
            var proto = constructeur.prototype;
            proto.requete      = "input:checkbox";
            proto.images = {
                bon:     sofad.questionnaires.widgets.CaseBon.prototype.imagesCorrige,
                mauvais: sofad.questionnaires.widgets.CaseMauvais.prototype.imagesCorrige
            };
            proto.verrouille = sofad.questionnaires.widgets.CaseBon.prototype.verrouille;            


            proto.estUneBonneReponse = function(corrige_case) {
                return  (this.noeuds.is(":checked")  &&  corrige_case.bon) ||
                    (!this.noeuds.is(":checked") && !corrige_case.bon);
            };

            proto.inscritCommeDeclencheurCorrection = function() {};

            return constructeur;
        })();



        widgets.QcmruQuiz = (function() {
            var constructeur = sofad.sousType( sofad.questionnaires.widgets.Qcmru );
            constructeur.prototype.typesEnfants = { radio: 'interactivites.widgets.RadioQuiz' };

            constructeur.prototype.afficheFeedbackInline = function(message) {
                this.controleurs.feedbackInline = new (this.factory("interactivites.controleurs.FeedbackInlineQuiz"))(this, [message]);
            };

            constructeur.prototype.videChamps = function() {
                for(var ii= 0; ii < this.enfants.length; ++ii) {
                    this.enfants[ii].videChamps();
                }
            };


            return constructeur;
        })();



        widgets.QcmrmQuiz = (function() {
            var constructeur = sofad.sousType( sofad.questionnaires.widgets.Qcmrm );
            constructeur.prototype.typesEnfants = { caseCocher: 'interactivites.widgets.CaseCocherQuiz' };
            constructeur.prototype.videChamps = widgets.QcmruQuiz.prototype.videChamps;
            return constructeur;
        })();



        widgets.TexteCorrigeQuiz = (function() {
            var constructeur = sofad.sousType( sofad.widgets.Widget);
            var proto = constructeur.prototype;
            proto.requete = "input:text.texte-corrige";
            

            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                this.parentEvent('correction').subscribe(this.corrige, null, this);
            };


            proto.corrige = function(nom_evenement, corrige) {
                if(this._estCorrige) return;

                var corrige_question = corrige[0].corriges[ this.widgetParent.index() ];
                if(undefined === corrige_question) throw "Corrigé non fourni.";
                
                this.corrigeChamp = corrige_question[ this.noeuds.attr("name") ];

                sofad.questionnaires.widgets.TexteCorrige.prototype.corrige.apply(this, []);
            };


            proto.valide = function() {
                if(!this.corrigeChamp.bon) {
                    this.reponsesAcceptees = [this.corrigeChamp.bonneReponse];
                    return false;
                }
                return this.noeuds[0].value;
            };

            proto.videChamps = function() {
                this.noeuds[0].value = "";
            };



            return constructeur;
        })();
        widgets.ListeDeroulanteQuiz = (function() {
            var constructeur = sofad.sousType(sofad.widgets.Widget);
            var proto = constructeur.prototype;
            proto.requete = 'select';


            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                this.parentEvent('correction').subscribe(this.corrige, null, this);
            };


            proto.corrige = function(nom_evenement, corrige) {
                if(this._estCorrige) return;
                this._estCorrige = true;
                var corrige_question = corrige[0].corriges[ this.widgetParent.index() ];
                if(undefined === corrige_question) throw "Corrigé non fourni.";
                corrige_champ = corrige_question[ this.noeuds.attr("name") ];
                var reponse_donnee = this.noeuds[0].options[ this.noeuds[0].selectedIndex ].value;

                if(corrige_champ.bon) {
                    this.controleurs.bonneReponse    = new (this.factory('questionnaires.controleurs.BonneReponse'))(this, [reponse_donnee]);
                } else {
                    this.controleurs.corrigeReponse  = new (this.factory('questionnaires.controleurs.CorrigeReponse'))(this, [corrige_champ.bonneReponse]);
                    this.controleurs.mauvaiseReponse = new (this.factory('questionnaires.controleurs.MauvaiseReponse'))(this, [reponse_donnee]);
                }
                this.noeuds.hide();
            }


            proto.videChamps = function() {
                this.noeuds[0].selectedIndex = 0;
            }


            return constructeur;
        })();


        widgets.QuestionQuiz = (function() {
            var constructeur = sofad.sousType( sofad.questionnaires.widgets.Question );
            var proto        = constructeur.prototype;
            proto.typesEnfants = {
                qcmru:          'interactivites.widgets.QcmruQuiz',
                qcmrm:          'interactivites.widgets.QcmrmQuiz',
                textesCorriges: 'interactivites.widgets.TexteCorrigeQuiz',
                listeDeroulante: 'interactivites.widgets.ListeDeroulanteQuiz'
            };

            proto.quiz  = function() {
                return this.widgetParent.widgetParent;
            };

            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                var type_quiz = sofad.interactivites.obtientType(this.quiz());
                if('sans-corrige' == type_quiz.sousType && "boutonCorrige" in this.controleurs) {
                    this.controleurs.boutonCorrige.noeuds.remove();
                }
            };

            proto.index = function() {
                var questionnaire = this.widgetParent;
                for(var ii=0; ii<questionnaire.enfants.length; ++ii) {
                    if(questionnaire.enfants[ii] === this) {
                        return ii;
                    } 
                }
                return -1;
            };


            proto.enregistre = function(fn, emplacement_indicateur) {
                if(!fn) fn = function() {};
                if(this._estCorrige) {
                    fn();
                    return;
                }
                var valeurs = sofad.valeursFormulaire(this.noeuds);
                valeurs.mode      = 'enregistre';
                valeurs.question  = this.index();
                var quiz_parent = this.quiz();
                quiz_parent.service(valeurs, function(reponse) {
                    if('temps_epuise' in reponse && 
                       reponse.temps_epuise &&
                      'tempsEpuiseImprevu' in quiz_parent.comportement) {
                        quiz_parent.comportement.tempsEpuiseImprevu(reponse);
                        return;
                    }
                    fn();
                    quiz_parent.metAJourBoutons(reponse);
                }, 
                                    emplacement_indicateur);
            };


            proto.cliqueBoutonCorrige = function() {
                var that = this;
                if(this._estCorrige) {
                    if("blocCorrige" in this.controleurs) {
                        this.controleurs.blocCorrige.noeuds.toggle();
                    }
                    return;
                }
                if('boutonCorrige' in that.controleurs) {
                    var emplacement_indicateur = that.controleurs.boutonCorrige.noeuds;
                    emplacement_indicateur.attr("disabled", true);
                    var ranime_bouton          = function() { emplacement_indicateur.attr("disabled", false); };
                } else {
                    var emplacement_indicateur = null;
                    var ranime_bouton          = function() {};
                }
                this.enregistre(function() {
                    that.quiz().service(
                        { mode:     "corrigeQuestion",
                          question: that.index() },
                        function(corrige) {
                            ranime_bouton();
                            that.appliqueCorrige(corrige);
                        },
                        emplacement_indicateur
                    );
                }, emplacement_indicateur);
            };


            proto.appliqueCorrige = function(corrige) {
                if(!corrige.corriges[ this.index() ]) {
                    return this.quiz().alert(sofad.lang("{L:interactivites.avertissement_correction_echouee}"));
                }
                this._estCorrige = true;
                this.events.correction.fire(corrige);
                this.quiz().metAJourBoutons(corrige);
                if(corrige.corriges[ this.index() ] && 
                   "messageCorrige" in corrige.corriges[ this.index() ]) {
                    this.controleurs.blocCorrige = new (this.factory("interactivites.controleurs.BlocCorrigeQuiz"))(this, [corrige.corriges[ this.index() ].messageCorrige]);
                    this.controleurs.blocCorrige.noeuds.show();
                }
            };

            proto.videChamps = function() {
                for(var ii= 0; ii < this.enfants.length; ++ii) {
                    this.enfants[ii].videChamps();
                }
            };


            return constructeur;
        })();

        
        controleurs.QuizPrecedent = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.Precedent);
            var proto        = constructeur.prototype;
            proto.requete = 'button.precedent';
            proto.html    = '<button class="precedent">{L:interactivites.quiz_btn_precedent}</button>';
            return constructeur;
        })();


        controleurs.QuizSuivant = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.Suivant);
            var proto        = constructeur.prototype;
            proto.requete = 'button.suivant';
            proto.html    = '<button class="suivant">{L:interactivites.quiz_btn_suivant}</button>';
            return constructeur;
        })();

        controleurs.QuizDebut = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.Debut);
            var proto        = constructeur.prototype;
            proto.requete = 'button.debut';
            proto.html    = '<button class="debut">{L:interactivites.quiz_btn_debut}</button>';
            return constructeur;
        })();


        controleurs.QuizFin = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.Fin);
            var proto        = constructeur.prototype;
            proto.requete = 'button.fin';
            proto.html    = '<button class="fin">{L:interactivites.quiz_btn_fin}</button>';
            return constructeur;
        })();

        controleurs.QuizBarreNav = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.BarreNav);
            constructeur.prototype.insere = function(widget_parent) {
                widget_parent.noeuds.prepend(this.renduHtml());
            };
            return constructeur;
        })();


        controleurs.QuizBarreNavComplement = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.BarreNav);
            constructeur.prototype.requete = 'div.barre-navigation-bas';
            constructeur.prototype.html    = '<div class="barre-navigation-bas"></div>';
            return constructeur;
        })();

        controleurs.QuizPrecedentComplement = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.Precedent);
            var proto        = constructeur.prototype;
            proto.html       = proto.html;
            proto.requete    = proto.requete;
            return constructeur;
        })();

        controleurs.QuizSuivantComplement = (function() {
            var constructeur = sofad.sousType(sofad.sequences.controleurs.Suivant);
            var proto        = constructeur.prototype;
            proto.html       = proto.html;
            proto.requete    = proto.requete;
            return constructeur;
        })();


        extensions.quizPrecSuivComplement = function(original) {
            var constructeur = function() {
                original.apply(this, arguments);

                if(undefined === this.controleurs.barreNavComplement) {
                    this.controleurs.barreNavComplement = new (this.factory('interactivites.controleurs.QuizBarreNavComplement'))(this);
                }
                this.controleurs.btnPrecComplement  = new (this.factory('interactivites.controleurs.QuizPrecedentComplement'))(this.controleurs.barreNavComplement);
                this.controleurs.btnSuivComplement  = new (this.factory('interactivites.controleurs.QuizSuivantComplement'))(this.controleurs.barreNavComplement);

                if(1 >= this.enfants.length) { // inutile si on a un seul segment
                    this.controleurs.btnPrecComplement.noeuds.remove();
                    this.controleurs.btnSuivComplement.noeuds.remove();
                }
            };
            
            var proto = sofad.objet(original.prototype);

            var parent_activeSegment = proto.activeSegment;
            proto.activeSegment = function() {
                parent_activeSegment.apply(this, arguments);
                if(0 == this.index || undefined === this.index) {
                    this.controleurs.btnPrecComplement.noeuds.addClass('inactif');
                } else {
                    this.controleurs.btnPrecComplement.noeuds.removeClass('inactif');
                }
                if(this.enfants.length-1 == this.index || undefined === this.index) {
                    this.controleurs.btnSuivComplement.noeuds.addClass('inactif');
                } else {
                    this.controleurs.btnSuivComplement.noeuds.removeClass('inactif');
                }
            };

            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                var that = this;
                this.controleurs.btnPrecComplement.noeuds.click(
                    function() { that.activeSegmentPrecedent(); return false; }
                );

                this.controleurs.btnSuivComplement.noeuds.click(
                    function() { that.activeSegmentSuivant(); return false; } 
                );

                this.controleurs.barreNavComplement.noeuds.append(this.widgetParent.controleurs.boutonCorrection.noeuds);
            };

            constructeur.prototype = proto;

            return constructeur;
        };


        
        widgets.SequenceQuiz = (function() {
            var ext = sofad.sequences.extensions;
            var constructeur =
                ext.precSuiv( 
                    ext.btnParPage( sofad.sequences.widgets.Sequence ) ) ;
            
            if(jQuery("body").hasClass("questions-nombreuses")) {
                 constructeur = sofad.sequences.extensions.pagesNombreuses( constructeur );
            }

            constructeur = ext.pagination( constructeur );

            var proto = constructeur.prototype;

            proto.classeQuestionRepondue  = "est-repondue";
            proto.classesQuestionCorrigee = ["est-corrigee-mauvaise", "est-corrigee-bonne"];


            var parent_activeSegment = proto.activeSegment;
            proto.activeSegment = function() {
                if(undefined !== this.index && !("correction" in this.widgetParent.controleurs)) {
                    this.widgetParent.enregistreQuestion(this.index);
                }
                if("correction" in this.widgetParent.controleurs) {
                    this.widgetParent.controleurs.correction.noeuds.hide();
                }
                parent_activeSegment.apply(this, arguments);
                this.noeuds[undefined === this.index ? 'addClass' : 'removeClass']('affiche-resultats');
            };


            proto.metAJourBoutons = function(modifications) {
                var remplis = modifications.remplis;
                if(remplis) {
                    for(var question in remplis) {
                        if(remplis[question]) {
                            this.controleurs.boutonsNav[question].noeuds.addClass(this.classeQuestionRepondue);
                        } else {
                            this.controleurs.boutonsNav[question].noeuds.removeClass(this.classeQuestionRepondue);
                        }
                    }
                }

                var corriges = modifications.corriges;
                if(corriges) {
                    for(var question in corriges) {
                        var question_reussie = 1;
                        for(var champ in corriges[question]) {
                            if("messageCorrige" == champ) continue;
                            if(!corriges[question][champ].bon) {
                                question_reussie = 0;
                                break;
                            }
                        }
                        this.controleurs.boutonsNav[question].noeuds.addClass(this.classesQuestionCorrigee[question_reussie]);
                    }
                }
            };

            constructeur.prototype.factory("sequences.controleurs.BarreNav", 
                                          controleurs.QuizBarreNav);
            constructeur.prototype.factory('sequences.controleurs.Precedent', controleurs.QuizPrecedent);
            constructeur.prototype.factory('sequences.controleurs.Suivant',   controleurs.QuizSuivant);
            constructeur.prototype.factory('sequences.controleurs.Debut', controleurs.QuizDebut);
            constructeur.prototype.factory('sequences.controleurs.Fin',   controleurs.QuizFin);

            return extensions.quizPrecSuivComplement(constructeur);
        })();



        widgets.interactivites.Quiz2 = (function() {
            var parent_constructeur = widgets.interactivites.Formulaire;
            var constructeur = sofad.sousType( parent_constructeur, function() {
                parent_constructeur.apply(this, arguments);

                for(var ii=0; ii<this.enfants.length; ++ii) {
                    if("Sequence" == this.enfants[ii].nomWidget) {
                        this.sequence = this.enfants[ii];
                    } else if ("Questionnaire" == this.enfants[ii].nomWidget) {
                        this.questionnaire = this.enfants[ii];
                    }
                }
                if(!(('sequence' in this) && ('questionnaire' in this))) {
                    throw sofad.ExceptionAucunSousWidget(this);
                }

                this.controleurs.but          = new (this.factory("interactivites.controleurs.ButQuiz"))(this);
                this.controleurs.boutonLancer = new (this.factory("interactivites.controleurs.BoutonLancerQuiz"))(this.controleurs.but);
                this.controleurs.boutonCorrection = new (this.factory("interactivites.controleurs.BoutonCorrectionQuiz"))(this.sequence.controleurs.barreNav);
                this.controleurs.boutonSuspendre = new (this.factory("interactivites.controleurs.BoutonSuspensionQuiz"))(this.sequence.controleurs.barreNav);
            } );


            var proto     = constructeur.prototype;
            proto.requete = '.type-quiz2';
            proto.requeteLiensSortie = 'a:not(.popup, .aide, a[@href^=#])';
            proto.htmlIndicateurChargement    = '<img class="indicateur-chargement" alt="{L:questionnaires.enregistre_ajax_encours}" src="{0}ajax-loader.gif" />';
            proto.requeteIndicateurChargement = '.indicateur-chargement';
                

            proto.factory('sequences.widgets.Sequence',      widgets.SequenceQuiz);
            proto.factory('questionnaires.widgets.Question', widgets.QuestionQuiz);
            proto.alert = function(m)   { return alert(m); };
            proto.confirm = function(m, foui, fnon) {
                if(!fnon) fnon = function () {};
                return confirm(m) ? foui() : fnon();
            };

            proto.attacheSurveillanceCompletion = function() {};

            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                this.sequence.noeuds.hide();
                this.questionnaire.noeuds.hide();

                var that = this;
                this.controleurs.boutonLancer.noeuds.bind("click", function() {
                    if(jQuery('body.page-demo').length) {
                        that.alert(jQuery(this).attr('title'));  
                        return false;  
                    }
                    that.comportement.lance(); return false;
                });
                this.controleurs.boutonCorrection.noeuds.bind("click", function() {
                    that.comportement.correctionQuiz(); return false;
                });
                this.controleurs.boutonSuspendre.noeuds.bind("click", function() {
                    that.comportement.suspend(); return false;
                });

                //Ne pas envoyer le form lorsqu'on appuie sur Entree
                jQuery(document).keypress(function(e) {
                    if(13 == e.which) return false;
                });
                jQuery('textarea').keypress(function(e) {
                    if(13 == e.which) e.stopPropagation();
                });

                this.changeComportement('ferme');
            };


            proto.changeComportement = function(nom_comportement, args) {
                this.comportement = new (this.comportements[nom_comportement])(this, args);
            };


            proto.enregistreQuestion = function(index) {
                this.comportement.enregistreQuestion(index);
            };
            

            proto.metAJourBoutons = function(changements) {
                this.comportement.metAJourBoutons(changements);
            };


            proto.service = function(params, callback, frere_indicateur_chargement, etouffe_erreur) {
                var that = this;                
                var callback_decore;

                if(frere_indicateur_chargement && frere_indicateur_chargement.length) {
                    frere_indicateur_chargement.after(sofad.lang(sofad.format(this.htmlIndicateurChargement, sofad.chemins.images)));
                    callback_decore = function () {
                        frere_indicateur_chargement.parent().find(that.requeteIndicateurChargement).remove();
                        callback.apply(this, arguments);
                    }
                } else {
                    callback_decore = callback;
                }

                params.idQuiz = this.idClient();
                jQuery.post(sofad.chemins.serviceQuiz, params, function(reponse) {
                    if(!etouffe_erreur && reponse.erreur) {
                        return that.alert(reponse.message);
                    }
                    
                    callback_decore.apply(null, arguments);
                }, "json");
            };

            proto.videChamps = function() {
                for(var ii=0; ii<this.questionnaire.enfants.length; ++ii) {
                    this.questionnaire.enfants[ii].videChamps();
                }
            }
            
            proto.comportements = {
                ferme: (function () {
                    var constructeur = function(quiz) {
                        this.quiz = quiz;
                        this.quiz.questionnaire.noeuds.hide();
                        this.quiz.controleurs.but.noeuds.show();
                        this.quiz.controleurs.boutonCorrection.noeuds.hide();
                        this.quiz.controleurs.boutonSuspendre.noeuds.hide();
                        this.quiz.controleurs.boutonLancer.noeuds.show();
                    };

                    constructeur.prototype = {
                        lance: function() {
                            var that = this;
                            this.quiz.controleurs.boutonLancer.noeuds.attr("disabled", true);
                            this.quiz.service(
                                {mode: 'lance'},
                                function(reponse) {
                                    if(reponse.vide_champs) {
                                        that.quiz.videChamps();
                                    }
                                    if(1 == reponse.est_lance) {
                                        if(reponse.correction_seulement) {
                                            that.lanceCorrectionSeulement(reponse);
                                        } else {
                                            that.lanceReussi(reponse);
                                        }
                                    } else if('prevoir_secondes_allouees' in reponse) {
                                        that.lanceChrono(reponse);
                                    } else {
                                        that.lanceEchec(reponse.message);
                                    }
                                },
                                this.quiz.controleurs.boutonLancer.noeuds);
                        },

                        lanceReussi: function(reponse) {
                            this.quiz.changeComportement('ouvert', [reponse]);
                            this.quiz.comportement.chargeEtat(reponse);
                            this.quiz.controleurs.boutonLancer.noeuds.attr("disabled", false);
                        },

                        lanceCorrectionSeulement: function(reponse) {
                            this.quiz.changeComportement('ouvert', [reponse]);
                            this.quiz.comportement.chargeEtat(reponse);
                            this.quiz.changeComportement('corrige', [reponse.message]);
                            this.quiz.controleurs.boutonLancer.noeuds.attr("disabled", false);
                        },

                        lanceEchec: function(message) {
                            this.quiz.controleurs.but.noeuds.hide();
                            this.quiz.controleurs.boutonLancer.noeuds.hide();
                            this.quiz.controleurs.boutonLancer.noeuds.attr("disabled", false);
                            this.quiz.controleurs.msgEchec = new (this.quiz.factory("interactivites.controleurs.MsgEchecQuiz"))(this.quiz, message);
                        },

                        lanceChrono: function(reponse) {
                            secondes_allouees = Number(reponse.prevoir_secondes_allouees);
                            secondes_compte_rebours = 'secondes_compte_rebours' in reponse ?
                                reponse.secondes_compte_rebours :
                                false;                                        
                            
                            var that = this;
                            that.quiz.service(
                                {mode: 'lance',
                                 secondes_allouees_prevues: secondes_allouees},
                                function(reponse) {
                                    if(1 == reponse.est_lance) {
                                        if(reponse.vide_champs) {
                                            that.quiz.videChamps();
                                        }
                                        that.quiz.changeComportement('ouvert', [reponse]);
                                        that.quiz.comportement.chargeEtat(reponse);
                                        that.quiz.comportement.chargeChronometre(secondes_allouees, secondes_compte_rebours);
                                    } else {
                                        that.lanceEchec(reponse.message);
                                    }
                                    that.quiz.controleurs.boutonLancer.noeuds.attr("disabled", false);
                                });

                        }
                    };

                    return constructeur;
                })(),


                ouvert: (function() {
                    var constructeur = function(quiz) {
                        this.quiz = quiz;
                        this.quiz.controleurs.but.noeuds.hide();
                        this.quiz.controleurs.boutonLancer.noeuds.hide();
                        this.quiz.controleurs.boutonCorrection.noeuds.show();
                        this.quiz.controleurs.boutonSuspendre.noeuds.hide();
                        this.quiz.sequence.noeuds.show();
                        this.quiz.questionnaire.noeuds.show();
                        this.brancheConfirmationSurSortie();
                        
                    };

                    constructeur.prototype = {
                        chargeChronometre: function(secondes_allouees, secondes_compte_rebours) {
                            this.departChrono     = new Date();
                            this.dureeCompteRebours = secondes_compte_rebours;

                            
                            var that = this;
                            this.chrono = setInterval(function() {
                                that.secondesEcoulees = (new Date() - that.departChrono) / 1000;

                                if(that.dureeCompteRebours &&
                                   that.dureeCompteRebours >= (secondes_allouees - that.secondesEcoulees)) {
                                    if(!('compteRebours' in that.quiz.controleurs)) {
                                        that.quiz.alert( sofad.format( sofad.lang("{L:interactivites.quiz_rebours_commence}"),
                                                                       Math.round(that.dureeCompteRebours / 60) ) );

                                        that.quiz.controleurs.compteRebours = 
                                            new (that.quiz.factory("interactivites.controleurs.CompteReboursQuiz"))
                                        (that.quiz.sequence.controleurs.barreNav);
                                    }
                                    that.quiz.controleurs.compteRebours.metAJour(secondes_allouees - that.secondesEcoulees);
                                }
                                if(that.secondesEcoulees >= secondes_allouees) {
                                    that.debrancheConfirmationSurSortie();
                                    that.debrancheChronometre();
                                    that.quiz.changeComportement("tempsEcoule");
                                }
                            }, 500);
                        },

                        tempsEpuiseImprevu: function(reponse) {
                            this.quiz.alert(sofad.lang('{L:interactivites.quiz_temps_ecoule}'));
                            this.debrancheConfirmationSurSortie();
                            this.debrancheChronometre();
                            if('sans-corrige' == sofad.interactivites.obtientType(this.quiz).sousType) {
                                this.metAJourBoutons(reponse);
                            } else {
                                this.chargeEtat(reponse); 
                            }
                            this.quiz.changeComportement("corrige", [reponse.message]);
                        },
                        
                        debrancheChronometre: function() {
                            clearInterval(this.chrono);
                            if('compteRebours' in this.quiz.controleurs) {
                                this.quiz.controleurs.compteRebours.noeuds.remove();
                                delete this.quiz.controleurs.compteRebours;
                            }
                        },

                        brancheConfirmationSurSortie: function() {
                            var that = this;
                            
                            this.quiz.noeuds.find(this.quiz.requeteLiensSortie).bind('click.quiz2', function() {
                                var lien = this;
                                that.quiz.confirm(sofad.lang("{L:interactivites.confirmation_quitter_quiz}"), function() {
                                    window.open(lien.href, lien.target || "_self"); 
                                });
                                return false;
                            });
                            
                            var menu_page = this.quiz.noeuds.find('#pagenav select');
                            if(menu_page.length) {
                                this.fnMenuPage = menu_page[0].onchange;
                                menu_page[0].onchange = null;
                                this.quiz.noeuds.find('#pagenav select').bind('change.quiz2', function() {
                                    that.quiz.confirm(sofad.lang("{L:interactivites.confirmation_quitter_quiz}"), function() {
                                        that.fnMenuPage.apply(this);
                                    });
                                });
                            }
                        },

                        debrancheConfirmationSurSortie: function() {
                            this.quiz.noeuds.find(this.quiz.requeteLiensSortie).unbind('click.quiz2');
                            if(this.fnMenuPage) {
                                this.quiz.noeuds.find('#pagenav select')[0].onchange = this.fnMenuPage;
                            }
                        },

                        enregistreQuestion: function(index, fn, emplacement_indicateur) {
                            this.quiz.questionnaire.enfants[index].enregistre(fn, emplacement_indicateur);
                        },

                        suspend: function() {
                            var that = this;
                            this.quiz.confirm(sofad.lang("{L:interactivites.confirmation_suspension_quiz}"), function() {
                                that.quiz.service({mode: "suspend"},
                                                  function(reponse) {
                                                      if(!reponse.est_suspendu) return that.quiz.alert("Erreur : demande de suspension refusée");
                                                      that.debrancheConfirmationSurSortie();
                                                      that.debrancheChronometre();
                                                      that.quiz.changeComportement("ferme");
                                                  });                            
                            });                            
                            return false;
                        },

                        chargeEtat: function(reponse_service) {
                            if("corriges" in reponse_service) {
                                for(var question in reponse_service.corriges) {
                                    this.quiz.questionnaire.enfants[question].appliqueCorrige( reponse_service );
                                }
                            }
                            this.metAJourBoutons(reponse_service);
                            if(reponse_service.suspension_permise) {
                                this.quiz.controleurs.boutonSuspendre.noeuds.show();
                            }
                        },

                        correctionQuiz: function() {
                            var that = this;
                            var emplacement_indicateur = this.quiz.controleurs.boutonCorrection.noeuds;
                            emplacement_indicateur.attr("disabled", true);
                            var ranime_bouton = function() { emplacement_indicateur.attr("disabled", false); };
                            this.enregistreQuestion( this.quiz.sequence.index, function() {
                                that.quiz.service({mode: "corrigeQuiz"},
                                                  function(reponse) {
                                                      if('sans-corrige' == sofad.interactivites.obtientType(that.quiz).sousType) {
                                                          that.metAJourBoutons(reponse);
                                                      } else {
                                                          that.chargeEtat(reponse); 
                                                      }
                                                      
                                                      ranime_bouton();
                                                      if(reponse.correctionAcceptee) {
                                                          that.debrancheConfirmationSurSortie();
                                                          that.debrancheChronometre();
                                                          that.quiz.changeComportement("corrige", [reponse.message]);
                                                      } else {
                                                          that.quiz.alert(reponse.message);
                                                      }
                                                  }, emplacement_indicateur);
                            }, emplacement_indicateur );
                        },

                        metAJourBoutons: function(changements) {
                            this.quiz.sequence.metAJourBoutons(changements);
                        }
                    };

                    return constructeur;
                })(),


                corrige: (function() {
                    var constructeur = function(quiz, args) {
                        this.quiz = quiz;
                        this.quiz.controleurs.boutonSuspendre.noeuds.hide();
                        this.quiz.controleurs.boutonCorrection.noeuds.css("display", "");
                        this.quiz.controleurs.correction = new (this.quiz.factory("interactivites.controleurs.CorrectionQuiz"))(this.quiz.sequence, [args[0]]);
                        for(var nom_widget in sofad.surfenetres.widgets.surfenetres) {
                            var widgets = sofad.batiWidgets( sofad.surfenetres.widgets.surfenetres[ nom_widget ], this.quiz.controleurs.correction );
                            for(var ii=0; ii<widgets.length; ++ii) widgets[ii].demarre();
                        }

                        this.quiz.noeuds.find("input, select").attr("disabled", true);
                        this.correctionQuiz();
                    };

                    constructeur.prototype = {
                        enregistreQuestion: function() {},

                        correctionQuiz: function() {
                            this.quiz.sequence.activeSegment(false);
                            this.quiz.controleurs.correction.noeuds.show();
                        },

                        metAJourBoutons: function(changements) {
                            this.quiz.sequence.metAJourBoutons(changements);
                        }

                    };

                    return constructeur;
                })(),

                tempsEcoule: (function() {
                    var constructeur = function(quiz, args) {
                        this.quiz = quiz;
                        this.quiz.controleurs.boutonSuspendre.noeuds.hide();
                        this.quiz.controleurs.boutonCorrection.noeuds.hide();
                        this.quiz.noeuds.find("input, select").attr("disabled", true);

                        this.quiz.alert(sofad.lang('{L:interactivites.quiz_temps_ecoule}'));

                        var that = this;
                        var est_ecoule = false;
                        var emplacement_indicateur = this.quiz.controleurs.boutonCorrection.noeuds;
                        var interval = setInterval(function() {
                            that.quiz.service({mode: "corrigeQuiz"},
                                              function(reponse) {
                                                  if(est_ecoule) return;
                                                  if('sans-corrige' == sofad.interactivites.obtientType(that.quiz).sousType) {
                                                      that.metAJourBoutons(reponse);
                                                  } else {
                                                      that.chargeEtat(reponse); 
                                                  }
                                                  
                                                  if(reponse.correctionAcceptee) {
                                                      est_ecoule = true;
                                                      clearInterval(interval);
                                                      that.quiz.changeComportement("corrige", [reponse.message]);
                                                  }
                                              }, undefined, true);
                        }, 500);
                    };

                    constructeur.prototype = {
                        enregistreQuestion: function() {},

                        correctionQuiz: function() {},

                        chargeEtat: function(reponse_service) {
                            if("corriges" in reponse_service) {
                                for(var question in reponse_service.corriges) {
                                    this.quiz.questionnaire.enfants[question].appliqueCorrige( reponse_service );
                                }
                            }

                            this.metAJourBoutons(reponse_service);

                            if(reponse_service.suspension_permise) {
                                this.quiz.controleurs.boutonSuspendre.noeuds.show();
                            }
                        },

                        metAJourBoutons: function(changements) {
                            this.quiz.sequence.metAJourBoutons(changements);
                        }

                    };

                    return constructeur;
                })()

            };


            return constructeur;
        })();


        controleurs.BoutonLancerQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'button.lancer-quiz';
            if(jQuery('body.page-demo').length) {
                constructeur.prototype.html    = sofad.lang("<p class='lancer-quiz'><button title='{L:interactivites.btn_quiz_demo_inactif}' class='lancer-quiz'>{L:interactivites.btn_lancer_quiz}</button></p>");
            } else {
                constructeur.prototype.html    = "<p class='lancer-quiz'><button class='lancer-quiz'>{L:interactivites.btn_lancer_quiz}</button></p>";
            }
            return constructeur;
        })();


        controleurs.BoutonCorrectionQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'button.correction-quiz';
            constructeur.prototype.html    = "<button class='correction-quiz'>{L:interactivites.btn_correction_quiz}</button>";
            return constructeur;
        })();


        controleurs.BoutonSuspensionQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'button.suspension-quiz';
            constructeur.prototype.html    = "<button class='suspension-quiz'>{L:interactivites.btn_suspension_quiz}</button>";
            return constructeur;
        })();


        controleurs.ButQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'div.but';
            constructeur.prototype.html    = "";
            return constructeur;
        })();


        controleurs.CorrectionQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'div.correction-quiz';
            constructeur.prototype.html    = "<div class='correction-quiz'>{0}</div>";
            constructeur.prototype.insere = function(widget_parent) {
                widget_parent.controleurs.barreNav.noeuds.after( this.renduHtml() );
            };
            return constructeur;
        })();


        controleurs.MsgEchecQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'div.msg-echec';
            constructeur.prototype.html    = "<div class='msg-echec'>{0}</div>";
            constructeur.prototype.insere  = function(widget_parent) { widget_parent.questionnaire.noeuds.before(this.renduHtml()); }; 
            return constructeur;
        })();


        controleurs.FeedbackInlineQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'td.feedback-inline > div';
            constructeur.prototype.html    = "<div>{0}</div>";
            constructeur.prototype.insere  = function(widget_parent) { widget_parent.noeuds.find("td.feedback-inline").append(this.renduHtml()); }; 
            return constructeur;
        })();

        controleurs.BlocCorrigeQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'div.corrige';
            constructeur.prototype.html    = "<div class='corrige'>{0}</div>";
            return constructeur;
        })();


        controleurs.CompteReboursQuiz = (function() {
            var constructeur = sofad.sousType( sofad.controleurs.Controleur );
            constructeur.prototype.requete = 'span.compte-rebours';
            constructeur.prototype.html    = " <span class='compte-rebours'></span>";
            constructeur.prototype.texte   = "{0}:{1}";

            constructeur.prototype.metAJour = function(secondes_restantes) {
                var secondes_formatte = ""+ Math.floor(secondes_restantes%60);
                var minutes_formatte  = ""+ Math.floor(secondes_restantes/60);
                if(1 == secondes_formatte.length) secondes_formatte = "0" + secondes_formatte;
                if(1 == minutes_formatte.length)  minutes_formatte  = "0" + minutes_formatte;

                this.noeuds.text(sofad.format(this.texte, minutes_formatte, secondes_formatte));
            };
            return constructeur;
        })();
        



        /* QUIZ */

        extensions.radioQuiz = function(original) {
            var constructeur = sofad.questionnaires.extensions.radioFeedback( original );
            constructeur     = sofad.questionnaires.extensions.radioCorrectionImmediate( constructeur );
            constructeur     = sofad.questionnaires.extensions.radioCorrigeEnregistre( constructeur );
            return constructeur;
        };


        
        /* ACTIVITES NOTEES */

        widgets.ChampPointage = (function() {
            var constructeur = sofad.questionnaires.extensions.affichePointageImmediat( sofad.questionnaires.widgets.Element, 'change' );
            var proto     = constructeur.prototype;
            proto.alert   = function(m) { return alert(m); };
            proto.requete = 'input:text.champ-note-partielle, input:text.app-champ-note-partielle';
            proto.requetePonderation = '.note-maximum';
            proto.msgHorsLimite = 'Les notes doivent être comprises entre zéro et leur maximum, sauf pour les bonis.';

            proto.ponderation = function() { 
                return this.noeuds.parent().find(this.requetePonderation).text(); 
            };

            proto.points  = function() {
                var points = [0, Number(this.ponderation())];
                var valeur = this.noeuds[0].value.replace(',', '.');
                if(!isNaN( valeur )) {
                    points[0] = Number(valeur);
                    this.noeuds[0].value = (""+valeur).replace('.', ',');
                }
                return points;
            };

            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                var that = this;
                this.noeuds.bind('change', function() {
                    var points = that.points();
                    if(points[0] < 0 || points[0] > points[1]) {
                        that.alert(that.msgHorsLimite);
                    }
                });
            };

            return constructeur;
        })();


        widgets.QuestionnairePointage = (function() {
            var constructeur = sofad.questionnaires.extensions.affichagePointage( sofad.questionnaires.widgets.Questionnaire );
            var proto = constructeur.prototype;
            proto.typesEnfants = sofad.copie( proto.typesEnfants );
            proto.typesEnfants.champPointage = 'interactivites.widgets.ChampPointage';
            proto.enfantsRequis = false;
            return constructeur;
            
        })();


        widgets.interactivites.ActiviteNotee = (function() {
            var constructeur = sofad.sousType( sofad.widgets.Widget, function() {
                sofad.widgets.Widget.apply(this, arguments);
                this.controleurs.btnTransmettreFmt = new (this.factory('interactivites.controleurs.BoutonTransmettreFmt'))(this);
                this.controleurs.btnTransmettreApp = new (this.factory('interactivites.controleurs.BoutonTransmettreApp'))(this);
                this.estModifie = false;
            } );
            var proto = constructeur.prototype;
            proto.alert   = function(m) { return alert(m); };
            proto.confirm = function(m, foui, fnon) {
                if(!fnon) fnon = function () {};
                return confirm(m) ? foui() : fnon();
            };
            proto.requete = 'body.type-activite-notee';
            proto.typesEnfants = {questionnairePointage: 'interactivites.widgets.QuestionnairePointage'};

            var aff_pt = sofad.sousType( sofad.questionnaires.controleurs.AfficheurPointage );
            aff_pt.prototype.requete = 'input:text.champ-note, input:text.app-champ-note';
            aff_pt.prototype.insere  = function() {};
            aff_pt.prototype.affiche   = function(pointage) { 
                if(!this.noeuds.length) return;
                this.noeuds[0].value = (""+pointage[0]).replace('.', ',');
            };
            proto.factory( 'questionnaires.controleurs.AfficheurPointage', aff_pt );

            proto.champsVides = function() {
                return this.noeuds.find('textarea:not([name$=commentaire-partiel]), \
                                         input:text:not(.champ-note, .app-champ-note, .champ-note-partielle, .app-champ-note-partielle)').filter( function() {
                    return ""==this.value;
                });
            };

            var parent_demarre = proto.demarre;
            proto.demarre = function() {
                parent_demarre.apply(this, arguments);
                var that = this;
                this.controleurs.btnTransmettreFmt.noeuds.bind("click", function() {
                    if(!that.champsVides().length || jQuery('.page-demo').length) return true;
                    that.alert(sofad.lang("{L:interactivites.activite_notee_questions_vides}") + that.champsVides().attr('name'));
                    return false;
                });
                this.controleurs.btnTransmettreApp.noeuds.bind("click", function() {
                    var bouton = jQuery(this);
                    if(bouton.hasClass('confirme') || 
                       !that.noeuds.find('input:text[name$=-fmt-note-partielle]').filter( function() {return ""==this.value;} ).length) return true;
                    
                    that.confirm(sofad.lang("{L:interactivites.activite_notee_notes_vides}"), function() {
                        bouton.addClass('confirme');
                        setTimeout(function() { bouton.click(); }, 10);
                    });
                    return false;
                });

                

                //Bouton Entree - controler le bouton "submit" active si on appuie sur Entree
                jQuery(document).keypress(function(e) {
                    if(e.which != 13 ||
                       that.noeuds.filter('.page-demo').length ||
                       !that.noeuds.find(".btn-enregistrer, .btn-transmettre").length) return;
                    
                    var btns_enregistrer = that.noeuds.find('input:submit[name$=-btn-enregistrer]');
                    if(btns_enregistrer.length) {
                        that.enfants[0].affichePointage();
                        that.noeuds.find('input:submit[name$=-btn-enregistrer]:eq(0)').click();
                    }
                    return false;
                });
                jQuery('textarea').keypress(function(e) {
                    if(13 == e.which) e.stopPropagation();
                });

                //monitorer si l'activite a ete modifiee
                this.noeuds.find("textarea, input:text, input:radio").change(function() {
                    that.estModifie = true;
                });

                this.noeuds.find(".btn-enregistrer, .btn-transmettre").click(function() {
                    that.estModifie = false;
                });

                //avertissement delai
                if(!that.noeuds.filter('.page-demo').length &&
                   that.noeuds.find(".btn-enregistrer, .btn-transmettre").length) {
                    this.chronoAvertissement = setTimeout(function() {
                        that.alert(sofad.lang("{L:interactivites.avertissement_sauvegarde}"));
                    }, 15 * 60 * 1000);
                }

            };

            return constructeur;
        })();


        //Controleurs

        controleurs.BoutonTransmettreFmt = (function () {
            var constructeur = sofad.sousType(sofad.controleurs.Controleur);
            constructeur.prototype.requete   = '*[name$=-btn-transmettre-vers-fmt]';
            constructeur.prototype.html      = '';
            constructeur.prototype.insere    = function(widget_parent) {};
            return constructeur;
        })();

        controleurs.BoutonTransmettreApp = (function () {
            var constructeur = sofad.sousType(controleurs.BoutonTransmettreFmt);
            constructeur.prototype.requete   = '*[name$=-btn-transmettre-vers-app]';
            return constructeur;
        })();

        controleurs.BoutonCorrigeResumer = (function () {
            var constructeur = sofad.sousType(sofad.controleurs.Controleur);
            constructeur.prototype.requete   = 'button.btn-corrige-resumer';
            constructeur.prototype.html      = '<button class="btn-corrige-resumer">{L:interactivites.resumer_btn_corrige}</button>';
            constructeur.prototype.insere  = function(widget_parent) {
                widget_parent.noeuds.prepend( this.renduHtml() );
            };
            return constructeur;
        })();


        controleurs.BoutonEnregistreResumer = (function () {
            var constructeur = sofad.sousType(sofad.controleurs.Controleur);
            constructeur.prototype.requete   = 'button.btn-enregistre-resumer';
            constructeur.prototype.html      = '<button class="btn-enregistre-resumer">{L:interactivites.resumer_btn_enregistre}</button>';
            constructeur.prototype.insere  = function(widget_parent) {
                widget_parent.noeuds.prepend( this.renduHtml() );
            };
            return constructeur;
        })();



        controleurs.BoutonReinitResumer = (function () {
            var constructeur = sofad.sousType(sofad.controleurs.Controleur);
            constructeur.prototype.requete   = 'button.btn-reinit-resumer';
            constructeur.prototype.html      = '<button class="btn-reinit-resumer">{L:interactivites.resumer_btn_reinit}</button>';
            constructeur.prototype.insere  = function(widget_parent) {
                widget_parent.noeuds.prepend( this.renduHtml() );
            };
            return constructeur;
        })();



    } catch(e) {
        if(e.name && 'AucunSousWidget' == e.name) {
            sofad.exposeExceptionAucunSousWidget(e);
        } else {
            alert("exception : " + e);
        }
    }
});


function interactiviteCompletee(resultat) {
    jQuery.getJSON(sofad.chemins.serviceQuestionnaire,
                   {mode: "insere",
                    resultat: resultat,
                    id_client: jQuery('body').attr('id').substr(5)});

};


