AutoSave.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.editor.plugins.AutoSave"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.editor.plugins.AutoSave"] = true;
  8. dojo.provide("dojox.editor.plugins.AutoSave");
  9. dojo.require("dojo.string");
  10. dojo.require("dojo.date.locale");
  11. dojo.require("dijit.Dialog");
  12. dojo.require("dijit.MenuItem");
  13. dojo.require("dijit.Menu");
  14. dojo.require("dijit.form.Button");
  15. dojo.require("dijit.form.ComboBox");
  16. dojo.require("dijit.form.TextBox");
  17. dojo.require("dijit.TooltipDialog");
  18. dojo.require("dijit._editor._Plugin");
  19. dojo.require("dijit.form.Button");
  20. dojo.require("dojo.i18n");
  21. dojo.require("dojox.editor.plugins.Save");
  22. dojo.requireLocalization("dojox.editor.plugins", "AutoSave", null, "ROOT,ar,bg,ca,cs,da,de,el,es,fi,fr,he,hr,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw");
  23. dojo.experimental("dojox.editor.plugins.AutoSave");
  24. dojo.declare("dojox.editor.plugins._AutoSaveSettingDialog", [dijit._Widget, dijit._Templated], {
  25. // dialogTitle [public] String
  26. // The tile of the Auto-Save setting dialog
  27. dialogTitle: "",
  28. // dialogDescription [public] String
  29. // The description of the Auto-Save setting dialog
  30. dialogDescription: "",
  31. // paramName [public] String
  32. // The name of the parameter (Auto-Save Interval)
  33. paramName: "",
  34. // paramLabel [public] String
  35. // Minute
  36. paramLabel: "",
  37. // btnOk [public] String
  38. // The label of the OK button
  39. btnOk: "",
  40. // btnCancel [public] String
  41. // The label of the Cancel button
  42. btnCancel: "",
  43. widgetsInTemplate: true,
  44. templateString:
  45. "<span id='${dialogId}' class='dijit dijitReset dijitInline' tabindex='-1'>" +
  46. "<div dojoType='dijit.Dialog' title='${dialogTitle}' dojoAttachPoint='dialog' " +
  47. "class='dijitEditorAutoSaveSettingDialog'>" +
  48. "<div tabindex='-1'>${dialogDescription}</div>" +
  49. "<div tabindex='-1' class='dijitEditorAutoSaveSettingInputArea'>${paramName}</div>" +
  50. "<div class='dijitEditorAutoSaveSettingInputArea' tabindex='-1'>" +
  51. "<input class='textBox' dojoType='dijit.form.TextBox' id='${textBoxId}' required='false' intermediateChanges='true' " +
  52. "selectOnClick='true' required='true' dojoAttachPoint='intBox' " +
  53. "dojoAttachEvent='onKeyDown: _onKeyDown, onChange: _onChange'/>" +
  54. "<label class='dijitLeft dijitInline boxLabel' " +
  55. "for='${textBoxId}' tabindex='-1'>${paramLabel}</label>" +
  56. "</div>" +
  57. "<div class='dijitEditorAutoSaveSettingButtonArea' tabindex='-1'>" +
  58. "<button dojoType='dijit.form.Button' dojoAttachEvent='onClick: onOk'>${btnOk}</button>" +
  59. "<button dojoType='dijit.form.Button' dojoAttachEvent='onClick: onCancel'>${btnCancel}</button>" +
  60. "</div>" +
  61. "</div>" +
  62. "</span>",
  63. postMixInProperties: function(){
  64. this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
  65. this.dialogId = this.id + "_dialog";
  66. this.textBoxId = this.id + "_textBox";
  67. },
  68. show: function(){
  69. // summary:
  70. // Display the setting dialog. If the internal interval value is ""
  71. // set it to zero
  72. // tags:
  73. // public
  74. if(this._value == ""){
  75. this._value = 0;
  76. this.intBox.set("value", 0);
  77. }else{
  78. this.intBox.set("value", this._value);
  79. }
  80. this.dialog.show();
  81. dijit.selectInputText(this.intBox.focusNode);
  82. },
  83. hide: function(){
  84. // summray:
  85. // Hide the setting dialog.
  86. // tags:
  87. // public
  88. this.dialog.hide();
  89. },
  90. onOk: function(){
  91. // summary:
  92. // Handle the OK event and close the dialog.
  93. // tags:
  94. // public
  95. this.dialog.hide();
  96. },
  97. onCancel: function(){
  98. // summary:
  99. // Handle the Cancel event and close the dialog.
  100. // tags:
  101. // public
  102. this.dialog.hide();
  103. },
  104. _onKeyDown: function(evt){
  105. // summary:
  106. // Handle the keydown event
  107. // tags:
  108. // private
  109. if(evt.keyCode == dojo.keys.ENTER){
  110. this.onOk();
  111. }
  112. },
  113. _onChange: function(/*String*/ val){
  114. // summary:
  115. // Check if the value is between 1 - 999.
  116. // tags:
  117. // public
  118. if(this._isValidValue(val)){
  119. this._value = val;
  120. }else{
  121. this.intBox.set("value", this._value);
  122. }
  123. },
  124. _setValueAttr: function(/*String*/ val){
  125. // summary:
  126. // Set the value attribute if it is acceptable
  127. // val:
  128. // The invertal value
  129. // tags:
  130. // private
  131. if(this._isValidValue(val)){
  132. this._value = val;
  133. }
  134. },
  135. _getValueAttr: function(){
  136. // summary:
  137. // Get the interval value
  138. // tags:
  139. // protected
  140. return this._value;
  141. },
  142. _isValidValue: function(/*String*/ val){
  143. // summary:
  144. // Check if this value between 1- 999
  145. // tags:
  146. // private
  147. var regExp = /^\d{0,3}$/,
  148. _v = String(val);
  149. return Boolean(_v.match ? _v.match(regExp) : "");
  150. }
  151. });
  152. dojo.declare("dojox.editor.plugins.AutoSave", dojox.editor.plugins.Save, {
  153. // summary:
  154. // This plugin provides the auto save capability to the editor. The
  155. // plugin saves the content of the editor in interval. When
  156. // the save action is performed, the document in the editor frame
  157. // will be posted to the URL provided, or none, if none provided.
  158. // url [public] String
  159. // The URL to POST the content back to. Used by the save function.
  160. url: "",
  161. // logErrors [public] boolean
  162. // Boolean flag to indicate that the default action for save and
  163. // error handlers is to just log to console. Default is true.
  164. logResults: true,
  165. // interval [public] Number
  166. // The interval to perform the save action.
  167. interval: 0,
  168. // _iconClassPrefix [private] String
  169. // This prefix of the CSS class
  170. _iconClassPrefix: "dijitEditorIconAutoSave",
  171. // _MIN [private const] Number
  172. // Default 1 minute
  173. _MIN: 60000,
  174. _setIntervalAttr: function(val){
  175. // summary:
  176. // Set the interval value.
  177. // Delay the boundary check to _isValidValue of the dialog class
  178. // val:
  179. // The interval value.
  180. // tags:
  181. // private
  182. this.interval = val;
  183. },
  184. _getIntervalAttr: function(){
  185. // summary:
  186. // Get the interval value
  187. // tags:
  188. // private
  189. return this._interval;
  190. },
  191. setEditor: function(editor){
  192. // summary:
  193. // Over-ride for the setting of the editor. No toggle button for
  194. // this plugin. And start to save the content of the editor in
  195. // interval
  196. // editor: Object
  197. // The editor to configure for this plugin to use.
  198. this.editor = editor;
  199. this._strings = dojo.i18n.getLocalization("dojox.editor.plugins", "AutoSave");
  200. this._initButton();
  201. this._saveSettingDialog = new dojox.editor.plugins._AutoSaveSettingDialog({
  202. "dialogTitle": this._strings["saveSettingdialogTitle"],
  203. "dialogDescription": this._strings["saveSettingdialogDescription"],
  204. "paramName": this._strings["saveSettingdialogParamName"],
  205. "paramLabel": this._strings["saveSettingdialogParamLabel"],
  206. "btnOk": this._strings["saveSettingdialogButtonOk"],
  207. "btnCancel": this._strings["saveSettingdialogButtonCancel"]
  208. });
  209. this.connect(this._saveSettingDialog, "onOk", "_onDialogOk");
  210. var pd = this._promDialog = new dijit.TooltipDialog();
  211. pd.startup();
  212. pd.set("content", "");
  213. },
  214. _initButton: function(){
  215. var menu = new dijit.Menu({
  216. style: "display: none"
  217. }),
  218. menuItemSave = new dijit.MenuItem({
  219. iconClass: this._iconClassPrefix + "Default " + this._iconClassPrefix,
  220. label: this._strings["saveLabel"]
  221. }),
  222. menuItemAutoSave = this._menuItemAutoSave = new dijit.MenuItem({
  223. iconClass: this._iconClassPrefix + "Setting " + this._iconClassPrefix,
  224. label: this._strings["saveSettingLabelOn"]
  225. });
  226. menu.addChild(menuItemSave);
  227. menu.addChild(menuItemAutoSave);
  228. this.button = new dijit.form.ComboButton({
  229. label: this._strings["saveLabel"],
  230. iconClass: this._iconClassPrefix + "Default " + this._iconClassPrefix,
  231. showLabel: false,
  232. dropDown: menu
  233. });
  234. this.connect(this.button, "onClick", "_save");
  235. this.connect(menuItemSave, "onClick", "_save");
  236. this._menuItemAutoSaveClickHandler = dojo.connect(menuItemAutoSave, "onClick", this, "_showAutSaveSettingDialog");
  237. },
  238. _showAutSaveSettingDialog: function(){
  239. // summary:
  240. // Show the setting dialog
  241. // tags:
  242. // private
  243. var dialog = this._saveSettingDialog;
  244. dialog.set("value", this.interval);
  245. dialog.show();
  246. },
  247. _onDialogOk: function(){
  248. // summary:
  249. // If the interval is set (larger than 0), enable auto-save.
  250. // tags:
  251. // private
  252. var interval = this.interval = this._saveSettingDialog.get("value") * this._MIN;
  253. if(interval > 0){
  254. this._setSaveInterval(interval);
  255. // Change the menu "Set Auto-Save Interval..." to "Turn off Auto-Save"
  256. // Connect it to another handler that terminates the auto-save.
  257. dojo.disconnect(this._menuItemAutoSaveClickHandler);
  258. this._menuItemAutoSave.set("label", this._strings["saveSettingLabelOff"]);
  259. this._menuItemAutoSaveClickHandler = dojo.connect(this._menuItemAutoSave, "onClick", this, "_onStopClick");
  260. // Change the icon of the main button to auto-save style
  261. this.button.set("iconClass", this._iconClassPrefix + "Setting " + this._iconClassPrefix);
  262. }
  263. },
  264. _onStopClick: function(){
  265. // summary:
  266. // Stop auto-save
  267. // tags:
  268. // private
  269. this._clearSaveInterval();
  270. // Change the menu "Turn off Auto-Save" to "Set Auto-Save Interval...".
  271. // Connect it to another handler that show the setting dialog.
  272. dojo.disconnect(this._menuItemAutoSaveClickHandler);
  273. this._menuItemAutoSave.set("label", this._strings["saveSettingLabelOn"]);
  274. this._menuItemAutoSaveClickHandler = dojo.connect(this._menuItemAutoSave, "onClick", this, "_showAutSaveSettingDialog");
  275. // Change the icon of the main button
  276. this.button.set("iconClass", this._iconClassPrefix + "Default " + this._iconClassPrefix);
  277. },
  278. _setSaveInterval: function(/*Number*/ interval){
  279. // summary:
  280. // Function to trigger saving of the editor document
  281. // tags:
  282. // private
  283. if(interval <= 0){
  284. return;
  285. }
  286. this._clearSaveInterval();
  287. this._intervalHandler = setInterval(dojo.hitch(this, function(){
  288. if(!this._isWorking && !this.get("disabled")){
  289. // If the plugin is not disabled (ViewSource, etc.)
  290. // and not working. Do saving!
  291. this._isWorking = true;
  292. this._save();
  293. }
  294. }), interval);
  295. },
  296. _clearSaveInterval: function(){
  297. if(this._intervalHandler){
  298. clearInterval(this._intervalHandler);
  299. this._intervalHandler = null;
  300. }
  301. },
  302. onSuccess: function(resp, ioargs){
  303. // summary:
  304. // User over-ridable save success function for editor content.
  305. // resp:
  306. // The response from the server, if any, in text format.
  307. // tags:
  308. // public
  309. this.button.set("disabled", false);
  310. // Show the successful message
  311. this._promDialog.set("content", dojo.string.substitute(
  312. this._strings["saveMessageSuccess"], {"0": dojo.date.locale.format(new Date(), {selector: "time"})}));
  313. dijit.popup.open({popup: this._promDialog, around: this.button.domNode});
  314. this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
  315. clearTimeout(this._promDialogTimeout);
  316. this._promDialogTimeout = null;
  317. dijit.popup.close(this._promDialog);
  318. }), 3000);
  319. this._isWorking = false;
  320. if(this.logResults){
  321. console.log(resp);
  322. }
  323. },
  324. onError: function(error, ioargs){
  325. // summary:
  326. // User over-ridable save success function for editor content.
  327. // resp:
  328. // The response from the server, if any, in text format.
  329. // tags:
  330. // public
  331. this.button.set("disabled", false);
  332. // Show the failure message
  333. this._promDialog.set("content", dojo.string.substitute(
  334. this._strings["saveMessageFail"], {"0": dojo.date.locale.format(new Date(), {selector: "time"})}));
  335. dijit.popup.open({popup: this._promDialog, around: this.button.domNode});
  336. this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
  337. clearTimeout(this._promDialogTimeout);
  338. this._promDialogTimeout = null;
  339. dijit.popup.close(this._promDialog);
  340. }), 3000);
  341. this._isWorking = false;
  342. if(this.logResults){
  343. console.log(error);
  344. }
  345. },
  346. destroy: function(){
  347. // summary:
  348. // Cleanup of our plugin.
  349. this.inherited(arguments);
  350. this._menuItemAutoSave = null;
  351. if(this._promDialogTimeout){
  352. clearTimeout(this._promDialogTimeout);
  353. this._promDialogTimeout = null;
  354. dijit.popup.close(this._promDialog);
  355. }
  356. this._clearSaveInterval();
  357. if(this._saveSettingDialog){
  358. this._saveSettingDialog.destroyRecursive();
  359. this._destroyRecursive = null;
  360. }
  361. if(this._menuItemAutoSaveClickHandler){
  362. dojo.disconnect(this._menuItemAutoSaveClickHandler);
  363. this._menuItemAutoSaveClickHandler = null;
  364. }
  365. }
  366. });
  367. // Register this plugin.
  368. dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
  369. if(o.plugin){ return; }
  370. var name = o.args.name.toLowerCase();
  371. if(name == "autosave"){
  372. o.plugin = new dojox.editor.plugins.AutoSave({
  373. url: ("url" in o.args) ? o.args.url : "",
  374. logResults: ("logResults" in o.args) ? o.args.logResults : true,
  375. interval: ("interval" in o.args) ? o.args.interval : 5
  376. });
  377. }
  378. });
  379. }