Plugin multitâche : méthode de construction personnelle et exemples

Adapter jQuery à vos besoins, niveau 2

Daniel Hagnoul

La plupart des plugins exécutent une seule tâche et les méthodes d'écriture de plugin utilisées dans « Mon Cahier d'exercices », dans la FAQ jQuery et dans l'article « Adapter jQuery à vos besoins » couvrent la majorité des besoins. Lorsque l'on souhaite inclure la modification des options et implémenter plusieurs méthodes on doit penser multitâche. Dans cet article, j'explique la méthode de construction que j'utilise et je donne trois exemples de plugins multitâches.
Commentez

- Titre : Plugin multitâche : méthode de construction personnelle et exemples

- Auteur : Daniel Hagnoul

- Parution : 16 mars 2012

- Mise à jour : 16 mars 2012

- Licence : Le contenu de cet article est rédigé par Daniel Hagnoul et est mis à disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transposé. Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright ® 2013 Developpez.com.

Sommaire

- I. Prérequis

- II. Introduction

- III. La méthode de construction

- III-A. La structure d'un plugin

- III-B. La fonction dvjhPluginCreate

- III-C. Squelette d'un objet méthodes

- IV. Les exemples

- IV-A. Le plugin dvjhTourne

- IV-B. Le plugin dvjhEventShow

- IV-C. Le plugin dvjhStorage

- V. Remerciements

I - Prérequis

Cet article est basé sur l'acquis après la lecture de l'article : « Adapter jQuery à vos besoins » et de ses prérequis.

De plus, le lecteur doit avoir une bonne maîtrise du JavaScript et de la bibliothèque jQuery, car il ne trouvera aucune aide sur les techniques réputées acquises dans cet article.

II - Introduction

On peut trouver sur le Web de nombreuses méthodes pour écrire un plugin multitâche.

Le guide officiel résume l'essentiel des bonnes pratiques, mais il ne s'agit que d'un point de départ. Il promeut l'usine de construction de widget UI, mais plusieurs auteurs trouvent cette méthode lourde et contraignante.

Plusieurs méthodes de construction utilisent une technique particulière pour résoudre un aspect particulier. Certains auteurs préfèrent mettre l'accent sur l'écriture de modules, sur l'utilisation de prototypes, sur l'utilisation des événements, etc.

Il n'existe pas un modèle idéal applicable en toutes circonstances et la méthode utilisée peut avoir une grande influence sur les performances, sur la lisibilité et sur la maintenabilité du code de votre plugin.

Addy Osmani a recensé et étudié les approches principales, j'ai résumé ci-dessous les principales qualités recherchées par les auteurs de méthodes de plugin.

La méthode de construction doit :

1. S'intégrer dans un espace de noms ou permettre l'usage d'un espace de noms ;

2. Cacher la « plomberie » et « automatiser » les tâches répétitives ;

3. Placer la logique du plugin dans un objet séparé du « système de construction » du plugin pour améliorer la lisibilité et la maintenabilité ;

4. Permettre la gestion de propriétés, d'objets, et de méthodes publiques et privées ;

5. Offrir une méthode versatile pour l'initialisation de l'instance (un objet jQuery) ;

6. Empêcher l'initialisation multiple ;

7. Offrir une méthode pour la destruction de l'instance ;

8. Sauvegarder l'état (les options) de l'instance ;

9. Être capable de gérer et de déclencher des événements, ce qui permet une utilisation asynchrone par un système de souscription et de publication d'événements ;

10. Permettre la définition et la modification des options par défaut ;

11. Permettre la définition d'options par l'intermédiaire d'un attribut data HTML5. Ce qui permet l'initialisation d'une collection d'instances avec les options par défaut, suivi d'une personnalisation par instance.

La méthode que j'ai mise au point respecte ce cahier des charges.

Ce n'est sans doute pas « La Méthode » (Addy Osmani conclut qu'il n'y en a pas) mais elle a deux qualités essentielles :

- elle a résisté à toutes les épreuves que je lui ai fait subir pendant plus de trois mois ;

- elle me convient bien.

Certes, le dernier argument n'est pas rationnel, mais à mes yeux c'est le principal et il est incontestable ! ;)

J'ai bien entendu des choses à reprocher aux autres méthodes, mais en dehors du fait que la plupart ne satisfont pas à mon cahier des charges, les autres arguments sont essentiellement subjectifs.

Pour tester les codes, veuillez charger le ZIP.

III - La méthode de construction

Le plugin multitâche appelle une fonction « universelle » qui gère l'appel aux méthodes d'un objet, que j'appelle simplement un objet méthodes, c'est lui qui contient l'intégralité du « savoir-faire » du plugin.

Par fonction « universelle », il faut comprendre que c'est la même fonction qui gère tous les dvjhPlugins.

Rappel : les fenêtres de code s'ouvrent en cliquant sur le bouton placé à droite.

III-A - La structure d'un plugin

Dans l'espace de nom dvjh (Adapter jQuery à vos besoins) on écrira :

Espace de nom

1. var dvjh = ( function( $ ){

3. // objet méthodes du plugin A

4. var dvjhPluginAMethods = {

5. };

7. // objet méthodes du plugin B

8. var dvjhPluginBMethods = {

9. };

11. /*

12. * Ajouts de méthodes (plugin) au prototype de l'objet jQuery ($.fn).

13. *

14. * Pour créer un dvjhPlugin il suffit de lui donner

15. * un nom et d'appeler la fonction dvjhPluginCreate dans le

16. * contexte du plugin.

17. * Les paramètres sont le nom de son objet méthodes et les

18. * arguments de l'utilisateur.

19. */

20. $.extend( $.fn, {

21. "dvjhPluginA" : function(){

22. return dvjhPluginCreate.call( this, dvjhPluginAMethods, arguments );

23. },

24. "dvjhPluginB" : function(){

25. return dvjhPluginCreate.call( this, dvjhPluginBMethods, arguments );

26. }

27. });

29. return {

30. "$" : $

31. };

33. })( jQuery.sub() );

III-B - La fonction dvjhPluginCreate

Cette fonction gère l'initialisation du plugin (avec ou sans options utilisateur, avec ou sans paramètres supplémentaires) et l'appel des méthodes du plugin (avec ou sans paramètres).

Si vous n'êtes pas un expert, je vous recommande de n'apporter aucune modification à cette méthode.

Toutes les instances du plugin sont traitées par un unique objet méthodes, chaque instance (jObj : un objet jQuery) doit par conséquent stocker une copie de son état (les options) dans jObj.data( objMethods._copyright.objMethodsName ).

Cet état est transmis à l'objet méthodes au début de l'action. Il est alors stocké temporairement dans l'objet options de l'objet méthodes. Lorsque l'action est terminée, l'état est sauvegardé dans l'instance et l'objet méthodes n'en conserve plus nulle trace.

Lors de l'initialisation, l'état de l'instance est constitué d'une copie des options par défaut et des options et paramètres transmis par l'utilisateur du plugin à la fonction d'initialisation de l'objet méthodes.

Chaque instance doit travailler sur sa copie des arguments (objMethods, method, params).

dvjhPluginCreate

1. /*

2. * Fonction "universelle" pour l'initialisation et l'appel des

3. * méthodes d'un plugin  multitâche.

4. *

5. * Ne pas copier-coller ni modifier sans nécessité.

6. */

7. var dvjhPluginCreate = function( objMethods, params ){

9. var args = Array.prototype.slice.call( params ),

10. method = args.shift();

12. // console.log( "dvjhPluginCreate, arguments : ", objMethods, method, args );

14. if ( ! objMethods ){

15. $.error( "dvjhPluginCreate : objMethods n'est pas défini !" );

16. }

18. if ( typeof method === "string" && method.slice( 0, 1 ) === "_" ){

19. $.error( "dvjhPluginCreate : les propriétés, les méthodes " +

20. "et les objets précédés d'un tiret bas (underscore) sont privés !" );

21. }

23. var boolOK, boolInit, boolDestroy, objOpts, jObj, cMethod, cParams,

24. name = objMethods._copyright.objMethodsName;

26. /*

27. * Attention ! Ici, this c'est l'objet jQuery !

28. *

29. * La valeur de this est particulière, elle

30. * correspond au sélecteur qui a créé le plugin.

31. * On ne doit donc jamais écrire $( this ) car

32. * cette écriture crée un $( $( selecteur ) ) inutile !

33. *

34. * Objet et array : attention chaque instance ($( item ),

35. * un objet jQuery) doit travailler sur sa copie.

36. *

37. * Les options de l'instance sont stockées dans l'instance

38. * (par data( name )). À l'initialisation, il s'agit d'une

39. * copie des options par défaut.

40. */

41. return this.each( function( i, item ){

42. boolOK = true;

43. boolInit = false;

44. boolDestroy = false;

45. objOpts = $( item ).data( name ) || null;

46. jObj = $( item );

48. if ( objOpts == null ){

49. boolInit = true;

50. jObj.data( name, $.extend( true, {}, objMethods._options ) );

51. objOpts = jObj.data( name );

52. }

54. if ( method ){

55. if ( $.isPlainObject( method ) ){

56. cMethod = $.extend( true, {}, method );

57. } else if ( $.isArray( method ) ){

58. cMethod = method.concat();

59. } else {

60. cMethod = method;

61. }

62. }

64. cParams = args.concat();

66. objMethods.options = objOpts; // important !

67. objMethods.jObj = $( item ); // important !

69. // debug

70. /*

71. console.log( "dvjhPluginCreate, boolOK : ", boolOK );

72. console.log( "dvjhPluginCreate, boolInit : ", boolInit );

73. console.log( "dvjhPluginCreate, jObj : ", jObj );

74. console.log( "dvjhPluginCreate, objOpts : ", objOpts );

75. console.log( "dvjhPluginCreate, objMethods.options : ",

76. objMethods.options );

77. console.log( "dvjhPluginCreate, cMethod, typeof cMethod : ",

78. cMethod, typeof cMethod );

79. console.log( "dvjhPluginCreate, cParams, $.isArray( cParams ) : ",

80. cParams, $.isArray( cParams ) );

81. */

83. if ( boolInit ){

84. if ( cMethod === "init" ){

85. objMethods[ cMethod ]( cParams );

86. } else if ( $.isPlainObject( cMethod ) || ! cMethod ){

87. objMethods.init( cMethod, cParams );

88. } else {

89. /*

90. * cMethod peut contenir un paramètre de n'importe

91. * quel type sauf un objet. Car si le premier argument

92. * est un objet il doit contenir les options de

93. * l'utilisateur.

94. *

95. * On peut passer un autre objet si l'on passe un objet

96. * anonyme vide comme premier argument, exemple :

97. * jObj.dvjhPlugin( {}, new Date() );

98. *

99. * On doit construire un nouvel array regroupant le

100. * contenu de cMethod et de l'array cParams.

101. */

102. var tab;

104. if ( typeof cMethod === "string" ||

105. typeof cMethod === "number" ){

106. tab = [ cMethod ];

107. } else {

108. tab = $.map( cMethod,

109. function( value, key ){ return value; } );

110. }

112. objMethods.init( {}, $.merge( tab, cParams ) );

113. }

114. } else {

115. if ( cMethod != "init" && cMethod in objMethods ){

117. if ( cMethod === "destroy" ){

118. boolDestroy = true;

119. }

121. objMethods[ cMethod ]( cParams );

122. } else {

123. boolOK = false;

124. }

125. }

127. jObj.data( name, objMethods.options );

129. objMethods.options = {}; // important !

130. objMethods.jObj = null; // important !

132. objOpts = cMethod = cParams = null;

134. if ( boolDestroy ){

135. jObj.removeData( name );

136. }

138. if ( ! boolOK ){

139. $.error( "dvjhPluginCreate : la méthode " +

140. method + " n'existe pas ou cet élément du DOM " +

141. "a déjà été initialisé !" );

142. }

143. });

144. };

