Changeset 6393
- Timestamp:
- 11/01/06 09:24:01 (19 months ago)
- Location:
- trunk
- Files:
-
- 2 added
- 1 removed
- 10 modified
-
src/widget/Editor2.js (modified) (19 diffs)
-
src/widget/Editor2Plugin/ContextMenu.js (modified) (7 diffs)
-
src/widget/Editor2Plugin/FindReplace.js (modified) (1 diff)
-
src/widget/Editor2Plugin/FindReplaceDialog.js (modified) (2 diffs)
-
src/widget/Editor2Plugin/InsertImageDialog.js (modified) (1 diff)
-
src/widget/Editor2Plugin/SimpleSignalCommands.js (modified) (3 diffs)
-
src/widget/Editor2Plugin/TableOperation.js (modified) (4 diffs)
-
src/widget/Editor2Toolbar.js (modified) (17 diffs)
-
src/widget/RichText.js (modified) (2 diffs)
-
src/widget/templates/EditorToolbarLight.html (deleted)
-
src/widget/templates/EditorToolbarOneline.html (modified) (28 diffs)
-
tests/widget/Editor/EditorToolbarLight.html (added)
-
tests/widget/Editor/test_Editor2_shared.html (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/widget/Editor2.js
r6370 r6393 6 6 7 7 // Object: Manager of current focused Editor2 Instance and available editor2 commands 8 dojo.widget.Editor2Manager = { 8 dojo.widget.Editor2Manager = new dojo.widget.HandlerManager; 9 dojo.lang.mixin(dojo.widget.Editor2Manager, 10 { 9 11 _currentInstance: null, 10 _loadedCommands: {},11 12 12 13 // Object: state a command may be in … … 21 22 this._currentInstance = inst; 22 23 }, 23 registerCommand: function(/*String*/name, /*Object*/cmd){ 24 // summary: Register an Editor2 command 25 // name: name of the command (case insensitive) 26 // cmd: an object which implements interface dojo.widget.Editor2Command 27 name = name.toLowerCase(); 28 if(this._loadedCommands[name]){ 29 delete this._loadedCommands[name]; 30 } 31 this._loadedCommands[name] = cmd; 32 }, 33 getCommand: function(/*String*/name){ 24 getCommand: function(/*dojo.widget.Editor2*/editor,/*String*/name){ 34 25 // summary: Return Editor2 command with the given name 35 26 // name: name of the command (case insensitive) 27 var oCommand; 36 28 name = name.toLowerCase(); 37 var oCommand = this._loadedCommands[name]; 38 if(oCommand){ 39 return oCommand; 29 for(var i=0;i<this._registeredHandlers.length;i++){ 30 oCommand = this._registeredHandlers[i](editor, name); 31 if(oCommand){ 32 return oCommand; 33 } 40 34 } 41 42 35 switch(name){ 43 36 case 'htmltoggle': 44 37 //Editor2 natively provide the htmltoggle functionalitity 45 38 //and it is treated as a builtin command 46 oCommand = new dojo.widget.Editor2BrowserCommand( name);39 oCommand = new dojo.widget.Editor2BrowserCommand(editor, name); 47 40 break; 48 41 case 'formatblock': 49 oCommand = new dojo.widget.Editor2FormatBlockCommand( name);42 oCommand = new dojo.widget.Editor2FormatBlockCommand(editor, name); 50 43 break; 51 44 case 'anchor': 52 oCommand = new dojo.widget.Editor2Command( name);45 oCommand = new dojo.widget.Editor2Command(editor, name); 53 46 break; 54 47 55 48 //dialog command 56 49 case 'createlink': 57 oCommand = new dojo.widget.Editor2DialogCommand( name,50 oCommand = new dojo.widget.Editor2DialogCommand(editor, name, 58 51 {contentFile: "dojo.widget.Editor2Plugin.CreateLinkDialog", 59 52 contentClass: "Editor2CreateLinkDialog", … … 61 54 break; 62 55 case 'insertimage': 63 oCommand = new dojo.widget.Editor2DialogCommand( name,56 oCommand = new dojo.widget.Editor2DialogCommand(editor, name, 64 57 {contentFile: "dojo.widget.Editor2Plugin.InsertImageDialog", 65 58 contentClass: "Editor2InsertImageDialog", … … 71 64 if((curtInst && curtInst.queryCommandAvailable(name)) || 72 65 (!curtInst && dojo.widget.Editor2.prototype.queryCommandAvailable(name))){ 73 oCommand = new dojo.widget.Editor2BrowserCommand( name);66 oCommand = new dojo.widget.Editor2BrowserCommand(editor, name); 74 67 }else{ 75 68 dojo.debug("dojo.widget.Editor2Manager.getCommand: Unknown command "+name); … … 77 70 } 78 71 } 79 this._loadedCommands[name] = oCommand;80 72 return oCommand; 81 73 }, … … 83 75 // summary: Cleaning up. This is called automatically on page unload. 84 76 this._currentInstance = null; 85 for(var cmd in this._loadedCommands){ 86 this._loadedCommands[cmd].destory(); 87 } 77 dojo.widget.HandlerManager.prototype.destroy.call(this); 88 78 } 89 } ;79 }); 90 80 91 81 dojo.addOnUnload(dojo.widget.Editor2Manager, "destroy"); … … 94 84 // dojo.widget.Editor2Command is the base class for all command in Editor2 95 85 dojo.lang.declare("dojo.widget.Editor2Command",null, 96 function(name){ 97 // summary: Constructor of this class 86 function(editor,name){ 87 this._editor = editor; 88 this._updateTime = 0; 98 89 this._name = name; 99 90 }, … … 177 168 // in commands 178 169 dojo.lang.declare("dojo.widget.Editor2BrowserCommand", dojo.widget.Editor2Command, 179 function( name){170 function(editor,name){ 180 171 // summary: Constructor of this class 181 172 … … 187 178 { 188 179 execute: function(para){ 189 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 190 if(curInst){ 191 curInst.execCommand(this._name, para); 192 } 180 this._editor.execCommand(this._name, para); 193 181 }, 194 182 getState: function(){ 195 var curInst = dojo.widget.Editor2Manager.getCurrentInstance();196 if(curInst){183 if(this._editor._lastStateTimestamp > this._updateTime || this._state == undefined){ 184 this._updateTime = this._editor._lastStateTimestamp; 197 185 try{ 198 if( curInst.queryCommandEnabled(this._name)){199 if( curInst.queryCommandState(this._name)){200 returndojo.widget.Editor2Manager.commandState.Latched;186 if(this._editor.queryCommandEnabled(this._name)){ 187 if(this._editor.queryCommandState(this._name)){ 188 this._state = dojo.widget.Editor2Manager.commandState.Latched; 201 189 }else{ 202 returndojo.widget.Editor2Manager.commandState.Enabled;190 this._state = dojo.widget.Editor2Manager.commandState.Enabled; 203 191 } 204 192 }else{ 205 returndojo.widget.Editor2Manager.commandState.Disabled;193 this._state = dojo.widget.Editor2Manager.commandState.Disabled; 206 194 } 207 195 }catch (e) { 208 196 //dojo.debug("exception when getting state for command "+this._name+": "+e); 209 returndojo.widget.Editor2Manager.commandState.Enabled;210 } 211 } 212 return dojo.widget.Editor2Manager.commandState.Disabled;197 this._state = dojo.widget.Editor2Manager.commandState.Enabled; 198 } 199 } 200 return this._state; 213 201 }, 214 202 getValue: function(){ 215 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 216 if(curInst){ 217 try{ 218 return curInst.queryCommandValue(this._name); 219 }catch(e){} 220 } 203 try{ 204 return this._editor.queryCommandValue(this._name); 205 }catch(e){} 221 206 } 222 207 } … … 350 335 } 351 336 dojo.widget.Editor2Dialog.superclass.hide.call(this); 337 }, 338 //modified from ModalDialogBase.checkSize to call _sizeBackground conditionally 339 checkSize: function(){ 340 if(this.isShowing()){ 341 if(this.modal){ 342 this._sizeBackground(); 343 } 344 this.placeModalDialog(); 345 this.onResized(); 346 } 352 347 } 353 348 } … … 377 372 // the command is executed. 378 373 dojo.lang.declare("dojo.widget.Editor2DialogCommand", dojo.widget.Editor2BrowserCommand, 379 function( name, dialogParas){374 function(editor, name, dialogParas){ 380 375 this.dialogParas = dialogParas; 381 376 }, … … 396 391 } 397 392 }); 393 394 // Object: keeping track of all available share toolbar groups 395 dojo.widget.Editor2ToolbarGroups = {}; 398 396 399 397 // summary: … … 407 405 "dojo.widget.Editor2", 408 406 dojo.widget.RichText, 407 function(){ 408 this._loadedCommands={}; 409 }, 409 410 { 410 411 // // String: url to which save action should send content to … … 415 416 // closeOnSave: false, 416 417 417 // Boolean: Whether to share toolbar with other instances of Editor2418 shareToolbar: false,419 418 // Boolean: Whether the toolbar should scroll to keep it in the view 420 419 toolbarAlwaysVisible: false, … … 435 434 _htmlEditNode: null, 436 435 436 // String: 437 // This instance of editor will share the same toolbar with other editor with the same toolbarGroup. 438 // By default, toolbarGroup is empty and standalone toolbar is used for this instance. 439 toolbarGroup: '', 440 // Boolean: Whether to share toolbar with other instances of Editor2. Deprecated in favor of toolbarGroup 441 shareToolbar: false, 442 443 // String: specify which context menu set should be used for this instance. Include ContextMenu plugin to use this 444 contextMenuGroupSet: '', 445 437 446 editorOnLoad: function(){ 438 447 // summary: … … 446 455 } 447 456 448 var toolbars = dojo.widget.byType("Editor2Toolbar"); 449 if((!toolbars.length)||(!this.shareToolbar)){ 450 if(this.toolbarWidget){ 451 this.toolbarWidget.show(); 452 //re-add the toolbar to the new domNode (caused by open() on another element) 453 dojo.html.insertBefore(this.toolbarWidget.domNode, this.domNode.firstChild); 454 }else{ 455 var tbOpts = {}; 456 tbOpts.templatePath = this.toolbarTemplatePath; 457 if(this.toolbarTemplateCssPath){ 458 tbOpts.templateCssPath = this.toolbarTemplateCssPath; 457 if(this.toolbarWidget){ 458 this.toolbarWidget.show(); 459 //re-add the toolbar to the new domNode (caused by open() on another element) 460 dojo.html.insertBefore(this.toolbarWidget.domNode, this.domNode.firstChild); 461 }else{ 462 if(this.shareToolbar){ 463 dojo.deprecated("Editor2:shareToolbar is deprecated in favor of toolbarGroup", "0.5"); 464 this.toolbarGroup = 'defaultDojoToolbarGroup'; 465 } 466 if(this.toolbarGroup){ 467 if(dojo.widget.Editor2ToolbarGroups[this.toolbarGroup]){ 468 this.toolbarWidget = dojo.widget.Editor2ToolbarGroups[this.toolbarGroup]; 459 469 } 460 this.toolbarWidget = dojo.widget.createWidget("Editor2Toolbar", tbOpts, this.domNode.firstChild, "before"); 461 462 dojo.event.connect(this, "close", this.toolbarWidget, "hide"); 463 464 this.toolbarLoaded(); 465 } 466 }else{ 467 // FIXME: selecting in one shared toolbar doesn't clobber 468 // selection in the others. This is problematic. 469 this.toolbarWidget = toolbars[0]; 470 } 471 if(!this.toolbarWidget){ 472 var tbOpts = {shareGroup: this.toolbarGroup, parent: this}; 473 tbOpts.templatePath = this.toolbarTemplatePath; 474 if(this.toolbarTemplateCssPath){ 475 tbOpts.templateCssPath = this.toolbarTemplateCssPath; 476 } 477 this.toolbarWidget = dojo.widget.createWidget("Editor2Toolbar", tbOpts, this.domNode.firstChild, "before"); 478 if(this.toolbarGroup){ 479 dojo.widget.Editor2ToolbarGroups[this.toolbarGroup] = this.toolbarWidget; 480 } 481 dojo.event.connect(this, "close", this.toolbarWidget, "hide"); 482 483 this.toolbarLoaded(); 484 } 470 485 } 471 486 … … 662 677 }, 663 678 679 _lastStateTimestamp: 0, 664 680 onDisplayChanged: function(/*Object*/e){ 681 this._lastStateTimestamp = (new Date()).getTime(); 665 682 dojo.widget.Editor2.superclass.onDisplayChanged.call(this,e); 666 683 this.updateToolbar(); … … 689 706 }, 690 707 708 getCommand: function(/*String*/name){ 709 // summary: return a command associated with this instance of editor 710 if(this._loadedCommands[name]){ 711 return this._loadedCommands[name]; 712 } 713 var cmd = dojo.widget.Editor2Manager.getCommand(this, name); 714 this._loadedCommands[name] = cmd; 715 return cmd; 716 }, 691 717 // Array: Commands shortcuts. Each element can has up to 3 fields: 692 718 // 1. String: the name of the command … … 702 728 var self = this; 703 729 dojo.lang.forEach(this.shortcuts, function(item){ 704 var cmd = dojo.widget.Editor2Manager.getCommand(item[0]);730 var cmd = self.getCommand(item[0]); 705 731 if(cmd){ 706 732 self.addKeyHandler(item[1]?item[1]:item[0].charAt(0), item[2]==undefined?self.KEY_CTRL:item[2], exec(cmd)); -
trunk/src/widget/Editor2Plugin/ContextMenu.js
r5993 r6393 1 1 dojo.provide("dojo.widget.Editor2Plugin.ContextMenu"); 2 2 3 //ContextMenu plugin should be dojo.required-ed before all other plugins which 4 //support contextmenu, otherwise the menu for that plugin won't be shown 3 // summary: dojo.widget.Editor2Plugin.ContextMenu provides context menu for Editor2 widget 4 // description: 5 // This plugin should be dojo.required-ed before all other plugins which 6 // support contextmenu, otherwise the menu for that plugin won't be shown 7 // For each Editor2, what will appear in its context menu can be set by changing 8 // Editor2.contextMenuGroupSet property (by default it is empty, which means use the 9 // default contextMenu). A contextMenuGroupSet has to be registered by calling 10 // dojo.widget.Editor2Plugin.ContextMenuManager.registerGroupSet() 11 // All Editor2 with the same contextMenuGroupSet will share the same ContextMenu 5 12 6 13 dojo.require("dojo.widget.Menu2"); 7 14 8 15 dojo.event.topic.subscribe("dojo.widget.Editor2::onLoad", function(editor){ 9 var p = new dojo.widget.Editor2Plugin.ContextMenu(editor); 10 }); 16 dojo.widget.Editor2Plugin.ContextMenuManager.getContextMenu(editor); 17 // var p = new dojo.widget.Editor2Plugin.ContextMenu(); 18 }); 19 11 20 dojo.widget.Editor2Plugin.ContextMenuManager = { 12 21 menuGroups: ['Generic', 'Link', 'Anchor', 'Image', 'List', 'Table'], 22 _contextMenuGroupSets: {}, 13 23 _registeredGroups: {}, 24 _menus: {}, 14 25 registerGroup: function(name, handler){ 15 26 if(this._registeredGroups[name]){ … … 33 44 case 'Link': 34 45 case 'Image': 35 return new dojo.widget.Editor2Plugin[name+"ContextMenu "](contextmenuplugin);46 return new dojo.widget.Editor2Plugin[name+"ContextMenuGroup"](contextmenuplugin); 36 47 //TODO 37 48 case 'Anchor': 38 49 case 'List': 39 50 } 51 }, 52 registerGroupSet: function(/*String*/name, /*Array*/set){ 53 // summary: register a group set 54 // name: name of the group set 55 // set: an array of groups, such as ['Generic','Link'] 56 this._contextMenuGroupSets[name] = set; 57 }, 58 removeGroupSet: function(name){ 59 var set = this._contextMenuGroupSets[name]; 60 delete this._contextMenuGroupSets[name]; 61 return set; 62 }, 63 getContextMenu: function(editor){ 64 var set = editor.contextMenuGroupSet || 'defaultDojoEditor2MenuGroupSet'; 65 if(this._menus[set]){ 66 this._menus[set].bindEditor(editor); 67 return this._menus[set]; 68 } 69 70 var gs = (editor.contextMenuGroupSet && this._contextMenuGroupSets[editor.contextMenuGroupSet]) || this.menuGroups; 71 var menu = new dojo.widget.Editor2Plugin.ContextMenu(editor, gs); 72 this._menus[set] = menu; 73 return menu; 40 74 } 41 75 }; 42 76 43 77 dojo.declare("dojo.widget.Editor2Plugin.ContextMenu", null, 44 function(editor ){78 function(editor, gs){ 45 79 this.groups = []; 46 80 this.separators = []; … … 49 83 this.contextMenu = dojo.widget.createWidget("PopupMenu2", {}); 50 84 dojo.body().appendChild(this.contextMenu.domNode); 51 this. contextMenu.bindDomNode(this.editor.document.body);85 this.bindEditor(this.editor); 52 86 53 87 dojo.event.connect(this.contextMenu, "aboutToShow", this, "aboutToShow"); 54 88 dojo.event.connect(this.editor, "destroy", this, "destroy"); 55 89 56 this.setup( );90 this.setup(gs); 57 91 }, 58 92 { 59 setup: function(){ 60 var gs = dojo.widget.Editor2Plugin.ContextMenuManager.menuGroups; 93 bindEditor: function(editor){ 94 this.contextMenu.bindDomNode(editor.document.body); 95 }, 96 setup: function(gs){ 61 97 for(var i in gs){ 62 98 var g = dojo.widget.Editor2Plugin.ContextMenuManager.getGroup(gs[i], this); … … 100 136 dojo.widget.defineWidget( 101 137 "dojo.widget.Editor2ContextMenuItem", 102 dojo.widget.MenuItem2, { 103 command: null, 104 postCreate: function(){ 105 if(!this.command){ 106 this.command = this.caption; 107 } 108 109 dojo.widget.Editor2ContextMenuItem.superclass.postCreate.apply(this, arguments); 110 }, 111 setup: function(){ 112 this.cmd = dojo.widget.Editor2Manager.getCommand(this.command); 113 if(!this.cmd){ 114 alert("command " + this.command + " is not recognized!"); 115 } 138 dojo.widget.MenuItem2, 139 { 140 command: '', 141 buildRendering: function(){ 142 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 143 this.caption = curInst.getCommand(this.command).getText(); 144 145 dojo.widget.Editor2ContextMenuItem.superclass.buildRendering.apply(this, arguments); 116 146 }, 117 147 onClick: function(){ 118 if(!this.cmd){ 119 this.setup(); 120 } 121 if(this.cmd){ 122 this.cmd.execute(); 148 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 149 if(curInst){ 150 var _command = curInst.getCommand(this.command); 151 if(_command){ 152 _command.execute(); 153 } 123 154 } 124 155 }, 125 156 refresh: function(){ 126 if(!this.cmd){ 127 this.setup(); 128 } 129 if(this.cmd){ 130 if(this.cmd.getState() == dojo.widget.Editor2Manager.commandState.Disabled){ 131 this.disable(); 132 return false; 133 }else{ 134 this.enable(); 135 return true; 157 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 158 if(curInst){ 159 var _command = curInst.getCommand(this.command); 160 if(_command){ 161 if(_command.getState() == dojo.widget.Editor2Manager.commandState.Disabled){ 162 this.disable(); 163 return false; 164 }else{ 165 this.enable(); 166 return true; 167 } 136 168 } 137 169 } … … 145 177 } 146 178 }); 147 dojo.declare("dojo.widget.Editor2Plugin.SimpleContextMenu ", null,179 dojo.declare("dojo.widget.Editor2Plugin.SimpleContextMenuGroup", null, 148 180 function(contextmenuplugin){ 149 181 this.contextMenu = contextmenuplugin.contextMenu; … … 184 216 } 185 217 }); 186 dojo.declare("dojo.widget.Editor2Plugin.GenericContextMenu ",187 dojo.widget.Editor2Plugin.SimpleContextMenu ,218 dojo.declare("dojo.widget.Editor2Plugin.GenericContextMenuGroup", 219 dojo.widget.Editor2Plugin.SimpleContextMenuGroup, 188 220 { 189 221 createItems: function(){ 190 this.items.push(dojo.widget.createWidget("Editor2ContextMenuItem", {c aption: "Cut", iconClass: "dojoE2TBIcon dojoE2TBIcon_Cut"}));191 this.items.push(dojo.widget.createWidget("Editor2ContextMenuItem", {c aption: "Copy", iconClass: "dojoE2TBIcon dojoE2TBIcon_Copy"}));192 this.items.push(dojo.widget.createWidget("Editor2ContextMenuItem", {c aption: "Paste", iconClass: "dojoE2TBIcon dojoE2TBIcon_Paste"}));193 } 194 }); 195 dojo.declare("dojo.widget.Editor2Plugin.LinkContextMenu ",196 dojo.widget.Editor2Plugin.SimpleContextMenu ,222 this.items.push(dojo.widget.createWidget("Editor2ContextMenuItem", {command: "cut", iconClass: "dojoE2TBIcon dojoE2TBIcon_Cut"})); 223 this.items.push(dojo.widget.createWidget("Editor2ContextMenuItem", {command: "copy", iconClass: "dojoE2TBIcon dojoE2TBIcon_Copy"})); 224 this.items.push(dojo.widget.createWidget("Editor2ContextMenuItem", {command: "paste", iconClass: "dojoE2TBIcon dojoE