Éviter de perdre le contenu rédigé sur le web, revu et corrigé
Cet après-midi, j'ai eu à apporter des modifications à un projet utilisant le framework JavaScript Prototype. Après un coup d'oeil rapide sur le projet, j'ai remarqué qu'il y avait un formulaire spécifique que l'utilisateur devait remplir et que la rédaction en ligne à l'intérieur d'un RTE pouvait représenter beaucoup de travail. Pour une raison qui m'a semblé évidente, je me suis dit que j'allais intégrer le snippet de code dont j'avais déjà parlé pour éviter de perdre le contenu rédigé en cas d'erreur de navigation (bouton back, cliquer sur un lien de navigation, etc). En intégrant ce code, ça permet d'offrir à l'utilisateur une dernière chance avant de changer de page.
De plus, le formulaire contenait un champ RTE avec le composant CKeditor. Petite anecdote sur CKeditor si vous ne la connaissez pas déjà : le nom original était FCKeditor, et provenait des initiales du nom de son créateur, Frederico Caldeira Knabben. Or, comme il l'a lui-même expliqué, au moment de lancer la version 3, il a rebaptisé son composant CKeditor en retirant la lettre F car ça causait un malaise chez certaines personnes dû à la ressemblance avec un "bad word" anglais (F*CK). Tous les détails ici. Passez le mot à la compagnie de voitures Audi, eux qui ont réussi à nommer un modèle E-Tron. En tant que francophone, je ressens un léger inconfort :-)
Je disais donc que je voulais protéger le formulaire contre la perte de données au cas où l'utilisateur changeait de page par accident. Je me suis fié au code de mon billet et j'ai testé. Un problème est apparu sur la ligne où Event.stopObserving est appelé. Cette ligne de code sert à retirer la vérification avant de soumettre le formulaire. En postant les données sur le serveur, un changement ou un rafraîchissement de page est nécessaire et on ne veut surtout pas embêter l'utilisateur avec un popup s'il clique volontairement sur le bouton Enregistrer!
JavaScript lance une erreur à travers la console de Firebug :
L.stopObserving is not a function
Pourtant, la documentation de Prototype est formelle : depuis la version 1.6, il existe 3 façons de désinscrire un événement de l'observateur. La version utilisée dans le projet ? 1.6.0.3. Alors pourquoi est-ce que ça ne marche pas alors qu'en avril dernier, lorsque j'ai écrit mon billet, ça fonctionnait bien ? J'ai trouvé la solution sur le forum de Prototype dans Google Groups. Le bogue est expliqué et la solution est de le mettre à jour pour la version la plus récente. Du coup, l'erreur disparaissait sous Prototype 1.6.1 (paru en sept.2009).
Pour CKeditor, je voulais plus particulièrement détecter si le contenu du RTE avait été modifié. Avec FCK 2.x, on pouvait appeler la fonction isDirty() pour vérifier si le contenu de l'éditeur avait changé. Depuis CK 3.x, la même fonction a été renommée checkDirty().
var editor = CKEDITOR.replace('rte_id', {C'est certain que pour cet exemple-ci, je ne fais que vérifier le champ le plus important, là où la majorité des efforts de rédaction sont concentrés. L'idéal serait de pouvoir faire la vérification pour l'ensemble du formulaire mais ce n'était pas nécessaire ici. Si compléter le formulaire prend du temps, malgré cette précaution, le plus fâchant est de perdre son travail au moment de l'enregistrer parce que la session est expirée. Assurez-vous d'augmenter suffisamment sa durée de vie et si possible, de trouver un moyen pour la maintenir active, par exemple avec une routine qui lance un appel AJAX à intervalle régulier.
toolbar : 'Basic',
defaultLanguage : 'fr',
language : 'fr',
});
Event.observe(window, 'beforeunload',
function(event){
if( editor.checkDirty() ){
event.returnValue = "Oups... le contenu du RTE a changé et n'a pas été enregistré!";
}
}
);