III-C - Squelette d'un objet méthodes

Les propriétés, les méthodes et les objets précédés d'un tiret bas sont privés !

Un objet méthodes doit contenir au minimum :

- les objets privés : _copyright et _options ;

- les objets publics : jObj et options ;

- les méthodes publiques : init, destroy, setOption et getOption.

L'espace de nom, qui contient l'objet méthodes, doit offrir :

- un accès, en lecture, à la propriété _copyright.objMethodsName ;

- une fonction gérant la modification des options par défaut (_options).

Pour simplifier l'écriture d'un objet méthodes, j'ai construit un « squelette », que j'ai dénommé dvjhSqueletteMethods. Il permet de construire l'ébauche d'un nouvel objet méthodes par copier-coller sans oublier aucun des objets et des méthodes qu'il doit impérativement contenir.

À l'usage, vous trouverez sans doute les commentaires dans dvjhSqueletteMethods surabondants et gênants, mais je vous conseille vivement de les conserver en production au bénéfice de la personne qui modifiera vos plugins.

dvjhSqueletteMethods

1. var dvjh = ( function( $ ){

3. /*

4. * dvjhSqueletteMethods est le squelette d'un objet méthodes.

5. *

6. * Il contient les méthodes minimales pour la création d'un

7. * plugin multitâche.

8. *

9. * Ne pas modifier le squelette sans nécessité.

10. *

11. * On copie-collera le code de cet objet pour créer

12. * son propre objet méthode.

13. *

14. * Attention ! $.extend( obj1, obj2 ) modifie

15. * le code de l'obj1.

16. *

17. * var obj3 = $.extend( true, {}, obj1, obj2 );

18. *

19. * Ce code crée un nouvel obj3 sans altérer le

20. * code de obj1 et de obj2. Mais ici l'utilisation de

21. * $.extend n'apporte rien puisque l'on doit personnaliser

22. * la quasi-totalité du code du squelette.

23. */

24. var dvjhSqueletteMethods = {

25. "_copyright" : { // informations sur le plugin

26. /*

27. * La propriété objMethodsName est importante.

28. * Sa valeur doit être unique, elle est

29. * utilisée par dvjhPluginCreate et l'objet

30. * méthodes, elle ne doit jamais être modifiée

31. * après la mise en production du dvjhPlugin.

32. */

33. "objMethodsName" : "dvjhSqueletteMethods",

34. "auteur" : "Daniel Hagnoul",

35. "version" : "1.0.0",

36. "date" : "2012-01-13T02:15:29.000+01:00",

37. "licence" : "libre de tous droits"

38. },

40. "_options" : { // les options par défaut

41. /*

42. * L'option boolDebug doit toujours exister !

43. *

44. * N'oubliez pas de la mettre à false dans la

45. * version de production de votre plugin.

46. */

47. "boolDebug" : true,

48. "class" : "dvjhClass"

49. },

51. /*

52. * Lors du traitement d'une instance (un objet

53. * jQuery), "jObj" contiendra l'objet jQuery

54. * et l'objet options contiendra les options de

55. * cette instance.

56. *

57. * C'est la fonction dvjhPluginCreate qui est

58. * responsable de la gestion de "jObj" et de

59. * "options".

60. */

61. "jObj" : null, // l'instance

62. "options" : {}, // les options de l'instance

64. "init" : function(){ // initialisation du plugin

65. /*

66. * Ne modifiez pas le traitement des arguments

67. * sans nécessité !

68. */

69. var args = Array.prototype.slice.call( arguments ),

70. param1 = args.shift(),

71. param2 = args.shift();

73. /*

74. * Traitement d'un éventuel objet anonyme contenant

75. * les options de l'utilisateur.

76. *

77. * Ne modifiez pas ce code sans nécessité !

78. */

79. if ( $.isPlainObject( param1 ) && ! $.isEmptyObject( param1 ) ){

81. if ( this.options.boolDebug ){

82. console.log( "init, options de l'utilisateur : ",

83. $.extend( true, {}, param1 ) );

84. }

86. $.extend( this.options, param1 );

87. }

89. /*

90. * Traitement dans this.jObj d'un éventuel attribut

91. * data HTML5, data-plugin-options, contenant

92. * les options de l'utilisateur.

93. *

94. * Ne modifiez pas ce code sans nécessité !

95. */

96. var dataOptions = this.jObj.data( "pluginOptions" );

98. if ( $.isPlainObject( dataOptions ) && ! $.isEmptyObject( dataOptions ) ){

100. if ( this.options.boolDebug ){

101. console.log( "init, options de l'utilisateur : ",

102. $.extend( true, {}, dataOptions ) );

103. }

105. $.extend( this.options, dataOptions );

106. }

108. /*

109. * Si votre fonction d'initialisation nécessite des

110. * arguments, il faut les chercher dans param1 ou

111. * dans param2.

112. *

113. * La méthode init peut recevoir de 0 à 2 arguments.

114. *

115. * S'il y a deux arguments, le premier doit être

116. * un objet contenant les options de l'utilisateur,

117. * le second argument est alors un array contenant les

118. * éventuels paramètres supplémentaires.

119. *

120. * S'il n'y a qu'un argument, ce peut être soit un

121. * objet anonyme contenant les options soit un array

122. * contenant les éventuels paramètres.

123. */

124. var mesArguments = [];

126. if ( $.isArray( param1 ) ){

127. mesArguments = param1.concat();

128. } else if ( $.isArray( param2 ) ){

129. mesArguments = param2.concat();

130. }

132. if ( this.options.boolDebug ){

133. console.log( "init, this.jObj : ", this.jObj );

134. console.log( "init, mesArguments : ", mesArguments.concat() );

135. }

137. /*

138. * Votre code pour traiter this.jObj.

139. *

140. * Exemple :

141. */

142. this._setClass( this.options.class );

143. },

145. "destroy" : function( params ){

146. // 1. Supprimer les gestionnaires d'événements.

148. // Exemple :

149. // this.options.jObjTexte.off( "click mouseenter mouseleave" );

151. // 2. Supprimer les composants UI.

153. // Exemple :

154. // this.options.jObjTexte.remove();

156. // 3. Rendre null les objets (y compris array)

158. // Exemple :

159. // this.options.jObjTexte = null;

160. },

162. "exemple" : function( params ){

163. /*

164. * params est un array.

165. *

166. * À l'exception d'init, toutes vos méthodes

167. * publiques doivent avoir cette signature.

168. *

169. * Vous devez extraire vos paramètres de

170. * l'array params.

171. *

172. * var monParam = params.shift();

173. *

174. * N'oubliez pas de contrôler la validité

175. * des paramètres extraits.

176. */

177. },

179. "setOption" : function( params ){

180. /*

181. * Ne modifiez pas le traitement des arguments

182. * sans nécessité !

183. */

184. var option = params.shift(),

185. value = params.shift();

187. if ( ! option || ! value ){

188. $.error( "Les paramètres ne sont pas conformes : ( " +

189. option + ", " + value + " )." );

190. }

192. if ( option in this.options ){

193. switch( option ){

194. case "boolDebug":

195. this._setBoolDebug( value );

196. break;

197. case "class":

198. this._setClass( value );

199. break;

200. default:

201. $.error( "Cette option existe mais elle n'est pas publique !" );

202. };

204. } else {

205. $.error( "Cette option n'existe pas !" );

206. }

207. },

209. "_setBoolDebug" : function( value ){

211. if ( typeof value === "boolean" ){

212. this.options.boolDebug = value;

213. }

214. },

217. "_setClass" : function( value ){

219. if ( typeof value === 'string' ){

221. if ( this.jObj.hasClass( this.options.class ) ){

223. this.jObj.removeClass( this.options.class );

224. }

226. this.options.class = value;

228. this.jObj.addClass( value );

229. }

230. },

232. "getOption" : function( params ){

233. /*

234. * Ne modifiez pas le traitement des arguments

235. * sans nécessité !

236. */

237. var option = params.shift(),

238. callback = params.shift() || function(){},

239. name = "getOption." + this._copyright.objMethodsName;

241. if ( ! option ){

242. $.error( "getOption : le paramètre n'est pas conforme : ( " +

243. option + " )." );

244. }

246. /*

247. * Objet et array : attention de toujours transmettre une copie !

248. */

250. if ( option in this.options ){

251. switch( option ){

252. case "boolDebug":

253. var value = this.options.boolDebug;

254. this.jObj.data( name, value );

255. callback( option, value );

256. break;

257. case "class":

258. var value = this.options.class;

259. this.jObj.data( name, value );

260. callback( option, value );

261. break;

262. default:

263. $.error( "getOption : cette option existe mais elle n'est pas publique !" );

264. };

266. } else {

267. $.error( "getOption : cette option n'existe pas !" );

268. }

269. }

270. };

272. /*

273. * Pour créer un plugin multitâche il vous suffit de

274. * copier-coller et de personnaliser ce code en changeant

275. * le nom du plugin et de son objet méthodes.

276. *

277. * La méthode peut recevoir de 0 à n arguments.

278. *

279. * L'objet contenant les options de l'utilisateur doit

280. * toujours être passé dans le premier argument.

281. *

282. * Si le premier argument est un objet, il doit

283. * contenir les options de l'utilisateur.

284. *

285. * Le String contenant le nom d'une méthode doit

286. * toujours être passé dans le premier argument.

287. *

288. * Si le premier argument est un String, il doit

289. * contenir le nom d'une méthode.

290. *

291. * Avec 0 argument, le premier argument

292. * contenant un objet ou le string "init", la

293. * fonction dvjhPluginCreate provoquera

294. * l'initialisation du dvjhPlugin ou une erreur

295. * si l'initialisation a déjà eu lieu.

296. *

297. * Ci-dessous, n'oubliez pas de remplacer

298. * dvjhSqueletteMethods par le nom de votre

299. * objet méthodes.

300. *

301. * Ajouts de méthodes (plugin) au prototype de l'objet jQuery ($.fn).

302. */

303. $.extend( $.fn, {

304. "dvjhSquelette" : function(){

305. return dvjhPluginCreate.call( this, dvjhSqueletteMethods, arguments );

306. }

307. });

309. return {

310. "$" : $,

311. "squeletteObjMethodsName" : dvjhSqueletteMethods._copyright.objMethodsName,

312. "squeletteObjMethodsDefaultOptions" : function( objOptions ){

313. /*

314. * Modifications des options par défaut.

315. *

316. * Ne modifiez pas ce code sans nécessité !

317. */

318. if ( $.isPlainObject( objOptions ) && ! $.isEmptyObject( objOptions ) ){

319. $.extend( dvjhSqueletteMethods._options, objOptions );

320. }

321. }

322. };

324. })( jQuery.sub() )

