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