]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dijit/Editor.js
Comment class stub
[eow] / static / dojo-release-1.1.1 / dijit / Editor.js
1 if(!dojo._hasResource["dijit.Editor"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dijit.Editor"] = true;
3 dojo.provide("dijit.Editor");
4 dojo.require("dijit._editor.RichText");
5 dojo.require("dijit.Toolbar");
6 dojo.require("dijit._editor._Plugin");
7 dojo.require("dijit._Container");
8 dojo.require("dojo.i18n");
9 dojo.requireLocalization("dijit._editor", "commands", null, "zh,pt,da,tr,ru,de,sv,ja,he,fi,nb,el,ar,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu,ROOT");
10
11 dojo.declare(
12         "dijit.Editor",
13         dijit._editor.RichText,
14         {
15         // summary: A rich-text Editing widget
16
17                 // plugins: Array
18                 //              a list of plugin names (as strings) or instances (as objects)
19                 //              for this widget.
20                 plugins: null,
21
22                 // extraPlugins: Array
23                 //              a list of extra plugin names which will be appended to plugins array
24                 extraPlugins: null,
25
26                 constructor: function(){
27                         if(!dojo.isArray(this.plugins)){
28                                 this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|",
29                                 "insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull"/*"createLink"*/];
30                         }
31
32                         this._plugins=[];
33                         this._editInterval = this.editActionInterval * 1000;
34                 },
35
36                 postCreate: function(){
37                         //for custom undo/redo
38                         if(this.customUndo){
39                                 dojo['require']("dijit._editor.range");
40                                 this._steps=this._steps.slice(0);
41                                 this._undoedSteps=this._undoedSteps.slice(0);
42 //                              this.addKeyHandler('z',this.KEY_CTRL,this.undo);
43 //                              this.addKeyHandler('y',this.KEY_CTRL,this.redo);
44                         }
45                         if(dojo.isArray(this.extraPlugins)){
46                                 this.plugins=this.plugins.concat(this.extraPlugins);
47                         }
48
49 //                      try{
50                         this.inherited(arguments);
51 //                      dijit.Editor.superclass.postCreate.apply(this, arguments);
52
53                         this.commands = dojo.i18n.getLocalization("dijit._editor", "commands", this.lang);
54
55                         if(!this.toolbar){
56                                 // if we haven't been assigned a toolbar, create one
57                                 this.toolbar = new dijit.Toolbar({});
58                                 dojo.place(this.toolbar.domNode, this.editingArea, "before");
59                         }
60
61                         dojo.forEach(this.plugins, this.addPlugin, this);
62                         this.onNormalizedDisplayChanged(); //update toolbar button status
63 //                      }catch(e){ console.debug(e); }
64                 },
65                 destroy: function(){
66                         dojo.forEach(this._plugins, function(p){
67                                 if(p && p.destroy){
68                                         p.destroy();
69                                 }
70                         });
71                         this._plugins=[];
72                         this.toolbar.destroy(); delete this.toolbar;
73                         this.inherited(arguments);
74                 },
75                 addPlugin: function(/*String||Object*/plugin, /*Integer?*/index){
76                         //      summary:
77                         //              takes a plugin name as a string or a plugin instance and
78                         //              adds it to the toolbar and associates it with this editor
79                         //              instance. The resulting plugin is added to the Editor's
80                         //              plugins array. If index is passed, it's placed in the plugins
81                         //              array at that index. No big magic, but a nice helper for
82                         //              passing in plugin names via markup.
83                         //      plugin: String, args object or plugin instance. Required.
84                         //      args: This object will be passed to the plugin constructor.
85                         //      index:  
86                         //              Integer, optional. Used when creating an instance from
87                         //              something already in this.plugins. Ensures that the new
88                         //              instance is assigned to this.plugins at that index.
89                         var args=dojo.isString(plugin)?{name:plugin}:plugin;
90                         if(!args.setEditor){
91                                 var o={"args":args,"plugin":null,"editor":this};
92                                 dojo.publish(dijit._scopeName + ".Editor.getPlugin",[o]);
93                                 if(!o.plugin){
94                                         var pc = dojo.getObject(args.name);
95                                         if(pc){
96                                                 o.plugin=new pc(args);
97                                         }
98                                 }
99                                 if(!o.plugin){
100                                         console.warn('Cannot find plugin',plugin);
101                                         return;
102                                 }
103                                 plugin=o.plugin;
104                         }
105                         if(arguments.length > 1){
106                                 this._plugins[index] = plugin;
107                         }else{
108                                 this._plugins.push(plugin);
109                         }
110                         plugin.setEditor(this);
111                         if(dojo.isFunction(plugin.setToolbar)){
112                                 plugin.setToolbar(this.toolbar);
113                         }
114                 },
115                 /* beginning of custom undo/redo support */
116
117                 // customUndo: Boolean
118                 //              Whether we shall use custom undo/redo support instead of the native
119                 //              browser support. By default, we only enable customUndo for IE, as it
120                 //              has broken native undo/redo support. Note: the implementation does
121                 //              support other browsers which have W3C DOM2 Range API.
122                 customUndo: dojo.isIE,
123
124                 //      editActionInterval: Integer
125                 //              When using customUndo, not every keystroke will be saved as a step.
126                 //              Instead typing (including delete) will be grouped together: after
127                 //              a user stop typing for editActionInterval seconds, a step will be
128                 //              saved; if a user resume typing within editActionInterval seconds,
129                 //              the timeout will be restarted. By default, editActionInterval is 3
130                 //              seconds.
131                 editActionInterval: 3,
132                 beginEditing: function(cmd){
133                         if(!this._inEditing){
134                                 this._inEditing=true;
135                                 this._beginEditing(cmd);
136                         }
137                         if(this.editActionInterval>0){
138                                 if(this._editTimer){
139                                         clearTimeout(this._editTimer);
140                                 }
141                                 this._editTimer = setTimeout(dojo.hitch(this, this.endEditing), this._editInterval);
142                         }
143                 },
144                 _steps:[],
145                 _undoedSteps:[],
146                 execCommand: function(cmd){
147                         if(this.customUndo && (cmd=='undo' || cmd=='redo')){
148                                 return this[cmd]();
149                         }else{
150                                 try{
151                                         if(this.customUndo){
152                                                 this.endEditing();
153                                                 this._beginEditing();
154                                         }
155                                         var r = this.inherited('execCommand',arguments);
156                                         if(this.customUndo){
157                                                 this._endEditing();
158                                         }
159                                         return r;
160                                 }catch(e){
161                                         if(dojo.isMoz && /copy|cut|paste/.test(cmd)){
162                                                 // Warn user of platform limitation.  Cannot programmatically access keyboard. See ticket #4136
163                                                 var sub = dojo.string.substitute,
164                                                         accel = {cut:'X', copy:'C', paste:'V'},
165                                                         isMac = navigator.userAgent.indexOf("Macintosh") != -1;
166                                                 alert(sub(this.commands.systemShortcutFF,
167                                                         [this.commands[cmd], sub(this.commands[isMac ? 'appleKey' : 'ctrlKey'], [accel[cmd]])]));
168                                         }
169                                         return false;
170                                 }
171                         }
172                 },
173                 queryCommandEnabled: function(cmd){
174                         if(this.customUndo && (cmd=='undo' || cmd=='redo')){
175                                 return cmd=='undo'?(this._steps.length>1):(this._undoedSteps.length>0);
176                         }else{
177                                 return this.inherited('queryCommandEnabled',arguments);
178                         }
179                 },
180                 _moveToBookmark: function(b){
181                         var bookmark=b;
182                         if(dojo.isIE){
183                                 if(dojo.isArray(b)){//IE CONTROL
184                                         bookmark=[];
185                                         dojo.forEach(b,function(n){
186                                                 bookmark.push(dijit.range.getNode(n,this.editNode));
187                                         },this);
188                                 }
189                         }else{//w3c range
190                                 var r=dijit.range.create();
191                                 r.setStart(dijit.range.getNode(b.startContainer,this.editNode),b.startOffset);
192                                 r.setEnd(dijit.range.getNode(b.endContainer,this.editNode),b.endOffset);
193                                 bookmark=r;
194                         }
195                         dojo.withGlobal(this.window,'moveToBookmark',dijit,[bookmark]);
196                 },
197                 _changeToStep: function(from,to){
198                         this.setValue(to.text);
199                         var b=to.bookmark;
200                         if(!b){ return; }
201                         this._moveToBookmark(b);
202                 },
203                 undo: function(){
204 //                      console.log('undo');
205                         this.endEditing(true);
206                         var s=this._steps.pop();
207                         if(this._steps.length>0){
208                                 this.focus();
209                                 this._changeToStep(s,this._steps[this._steps.length-1]);
210                                 this._undoedSteps.push(s);
211                                 this.onDisplayChanged();
212                                 return true;
213                         }
214                         return false;
215                 },
216                 redo: function(){
217 //                      console.log('redo');
218                         this.endEditing(true);
219                         var s=this._undoedSteps.pop();
220                         if(s && this._steps.length>0){
221                                 this.focus();
222                                 this._changeToStep(this._steps[this._steps.length-1],s);
223                                 this._steps.push(s);
224                                 this.onDisplayChanged();
225                                 return true;
226                         }
227                         return false;
228                 },
229                 endEditing: function(ignore_caret){
230                         if(this._editTimer){
231                                 clearTimeout(this._editTimer);
232                         }
233                         if(this._inEditing){
234                                 this._endEditing(ignore_caret);
235                                 this._inEditing=false;
236                         }
237                 },
238                 _getBookmark: function(){
239                         var b=dojo.withGlobal(this.window,dijit.getBookmark);
240                         var tmp=[];
241                         if(dojo.isIE){
242                                 if(dojo.isArray(b)){//CONTROL
243                                         dojo.forEach(b,function(n){
244                                                 tmp.push(dijit.range.getIndex(n,this.editNode).o);
245                                         },this);
246                                         b=tmp;
247                                 }
248                         }else{//w3c range
249                                 tmp=dijit.range.getIndex(b.startContainer,this.editNode).o;
250                                 b={startContainer:tmp,
251                                         startOffset:b.startOffset,
252                                         endContainer:b.endContainer===b.startContainer?tmp:dijit.range.getIndex(b.endContainer,this.editNode).o,
253                                         endOffset:b.endOffset};
254                         }
255                         return b;
256                 },
257                 _beginEditing: function(cmd){
258                         if(this._steps.length===0){
259                                 this._steps.push({'text':this.savedContent,'bookmark':this._getBookmark()});
260                         }
261                 },
262                 _endEditing: function(ignore_caret){
263                         var v=this.getValue(true);
264
265                         this._undoedSteps=[];//clear undoed steps
266                         this._steps.push({text: v, bookmark: this._getBookmark()});
267                 },
268                 onKeyDown: function(e){
269                         if(!this.customUndo){
270                                 this.inherited('onKeyDown',arguments);
271                                 return;
272                         }
273                         var k = e.keyCode, ks = dojo.keys;
274                         if(e.ctrlKey && !e.altKey){//undo and redo only if the special right Alt + z/y are not pressed #5892
275                                 if(k == 90 || k == 122){ //z
276                                         dojo.stopEvent(e);
277                                         this.undo();
278                                         return;
279                                 }else if(k == 89 || k == 121){ //y
280                                         dojo.stopEvent(e);
281                                         this.redo();
282                                         return;
283                                 }
284                         }
285                         this.inherited('onKeyDown',arguments);
286
287                         switch(k){
288                                         case ks.ENTER:
289                                         case ks.BACKSPACE:
290                                         case ks.DELETE:
291                                                 this.beginEditing();
292                                                 break;
293                                         case 88: //x
294                                         case 86: //v
295                                                 if(e.ctrlKey && !e.altKey && !e.metaKey){
296                                                         this.endEditing();//end current typing step if any
297                                                         if(e.keyCode == 88){
298                                                                 this.beginEditing('cut');
299                                                                 //use timeout to trigger after the cut is complete
300                                                                 setTimeout(dojo.hitch(this, this.endEditing), 1);
301                                                         }else{
302                                                                 this.beginEditing('paste');
303                                                                 //use timeout to trigger after the paste is complete
304                                                                 setTimeout(dojo.hitch(this, this.endEditing), 1);
305                                                         }
306                                                         break;
307                                                 }
308                                                 //pass through
309                                         default:
310                                                 if(!e.ctrlKey && !e.altKey && !e.metaKey && (e.keyCode<dojo.keys.F1 || e.keyCode>dojo.keys.F15)){
311                                                         this.beginEditing();
312                                                         break;
313                                                 }
314                                                 //pass through
315                                         case ks.ALT:
316                                                 this.endEditing();
317                                                 break;
318                                         case ks.UP_ARROW:
319                                         case ks.DOWN_ARROW:
320                                         case ks.LEFT_ARROW:
321                                         case ks.RIGHT_ARROW:
322                                         case ks.HOME:
323                                         case ks.END:
324                                         case ks.PAGE_UP:
325                                         case ks.PAGE_DOWN:
326                                                 this.endEditing(true);
327                                                 break;
328                                         //maybe ctrl+backspace/delete, so don't endEditing when ctrl is pressed
329                                         case ks.CTRL:
330                                         case ks.SHIFT:
331                                         case ks.TAB:
332                                                 break;
333                                 }       
334                 },
335                 _onBlur: function(){
336                         this.inherited('_onBlur',arguments);
337                         this.endEditing(true);
338                 },
339                 onClick: function(){
340                         this.endEditing(true);
341                         this.inherited('onClick',arguments);
342                 }
343                 /* end of custom undo/redo support */
344         }
345 );
346
347 /* the following code is to registered a handler to get default plugins */
348 dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
349         if(o.plugin){ return; }
350         var args = o.args, p;
351         var _p = dijit._editor._Plugin;
352         var name = args.name;
353         switch(name){
354                 case "undo": case "redo": case "cut": case "copy": case "paste": case "insertOrderedList":
355                 case "insertUnorderedList": case "indent": case "outdent": case "justifyCenter":
356                 case "justifyFull": case "justifyLeft": case "justifyRight": case "delete":
357                 case "selectAll": case "removeFormat":
358                 case "insertHorizontalRule":
359                         p = new _p({ command: name });
360                         break;
361
362                 case "bold": case "italic": case "underline": case "strikethrough":
363                 case "subscript": case "superscript":
364                         p = new _p({ buttonClass: dijit.form.ToggleButton, command: name });
365                         break;
366                 case "|":
367                         p = new _p({ button: new dijit.ToolbarSeparator() });
368         }
369 //      console.log('name',name,p);
370         o.plugin=p;
371 });
372
373 }