Rappel : pour tester les codes, veuillez charger le ZIP.

Examinons le code jQuery du fichier dvjhSquelette.html :

DvjhSquelette.html

1. $(function(){

2. try {

3. /*

4. * Construction d'un objet jQuery : jObj.

5. * Il peut être exploité comme un array d'objet jQuery, un pour chaque

6. * division dont l'ID commence par "divTest".

7. *

8. * N'oubliez pas que seule la version de jQuery accessible

9. * par dvjh.S a accès au dvjhPlugin.

10. */

11. var jObj = dvjh.$( "[id^='divTest']" );

13. // Il est possible de modifier ou d'ajouter des options par défaut.

14. dvjh.squeletteObjMethodsDefaultOptions({

15. "moi" : "Prénom Nom"

16. });

18. // Initialisation du dvjhSquelette avec modification de l'option "moi".

19. jObj.dvjhSquelette({ "moi" : "Daniel Hagnoul" });

21. /*

22. * On peut initialiser un dvjhPlugin de plusieurs

23. * manières différentes en fonction des besoins

24. * du plugin.

25. *

26. * jObj.dvjhSquelette();

27. * jObj.dvjhSquelette({ "key" : "value" });

28. * jObj.dvjhSquelette({ "key" : "value" }, "hello everybody !" );

29. *

30. * Si le premier argument est un objet, il doit

31. * contenir les options ou être vide.

32. * jObj.dvjhSquelette({ }, new Date() );

33. *

34. * jObj.dvjhSquelette( "init", "hello everybody !" );

35. *

36. * La double initialisation provoque une erreur

37. * Exemple : jObj.eq( 2 ).dvjhSquelette();

38. */

40. /*

41. * Nota bene : pour les besoins du débogage on peut

42. * facilement consulter les options appliquées à une

43. * instance (un objet jQuery).

44. * Pour des raisons évidentes de sécurité (le respect

45. * des données) vous devez toujours manipuler une

46. * copie d'un objet (object et array).

47. */

48. jObj.each( function( i, item ){

49. console.log( "options : ", i, item, $.extend( true, {}, $( item ).data( dvjh.squeletteObjMethodsName ) ) );

50. });

52. /*

53. * Vous remarquerez certainement que le troisième

54. * objet jQuery n'a pas la "class" par défaut !

55. * En effet, au lieu d'être rouge (dvjhClass) il est orange !

56. * C'est le résultat de la modification des options d'une

57. * instance par l'intermédiaire d'un attribut data HTML5.

58. */

60. /*

61. * Modification de l'option "class" du deuxième

62. * objet jQuery en utilisant "setOption"

63. */

64. jObj.eq( 1 ).dvjhSquelette( "setOption", "class", "helloClass" );

66. /*

67. * Consultation de la valeur de l'option "class" avec "getOption".

68. *

69. * Dans la majorité des cas, on manipulera cette valeur dans

70. * une fonction de rappel. Mais cette valeur est également

71. * disponible par jObj.data( "getOption." + dvjh.squeletteObjMethodsName ).

72. *

73. * Avec une fonction de rappel (callback) :

74. */

75. jObj.dvjhSquelette( "getOption", "class", function( option, value ){

76. console.log( "getOption, option = ", option, ", value = ", value );

77. });

79. // Avec jObj.data( "getOption." + dvjh.squeletteObjMethodsName ).

80. jObj.each( function( i, item ){

81. console.log( "class : ", i, item, $( item ).data( "getOption." + dvjh.squeletteObjMethodsName ) );

82. });

83. }

84. catch(e){

85. alert( "dvjhSquelette, " + e.message );

86. }

87. });

Le code d'utilisation d'un dvjhPlugin doit toujours se trouver dans un bloc « try catch », c'est l'ultime rempart avant le crash global.

Extrait du code HTML

1. <!--

2. Attention ! Le contenu de l'attribut data-plugin-options

3. doit impérativement être un JSON bien formé sous peine

4. d'être ignoré par JSON.parse().

5. -->

6. <div id="divTest3" data-plugin-options='{ "class" : "surpriseClass" }'>

7. <p>Un mot pour remplir</p>

8. </div>

Ne surchargez pas inutilement l'objet _options (les options par défaut) ! Je n'ai rencontré aucun problème de performance avec le stockage des options dans l'instance lors de mes tests, mais pour des données encombrantes et communes à toutes les instances, il est important de se souvenir que dans le code de l'objet méthodes vous avez accès au contenu de la clôture jQuery.

IV - Les exemples

Commençons par un exemple simple. Un plugin multitâche qui gère la modification de ses options.

IV-A - Le plugin dvjhTourne

Dans le tutoriel « Adapter jQuery à vos besoins », le plugin tourne est un bon candidat car pour gérer les modifications de son option « degrees » il avait besoin de deux autres plugins : tourneSetOptions et tourneGetOptions. De plus, toutes les instances du plugin tourne utilisaient la même option.

dvjhTourne

1. var dvjh = ( function( $ ){

3. /*

4. * L'objet méthodes ci-dessous reprend le code des plugins tourne,

5. * tourneSetOptions, tourneGetOptions et celui de l'objet privé

6. * _objTourne publié dans le tutoriel "Adapter jQuery à vos besoins".

7. */

8. var dvjhTourneMethods = {

9. "_copyright" : { // informations sur le plugin

10. "objMethodsName" : "dvjhTourneMethods",

11. "auteur" : "Daniel Hagnoul",

12. "version" : "1.0.0",

13. "date" : "2012-01-17T15:53:15.000+01:00",

14. "licence" : "libre de tous droits"

15. },

16. "_options" : { // les options par défaut

17. "boolDebug" : false,

18. "boolInfos" : true,

19. "degrees" : 0

20. },

21. "jObj" : null, // l'instance (objet jQuery)

22. "options" : {}, // les options de l'instance

23. "init" : function(){ // initialisation du plugin

24. var args = Array.prototype.slice.call( arguments ),

25. param1 = args.shift(),

26. param2 = args.shift();

28. /*

29. * Traitement d'un éventuel objet anonyme contenant

30. * les options de l'utilisateur.

31. *

32. * Ne modifiez pas ce code sans nécessité !

33. */

34. if ( $.isPlainObject( param1 ) && ! $.isEmptyObject( param1 ) ){

36. if ( this.options.boolDebug ){

37. console.log( "init, options de l'utilisateur : ",

38. $.extend( true, {}, param1 ) );

39. }

41. $.extend( this.options, param1 );

42. }

44. /*

45. * Traitement dans this.jObj d'un éventuel attribut

46. * data HTML5, data-plugin-options, contenant

47. * les options de l'utilisateur.

48. *

49. * Ne modifiez pas ce code sans nécessité !

50. */

51. var dataOptions = this.jObj.data( "pluginOptions" );

53. if ( $.isPlainObject( dataOptions ) && ! $.isEmptyObject( dataOptions ) ){

55. if ( this.options.boolDebug ){

56. console.log( "init, options de l'utilisateur : ",

57. $.extend( true, {}, dataOptions ) );

58. }

60. $.extend( this.options, dataOptions );

61. }

63. /*

64. * Si votre fonction d'initialisation nécessite des

65. * arguments, il faut les chercher dans param1 ou

66. * dans param2.

67. *

68. * La méthode init peut recevoir de 0 à 2 arguments.

69. *

70. * S'il y a deux arguments, le premier doit être

71. * un objet contenant les options de l'utilisateur,

72. * le second argument est alors un array contenant les

73. * éventuels paramètres supplémentaires.

74. *

75. * S'il n'y a qu'un argument, ce peut être soit un

76. * objet anonyme contenant les options soit un array

77. * contenant les éventuels paramètres.

78. */

79. var mesArguments = [];

81. if ( $.isArray( param1 ) ){

82. mesArguments = param1.concat();

83. } else if ( $.isArray( param2 ) ){

84. mesArguments = param2.concat();

85. }

87. if ( this.options.boolDebug ){

88. console.log( "init, this.jObj : ", this.jObj );

89. console.log( "init, mesArguments : ", mesArguments.concat() );

90. }

92. /*

93. * Votre code pour traiter this.jObj.

94. */

96. if ( this.options.boolInfos ){

98. this.jObj.on( "optionsChanged.dvjhTourne" , function( event ){

99. var obj = event.dvjh,

100. el = obj.initiateur[0];

102. console.log( new Date(event.timeStamp).formatISO() +

103. " : l'élément " +

104. el.tagName +

105. " , ID = " +

106. el.id +

107. " , Class = '" +

108. el.className +

109. "' a modifié son option " +

110. obj.optionsKey +

111. ", elle a pris la valeur " +

112. obj.optionsValue );

113. });

114. }

116. /*

117. * Rotation.

118. *

119. * Traite le cas dvjhTourne( "init", "25" ),

120. * sinon traite la valeur de l'option degrees

121. */

123. if ( $.isNumeric( mesArguments[0] ) ){

124. this._setDegrees( mesArguments[0] );

125. } else {

126. this._setDegrees( this.options.degrees );

127. }

128. },

129. "destroy" : function( params ){

130. // 1. Supprimer les gestionnaires d'événements.

131. this.jObj.off( "optionsChanged.dvjhTourne" );

133. // 2. Supprimer les composants UI.

135. // 3. Rendre null les objets (y compris array)

136. },

137. "setOption" : function( params ){

138. var option = params.shift(),

139. value = params.shift();

141. if ( ! option || ! value ){

142. $.error( "Les paramètres ne sont pas conformes : ( " +

143. option + ", " + value + " )." );

144. }

146. if ( option in this.options ){

147. switch( option ){

148. case "boolDebug":

149. this._setBoolDebug( value );

150. break;

151. case "degrees":

152. this._setDegrees( value );

153. break;

154. default:

155. $.error( "Cette option existe mais elle n'est pas publique !" );

156. };

158. } else {

159. $.error( "Cette option n'existe pas !" );

160. }

161. },

162. "_setBoolDebug" : function( value ){

164. if ( typeof value === "boolean" ){

165. this.options.boolDebug = value;

166. }

167. },

168. "_setDegrees" : function( value ){

170. /*

171. * Cette méthode traite la rotation

172. * initiale et les rotations demandées

173. * par la méthode setOption.

174. */

175. if ( $.isNumeric( value ) ){

177. var v = parseInt( value, 10 ) || 0;

179. this.options.degrees = v;

181. var rad = v * Math.PI * 2.0 / 360.0,

182. costheta = Math.cos(rad),

183. sintheta = Math.sin(rad),

184. a = parseFloat(costheta, 10).toFixed(8),

185. c = parseFloat(-sintheta, 10).toFixed(8),

186. b = parseFloat(sintheta, 10).toFixed(8),

187. d = parseFloat(costheta, 10).toFixed(8),

188. matrix = "matrix(" + a + ", " + b + ", " + c + ", " + d + ", 0, 0);";

190. this._avecStyle( matrix );

192. var optionsChangedEvent = new $.Event( "optionsChanged.dvjhTourne" );

194. optionsChangedEvent.dvjh = {

195. "initiateur" : this.jObj,

196. "optionsKey" : "degrees",

197. "optionsValue" : v

198. };

200. this.jObj.trigger( optionsChangedEvent );

201. } else {

202. $.error( "_setDegrees : " + value + " n'est pas un nombre !" );

203. }

204. },

205. "_avecStyle" : function( matrix ){

206. if ( this.options.boolDebug ){

207. console.log( "_avecStyle : ", this.jObj, matrix );

208. }

210. this.jObj.attr( "style", "-moz-transform:" + matrix +

211. "; -webkit-transform:" + matrix +

212. "; -ms-transform:" + matrix +

213. "; -o-transform:" + matrix +

214. "; transform:" + matrix +

215. ";" );

216. },

217. "getOption" : function( params ){

218. var option = params.shift(),

219. callback = params.shift() || function(){},

220. name = "getOption." + this._copyright.objMethodsName;

222. if ( ! option ){

223. $.error( "getOption : le paramètre n'est pas conforme : ( " +

224. option + " )." );

225. }

227. /*

228. * Objet et array : attention de toujours transmettre une copie !

229. */

231. if ( option in this.options ){

232. switch( option ){

233. case "boolDebug":

234. var value = this.options.boolDebug;

235. this.jObj.data( name, value );

236. callback( option, value );

237. break;

238. case "degrees":

239. var value = this.options.degrees;

240. this.jObj.data( name, value );

241. callback( option, value );

242. break;

243. default:

244. $.error( "getOption : cette option existe mais elle n'est pas publique !" );

245. };

246. } else {

247. $.error( "getOption : cette option n'existe pas !" );

248. }

249. }

250. };

252. // Ajouts de méthodes (plugin) au prototype de l'objet jQuery ($.fn).

253. $.extend( $.fn, {

254. "dvjhTourne" : function(){ // un plugin multitâche

255. return dvjhPluginCreate.call( this, dvjhTourneMethods, arguments );

256. }

257. });

259. return {

260. "$": $, // voir le tutoriel "Adapter jQuery à vos besoins".

261. "dvjhTourneObjMethodsName" : dvjhTourneMethods._copyright.objMethodsName,

262. "dvjhTourneObjMethodsDefaultOptions" : function( objOptions ){

263. /*

264. * Modifications des options par défaut.

265. *

266. * Ne modifiez pas ce code sans nécessité !

267. */

268. if ( $.isPlainObject( objOptions ) && ! $.isEmptyObject( objOptions ) ){

269. $.extend( dvjhTourneMethods._options, objOptions );

270. }

271. }

272. };

273. })( jQuery.sub() );

Rappel : pour tester les codes, veuillez charger le ZIP.

Utilisation du plugin, extrait de dvjhTourne.html :

DvjhTourne.html

1. $(function(){

2. $( "#rotationBtnID" ).on( "click" , function(){

3. $( this ).hide();

5. /*

6. * Rappel, le prototype de jQuery n'a pas de méthode dvjhTourne !

7. * Voir le tutoriel "Adapter jQuery à vos besoins".

8. */

9. // $( ".divTest" ).dvjhTourne();

11. var jObjs = dvjh.$( ".divTest" ),

12. name = dvjh.dvjhTourneObjMethodsName;

14. try {

15. // initialisation

16. // jObjs.dvjhTourne({ "degrees" : "45" }).css( "color", "blue" );

18. // ou

19. jObjs.dvjhTourne( "init", "25" ).css( "color", "blue" );

21. var jObj2 = jObjs.eq( 1 );

23. // modification de la rotation du deuxième objet jQuery

24. jObj2.dvjhTourne( "setOption", "degrees", "-105" ).css( "color", "red" );

26. setTimeout( function(){

27. jObj2.dvjhTourne( "getOption", "degrees", function( option, value ){

29. /*

30. * Rappel : this est undefined !

31. */

32. //console.log( this );

34. /*

35. * L'instance restaure son état à partir de ses options

36. * qui ne contiennent pas la couleur rouge du texte.

37. */

38. jObj2.dvjhTourne( "setOption", "degrees", value + 52 ).css( "color", "red" );

39. });

40. }, 2000 );

41. }

42. catch( e ){

43. alert( "dvjhTourne, " + e.message );

44. }

45. });

46. });

IV-B - Le plugin dvjhEventShow

On crée un nouveau fragment du DOM, jObjText, et on le stocke dans les options de l'instance. Ce fragment du DOM initialise trois gestionnaires d'événements (click, mouseenter et mouseleave) qui manipulent l'état de l'instance.
Bien entendu, lorsqu'un événement se produit l'objet méthodes est inactif et this.jObj a la valeur « null » !
On est donc obligé d'activer l'objet méthodes à partir du gestionnaire d'événements.

Deux méthodes possibles, soit :

1. Stocker la valeur de this.jObj par un $( l'élément du DOM qui intercepte l'événement ).data( "dvjhEventShowElement", this.jObj[0] ) ;

2. Pour les cas simples, retrouver this.jObj à partir de l'élément du DOM qui intercepte l'événement. Ici: $( this ).parent().

Dans dvjhEventShow le premier cas est mis en commentaires, mais il est utilisable.

dvjhEventShow

1. var dvjh = (function($){

3. /*

4. * Le plugin dvjhEventShow illustre la gestion

5. * des événements.

6. */

7. var dvjhEventShowMethods = {

8. "_copyright" : { // informations sur le plugin

9. "objMethodsName" : "dvjhEventShowMethods",

10. "auteur" : "Daniel Hagnoul",

11. "version" : "1.0.0",

12. "date" : "2012-02-07T22:04:41.000+01:00",

13. "licence" : "libre de tous droits"

14. },

15. "_options" : { // les options par défaut

16. "boolDebug" : false,

17. "eventShowTexteCSS" : {

18. "font-family" : "Sofia",

19. "font-size" : "2rem",

20. "color" : "rgba( 211, 28, 56, 0.75)",

21. "background-color" : "rgba( 21, 68, 77, 0.5)",

22. "width" : "40rem",

23. "height" : "4rem",

24. "margin" : "1.4rem",

25. "padding" : "0.6rem",

26. "border" : "0.1rem dotted grey"

27. },

28. "number" : -1

29. },

30. "jObj" : null, // l'instance (un objet jQuery)

31. "options" : {}, // les options de l'instance

32. "init" : function(){ // initialisation du plugin

33. var args = Array.prototype.slice.call( arguments ),

34. param1 = args.shift(),

35. param2 = args.shift();

37. if ( $.isPlainObject( param1 ) && ! $.isEmptyObject( param1 ) ){

39. if ( this.options.boolDebug ){

40. console.log( "init, options de l'utilisateur : ",

41. $.extend( true, {}, param1 ) );

42. }

44. $.extend( this.options, param1 );

45. }

47. var dataOptions = this.jObj.data( "pluginOptions" );

49. if ( $.isPlainObject( dataOptions ) && ! $.isEmptyObject( dataOptions ) ){

51. if ( this.options.boolDebug ){

52. console.log( "init, options de l'utilisateur : ",

53. $.extend( true, {}, dataOptions ) );

54. }

56. $.extend( this.options, dataOptions );

57. }

59. var mesArguments = [];

61. if ( $.isArray( param1 ) ){

62. mesArguments = param1.concat();

63. } else if ( $.isArray( param2 ) ){

64. mesArguments = param2.concat();

65. }

67. if ( this.options.boolDebug ){

68. console.log( "init, this.jObj : ", this.jObj );

69. console.log( "init, mesArguments : ", mesArguments.concat() );

70. }

72. if ( mesArguments.length > 0 ){

74. /*

75. * Déclenche une exception si l'argument ne peut pas

76. * être converti dans une couleur valide.

77. */

78. $.parseColor( mesArguments[0] );

80. this.options.eventShowTexteCSS["background-color"] = mesArguments[0];

81. }

83. var self = this;

85. this.options.jObjTexte = $("<div/>", {

86. "id" : "eventShowTexte" + $.now(),

87. "html" : "<p> " + self.options.number + ". Un mot pour remplir.</p>",

88. "css" : self.options.eventShowTexteCSS,

89. "click" : function( e ){

90. /*

91. var jObj = $( $( this ).data( "dvjhEventShowElement" ) );

93. jObj.dvjhEventShow( "eventClickHandler", e );

94. */

96. $( this ).parent().dvjhEventShow( "eventClickHandler", e );

97. },

98. "mouseenter" : function( e ){

99. /*

100. var jObj = $( $( this ).data( "dvjhEventShowElement" ) );

102. jObj.dvjhEventShow( "eventMouseEnterHandler", e );

103. */

105. $( this ).parent().dvjhEventShow( "eventMouseEnterHandler", e );

106. },

107. "mouseleave" : function( e ){

108. /*

109. var jObj = $( $( this ).data( "dvjhEventShowElement" ) );

111. jObj.dvjhEventShow( "eventMouseLeaveHandler", e );

112. */

114. $( this ).parent().dvjhEventShow( "eventMouseLeaveHandler", e );

115. }

116. }).data( "dvjhEventShowElement", this.jObj[0] ).appendTo( this.jObj );

118. self = null;

119. },

120. "destroy" : function( params ){

121. // 1. Supprimer les gestionnaires d'événements.

122. this.options.jObjTexte.off( "click mouseenter mouseleave" );

124. // 2. Supprimer les composants UI.

125. this.options.jObjTexte.remove();

127. // 3. Rendre null les objets (y compris array)

128. this.options.jObjTexte = null;

129. },

130. "eventClickHandler" : function( params ){

131. var e = params.shift();

133. /*

134. * N'oubliez pas que l'élément cliqué est disponible

135. * dans event.target, et que l'élément qui a intercepté

136. * l'événement est disponible dans event.currentTarget.

137. *

138. * Suivant la composition de l'élément et l'endroit cliqué

139. * le target et le currentTarget peuvent être identiques.

140. */

142. console.log( e.target, e.currentTarget, " : ", this.options.number );

143. },

144. "eventMouseEnterHandler" : function( params ){

145. var e = params.shift();

147. this.options.jObjTexte.css( "background-color", "yellow" );

148. },

149. "eventMouseLeaveHandler" : function( params ){

150. var e = params.shift();

152. this.options.jObjTexte.css( "background-color",

153. this.options.eventShowTexteCSS["background-color"] );

154. },

155. "setOption" : function( params ){

156. var option = params.shift(),

157. value = params.shift();

159. if ( ! option || ! value ){

160. $.error( "Les paramètres ne sont pas conformes : ( " +

161. option + ", " + value + " )." );

162. }

164. if ( option in this.options ){

165. switch( option ){

166. case "boolDebug":

167. this._setBoolDebug( value );

168. break;

169. default:

170. $.error( "Cette option existe mais elle n'est pas publique !" );

171. };

172. } else {

173. $.error( "Cette option n'existe pas !" );

174. }

175. },

176. "_setBoolDebug" : function( value ){

177. if ( typeof value === "boolean" ){

178. this.options.boolDebug = value;

179. }

180. },

181. "getOption" : function( params ){

182. var option = params.shift(),

183. callback = params.shift() || function(){},

184. name = "getOption." + this._copyright.objMethodsName;

186. if ( ! option ){

187. $.error( "getOption : le paramètre n'est pas conforme : ( " +

188. option + " )." );

189. }

191. /*

192. * Objet et array : attention de toujours transmettre une copie !

193. */

195. if ( option in this.options ){

196. switch( option ){

197. case "boolDebug":

198. var value = this.options.boolDebug;

199. this.jObj.data( name, value );

200. callback( option, value );

201. break;

202. default:

203. $.error( "getOption : cette option existe mais " +

204. "elle n'est pas publique !" );

205. };

206. } else {

207. $.error( "getOption : cette option n'existe pas !" );

208. }

209. }

210. };

212. // Ajouts de méthodes (plugin) au prototype de l'objet jQuery ($.fn).

213. $.extend( $.fn, {

214. "dvjhEventShow" : function(){ // un plugin multitâche

215. return dvjhPluginCreate.call( this, dvjhEventShowMethods, arguments );

216. }

217. });

219. return {

220. "$" : $,

221. "eventShowObjMethodsName" : dvjhEventShowMethods._copyright.objMethodsName,

222. "eventShowObjMethodsDefaultOptions" : function( objOptions ){

223. /*

224. * Modifications des options par défaut.

225. *

226. * Ne modifiez pas ce code sans nécessité !

227. */

228. if ( $.isPlainObject( objOptions ) && ! $.isEmptyObject( objOptions ) ){

229. $.extend( dvjhEventShowMethods._options, objOptions );

230. }

231. }

232. };

233. })( jQuery.sub() );

Cet exemple montre également comment gérer la destruction d'une instance.

Rappel : pour tester les codes, veuillez charger le ZIP.

Utilisation du plugin, extrait de dvjhEventShow.html :

dvjhEventShow.html

1. $(function(){

2. try {

3. var bgColor = [

4. "rgba( 159, 159, 234, 0.95 )",

5. "rgba( 159, 159, 234, 0.75 )",

6. "rgba( 159, 159, 234, 0.55 )",

7. "rgba( 159, 159, 234, 0.35 )",

8. "rgba( 159, 159, 234, 0.15 )",

9. ];

11. var jObjTab = [];

13. $( "div", "#test" ).each( function( i, item ){

15. /*

16. * Pour chaque division on initialise le plugin et

17. * on stocke l'objet jQuery.

18. *

19. * Lors de l'initialisation, on modifie l'option

20. * number de l'instance et on modifie la valeur

21. * par défaut du "background-color" pour la division

22. * ajoutée dans l'instance par le plugin.

23. *

24. * Signatures :

25. * jObj.dvjhEventShow( [options] [, bgColor] );

26. * jObj.dvjhEventShow( "init" [, bgColor] );

27. */

28. jObjTab.push(

30. dvjh.$( item ).dvjhEventShow({

31. "number" : i + 1 // numérotation de 1 à n.

32. }, bgColor[i] )

34. /*

35. * Exemples d'initialisations alternatives :

36. *

37. * dvjh.$( item ).dvjhEventShow()

38. *

39. * Test du déclenchement d'une exception par $.parseColor().

40. * dvjh.$( item ).dvjhEventShow( "rgba(-16, 210, 27, 0.25)" )

41. *

42. * dvjh.$( item ).dvjhEventShow( bgColor[i] )

43. *

44. * dvjh.$( item ).dvjhEventShow( "init" )

45. *

46. * dvjh.$( item ).dvjhEventShow( "init", bgColor[i] )

47. *

48. * dvjh.$( item ).dvjhEventShow({

49. *    "number" : i + 1 // numérotation de 1 à n.

50. * })

51. */

52. );

53. });

55. for (var i in jObjTab){

56. // une copie des options de chaque objet jQuery

57. console.log( $.extend( true, {}, jObjTab[i].data( dvjh.eventShowObjMethodsName ) ) );

58. }

60. for (var i in jObjTab){

61. jObjTab[i].dvjhEventShow( "getOption", "boolDebug", function( option, value ){

62. console.log( "getOption, option = ", option, ", value = ", value );

63. });

64. }

66. jObjTab[0].dvjhEventShow( "destroy" );

68. // les options de l'objet jQuery jObjTab[0] n'existent plus !

69. console.log( jObjTab[0].data( dvjh.eventShowObjMethodsName ) );

71. /*

72. * Après la destruction, il est de votre

73. * responsabilité de rendre l'objet null.

74. */

75. jObjTab[0] = null;

77. console.log( jObjTab );

78. }

79. catch( e ){

80. alert( "dvjhEventShow, " + e.message );

81. }

82. });

IV-C - Le plugin dvjhStorage

Ce plugin n'agit pas sur l'interface utilisateur, mais qui dit multitâche implique la complexité.

Le plugin dvjhStorage gère simplement le stockage de données dans un objet jQuery (jObj.data( "dvjhStorage" )), dans le sessionStorage et dans le localStorage des navigateurs non obsolètes.

Bien entendu on peut ajouter, supprimer ou chercher des données. Mais on peut aussi copier ou transférer des données d'un espace de stockage à l'autre.

Chaque donnée est représentée par un couple « key, value ». La variable « key » doit être du type « string ». La variable « value » peut contenir n'importe quoi car elle sera sauvegardée au format JSON. Lorsque la donnée est extraite du stockage, elle est restaurée dans son type d'origine. Lorsque la donnée est copiée ou transférée dans un autre stockage elle reste au format JSON.

Firefox : le sessionStorage n'est pas disponible en « local mode ».

On sauvegarde des données au format JSON. Si l'on passe un objet qui contient une fonction elle sera supprimée de la sauvegarde. De même toute clé (key) qui n'est pas un texte (string) ou un nombre (number).

Méthode

Signature

initialisation

jObj = dvjh.initStorage( selector );

set

jObj.dvjhStorage( "set", ( "data" || "session" || "local" ), key, value );

get

jObj.dvjhStorage( "get", ( "data" || "session" || "local" ), key [, callback] );

has

jObj.dvjhStorage( "has", key [, callback] );

remove

jObj.dvjhStorage( "remove", ( "data" || "session" || "local" ), key );

copy

jObj.dvjhStorage( "copy", origine ( "data" || "session" || "local" ), destination ( "data" || "session" || "local" ), key );

relocate

jObj.dvjhStorage( "relocate", origine ( "data" || "session" || "local" ), destination ( "data" || "session" || "local" ), key );

clear

jObj.dvjhStorage( "clear", ( "data" || "session" || "local" ) );

clearAll

jObj.dvjhStorage( "clearAll" );

dvjhStorage

1. var dvjh = (function($){

3. /*

4. * Plugin pour gérer le stockage des données au format JSON.

5. * On peut stocker dans le navigateur (sessionStorage ou localSorage)

6. * ou dans l'élément du DOM ( jObj.data( "dvjhStorage" ) ).

7. *

8. * Firefox : le sessionStorage n'est pas disponible en

9. * "local mode", mais il fonctionnera lorsque vous

10. * chargerez cette page Web à partir d'un serveur !

11. *

12. * On sauvegarde des données. Si l'on passe un objet qui contient

13. * une fonction elle sera supprimée. "Non-integer/string keys are

14. * skipped in the object, as are keys that point to a function".

15. */

16. var dvjhStorageMethods = {

17. "_copyright" : { // informations sur le plugin

18. "objMethodsName" : "dvjhStorageMethods",

19. "auteur" : "Daniel Hagnoul",

20. "version" : "1.0.0",

21. "date" : "2012-01-21T20:30:45.000+01:00",

22. "licence" : "libre de tous droits"

23. },

24. "_options" : { // les options par défaut

25. "boolDebug" : true

26. },

27. "jObj" : null, // l'instance (un objet jQuery )

28. "options" : {}, // les options de l'instance

29. "init" : function(){ // initialisation du plugin

30. var args = Array.prototype.slice.call( arguments ),

31. param1 = args.shift(),

32. param2 = args.shift();

34. if ( $.isPlainObject( param1 ) && ! $.isEmptyObject( param1 ) ){

36. if ( this.options.boolDebug ){

37. console.log( "init, options de l'utilisateur : ",

38. $.extend( true, {}, param1 ) );

39. }

41. $.extend( this.options, param1 );

42. }

44. var dataOptions = this.jObj.data( "pluginOptions" );

46. if ( $.isPlainObject( dataOptions ) && ! $.isEmptyObject( dataOptions ) ){

48. if ( this.options.boolDebug ){

49. console.log( "init, options de l'utilisateur : ",

50. $.extend( true, {}, dataOptions ) );

51. }

53. $.extend( this.options, dataOptions );

54. }

56. var mesArguments = [];

58. if ( $.isArray( param1 ) ){

59. mesArguments = param1.concat();

60. } else if ( $.isArray( param2 ) ){

61. mesArguments = param2.concat();

62. }

64. if ( this.options.boolDebug ){

65. console.log( "init, this.jObj : ", this.jObj );

66. console.log( "init, mesArguments : ", mesArguments.concat() );

67. }

69. /*

70. * Si le navigateur n'est pas compatible, l'objet

71. * jQuery n'est pas créé !

72. */

73. if ( ! window.localStorage ){

74. $.error( "Le localStorage n'est pas disponible ! " +

75. "Le navigateur est obsolète !" );

76. }

78. this.jObj.data( "dvjhStorage", {} );

80. if ( window.location.protocol === "file:" ){

81. console.log( "Sur Firefox, le sessionStorage n'est pas disponible " +

82. "en \"local mode\", mais il fonctionnera lorsque vous " +

83. "chargerez cette page Web à partir d'un serveur !");

84. }

85. },

86. "destroy" : function( params ){

87. // 1. Supprimer les gestionnaires d'événements.

89. // 2. Supprimer les composants UI.

91. // 3. Rendre null les objets (y compris array)

92. },

93. "set" : function( params ){

94. var location = params.shift(),

95. key = params.shift(),

96. value = params.shift();

98. if ( typeof location === "string" &&

99. typeof key === "string" &&

100. value ){

102. var jsonValue = JSON.stringify( value );

104. if ( this.options.boolDebug ){

105. console.log( "set, location : ", location );

106. console.log( "set, key : ", key );

108. if ( $.isArray( value ) ){

109. console.log( "set, value : ", value.concat() );

110. } else if ( $.isPlainObject( value ) ){

111. console.log( "set, value : ", $.extend( true, {}, value ) );

112. } else {

113. console.log( "set, value : ", value );

114. }

115. }

117. switch( location ){

118. case "session":

119. this._sessionSet( key, jsonValue );

120. break;

121. case "local":

122. this._localSet( key, jsonValue );

123. break;

124. case "data":

125. this._dataSet( key, jsonValue );

126. break;

127. default:

128. $.error( "Cette location (" + location + ") n'existe pas !" );

129. }

130. } else {

131. $.error( "dvjhStorageMethods, set : les paramètres location ( " +

132. location +

133. " ) ( session || local || data ) et key ( " +

134. key +

135. " ) doivent être de type text et le paramètre value ( " +

136. value +

137. " ) doit exiter !" );

138. }

139. },

140. "_sessionSet" : function( key, jsonValue ){

141. try {

142. window.sessionStorage.setItem( key, jsonValue );

143. }

144. catch( e ){

145. $.error( "dvjhStorage, sessionSet : " + e.message );

146. }

147. },

148. "_localSet" : function( key, jsonValue ){

149. try {

150. window.localStorage.setItem( key, jsonValue );

151. }

152. catch( e ){

153. $.error( "dvjhStorage, localSet : " + e.message );

154. }

155. },

156. "_dataSet" : function( key, jsonValue ){

157. try {

158. var objAnonyme = this.jObj.data( "dvjhStorage" );

160. objAnonyme[ key ] = jsonValue;

162. this.jObj.data( "dvjhStorage", objAnonyme );

163. }

164. catch( e ){

165. $.error( "dvjhStorage, dataSet : " + e.message );

166. }

167. },

168. "get" : function( params ){

169. var location = params.shift(),

170. key = params.shift(),

171. callback = params.shift() || function(){};

173. if ( typeof location === "string" && typeof key === "string" ){

175. if ( this.options.boolDebug ){

176. console.log( "get, location : ", location );

177. console.log( "get, key : ", key );

178. }

180. switch( location ){

181. case "session":

182. this._sessionGet( key, callback );

183. break;

184. case "local":

185. this._localGet( key, callback );

186. break;

187. case "data":

188. this._dataGet( key, callback );

189. break;

190. default:

191. $.error( "Cette location (" + location + ") n'existe pas !" );

192. }

193. } else {

194. $.error( "dvjhStorageMethods, get : les paramètres location ( " +

195. location + " ) ( session || local || data ) et key ( " +

196. key + " ) doivent être de type text !" );

197. }

198. },

199. "_sessionGet" : function( key, callback ){

200. var name = "get." + this._copyright.objMethodsName;

202. try {

203. // getItem retourne null si key n'existe pas !

204. var value = JSON.parse( window.sessionStorage.getItem( key ) );

206. this.jObj.data( name, value );

208. callback( key, value );

209. }

210. catch( e ){

211. $.error( "dvjhStorage, sessionGet : " + e.message );

212. }

213. },

214. "_localGet" : function( key, callback ){

215. var name = "get." + this._copyright.objMethodsName;

217. try {

218. // getItem retourne null si key n'existe pas !

219. var value = JSON.parse( window.localStorage.getItem( key ) );

221. this.jObj.data( name, value );

223. callback( key, value );

224. }

225. catch( e ){

226. $.error( "dvjhStorage, localGet : " + e.message );

227. }

228. },

229. "_dataGet" : function( key, callback ){

230. var name = "get." + this._copyright.objMethodsName;

232. try {

233. // getItem retourne null si key n'existe pas !

235. var objAnonyme = this.jObj.data( "dvjhStorage" ),

236. value = null;

238. if ( key in objAnonyme ){

239. value = JSON.parse( objAnonyme[ key ] );

240. }

242. this.jObj.data( name, value );

244. callback( key, value );

245. }

246. catch( e ){

247. $.error( "dvjhStorage, dataGet : " + e.message );

248. }

249. },

250. "has" : function( params ){

251. var key = params.shift(),

252. callback = params.shift() || function(){},

253. name = "has." + this._copyright.objMethodsName;

255. if ( typeof key === "string" ){

257. if ( this.options.boolDebug ){

258. console.log( "has, key : ", key );

259. }

261. try {

262. var boolSession = false,

263. boolLocal = false,

264. boolData = false;

266. if ( key in window.sessionStorage ){

267. boolSession = true;

268. }

270. if ( key in window.localStorage ){

271. boolLocal = true;

272. }

274. if ( key in this.jObj.data( "dvjhStorage" ) ){

275. boolData = true;

276. }

278. this.jObj.data( name, {

279. "session" : boolSession,

280. "local" : boolLocal,

281. "data" : boolData

282. });

284. callback( key, {

285. "session" : boolSession,

286. "local" : boolLocal,

287. "data" : boolData

288. });

289. }

290. catch( e ){

291. $.error( "dvjhStorage, has : " + e.message );

292. }

293. } else {

294. $.error( "dvjhStorageMethods, has : le paramètre key ( " +

295. key + " ) doit être de type text !" );

296. }

297. },

298. "remove" : function( params ){

299. var location = params.shift(),

300. key = params.shift();

302. if ( typeof location === "string" && typeof key === "string" ){

304. if ( this.options.boolDebug ){

305. console.log( "remove, location : ", location );

306. console.log( "remove, key : ", key );

307. }

309. switch( location ){

310. case "session":

311. this._sessionRemove( key );

312. break;

313. case "local":

314. this._localRemove( key );

315. break;

316. case "data":

317. this._dataRemove( key );

318. break;

319. default:

320. $.error( "Cette location (" + location + ") n'existe pas !" );

321. }

322. } else {

323. $.error( "dvjhStorageMethods, remove : les paramètres location ( " +

324. location + " ) ( session || local || data ) et key ( " +

325. key + " ) doivent être de type text !" );

326. }

327. },

328. "_sessionRemove" : function( key ){

329. try {

330. // removeItem ne fait rien si key n'existe pas !

331. window.sessionStorage.removeItem( key );

332. }

333. catch( e ){

334. $.error( "dvjhStorage, sessionRemove : " + e.message );

335. }

336. },

337. "_localRemove" : function( key ){

338. try {

339. // removeItem ne fait rien si key n'existe pas !

340. window.localStorage.removeItem( key );

341. }

342. catch( e ){

343. $.error( "dvjhStorage, localRemove : " + e.message );

344. }

345. },

346. "_dataRemove" : function( key ){

347. try {

348. // remove ne fait rien si key n'existe pas !

350. var objAnonyme = this.jObj.data( "dvjhStorage" );

352. if ( key in objAnonyme ){

353. delete objAnonyme[ key ];

354. }

356. this.jObj.data( "dvjhStorage", objAnonyme );

357. }

358. catch( e ){

359. $.error( "dvjhStorage, dataRemove : " + e.message );

360. }

361. },

362. "clear" : function( params ){

363. var location = params.shift();

365. if ( typeof location === "string" ){

367. if ( this.options.boolDebug ){

368. console.log( "clear, location : ", location );

369. }

371. switch( location ){

372. case "session":

373. this._sessionClear();

374. break;

375. case "local":

376. this._localClear();

377. break;

378. case "data":

379. this._dataClear();

380. break;

381. default:

382. $.error( "Cette location (" + location + ") n'existe pas !" );

383. }

384. } else {

385. $.error( "dvjhStorageMethods, setItem : le paramètre location ( " +

386. location + " ) ( session || local || data ) et key ( " +

387. " ) doit être de type text !" );

388. }

389. },

390. "clearAll" : function( params ){

391. if ( this.options.boolDebug ){

392. console.log( "clearAll" );

393. }

395. this._sessionClear();

396. this._localClear();

397. this._dataClear();

398. },

399. "_sessionClear" : function(){

400. try {

401. window.sessionStorage.clear();

402. }

403. catch( e ){

404. $.error( "dvjhStorage, sessionClear : " + e.message );

405. }

406. },

407. "_localClear" : function(){

408. try {

409. window.localStorage.clear();

410. }

411. catch( e ){

412. $.error( "dvjhStorage, localClear : " + e.message );

413. }

414. },

415. "_dataClear" : function(){

416. try {

417. this.jObj.data( "dvjhStorage", {} );

418. }

419. catch( e ){

420. $.error( "dvjhStorage, dataClear : " + e.message );

421. }

422. },

423. "relocate" : function( params ){

424. var origine = params.shift(),

425. destination = params.shift(),

426. key = params.shift();

428. if ( typeof origine === "string" &&

429. typeof destination === "string" &&

430. typeof key === "string" ){

432. if ( this.options.boolDebug ){

433. console.log( "relocate, origine : ", origine );

434. console.log( "relocate, destination : ", destination );

435. console.log( "relocate, key : ", key );

436. }

438. switch( origine ){

439. case "session":

440. this._sessionRelocate( key, destination );

441. break;

442. case "local":

443. this._localRelocate( key, destination );

444. break;

445. case "data":

446. this._dataRelocate( key, destination );

447. break;

448. default:

449. $.error( "Cette origine (" + origine + ") n'existe pas !" );

450. }

451. } else {

452. $.error( "dvjhStorageMethods, relocate : les paramètres origine ( " +

453. origine +

454. " ) ( session || local || data ), destination ( " +

455. destination +

456. " ) ( session || local || data ) et key " +

457. " doivent être de type text !" );

458. }

459. },

460. "_sessionRelocate" : function( key, destination ){

461. try {

462. // getItem retourne null si key n'existe pas !

463. var jsonValue = window.sessionStorage.getItem( key );

465. if ( jsonValue ){

466. // removeItem ne fait rien si key n'existe pas !

467. window.sessionStorage.removeItem( key );

469. switch( destination ){

470. case "local":

471. this._localSet( key, jsonValue );

472. break;

473. case "data":

474. this._dataSet( key, jsonValue );

475. break;

476. default:

477. $.error( "Cette destination (" + destination + ") n'existe pas !" );

478. }

479. }

480. }

481. catch( e ){

482. $.error( "dvjhStorage, sessionRelocate : " + e.message );

483. }

484. },

485. "_localRelocate" : function( key, destination ){

486. try {

487. // getItem retourne null si key n'existe pas !

488. var jsonValue = window.localStorage.getItem( key );

490. if ( jsonValue ){

491. // removeItem ne fait rien si key n'existe pas !

492. window.localStorage.removeItem( key );

494. switch( destination ){

495. case "session":

496. this._sessionSet( key, jsonValue );

497. break;

498. case "data":

499. this._dataSet( key, jsonValue );

500. break;

501. default:

502. $.error( "Cette destination (" + destination + ") n'existe pas !" );

503. }

504. }

505. }

506. catch( e ){

507. $.error( "dvjhStorage, localRelocate : " + e.message );

508. }

509. },

510. "_dataRelocate" : function( key, destination ){

511. try {

512. var objAnonyme = this.jObj.data( "dvjhStorage" ),

513. jsonValue = null;

515. if ( key in objAnonyme ){

516. jsonValue = objAnonyme[ key ];

517. delete objAnonyme[ key ];

518. }

520. this.jObj.data( "dvjhStorage", objAnonyme )

522. if ( jsonValue ){

523. switch( destination ){

524. case "local":

525. this._localSet( key, jsonValue );

526. break;

527. case "session":

528. this._sessionSet( key, jsonValue );

529. break;

530. default:

531. $.error( "Cette destination (" + destination + ") n'existe pas !" );

532. }

533. }

534. }

535. catch( e ){

536. $.error( "dvjhStorage, dataRelocate : " + e.message );

537. }

538. },

539. "copy" : function( params ){

540. var origine = params.shift(),

541. destination = params.shift(),

542. key = params.shift();

544. if ( typeof origine === "string" &&

545. typeof destination === "string" &&

546. typeof key === "string" ){

548. if ( this.options.boolDebug ){

549. console.log( "copy, origine : ", origine );

550. console.log( "copy, destination : ", destination );

551. console.log( "copy, key : ", key );

552. }

554. switch( origine ){

555. case "session":

556. this._sessionCopy( key, destination );

557. break;

558. case "local":

559. this._localCopy( key, destination );

560. break;

561. case "data":

562. this._dataCopy( key, destination );

563. break;

564. default:

565. $.error( "Cette origine (" + origine + ") n'existe pas !" );

566. }

567. } else {

568. $.error( "dvjhStorageMethods, copy : les paramètres origine ( " +

569. origine +

570. " ) ( session || local || data ), destination ( " +

571. destination +

572. " ) ( session || local || data ) et key " +

573. " doivent être de type text !" );

574. }

575. },

576. "_sessionCopy" : function( key, destination ){

577. try {

578. // getItem retourne null si key n'existe pas !

579. var jsonValue = window.sessionStorage.getItem( key );

581. if ( jsonValue ){

582. switch( destination ){

583. case "local":

584. this._localSet( key, jsonValue );

585. break;

586. case "data":

587. this._dataSet( key, jsonValue );

588. break;

589. default:

590. $.error( "Cette destination (" + destination + ") n'existe pas !" );

591. }

592. }

593. }

594. catch( e ){

595. $.error( "dvjhStorage, sessionCopy : " + e.message );

596. }

597. },

598. "_localCopy" : function( key, destination ){

599. try {

600. // getItem retourne null si key n'existe pas !

601. var jsonValue = window.localStorage.getItem( key );

603. if ( jsonValue ){

604. switch( destination ){

605. case "session":

606. this._sessionSet( key, jsonValue );

607. break;

608. case "data":

609. this._dataSet( key, jsonValue );

610. break;

611. default:

612. $.error( "Cette destination (" + destination + ") n'existe pas !" );

613. }

614. }

615. }

616. catch( e ){

617. $.error( "dvjhStorage, localCopy : " + e.message );

618. }

619. },

620. "_dataCopy" : function( key, destination ){

621. try {

622. var objAnonyme = this.jObj.data( "dvjhStorage" ),

623. jsonValue = null;

625. if ( key in objAnonyme ){

626. jsonValue = objAnonyme[ key ];

627. }

629. if ( jsonValue ){

630. switch( destination ){

631. case "local":

632. this._localSet( key, jsonValue );

633. break;

634. case "session":

635. this._sessionSet( key, jsonValue );

636. break;

637. default:

638. $.error( "Cette destination (" + destination + ") n'existe pas !" );

639. }

640. }

641. }

642. catch( e ){

643. $.error( "dvjhStorage, dataCopy : " + e.message );

644. }

645. },

646. "setOption" : function( params ){

647. var option = params.shift(),

648. value = params.shift();

650. if ( ! option || ! value ){

651. $.error( "Les paramètres ne sont pas conformes : ( " +

652. option + ", " + value + " )." );

653. }

655. if ( option in this.options ){

656. switch( option ){

657. case "boolDebug":

658. this._setBoolDebug( value );

659. break;

660. default:

661. $.error( "Cette option existe mais elle n'est \

662. pas publique !" );

663. };

665. } else {

666. $.error( "Cette option n'existe pas !" );

667. }

668. },

669. "_setBoolDebug" : function( value ){

670. if ( typeof value === "boolean" ){

671. this.options.boolDebug = value;

672. }

673. },

674. "getOption" : function( params ){

675. var option = params.shift(),

676. callback = params.shift() || function(){},

677. name = "getOption." + this._copyright.objMethodsName;

679. if ( ! option ){

680. $.error( "getOption : le paramètre n'est pas conforme : ( " +

681. option + " )." );

682. }

684. /*

685. * Objet et array : attention de toujours transmettre une copie !

686. */

688. if ( option in this.options ){

689. switch( option ){

690. case "boolDebug":

691. var value = this.options.boolDebug;

692. this.jObj.data( name, value );

693. callback( option, value );

694. break;

695. default:

696. $.error( "getOption : cette option existe mais " +

697. "elle n'est pas publique !" );

698. };

699. } else {

700. $.error( "getOption : cette option n'existe pas !" );

701. }

702. }

703. };

705. // Ajouts de méthodes (plugin) au prototype de l'objet jQuery ($.fn).

706. $.extend( $.fn, {

707. "dvjhStorage" : function(){ // un plugin multitâche

708. return dvjhPluginCreate.call( this, dvjhStorageMethods, arguments );

709. }

710. });

712. return {

713. "initStorage" : function( selector ){

714. /*

715. * La seule méthode disponible pour l'initialisation

716. * d'un dvjhStorage.

717. *

718. * Cette méthode garantit que l'on ne traite qu'un seul objet

719. * jQuery à la fois. Dans le cas contraire, on aurait autant

720. * d'opérations sur le navigateur (localStorage et

721. * sessionStorage) qu'il y a d'instances dans selector.

722. *

723. * Si le navigateur n'est pas compatible jObj est null !

724. */

725. var jObj = null;

727. try {

728. if ( typeof selector === "string" &&

729. $.isFunction( $( selector ).is ) ){

731. jObj = $( selector ).eq(0).dvjhStorage();

732. }

733. }

734. catch( e ){

735. console.log( "dvjhStorage, initStorage : " + e.message );

736. }

738. return jObj;

739. },

740. "storageObjMethodsName" : dvjhStorageMethods._copyright.objMethodsName;

741. "storageObjMethodsDefaultOptions" : function( objOptions ){

742. /*

743. * Modifications des options par défaut.

744. *

745. * Ne modifiez pas ce code sans nécessité !

746. */

747. if ( $.isPlainObject( objOptions ) && ! $.isEmptyObject( objOptions ) ){

748. $.extend( dvjhStorageMethods._options, objOptions );

749. }

750. }

751. };

752. })( jQuery.sub() );

Rappel : pour tester les codes, veuillez charger le ZIP.

Utilisation du plugin, extrait de dvjhStorage.html :

dvjhStorage.html

1. $(function(){

2. // fonction de rappel pour traiter le résultat de "get"

3. function getResult( key, value ){

4. console.log( "getResult, key = ", key, ", value = ", value )

5. }

7. // fonction de rappel pour traiter le résultat de "has"

8. function hasResult( key, boolObj ){

9. console.log( "hasResult, key = ", key, ", boolObj = " );

11. for (var n in boolObj){

12. console.log( "prop = ", n, ", value = ", boolObj[ n ] );

13. }

14. }

16. try {

17. /*

18. * Initialisation du premier élément du DOM

19. * contenu dans le sélecteur.

20. *

21. * Bien entendu, dans une page Web, plusieurs éléments du DOM

22. * peuvent posséder un espace de stockage (data) distinct.

23. *

24. * Pour sélectionner un seul élément du DOM, utilisez une

25. * classe spécifique ou un ID.

26. *

27. * Si le navigateur n'est pas compatible, jObjStorage est null !

28. */

29. var jObjStorage = dvjh.initStorage( "section.conteneur" );

31. if ( jObjStorage ){

32. /*

33. * L'usage d'un espace de noms pour étiqueter les

34. * données sauvegardées n'est pas une obligation

35. * mais une recommandation car cela diminue le

36. * risque d'une collision de noms dans le

37. * navigateur (session et local storage).

38. */

39. var strNamespace = "sectionConteneur";

41. /*

42. * L'objet JavaScript qui sera sauvegardé au format JSON

43. */

44. var mesDatas = {

45. "maProp" : "Daniel Hagnoul",

46. "monArray" : [ "hello", 42.42, -42, "bye" ],

47. "monObj" : {

48. "uneProp" : "dvjh",

49. "unArray" : [ "bonjour", 42.42, -42, "bonsoir" ]

50. }

51. };

53. var dataKey = "mesDatas." + strNamespace;

55. // stocke dataKey et sa valeur dans data

56. jObjStorage.dvjhStorage( "set", "data", dataKey, mesDatas );

58. // trouve dataKey et sa valeur dans data et place une copie

59. // dans une éventuelle fonction de rappel (callback)

60. jObjStorage.dvjhStorage( "get", "data", dataKey, getResult );

62. // et dans :

63. var lesDatas = jObjStorage.data( "get." + dvjh.storageObjMethodsName );

65. // lesDatas est un véritable objet JavaScript

66. console.log( "lesDatas = ", lesDatas );

68. // une copie des options du plugin pour jObjStorage

69. console.log( $.extend( true, {}, jObjStorage.data( dvjh.storageObjMethodsName ) ) );

71. // une copie du contenu du stockage dans data

72. console.log( $.extend( true, {}, jObjStorage.data( "dvjhStorage" ) ) );

74. // supprime dataKey et sa valeur dans data

75. //jObjStorage.dvjhStorage( "remove", "data", dataKey );

77. // console.log( $.extend( true, {}, jObjStorage.data( "dvjhStorage" ) ) );

79. // supprime toutes les données dans data

80. //jObjStorage.dvjhStorage( "clear", "data" );

82. // copie dataKey et sa valeur dans le sessionStorage du navigateur

83. jObjStorage.dvjhStorage( "copy", "data", "session", dataKey );

85. //console.log( $.extend( true, {}, jObjStorage.data( "dvjhStorage" ) ) );

87. // copie dataKey et sa valeur dans le localStorage du navigateur

88. // puis supprime dataKey et sa valeur dans data

89. jObjStorage.dvjhStorage( "relocate", "data", "local", dataKey );

91. console.log( $.extend( true, {}, jObjStorage.data( "dvjhStorage" ) ) );

93. // cherche si dataKey existe dans data et dans le navigateur

94. // place le résultat dans une éventuelle fonction de rappel (callback)

95. jObjStorage.dvjhStorage( "has", dataKey, hasResult );

97. // et dans :

98. console.log( jObjStorage.data( "has." + dvjh.storageObjMethodsName ) );

100. // efface toutes les données dans data et dans le navigateur

101. jObjStorage.dvjhStorage( "clearAll" );

102. }

103. }

104. catch( e ){

105. alert( "dvjhStorage, " + e.message );

106. }

107. });

V - Remerciements

Un grand merci à ceux qui auront le courage de lire et de tester mon travail !

Un grand merci au correcteur Claude LELOUP pour son excellent travail.