Changeset 5306
- Timestamp:
- 08/17/06 17:40:21 (3 years ago)
- Location:
- trunk/src/widget
- Files:
-
- 20 added
- 5 modified
-
Editor2.js (modified) (9 diffs)
-
Editor2Plugin (added)
-
Editor2Plugin/AlwaysShowToolbar.js (added)
-
Editor2Plugin/ContextMenu.js (added)
-
Editor2Plugin/FindReplace.js (added)
-
Editor2Plugin/TableOperation.js (added)
-
Editor2Plugin/ToolbarDndSupport.js (added)
-
Editor2Plugin/__package__.js (added)
-
Editor2Toolbar.js (modified) (2 diffs)
-
RichText.js (modified) (14 diffs)
-
templates/Editor2 (added)
-
templates/Editor2/Dialog (added)
-
templates/Editor2/Dialog/createlink.html (added)
-
templates/Editor2/Dialog/find.html (added)
-
templates/Editor2/Dialog/insertimage.html (added)
-
templates/Editor2/Dialog/inserttable.html (added)
-
templates/Editor2/Dialog/replace.html (added)
-
templates/Editor2/EditorDialog.html (added)
-
templates/Editor2/EditorToolbar_FontName.html (added)
-
templates/Editor2/EditorToolbar_FontSize.html (added)
-
templates/Editor2/EditorToolbar_FormatBlock.html (added)
-
templates/Editor2/showtableborder_gecko.css (added)
-
templates/Editor2/showtableborder_ie.css (added)
-
templates/EditorToolbar.css (modified) (3 diffs)
-
templates/EditorToolbarOneline.html (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/widget/Editor2.js
r5180 r5306 7 7 dojo.require("dojo.html.*"); 8 8 dojo.require("dojo.html.layout"); 9 dojo.require("dojo.html.iframe");10 9 dojo.require("dojo.widget.*"); 11 10 dojo.require("dojo.widget.RichText"); 12 11 dojo.require("dojo.widget.Editor2Toolbar"); 12 13 13 // dojo.require("dojo.widget.ColorPalette"); 14 14 // dojo.require("dojo.string.extras"); 15 15 16 //The current focused Editor2 Instance 17 dojo.widget.Editor2._CurrentInstance = null; 16 //API to manage current focused Editor2 Instance 17 dojo.widget.Editor2Manager = { 18 //private variables 19 _currentInstance: null, 20 _loadedCommands: {}, 21 22 destroy: function(){ 23 this._currentInstance = null; 24 for(var cmd in this._loadedCommands){ 25 this._loadedCommands[cmd].destory(); 26 } 27 }, 28 29 commandState: {Disabled: 0, Latched: 1, Enabled: 2}, 30 //Public API 31 getCurrentInstance: function(){ 32 return this._currentInstance; 33 }, 34 setCurrentInstance: function(inst){ 35 this._currentInstance = inst; 36 }, 37 registerCommand: function(name, cmd){ 38 name = name.toLowerCase(); 39 if(this._loadedCommands[name]){ 40 delete this._loadedCommands[name]; 41 } 42 this._loadedCommands[name] = cmd; 43 }, 44 getCommand: function(name){ 45 name = name.toLowerCase(); 46 var oCommand = this._loadedCommands[name]; 47 if(oCommand){ 48 return oCommand; 49 } 50 51 switch(name){ 52 case 'htmltoggle': 53 //Editor2 natively provide the htmltoggle functionalitity 54 //and it is treated as a builtin command 55 oCommand = new dojo.widget.Editor2BrowserCommand(name); 56 break; 57 case 'formatblock': 58 oCommand = new dojo.widget.Editor2FormatBlockCommand(name); 59 break; 60 case 'anchor': 61 oCommand = new dojo.widget.Editor2Command(name); 62 break; 63 64 //dialog command 65 case 'createlink': 66 oCommand = new dojo.widget.Editor2DialogCommand(name, 67 {href: dojo.uri.dojoUri("src/widget/templates/Editor2/Dialog/createlink.html"), 68 title: "Insert/Edit Link", width: "300px", height: "200px"}); 69 break; 70 case 'insertimage': 71 oCommand = new dojo.widget.Editor2DialogCommand(name, 72 {href: dojo.uri.dojoUri("src/widget/templates/Editor2/Dialog/insertimage.html"), 73 title: "Insert/Edit Image", width: "400px", height: "270px"}); 74 break; 75 // By default we assume that it is a builtin simple command. 76 default: 77 var curtInst = this.getCurrentInstance(); 78 if((curtInst && curtInst.queryCommandAvailable(name)) || 79 (!curtInst && dojo.widget.Editor2.prototype.queryCommandAvailable(name))){ 80 oCommand = new dojo.widget.Editor2BrowserCommand(name); 81 }else{ 82 dojo.debug("dojo.widget.Editor2Manager.getCommand: Unknown command "+name); 83 return; 84 } 85 } 86 this._loadedCommands[name] = oCommand; 87 return oCommand; 88 }//, 89 // registerPerInstancePlugin: function(name){ 90 // if(!this._perInstancePlugins){ this._perInstancePlugins = []; } 91 // this._perInstancePlugins.push(name); 92 // }, 93 // getPlugin: function(pluginname, editor){ 94 // dojo.require(pluginname); 95 // if(dojo.lang.find(this._perInstancePlugins, pluginname) != -1){ 96 // var plugin = dojo.evalObjPath(pluginname); 97 // return new plugin(editor); 98 // } 99 // return null; 100 // } 101 }; 102 103 dojo.addOnUnload(dojo.widget.Editor2Manager, "destroy"); 104 105 /* base class for all command in Editor2 */ 106 dojo.lang.declare("dojo.widget.Editor2Command",null,{ 107 initializer: function(name){ 108 this._name = name; 109 }, 110 //this function should be re-implemented in subclass 111 execute: function(para){ 112 alert("Please implement your own execute() function for subclass of Editor2Command."); 113 }, 114 //default implemetation always returns Enabled 115 getState: function(){ 116 return dojo.widget.Editor2Manager.commandState.Enabled; 117 }, 118 destory: function(){} 119 } 120 ); 121 122 dojo.lang.declare("dojo.widget.Editor2BrowserCommand", dojo.widget.Editor2Command, { 123 execute: function(para){ 124 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 125 if(curInst){ 126 dojo.debug("execute "+this._name); 127 curInst.execCommand(this._name, para); 128 } 129 }, 130 getState: function(){ 131 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 132 if(curInst){ 133 try{ 134 if(curInst.queryCommandEnabled(this._name)){ 135 if(curInst.queryCommandState(this._name)){ 136 return dojo.widget.Editor2Manager.commandState.Latched; 137 }else{ 138 return dojo.widget.Editor2Manager.commandState.Enabled; 139 } 140 }else{ 141 return dojo.widget.Editor2Manager.commandState.Disabled; 142 } 143 }catch (e) { 144 //dojo.debug("exception when getting state for command "+this._name+": "+e); 145 return dojo.widget.Editor2Manager.commandState.Enabled; 146 } 147 } 148 return dojo.widget.Editor2Manager.commandState.Disabled; 149 }, 150 getValue: function(){ 151 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 152 if(curInst){ 153 try{ 154 return curInst.queryCommandValue(this._name); 155 }catch(e){} 156 } 157 } 158 } 159 ); 160 161 dojo.lang.declare("dojo.widget.Editor2FormatBlockCommand", dojo.widget.Editor2BrowserCommand, { 162 /* In none-ActiveX mode under IE, <p> and no <p> text can not be distinguished 163 getCurrentValue: function(){ 164 var curInst = dojo.widget.Editor2Manager.getCurrentInstance(); 165 if(!curInst){ return ''; } 166 167 var h = dojo.render.html; 168 169 // safari f's us for selection primitives 170 if(h.safari){ return ''; } 171 172 var selectedNode = (h.ie) ? curInst.document.selection.createRange().parentElement() : curInst.window.getSelection().anchorNode; 173 // make sure we actuall have an element 174 while((selectedNode)&&(selectedNode.nodeType != 1)){ 175 selectedNode = selectedNode.parentNode; 176 } 177 if(!selectedNode){ return ''; } 178 179 var formats = ["p", "pre", "h1", "h2", "h3", "h4", "h5", "h6", "address"]; 180 // gotta run some specialized updates for the various 181 // formatting options 182 var type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())]; 183 while((selectedNode!=curInst.editNode)&&(!type)){ 184 selectedNode = selectedNode.parentNode; 185 if(!selectedNode){ break; } 186 type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())]; 187 } 188 if(!type){ 189 type = ""; 190 } 191 return type; 192 }*/ 193 } 194 ); 195 196 dojo.require("dojo.widget.FloatingPane"); 197 dojo.widget.defineWidget( 198 "dojo.widget.Editor2Dialog", 199 [dojo.widget.FloatingPane, dojo.widget.ModalDialogBase], 200 { 201 modal: true, 202 templatePath: dojo.uri.dojoUri("src/widget/templates/Editor2/EditorDialog.html"), 203 executeScripts: true, 204 refreshOnShow: true, //for debug for now 205 206 width: false, 207 height: false, 208 209 windowState: "minimized", 210 displayCloseAction: true, 211 212 postCreate: function(){ 213 if(this.modal){ 214 dojo.widget.ModalDialogBase.prototype.postCreate.call(this); 215 }else{ 216 with(this.domNode.style) { 217 zIndex = 999; 218 display = "none"; 219 } 220 // dojo.body().appendChild(this.domNode); 221 } 222 dojo.widget.Editor2Dialog.superclass.postCreate.call(this); 223 if(this.width && this.height){ 224 with(this.domNode.style){ 225 width = this.width; 226 height = this.height; 227 } 228 } 229 }, 230 show: function(){ 231 dojo.widget.Editor2Dialog.superclass.show.apply(this, arguments); 232 if(this.modal){ 233 dojo.widget.ModalDialogBase.prototype.show.call(this); 234 } 235 this.placeModalDialog(); 236 if(this.modal){ 237 //place the background div under this modal pane 238 this.shared.bg.style.zIndex = this.domNode.style.zIndex-1; 239 } 240 }, 241 closeWindow: function(){ 242 this.hide(); 243 dojo.widget.Editor2Dialog.superclass.closeWindow.apply(this, arguments); 244 }, 245 hide: function(){ 246 if(this.modal){ 247 dojo.widget.ModalDialogBase.prototype.hide.call(this); 248 }else{ 249 dojo.widget.Editor2Dialog.superclass.hide.call(this); 250 } 251 } 252 } 253 ); 254 255 dojo.lang.declare("dojo.widget.Editor2DialogCommand", dojo.widget.Editor2BrowserCommand, 256 function(name, dialogParas){ 257 this.dialogParas = dialogParas; 258 }, 259 { 260 execute: function(){ 261 if(!this.dialog){ 262 if(!this.dialogParas.href){ 263 alert("Href should be set for dojo.widget.Editor2DialogCommand.dialogParas!"); 264 return; 265 } 266 this.dialog = dojo.widget.createWidget("Editor2Dialog", this.dialogParas); 267 268 dojo.body().appendChild(this.dialog.domNode); 269 270 dojo.event.connect(this, "destroy", this.dialog, "destroy"); 271 } 272 this.dialog.show(); 273 } 274 }); 275 / 276 //uncomment these plugins to enable them 277 //dojo.require("dojo.widget.Editor2Plugin.FindReplace"); 278 279 //ContextMenu plugin should come before all other plugins which support 280 //contextmenu, otherwise the menu for that plugin won't be shown 281 dojo.require("dojo.widget.Editor2Plugin.ContextMenu"); 282 //dojo.require("dojo.widget.Editor2Plugin.TableOperation"); 283 //dojo.require("dojo.widget.Editor2Plugin.ToolbarDndSupport"); 18 284 19 285 dojo.widget.defineWidget( … … 28 294 toolbarAlwaysVisible: false, 29 295 htmlEditing: false, 30 _in HtmlMode: false,296 _inSourceMode: false, 31 297 _htmlEditNode: null, 32 298 33 commandList: dojo.widget.Editor2Toolbar.prototype.commandList,34 299 toolbarWidget: null, 35 300 scrollInterval: null, 36 toolbarTemplatePath: null, 37 301 toolbarTemplatePath: "src/widget/templates/Editor2/EditorToolbarFCKStyle.html", 302 toolbarTemplateCssPath: "src/widget/templates/Editor2/FCKDefault/EditorToolbarFCKStyle.css", 303 304 plugins: "", 38 305 39 306 editorOnLoad: function(){ 307 dojo.profile.start("dojo.widget.Editor2::editorOnLoad"); 308 309 dojo.event.topic.publish("dojo.widget.Editor2::preLoadingToolbar", this); 310 if(this.toolbarAlwaysVisible){ 311 dojo.require("dojo.widget.Editor2Plugin.AlwaysShowToolbar"); 312 } 313 40 314 var toolbars = dojo.widget.byType("Editor2Toolbar"); 41 315 if((!toolbars.length)||(!this.shareToolbar)){ … … 43 317 this.toolbarTemplatePath = this.toolbarTemplatePath || "src/widget/templates/EditorToolbarOneline.html"; 44 318 tbOpts.templatePath = dojo.uri.dojoUri(this.toolbarTemplatePath); 319 if(this.toolbarTemplateCssPath){ 320 tbOpts.templateCssPath = this.toolbarTemplateCssPath; 321 } 45 322 if(this.toolbarWidget){ 46 323 this.toolbarWidget.show(); … … 50 327 dojo.event.connect(this, "close", this.toolbarWidget, "hide"); 51 328 dojo.event.connect(this, "destroy", this.toolbarWidget, "destroy"); 52 this.toolbarWidget.hideUnusableButtons(this); 53 } 54 55 if(this.object){ 56 this.tbBgIframe = new dojo.html.BackgroundIframe(this.toolbarWidget.domNode); 57 this.tbBgIframe.iframe.style.height = "30px"; 58 } 59 60 // need to set position fixed to wherever this thing has landed 61 if(this.toolbarAlwaysVisible){ 62 var src = document.documentElement||window; 63 this.scrollInterval = setInterval(dojo.lang.hitch(this, "globalOnScrollHandler"), 100); 64 // dojo.event.connect(src, "onscroll", this, "globalOnScrollHandler"); 65 dojo.event.connect("before", this, "destroyRendering", this, "unhookScroller"); 66 } 329 } 330 331 this.toolbarLoaded(); 67 332 }else{ 68 // FIXME: should we try harder to explicitly manage focus in69 // order to prevent too many editors from all querying70 // for button status concurrently?71 333 // FIXME: selecting in one shared toolbar doesn't clobber 72 334 // selection in the others. This is problematic. 73 335 this.toolbarWidget = toolbars[0]; 74 336 } 337 75 338 dojo.event.topic.registerPublisher("Editor2.clobberFocus", this, "clobberFocus"); 76 339 dojo.event.topic.subscribe("Editor2.clobberFocus", this, "setBlur"); 77 dojo.event.connect(this.toolbarWidget.linkButton, "onclick", 78 dojo.lang.hitch(this, function(){ 79 var range; 80 if(this.document.selection){ 81 range = this.document.selection.createRange().text; 82 }else if(dojo.render.html.mozilla){ 83 range = this.window.getSelection().toString(); 84 } 85 if(range.length){ 86 this.toolbarWidget.exec("createlink", 87 prompt("Please enter the URL of the link:", "http://")); 88 }else{ 89 alert("Please select text to link"); 90 } 91 }) 92 ); 93 94 dojo.event.connect(this.toolbarWidget, "formatSelectClick", this, "focus"); 95 dojo.event.connect(this.toolbarWidget, "saveClick", this, "save"); 96 dojo.event.connect(this.toolbarWidget, "insertimageClick", this, "insertImage"); 97 dojo.event.connect(this, "execCommand", this, "focus"); 98 99 if(this.htmlEditing){ 100 var tb = this.toolbarWidget.htmltoggleButton; 101 if(tb){ 102 tb.style.display = ""; 103 dojo.event.connect(this.toolbarWidget, "htmltoggleClick", 104 this, "toggleHtmlEditing"); 105 } 340 341 dojo.event.topic.publish("dojo.widget.Editor2::onLoad", this); 342 dojo.profile.end("dojo.widget.Editor2::editorOnLoad"); 343 }, 344 345 //event for plugins to use 346 toolbarLoaded: function(){}, 347 348 registerLoadedPlugin: function(/*Object*/obj){ 349 if(!this.loadedPlugins){ 350 this.loadedPlugins = []; 351 } 352 this.loadedPlugins.push(obj); 353 }, 354 unregisterLoadedPlugin: function(/*Object*/obj){ 355 for(var i in this.loadedPlugins){ 356 if(this.loadedPlugins[i] === obj){ 357 delete this.loadedPlugins[i]; 358 return; 359 } 360 } 361 dojo.debug("dojo.widget.Editor2.unregisterLoadedPlugin: unknow plugin object: "+obj); 362 }, 363 //override the default one to provide extra commands 364 execCommand: function(command, argument){ 365 switch(command.toLowerCase()){ 366 case 'htmltoggle': 367 this.toggleHtmlEditing(); 368 break; 369 default: 370 dojo.widget.Editor2.superclass.execCommand.call(this, command, argument); 371 } 372 }, 373 queryCommandEnabled: function(command, argument){ 374 switch(command.toLowerCase()){ 375 case 'htmltoggle': 376 return true; 377 default: 378 if(this._inSourceMode){ return false;} 379 return dojo.widget.Editor2.superclass.queryCommandEnabled.call(this, command, argument); 380 } 381 }, 382 queryCommandState: function(command, argument){ 383 switch(command.toLowerCase()){ 384 case 'htmltoggle': 385 return this._inSourceMode; 386 default: 387 return dojo.widget.Editor2.superclass.queryCommandState.call(this, command, argument); 388 } 389 }, 390 391 onClick: function(e){ 392 dojo.widget.Editor2.superclass.onClick.call(this, e); 393 //if Popup is used, call dojo.widget.PopupManager.onClick 394 //manually when click in the editing area to close all 395 //open popups (dropdowns) 396 if(dojo.widget.PopupManager){ 397 if(!e){ //IE 398 e = this.window.event; 399 } 400 dojo.widget.PopupManager.onClick(e); 106 401 } 107 402 }, … … 111 406 insertImage: function(){ dojo.debug("Editor2.insertImage"); }, 112 407 toggleHtmlEditing: function(){ 113 if(this===dojo.widget.Editor2 ._CurrentInstance){114 if(!this._in HtmlMode){115 this._in HtmlMode = true;116 this.toolbarWidget.highlightButton("htmltoggle"); 408 if(this===dojo.widget.Editor2Manager.getCurrentInstance()){ 409 if(!this._inSourceMode){ 410 this._inSourceMode = true; 411 117 412 if(!this._htmlEditNode){ 118 this._htmlEditNode = do cument.createElement("textarea");413 this._htmlEditNode = dojo.doc().createElement("textarea"); 119 414 dojo.html.insertBefore(this._htmlEditNode, this.domNode); 120 415 } … … 123 418 this._htmlEditNode.style.height = dojo.html.getBorderBox(this.editNode).height+"px"; 124 419 this._htmlEditNode.value = this.editNode.innerHTML; 125 this.domNode.style.display = "none"; 420 421 with(this.domNode.style){ 422 if(this.object){ 423 //activeX object doesn't like to be hidden, so move it outside of screen instead 424 position = "absolute"; 425 left = "-2000px"; 426 top = "-2000px"; 427 }else{ 428 display = "none"; 429 } 430 } 126 431 }else{ 127 this._inHtmlMode = false; 128 this.domNode.style.display = ""; 129 this.toolbarWidget.unhighlightButton("htmltoggle"); 432 this._inSourceMode = false; 433 434 //In IE activeX mode, if _htmlEditNode is focused, 435 //when toggling, an error would occur, so unfocus it 436 this._htmlEditNode.blur(); 437 438 with(this.domNode.style){ 439 if(this.object){ 440 position = ""; 441 left = ""; 442 top = ""; 443 }else{ 444 display = ""; 445 } 446 } 447 130 448 dojo.lang.setTimeout(this, "replaceEditorContent", 1, this._htmlEditNode.value); 131 449 this._htmlEditNode.style.display = "none"; 132 this.editNode.focus(); 133 } 450 this.focus(); 451 } 452 this.updateToolbar(true); 134 453 } 135 454 }, 136 455 137 456 setFocus: function(){ 138 if(dojo.widget.Editor2._CurrentInstance == this){ return; } 139 140 if(this.toolbarWidget){ 141 this.clobberFocus(); 142 // dojo.debug("setFocus:", this); 143 dojo.widget.Editor2._CurrentInstance = this; 144 dojo.event.connect(this.toolbarWidget, "exec", this, "execCommand"); 145 } 457 dojo.debug("setFocus: start "+this.widgetId); 458 if(dojo.widget.Editor2Manager.getCurrentInstance() === this){ return; } 459 460 this.clobberFocus(); 461 dojo.debug("setFocus:", this); 462 dojo.widget.Editor2Manager.setCurrentInstance(this); 146 463 }, 147 464 148 465 setBlur: function(){ 149 // dojo.debug("setBlur:", this); 150 dojo.event.disconnect(this.toolbarWidget, "exec", this, "execCommand"); 151 }, 152 153 _scrollSetUp: false, 154 _fixEnabled: false, 155 _scrollThreshold: false, 156 _handleScroll: true, 157 globalOnScrollHandler: function(){ 158 var isIE = dojo.render.html.ie; 159 if(!this._handleScroll){ return; } 160 var dh = dojo.html; 161 var tdn = this.toolbarWidget.domNode; 162 var db = dojo.body(); 163 var totalHeight = dh.getMarginBox(tdn).height; 164 if(!this._scrollSetUp){ 165 this._scrollSetUp = true; 166 var editorWidth = dh.getMarginBox(this.domNode).width; 167 this._scrollThreshold = dh.abs(tdn, false).y; 168 // dojo.debug("threshold:", this._scrollThreshold); 169 if((isIE)&&(db)&&(dh.getStyle(db, "background-image")=="none")){ 170 with(db.style){ 171 backgroundImage = "url(" + dojo.uri.dojoUri("src/widget/templates/images/blank.gif") + ")"; 172 backgroundAttachment = "fixed"; 173 } 174 } 175 } 176 177 var scrollPos = (window["pageYOffset"]) ? window["pageYOffset"] : (document["documentElement"]||document["body"]).scrollTop; 178 179 // FIXME: need to have top and bottom thresholds so toolbar doesn't keep scrolling past the bottom 180 if(scrollPos > this._scrollThreshold){ 181 // dojo.debug(scrollPos); 182 if(!this._fixEnabled){ 183 this.domNode.style.marginTop = totalHeight+"px"; 184 if(isIE){ 185 // FIXME: should we just use setBehvior() here instead? 186 var cl = dojo.html.abs(tdn).x; 187 document.body.appendChild(tdn); 188 tdn.style.left = cl+dojo.html.getPixelValue(document.body, "margin-left")+"px"; 189 dojo.html.addClass(tdn, "IEFixedToolbar"); 190 if(this.object){ 191 dojo.html.addClass(this.tbBgIframe, "IEFixedToolbar"); 192 } 193 194 }else{ 195 with(tdn.style){ 196 position = "fixed"; 197 top = "0px"; 198 } 199 } 200 tdn.style.zIndex = 1000; 201 this._fixEnabled = true; 202 } 203 // if we're showing the floating toolbar, make sure that if 204 // we've scrolled past the bottom of the editor that we hide 205 // the toolbar for this instance of the editor. 206 207 // TODO: when we get multiple editor toolbar support working 208 // correctly, ensure that we check this against the scroll 209 // position of the bottom-most editor instance. 210 if(!dojo.render.html.safari){ 211 // safari reports a bunch of things incorrectly here 212 var eHeight = (this.height) ? parseInt(this.height) : ((this.object) ? dojo.html.getBorderBox(this.editNode).height : this._lastHeight); 213 if(scrollPos > (this._scrollThreshold+eHeight)){ 214 tdn.style.display = "none"; 215 }else{ 216 tdn.style.display = ""; 217 } 218 } 219 220 }else if(this._fixEnabled){ 221 this.domNode.style.marginTop = null; 222 with(tdn.style){ 223 position = ""; 224 top = ""; 225 zIndex = ""; 226 if(isIE){ 227 marginTop = ""; 228 } 229 } 230 if(isIE){ 231 dojo.html.removeClass(tdn, "IEFixedToolbar"); 232 dojo.html.insertBefore(tdn, this._htmlEditNode||this.domNode); 233 } 234 this._fixEnabled = false; 235 } 236 }, 237 238 unhookScroller: function(){ 239 this._handleScroll = false; 240 clearInterval(this.scrollInterval); 241 // var src = document["documentElement"]||window; 242 // dojo.event.disconnect(src, "onscroll", this, "globalOnScrollHandler"); 243 if(dojo.render.html.ie){ 244 dojo.html.removeClass(this.toolbarWidget.domNode, "IEFixedToolbar"); 245 } 466 dojo.debug("setBlur:", this); 467 //dojo.event.disconnect(this.toolbarWidget, "exec", this, "execCommand"); 246 468 }, 247 469 … … 271 493 // end frequency checker 272 494 273 // FIXME: SEVERE: This forEach block breaks undo on IE 274 dojo.lang.forEach(this.commandList, 275 function(cmd){ 276 if((cmd == "inserthtml") || (cmd == "save")){ return; } 277 try{ 278 if(this.queryCommandEnabled(cmd)){ 279 if(this.queryCommandState(cmd)){ 280 this.toolbarWidget.highlightButton(cmd); 281 }else{ 282 this.toolbarWidget.unhighlightButton(cmd); 283 } 284 } 285 }catch(e){ 286 // alert(cmd+":"+e); 287 } 288 }, 289 this 290 ); 291 292 var h = dojo.render.html; 293 294 // safari f's us for selection primitives 295 if(h.safari){ return; } 296 297 var selectedNode = (h.ie) ? this.document.selection.createRange().parentElement() : this.window.getSelection().anchorNode; 298 // make sure we actuall have an element 299 while((selectedNode)&&(selectedNode.nodeType != 1)){ 300 selectedNode = selectedNode.parentNode; 301 } 302 if(!selectedNode){ return; } 303 304 var formats = ["p", "pre", "h1", "h2", "h3", "h4"]; 305 // gotta run some specialized updates for the various 306 // formatting options 307 var type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())]; 308 while((selectedNode)&&(selectedNode!=this.editNode)&&(!type)){ 309 selectedNode = selectedNode.parentNode; 310 type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())]; 311 } 312 if(!type){ 313 type = ""; 314 }else{ 315 if(type.charAt(0)=="h"){ 316 this.toolbarWidget.unhighlightButton("bold"); 317 } 318 } 319 this.toolbarWidget.selectFormat(type); 320 }, 321 322 updateItem: function(item) { 323 try { 324 var cmd = item._name; 325 var enabled = this._richText.queryCommandEnabled(cmd); 326 item.setEnabled(enabled, false, true); 327 328 var active = this._richText.queryCommandState(cmd); 329 if(active && cmd == "underline") { 330 // don't activate underlining if we are on a link 331 active = !this._richText.queryCommandEnabled("unlink"); 332 } 333 item.setSelected(active, false, true); 334 return true; 335 } catch(err) { 336 return false; 337 } 495 //TODO 496 //if((cmd == "inserthtml") || (cmd == "save")){ return; } 497 498 //IE has the habit of generating events even when this editor is blurred, prevent this 499 if(dojo.widget.Editor2Manager.getCurrentInstance() !== this){ return; } 500 501 this.toolbarWidget.update(); 502 }, 503 504 destroy: function(){ 505 //clean all loaded plugins 506 for(var index in this.loadedPlugins){ 507 this.loadedPlugins[index].destroy(); 508 delete this.loadedPlugins[index]; 509 } 510 this._htmlEditNode = null; 511 this.document = null; 512 this.window = null; 513 this.object = null; 514 dojo.widget.Editor2.superclass.destroy.call(this); 515 }, 516 517 onDisplayChanged: function(e){ 518 dojo.widget.Editor2.superclass.onDisplayChanged.call(this,e); 519 this.updateToolbar(); 520 }, 521 522 onLoad: function(){ 523 try{ 524 dojo.widget.Editor2.superclass.onLoad.call(this); 525 }catch(e){ // FIXME: debug why this is throwing errors in IE! 526 dojo.debug(e); 527 } 528 this.editorOnLoad(); 529 }, 530 531 onFocus: function(){ 532 dojo.widget.Editor2.superclass.onFocus.call(this); 533 this.setFocus(); 338 534 }, 339 535 … … 344 540 if(this.saveUrl.length){ 345 541 var content = {}; 346 content[this.saveArgName] = this.get Html();542 content[this.saveArgName] = this.getEditorContent(); 347 543 dojo.io.bind({ 348 544 method: this.saveMethod, … … 359 555 } 360 556 }, 361 "html", 362 function(){ 363 var cp = dojo.widget.Editor2.prototype; 364 if(!cp._wrappersSet){ 365 cp._wrappersSet = true; 366 367 cp.onDisplayChanged = (function(odc){ 368 return function(){ 369 try{ 370 odc.call(this); 371 this.updateToolbar(); 372 }catch(e){} 373 }; 374 })(cp.onDisplayChanged); 375 376 cp.onLoad = (function(ol){ 377 return function(){ 378 try{ 379 ol.call(this); 380 }catch(e){ // FIXME: debug why this is throwing errors in IE! 381 dojo.debug(e); 382 } 383 this.editorOnLoad(); 384 }; 385 })(cp.onLoad); 386 387 cp.onFocus = (function(of){ 388 return function(){ 389 of.call(this); 390 this.setFocus(); 391 }; 392 })(cp.onFocus); 393 } 394 } 557 "html" 395 558 ); -
trunk/src/widget/Editor2Toolbar.js
r5167 r5306 7 7 dojo.require("dojo.html.display"); 8 8 dojo.require("dojo.widget.RichText"); 9 dojo.require("dojo.widget.Menu2"); 9 10 dojo.require("dojo.widget.ColorPalette"); 11 12 dojo.widget.Editor2ToolbarItemManager = { 13 _registeredItemHandlers: [], 14 registerHandler: function(obj, func){ 15 if(arguments.length == 1){ 16 // for(i in this._registeredItemHandlers){ 17 // if(func === this._registeredItemHandlers[i]){ 18 // dojo.debug("Editor2ToolbarItemManager handler "+func+" is already registered, ignored"); 19 // return; 20 // } 21 // } 22 this._registeredItemHandlers.push(obj); 23 }else{ 24 this._registeredItemHandlers.push(function(){return obj[func].apply(obj, arguments);}); 25 } 26 }, 27 removeHandler: function(func){ 28 for(i in this._registeredItemHandlers){ 29 if(func === this._registeredItemHandlers[i]){ 30 delete this._registeredItemHandlers[i]; 31 return; 32 } 33 } 34 dojo.debug("Editor2ToolbarItemManager handler "+func+" is not registered, can not remove."); 35 }, 36 destroy: function(){ 37 for(var i in this._registeredItemHandlers){ 38 delete this._registeredItemHandlers[i]; 39 } 40 }, 41 getToolbarItem: function(name){ 42 var item; 43 name = name.toLowerCase(); 44 for(i in this._registeredItemHandlers){ 45 item = this._registeredItemHandlers[i](name); 46 if(item){ 47 break; 48 } 49 } 50 51 if(!item){ 52 switch(name){ 53 //button for builtin functions 54 case 'bold': 55 case 'copy': 56 case 'cut': 57 case 'delete': 58 case 'indent': 59 case 'inserthorizontalrule': 60 case 'insertorderedlist': 61 case 'insertunorderedlist': 62 case 'italic': 63 case 'justifycenter': 64 case 'justifyfull': 65 case 'justifyleft': 66 case 'justifyright': 67 case 'outdent': 68 case 'paste': 69 case 'redo': 70 case 'removeformat': 71 case 'selectall': 72 case 'strikethrough': 73 case 'subscript': 74 case 'superscript': 75 case 'underline': 76 case 'undo': 77 case 'unlink': 78 case 'createlink': 79 case 'insertimage': 80 //extra simple buttons 81 case 'htmltoggle': 82 item = new dojo.widget.Editor2ToolbarButton(name); 83 break; 84 case 'forecolor': 85 case 'hilitecolor': 86 item = new dojo.widget.Editor2ToolbarColorPaletteButton(name); 87 break; 88 case 'plainformatblock': 89 item = new dojo.widget.Editor2ToolbarFormatBlockPlainSelect("formatblock"); 90 break; 91 case 'formatblock': 92 item = new dojo.widget.Editor2ToolbarFormatBlockSelect("formatblock"); 93 break; 94 case 'fontsize': 95 item = new dojo.widget.Editor2ToolbarFontSizeSelect("fontsize"); 96 break; 97 case 'fontname': 98 item = new dojo.widget.Editor2ToolbarFontNameSelect("fontname"); 99 break; 100 case 'inserttable': 101 case 'insertcell': 102 case 'insertcol': 103 case 'insertrow': 104 case 'deletecells': 105 case 'deletecols': 106 case 'deleterows': 107 case 'mergecells': 108 case 'splitcell': 109 dojo.debug(name + " is implemented in dojo.widget.Editor2Plugin.TableOperation, please require it first."); 110 break; 111 //TODO: 112 case 'inserthtml': 113 case 'blockdirltr': 114 case 'blockdirrtl': 115 case 'dirltr': 116 case 'dirrtl': 117 case 'inlinedirltr': 118 case 'inlinedirrtl': 119 dojo.debug("Not yet implemented toolbar item: "+name); 120 break; 121 default: 122 dojo.debug("dojo.widget.Editor2ToolbarItemManager.getToolbarItem: Unknown toolbar item: "+name); 123 } 124 } 125 return item; 126 } 127 }; 128 129 dojo.addOnUnload(dojo.widget.Editor2ToolbarItemManager, "destroy"); 130 131 dojo.declare("dojo.widget.Editor2ToolbarButton", null,{ 132 initializer: function(name){ 133 this._name = name; 134 this._command = dojo.widget.Editor2Manager.getCommand(name); 135 }, 136 create: function(node, toolbar, isMenu){ 137 this._domNode = node; 138 //make this unselectable: different browsers 139 //use different properties for this, so use 140 //js do it automatically 141 this.disableSelection(this._domNode); 142 this._parentToolbar = toolbar; 143 dojo.event.connect(this._domNode, 'onclick', this, 'onClick'); 144 if(!isMenu){ 145 dojo.event.connect(this._domNode, 'onmouseover', this, 'onMouseOver'); 146 dojo.event.connect(this._domNode, 'onmouseout', this, 'onMouseOut'); 147 } 148 }, 149 disableSelection: function(rootnode){ 150 dojo.html.disableSelection(rootnode); 151 var nodes = rootnode.all || rootnode.getElementsByTagName("*"); 152 for(var x=0; x<nodes.length; x++){ 153 dojo.html.disableSelection(nodes[x]); 154 } 155 }, 156 onMouseOver: function(){ 157 if(this._command.getState() != dojo.widget.Editor2Manager.commandState.Disabled){ 158 this.highlightToolbarItem(); 159 } 160 }, 161 onMouseOut: function(){ 162 this.unhighlightToolbarItem(); 163 }, 164 destroy: function(){ 165 // dojo.event.disconnect(this._domNode, 'onclick', this, 'onClick'); 166 // dojo.event.disconnect(this._domNode, 'onmouseover', this, 'onMouseOver'); 167 // dojo.event.disconnect(this._domNode, 'onmouseout', this, 'onMouseOut'); 168 this._domNode = null; 169 delete this._command; 170 this._parentToolbar = null; 171 }, 172 onClick: function(e){ 173 if(this._domNode && !this._domNode.disabled && this._command){ 174 e.preventDefault(); 175 e.stopPropagation(); 176 this._command.execute(); 177 } 178 }, 179 refreshState: function(){ 180 if(this._domNode && this._command){ 181 var em = dojo.widget.Editor2Manager; 182 var state = this._command.getState(); 183 if(state != this._lastState){ 184 switch(state){ 185 case em.commandState.Latched: 186 this.latchToolbarItem(); 187 break; 188 case em.commandState.Enabled: 189 this.enableToolbarItem(); 190 break; 191 case em.commandState.Disabled: 192 default: 193 this.disableToolbarItem(); 194 } 195 this._lastState = state; 196 } 197 return state; 198 } 199 }, 200 201 latchToolbarItem: function(){ 202 this._domNode.disabled = false; 203 this.removeToolbarItemStyle(this._domNode); 204 dojo.html.addClass(this._domNode, this._parentToolbar.ToolbarLatchedItemStyle); 205 }, 206 207 enableToolbarItem: function(){ 208 this._domNode.disabled = false; 209 this.removeToolbarItemStyle(this._domNode); 210 dojo.html.addClass(this._domNode, this._parentToolbar.ToolbarEnabledItemStyle); 211 }, 212 213 disableToolbarItem: function(){ 214 this._domNode.disabled = true; 215 this.removeToolbarItemStyle(this._domNode); 216 dojo.html.addClass(this._domNode, this._parentToolbar.ToolbarDisabledItemStyle); 217 }, 218 219 highlightToolbarItem: function(){ 220 dojo.html.addClass(this._domNode, this._parentToolbar.ToolbarHighlightedItemStyle); 221 }, 222 223 unhighlightToolbarItem: function(){ 224 dojo.html.removeClass(this._domNode, this._parentToolbar.ToolbarHighlightedItemStyle); 225 }, 226 227 removeToolbarItemStyle: function(){ 228 dojo.html.removeClass(this._domNode, this._parentToolbar.ToolbarEnabledItemStyle); 229 dojo.html.removeClass(this._domNode, this._parentToolbar.ToolbarLatchedItemStyle); 230 dojo.html.removeClass(this._domNode, this._parentToolbar.ToolbarDisabledItemStyle); 231 this.unhighlightToolbarItem(); 232 } 233 }); 234 235 dojo.declare("dojo.widget.Editor2ToolbarDropDownButton", dojo.widget.Editor2ToolbarButton,{ 236 onClick: function(){ 237 if(this._domNode){ 238 if(!this._dropdown){ 239 this._dropdown = dojo.widget.createWidget("PopupContainer", {}); 240 this._domNode.appendChild(this._dropdown.domNode); 241 } 242 if(this._dropdown.isShowingNow){ 243 this._dropdown.close(); 244 }else{ 245 this.onDropDownShown(); 246 this._dropdown.open(this._domNode, null, this._domNode); 247 } 248 } 249 }, 250 destroy: function(){ 251 this.onDropDownDestroy(); 252 if(this._dropdown){ 253 this._dropdown.destroy(); 254 } 255 dojo.widget.Editor2ToolbarDropDownButton.superclass.destroy.call(this); 256 }, 257 onDropDownShown: function(){}, 258 onDropDownDestroy: function(){} 259 }); 260 261 dojo.declare("dojo.widget.Editor2ToolbarColorPaletteButton", dojo.widget.Editor2ToolbarDropDownButton,{ 262 onDropDownShown: function(){ 263 if(!this._colorpalette){ 264 this._colorpalette = dojo.widget.createWidget("ColorPalette", {}); 265 this._dropdown.addChild(this._colorpalette); 266 267 this.disableSelection(this._dropdown.domNode); 268 this.disableSelection(this._colorpalette.domNode); 269 //do we need a destory to delete this._colorpalette manually? 270 //I assume as it is added to this._dropdown via addChild, it 271 //should be deleted when this._dropdown is destroyed 272 273 dojo.event.connect(this._colorpalette, "onColorSelect", this, 'setColor'); 274 dojo.event.connect(this._dropdown, "open", this, 'latchToolbarItem'); 275 dojo.event.connect(this._dropdown, "close", this, 'enableToolbarItem'); 276 } 277 }, 278 setColor: function(color){ 279 this._dropdown.close(); 280 this._command.execute(color); 281 } 282 }); 283 284 dojo.declare("dojo.widget.Editor2ToolbarFormatBlockPlainSelect", dojo.widget.Editor2ToolbarButton,{ 285 create: function(node, toolbar){ 286 //TODO: check node is a select 287 this._domNode = node; 288 this.disableSelection(this._domNode); 289 this._parentToolbar = toolbar; 290 dojo.event.connect(this._domNode, 'onchange', this, 'onChange'); 291 }, 292 293 destroy: function(){ 294 this._domNode = null; 295 this._command = null; 296 this._parentToolbar = null; 297 }, 298 299 onChange: function(){ 300 if(this._domNode){ 301 var sv = this._domNode.value.toLowerCase(); 302 this._command.execute(sv); 303 } 304 }, 305 306 refreshState: function(){ 307 if(this._domNode && this._command){ 308 dojo.widget.Editor2ToolbarFormatBlockPlainSelect.superclass.refreshState.call(this); 309 var format = this._command.getValue(); 310 if(!format){ format = ""; } 311 dojo.lang.forEach(this._domNode.options, function(item){ 312 if(item.value.toLowerCase() == format.toLowerCase()){ 313 item.selected = true; 314 } 315 }); 316 } 317 } 318 }); 319 320 dojo.declare("dojo.widget.Editor2ToolbarComboItem", dojo.widget.Editor2ToolbarDropDownButton,{ 321 href: null, 322 create: function(node, toolbar){ 323 dojo.widget.Editor2ToolbarComboItem.superclass.create.call(this, node, toolbar); 324 //do not use lazy initilization, as we need the local names in refreshState() 325 if(!this._contentPane){ 326 dojo.require("dojo.widget.ContentPane"); 327 this._contentPane = dojo.widget.createWidget("ContentPane", {preload: 'true'}); 328 this._contentPane.addOnLoad(this, "setup"); 329 this._contentPane.setUrl(this.href); 330 } 331 }, 332 333 onMouseOver: function(e){ 334 dojo.html.addClass(e.currentTarget, this._parentToolbar.ToolbarHighlightedSelectStyle); 335 }, 336 onMouseOut:function(e){ 337 dojo.html.removeClass(e.currentTarget, this._parentToolbar.ToolbarHighlightedSelectStyle); 338 }, 339 340 onDropDownShown: function(){ 341 if(!this._dropdown.__addedContentPage){ 342 this._dropdown.addChild(this._contentPane); 343 this._dropdown.__addedContentPage = true; 344 } 345 }, 346 347 //overload this to connect event 348 setup: function(){}, 349 350 onChange: function(e){ 351 var name = e.currentTarget.getAttribute("dropDownItemName"); 352 this._command.execute(name); 353 this._dropdown.close(); 354 }, 355 356 onMouseOverItem: function(e){ 357 dojo.html.addClass(e.currentTarget, this._parentToolbar.ToolbarHighlightedSelectItemStyle); 358 }, 359 360 onMouseOutItem: function(e){ 361 dojo.html.removeClass(e.currentTarget, this._parentToolbar.ToolbarHighlightedSelectItemStyle); 362 }, 363 364 //overload this to update GUI item 365 refreshState: function(){} 366 }); 367 368 dojo.declare("dojo.widget.Editor2ToolbarFormatBlockSelect", dojo.widget.Editor2ToolbarComboItem,{ 369 href: dojo.uri.dojoUri("src/widget/templates/Editor2/EditorToolbar_FormatBlock.html"), 370 371 setup: function(){ 372 dojo.widget.Editor2ToolbarFormatBlockSelect.superclass.setup.call(this); 373 374 var nodes = this._contentPane.domNode.all || this._contentPane.domNode.getElementsByTagName("*"); 375 this._blockNames = {}; 376 this._blockDisplayNames = {}; 377 for(var x=0; x<nodes.length; x++){ 378 var node = nodes[x]; 379 dojo.html.disableSelection(node); 380 var name=node.getAttribute("dropDownItemName") 381 if(name){ 382 this._blockNames[name] = node; 383 var childrennodes = node.getElementsByTagName(name); 384 this._blockDisplayNames[name] = childrennodes[childrennodes.length-1].innerHTML; 385 } 386 } 387 for(var name in this._blockNames){ 388 dojo.event.connect(this._blockNames[name], "onclick", this, "onChange"); 389 dojo.event.connect(this._blockNames[name], "onmouseover", this, "onMouseOverItem"); 390 dojo.event.connect(this._blockNames[name], "onmouseout", this, "onMouseOutItem"); 391 } 392 }, 393 394 onDropDownDestroy: function(){ 395 if(this._blockNames){ 396 for(var name in this._blockNames){ 397 delete this._blockNames[name]; 398 delete this._blockDisplayNames[name]; 399 } 400 } 401 }, 402 403 refreshState: function(){ 404 if(this._command){ 405 //dojo.widget.Editor2ToolbarFormatBlockSelect.superclass.refreshState.call(this); 406 var format = this._command.getValue(); 407 if(format == this._lastSelectedFormat && this._blockDisplayNames){ 408 return; 409 } 410 this._lastSelectedFormat = format; 411 var label = this._domNode.getElementsByTagName("label")[0]; 412 var isSet = false; 413 if(this._blockDisplayNames){ 414 for(var name in this._blockDisplayNames){ 415 if(name == format){ 416 label.innerHTML = this._blockDisplayNames[name]; 417 isSet = true; 418 break; 419 } 420 } 421 if(!isSet){ 422 label.innerHTML = " "; 423 } 424 } 425 } 426 } 427 }); 428 429 dojo.declare("dojo.widget.Editor2ToolbarFontSizeSelect", dojo.widget.Editor2ToolbarComboItem,{ 430 href: dojo.uri.dojoUri("src/widget/templates/Editor2/EditorToolbar_FontSize.html"), 431 432 setup: function(){ 433 dojo.widget.Editor2ToolbarFormatBlockSelect.superclass.setup.call(this); 434 435 var nodes = this._contentPane.domNode.all || this._contentPane.domNode.getElementsByTagName("*"); 436 this._fontsizes = {}; 437 this._fontSizeDisplayNames = {}; 438 for(var x=0; x<nodes.length; x++){ 439 var node = nodes[x]; 440 dojo.html.disableSelection(node); 441 var name=node.getAttribute("dropDownItemName") 442 if(name){ 443 this._fontsizes[name] = node; 444 this._fontSizeDisplayNames[name] = node.getElementsByTagName('font')[0].innerHTML; 445 } 446 } 447 for(var name in this._fontsizes){ 448 dojo.event.connect(this._fontsizes[name], "onclick", this, "onChange"); 449 dojo.event.connect(this._fontsizes[name], "onmouseover", this, "onMouseOverItem"); 450 dojo.event.connect(this._fontsizes[name], "onmouseout", this, "onMouseOutItem"); 451 } 452 }, 453 454 onDropDownDestroy: function(){ 455 if(this._fontsizes){ 456 for(var name in this._fontsizes){ 457 delete this._fontsizes[name]; 458 delete this._fontSizeDisplayNames[name]; 459 } 460 } 461 }, 462 463 refreshState: function(){ 464 if(this._command){ 465 //dojo.widget.Editor2ToolbarFormatBlockSelect.superclass.refreshState.call(this); 466 var size = this._command.getValue(); 467 if(size == this._lastSelectedSize && this._fontSizeDisplayNames){ 468 return; 469 } 470 this._lastSelectedSize = size; 471 var label = this._domNode.getElementsByTagName("label")[0]; 472 var isSet = false; 473 if(this._fontSizeDisplayNames){ 474 for(var name in this._fontSizeDisplayNames){ 475 if(name == size){ 476 label.innerHTML = this._fontSizeDisplayNames[name]; 477 isSet = true; 478 break; 479 } 480 } 481 if(!isSet){ 482 label.innerHTML = " "; 483 } 484 } 485 } 486 } 487 }); 488 489 dojo.declare("dojo.widget.Editor2ToolbarFontNameSelect", dojo.widget.Editor2ToolbarFontSizeSelect,{ 490 href: dojo.uri.dojoUri("src/widget/templates/Editor2/EditorToolbar_FontName.html") 491 }); 10 492 11 493 dojo.widget.defineWidget( … … 13 495 dojo.widget.HtmlWidget, 14 496 { 15 commandList: [ "bold", "italic", "underline", "subscript", "superscript", 16 "fontname", "fontsize", "forecolor", "hilitecolor", "justifycenter", 17 "justifyfull", "justifyleft", "justifyright", "cut", "copy", "paste", 18 "delete", "undo", "redo", "createlink", "unlink", "removeformat", 19 "inserthorizontalrule", "insertimage", "insertorderedlist", 20 "insertunorderedlist", "indent", "outdent", "formatblock", "strikethrough", 21 "inserthtml", "blockdirltr", "blockdirrtl", "dirltr", "dirrtl", 22 "inlinedirltr", "inlinedirrtl", "inserttable", "insertcell", 23 "insertcol", "insertrow", "deletecells", "deletecols", "deleterows", 24 "mergecells", "splitcell" 25 ], 26 27 templatePath: dojo.uri.dojoUri("src/widget/templates/EditorToolbarOneline.html"), 28 // templatePath: dojo.uri.dojoUri("src/widget/templates/EditorToolbar.html"), 497 templatePath: dojo.uri.dojoUri("src/widget/templates/EditorToolbar.html"), 29 498 templateCssPath: dojo.uri.dojoUri("src/widget/templates/EditorToolbar.css"), 30 499 31 forecolorPalette: null,32 hilitecolorPalette: null,33 34 500 // DOM Nodes 35 wikiwordButton: null,36 htmltoggleButton: null,37 insertimageButton: null,38 styleDropdownButton: null,39 styleDropdownContainer: null,40 copyButton: null,41 boldButton: null,42 italicButton: null,43 underlineButton: null,44 justifycenterButton: null,45 justifyleftButton: null,46 justifyfullButton: null,47 justifyrightButton: null,48 pasteButton: null,49 undoButton: null,50 redoButton: null,51 linkButton: null,52 insertunorderedlistButton: null,53 insertorderedlistButton: null,54 forecolorButton: null,55 forecolorDropDown: null,56 hilitecolorButton: null,57 hilitecolorDropDown: null,58 formatSelectBox: null,59 inserthorizontalruleButton: null,60 strikethroughButton: null,61 clickInterceptDiv: null,62 oneLineTr: null,63 501 saveButton: null, 64 502 65 buttonClick: function(e){ e.preventDefault(); /* dojo.debug("buttonClick"); */ }, 66 67 buttonMouseOver: function(e){ }, 68 buttonMouseOut: function(e){ }, 69 503 ToolbarLatchedItemStyle: "ToolbarButtonLatched", 504 ToolbarEnabledItemStyle: "ToolbarButtonEnabled", 505 ToolbarDisabledItemStyle: "ToolbarButtonDisabled", 506 ToolbarHighlightedItemStyle: "ToolbarButtonHighlighted", 507 ToolbarHighlightedSelectStyle: "ToolbarSelectHighlighted", 508 ToolbarHighlightedSelectItemStyle: "ToolbarSelectHighlightedItem", 509 510 // itemNodeType: 'span', //all the items (with attribute dojoETItemName set) defined in the toolbar should be a of this type 511 512 postCreate: function(){ 513 var nodes = dojo.html.getElementsByClass("dojoEditorToolbarItem", this.domNode/*, this.itemNodeType*/); 514 515 this.items = {}; 516 for(var x=0; x<nodes.length; x++){ 517 var node = nodes[x]; 518 var itemname = node.getAttribute("dojoETItemName"); 519 if(itemname){ 520 var item = dojo.widget.Editor2ToolbarItemManager.getToolbarItem(itemname); 521 if(item){ 522 item.create(node, this); 523 this.items[itemname.toLowerCase()] = item; 524 }else{ 525 //hide unsupported toolbar items 526 node.style.display = "none"; 527 } 528 } 529 } 530 }, 70 531 71 532 // event signals 72 preventSelect: function(e){ if(dojo.render.html.safari){ e.preventDefault(); } },73 533 wikiwordClick: function(){ }, 74 insertimageClick: function(){ }, 75 htmltoggleClick: function(){ }, 534 // insertimageClick: function(){ }, 76 535 saveClick: function(){ }, 77 536 78 styleDropdownClick: function(){ 79 dojo.debug("styleDropdownClick:", this.styleDropdownContainer); 80 dojo.html.toggleShowing(this.styleDropdownContainer); 537 update: function(){ 538 for(var cmd in this.items){ 539 this.items[cmd].refreshState(); 540 } 81 541 }, 82 542 83 copyClick: function(){ this.exec("copy"); }, 84 boldClick: function(){ this.exec("bold"); }, 85 italicClick: function(){ this.exec("italic"); }, 86 underlineClick: function(){ this.exec("underline"); }, 87 justifyleftClick: function(){ this.exec("justifyleft"); }, 88 justifycenterClick: function(){ this.exec("justifycenter"); }, 89 justifyfullClick: function(){ this.exec("justifyfull"); }, 90 justifyrightClick: function(){ this.exec("justifyright"); }, 91 pasteClick: function(){ this.exec("paste"); }, 92 undoClick: function(){ this.exec("undo"); }, 93 redoClick: function(){ this.exec("redo"); }, 94 linkClick: function(){ 95 // FIXME: we need to alert the user if they haven't selected any text 96 // this.exec( "createlink", 97 // prompt("Please enter the URL of the link:", "http://")); 98 }, 99 insertunorderedlistClick: function(){ this.exec("insertunorderedlist"); }, 100 insertorderedlistClick: function(){ this.exec("insertorderedlist"); }, 101 inserthorizontalruleClick: function(){ this.exec("inserthorizontalrule"); }, 102 strikethroughClick: function(){ this.exec("strikethrough"); }, 103 104 formatSelectClick: function(){ 105 var sv = this.formatSelectBox.value.toLowerCase(); 106 this.exec("formatblock", sv); 107 }, 108 109 normalTextClick: function(){ this.exec("formatblock", "p"); }, 110 h1TextClick: function(){ this.exec("formatblock", "h1"); }, 111 h2TextClick: function(){ this.exec("formatblock", "h2"); }, 112 h3TextClick: function(){ this.exec("formatblock", "h3"); }, 113 h4TextClick: function(){ this.exec("formatblock", "h4"); }, 114 indentClick: function(){ this.exec("indent"); }, 115 outdentClick: function(){ this.exec("outdent"); }, 116 117 118 hideAllDropDowns: function(){ 119 this.domNode.style.height = ""; 120 dojo.lang.forEach(dojo.widget.byType("Editor2Toolbar"), function(tb){ 121 try{ 122 dojo.html.hide(tb.forecolorDropDown); 123 dojo.html.hide(tb.hilitecolorDropDown); 124 dojo.html.hide(tb.styleDropdownContainer); 125 if(tb.clickInterceptDiv){ 126 dojo.html.hide(tb.clickInterceptDiv); 127 } 128 }catch(e){} 129 if(dojo.render.html.ie){ 130 try{ 131 dojo.html.hide(tb.forecolorPalette.bgIframe); 132 }catch(e){} 133 try{ 134 dojo.html.hide(tb.hilitecolorPalette.bgIframe); 135 }catch(e){} 136 } 137 }); 138 }, 139 140 selectFormat: function(format){ 141 if(this.formatSelectBox) { 142 dojo.lang.forEach(this.formatSelectBox.options, function(item){ 143 if(item.value.toLowerCase() == format.toLowerCase()){ 144 // FIXME: SEVERE: setting selected on this item breaks the undo stack on IE 145 item.selected = true; 146 } 147 }); 148 } 149 }, 150 151 forecolorClick: function(e){ 152 this.colorClick(e, "forecolor"); 153 }, 154 155 hilitecolorClick: function(e){ 156 this.colorClick(e, "hilitecolor"); 157 }, 158 159 // FIXME: these methods aren't currently dealing with clicking in the 160 // general document to hide the menu 161 colorClick: function(e, type){ 162 var h = dojo.render.html; 163 this.hideAllDropDowns(); 164 // FIXME: if we've been "popped out", we need to set the height of the toolbar. 165 e.stopPropagation(); 166 var dd = this[type+"DropDown"]; 167 var pal = this[type+"Palette"]; 168 dojo.html.toggleShowing(dd); 169 if(!pal){ 170 pal = this[type+"Palette"] = dojo.widget.createWidget("ColorPalette", {}, dd, "first"); 171 var fcp = pal.domNode; 172 var mb = dojo.html.getMarginBox(fcp); 173 with(dd.style){ 174 width = mb.width + "px"; 175 height = mb.height + "px"; 176 zIndex = 1002; 177 position = "absolute"; 178 } 179 180 dojo.event.connect( "after", 181 pal, "onColorSelect", 182 this, "exec", 183 function(mi){ mi.args.unshift(type); return mi.proceed(); } 184 ); 185 186 dojo.event.connect( "after", 187 pal, "onColorSelect", 188 dojo.html, "toggleShowing", 189 this, function(mi){ mi.args.unshift(dd); return mi.proceed(); } 190 ); 191 192 var cid = this.clickInterceptDiv; 193 if(!cid){ 194 cid = this.clickInterceptDiv = document.createElement("div"); 195 document.body.appendChild(cid); 196 with(cid.style){ 197 backgroundColor = "transparent"; 198 top = left = "0px"; 199 height = width = "100%"; 200 position = "absolute"; 201 border = "none"; 202 display = "none"; 203 zIndex = 1001; 204 } 205 dojo.event.connect(cid, "onclick", function(){ cid.style.display = "none"; }); 206 } 207 dojo.event.connect(pal, "onColorSelect", function(){ cid.style.display = "none"; }); 208 209 dojo.event.kwConnect({ 210 srcObj: document.body, 211 srcFunc: "onclick", 212 targetObj: this, 213 targetFunc: "hideAllDropDowns", 214 once: true 215 }); 216 document.body.appendChild(dd); 217 } 218 dojo.html.toggleShowing(this.clickInterceptDiv); 219 var pos = dojo.html.abs(this[type+"Button"]); 220 dojo.html.placeOnScreenPoint(dd, pos.x, pos.y, 0, false); 221 if(pal.bgIframe){ 222 var mb = dojo.html.getMarginBox(dd); 223 with(pal.bgIframe.style){ 224 display = "block"; 225 left = dd.style.left; 226 top = dd.style.top; 227 width = mb.width+"px"; 228 height = mb.height+"px"; 229 } 230 } 231 }, 232 233 uninitialize: function(){ 234 if(!dojo.render.html.ie){ 235 // apparently this causes leakage on IE! 236 dojo.event.kwDisconnect({ 237 srcObj: document.body, 238 srcFunc: "onclick", 239 targetObj: this, 240 targetFunc: "hideAllDropDowns", 241 once: true 242 }); 243 } 244 }, 543 destroy: function(){ 544 for(var it in this.items){ 545 this.items[it].destroy(); 546 delete this.items[it]; 547 } 548 dojo.widget.Editor2Toolbar.superclass.destroy.call(this); 549 }//, 245 550 246 551 // stub for observers 247 exec: function(what, arg){ /* dojo.debug(what, new Date()); */ }, 248 249 hideUnusableButtons: function(obj){ 250 var op = obj||dojo.widget.RichText.prototype; 251 dojo.lang.forEach(this.commandList, 252 function(cmd){ 253 if(this[cmd+"Button"]){ 254 var cb = this[cmd+"Button"]; 255 if(!op.queryCommandAvailable(cmd)){ 256 cb.style.display = "none"; 257 cb.parentNode.style.display = "none"; 258 } 259 } 260 }, 261 this); 262 if(this.oneLineTr){ 263 var lastVisibleIsSpacer = false; 264 var lastVisible = false; 265 var tds = this.oneLineTr.getElementsByTagName("td"); 266 dojo.lang.forEach(tds, function(td){ 267 if(td.getAttribute("isSpacer")){ 268 if(td.style.display != "none"){ 269 if(lastVisibleIsSpacer){ 270 td.style.display = "none"; 271 } 272 lastVisibleIsSpacer = true; 273 }else{ 274 lastVisible = td; 275 lastVisibleIsSpacer = true; 276 } 277 }else{ 278 if(td.style.display != "none"){ 279 lastVisible = td; 280 lastVisibleIsSpacer = false; 281 } 282 } 283 }); 284 } 285 }, 286 287 highlightButton: function(name){ 288 var bn = name+"Button"; 289 if(this[bn]){ 290 with(this[bn].style){ 291 backgroundColor = "White"; 292 border = "1px solid #aeaeab"; 293 } 294 } 295 }, 296 297 unhighlightButton: function(name){ 298 var bn = name+"Button"; 299 if(this[bn]){ 300 // dojo.debug("unhighlighting:", name); 301 with(this[bn].style){ 302 backgroundColor = ""; 303 border = ""; 304 } 305 } 306 } 552 // exec: function(what, arg){ /* dojo.debug(what, new Date()); */ } 307 553 }, 308 554 "html", 309 555 function(){ 310 // dojo.event.connect(this, "fillInTemplate", this, "hideUnusableButtons");311 556 dojo.event.connect(this, "fillInTemplate", dojo.lang.hitch(this, function(){ 312 557 if(dojo.render.html.ie){ -
trunk/src/widget/RichText.js
r5280 r5306 293 293 var node = this.editNode.firstChild; 294 294 while(node){ 295 dojo.withGlobal(this.window, "selectElement", dojo.html.selection, node.firstChild);295 dojo.withGlobal(this.window, "selectElement", dojo.html.selection, [node.firstChild]); 296 296 var nativename = node.tagName.toLowerCase(); 297 297 this._local2NativeFormatNames[nativename] = this.queryCommandValue("formatblock"); … … 622 622 ' body,html { padding: 0; margin: 0; }' + //font: ' + font + '; }' + 623 623 (this.height ? '' : ' body, { overflow: hidden; }') + 624 //' #bodywrapper { }' +625 624 '</style>' + 626 625 //'<base href="' + dojo.global().location + '">' + 627 '<body> <div id="bodywrapper">' + html + '</div></body></html>';626 '<body>' + html + '</body></html>'; 628 627 629 628 this._cacheLocalBlockFormatNames(); … … 678 677 this.document = this.object.DOM; 679 678 this.window = this.document.parentWindow; 680 this.editNode = this.document.body .firstChild;679 this.editNode = this.document.body; 681 680 this.domNode.style.height = this.height ? this.height : this.minHeight; 682 681 this.connect(this, "onDisplayChanged", "_updateHeight"); … … 718 717 dojo.event.connect("before", this, "close", unBlur, "unBlur"); 719 718 dojo.event.browser.addListener(this.document, "focus", dojo.lang.hitch(this, "onFocus")); 720 721 // safari can't handle key listeners, it kills the speed 719 722 720 var addListener = dojo.event.browser.addListener; 723 721 addListener(this.document, "keypress", dojo.lang.hitch(this, "onKeyPress")); … … 1035 1033 if(command == "formatblock"){ 1036 1034 if(drh.safari){ command = "heading"; } 1037 if(this.object ){ //IE activeX mode1035 if(this.object && joinObject.args[1]){ //IE activeX mode 1038 1036 joinObject.args[1] = this._native2LocalFormatNames[joinObject.args[1]]; 1039 1037 } … … 1160 1158 if(this.object){ 1161 1159 switch (command) { 1160 case "hilitecolor": 1161 command = "setbackcolor"; 1162 break; 1162 1163 case "forecolor": 1163 1164 case "backcolor": … … 1176 1177 return; 1177 1178 } 1178 argument= "<strike>"+range.htmlText+"<strike>";1179 argument=range.htmlText.strike(); 1179 1180 }else if(command == "inserthorizontalrule"){ 1180 1181 command = "inserthtml"; … … 1251 1252 1252 1253 // select our link and unlink 1253 var a = dojo.withGlobal(this.window, "getAncestorElement", dojo.html.selection, 'a');1254 dojo.withGlobal(this.window, "selectElement", dojo.html.selection, a);1254 var a = dojo.withGlobal(this.window, "getAncestorElement", dojo.html.selection, ['a']); 1255 dojo.withGlobal(this.window, "selectElement", dojo.html.selection, [a]); 1255 1256 1256 1257 returnValue = this.document.execCommand("unlink", false, null); … … 1303 1304 if(this.object){ 1304 1305 switch (command) { 1306 case "hilitecolor": 1307 command = "setbackcolor"; 1308 break; 1305 1309 case "forecolor": 1306 1310 case "backcolor": … … 1327 1331 // mozilla returns true always 1328 1332 if(command == "unlink" && dojo.render.html.mozilla){ 1329 return dojo.withGlobal(this.window, "hasAncestorElement", dojo.html.selection, 'a');1333 return dojo.withGlobal(this.window, "hasAncestorElement", dojo.html.selection, ['a']); 1330 1334 } else if (command == "inserttable" && dojo.render.html.mozilla) { 1331 1335 return true; … … 1346 1350 }else if(command == "strikethrough"){ 1347 1351 //check whether we are under a <strike> 1348 return dojo.withGlobal(this.window, "hasAncestorElement", dojo.html.selection, 'strike');1352 return dojo.withGlobal(this.window, "hasAncestorElement", dojo.html.selection, ['strike']); 1349 1353 }else if(command == "inserthorizontalrule"){ 1350 1354 return false; … … 1393 1397 placeCursorAtStart: function(){ 1394 1398 this.focus(); 1395 dojo.withGlobal(this.window, "selectElementChildren", dojo.html.selection, this.editNode); 1396 dojo.withGlobal(this.window, "collapse", dojo.html.selection, true); 1399 //see comments in placeCursorAtEnd 1400 if(dojo.render.html.moz && this.editNode.firstChild && 1401 this.editNode.firstChild.nodeType != dojo.dom.TEXT_NODE){ 1402 dojo.withGlobal(this.window, "selectElementChildren", dojo.html.selection, [this.editNode.firstChild]); 1403 }else{ 1404 dojo.withGlobal(this.window, "selectElementChildren", dojo.html.selection, [this.editNode]); 1405 } 1406 dojo.withGlobal(this.window, "collapse", dojo.html.selection, [true]); 1397 1407 }, 1398 1408 … … 1403 1413 if(dojo.render.html.moz && this.editNode.lastChild && 1404 1414 this.editNode.lastChild.nodeType != dojo.dom.TEXT_NODE){ 1405 dojo.withGlobal(this.window, "selectElementChildren", dojo.html.selection, this.editNode.lastChild);1415 dojo.withGlobal(this.window, "selectElementChildren", dojo.html.selection, [this.editNode.lastChild]); 1406 1416 }else{ 1407 dojo.withGlobal(this.window, "selectElementChildren", dojo.html.selection, this.editNode);1408 } 1409 dojo.withGlobal(this.window, "collapse", dojo.html.selection, false);1417 dojo.withGlobal(this.window, "selectElementChildren", dojo.html.selection, [this.editNode]); 1418 } 1419 dojo.withGlobal(this.window, "collapse", dojo.html.selection, [false]); 1410 1420 }, 1411 1421 … … 1522 1532 }catch(e){ /* squelch */ } 1523 1533 1534 if(dojo.render.html.ie && !this.object){ 1535 //removing appended <P> </P> for IE in none-activeX mode 1536 var re = new RegExp("(?:<p> </p>[\n\r]*)+$", "i"); 1537 ec = ec.replace(re,""); 1538 } 1539 1524 1540 ec = this._postFilterContent(ec); 1525 1541 -
trunk/src/widget/templates/EditorToolbar.css
r5163 r5306 67 67 } 68 68 69 span.icon {69 .dojoE2TBIcon { 70 70 display: block; 71 71 text-align: center; … … 79 79 80 80 81 span.icon[class~=icon] { 81 .dojoE2TBIcon[class~=dojoE2TBIcon] { 82 } 83 84 .ToolbarButtonLatched { 85 border: #316ac5 1px solid; 86 background-color: #c1d2ee; 87 } 88 89 .ToolbarButtonHighlighted { 90 border: #316ac5 1px solid; 91 background-color: #dff1ff; 92 } 93 94 .ToolbarButtonDisabled{ 95 filter: gray() alpha(opacity=30); /* IE */ 96 opacity: 0.30; /* Safari, Opera and Mozilla */ 82 97 } 83 98 … … 96 111 font-size: 14px; 97 112 } 113 114 .dojoE2TBIcon_Sep { width: 5px; min-width: 5px; max-width: 5px; background-position: 0px 0px} 115 .dojoE2TBIcon_Backcolor { background-position: -18px 0px} 116 .dojoE2TBIcon_Bold { background-position: -36px 0px} 117 .dojoE2TBIcon_Cancel { background-position: -54px 0px} 118 .dojoE2TBIcon_Copy { background-position: -72px 0px} 119 .dojoE2TBIcon_Link { background-position: -90px 0px} 120 .dojoE2TBIcon_Cut { background-position: -108px 0px} 121 .dojoE2TBIcon_Delete { background-position: -126px 0px} 122 .dojoE2TBIcon_TextColor { background-position: -144px 0px} 123 .dojoE2TBIcon_BackgroundColor { background-position: -162px 0px} 124 .dojoE2TBIcon_Indent { background-position: -180px 0px} 125 .dojoE2TBIcon_HorizontalLine { background-position: -198px 0px} 126 .dojoE2TBIcon_Image { background-position: -216px 0px} 127 .dojoE2TBIcon_NumberedList { background-position: -234px 0px} 128 .dojoE2TBIcon_Table { background-position: -252px 0px} 129 .dojoE2TBIcon_BulletedList { background-position: -270px 0px} 130 .dojoE2TBIcon_Italic { background-position: -288px 0px} 131 .dojoE2TBIcon_CenterJustify { background-position: -306px 0px} 132 .dojoE2TBIcon_BlockJustify { background-position: -324px 0px} 133 .dojoE2TBIcon_LeftJustify { background-position: -342px 0px} 134 .dojoE2TBIcon_RightJustify { background-position: -360px 0px} 135 .dojoE2TBIcon_left_to_right { background-position: -378px 0px} 136 .dojoE2TBIcon_list_bullet_indent { background-position: -396px 0px} 137 .dojoE2TBIcon_list_bullet_outdent { background-position: -414px 0px} 138 .dojoE2TBIcon_list_num_indent { background-position: -432px 0px} 139 .dojoE2TBIcon_list_num_outdent { background-position: -450px 0px} 140 .dojoE2TBIcon_Outdent { background-position: -468px 0px} 141 .dojoE2TBIcon_Paste { background-position: -486px 0px} 142 .dojoE2TBIcon_Redo { background-position: -504px 0px} 143 dojoE2TBIcon_RemoveFormat { background-position: -522px 0px} 144 .dojoE2TBIcon_right_to_left { background-position: -540px 0px} 145 .dojoE2TBIcon_Save { background-position: -558px 0px} 146 .dojoE2TBIcon_Space { background-position: -576px 0px} 147 .dojoE2TBIcon_StrikeThrough { background-position: -594px 0px} 148 .dojoE2TBIcon_Subscript { background-position: -612px 0px} 149 .dojoE2TBIcon_Superscript { background-position: -630px 0px} 150 .dojoE2TBIcon_Underline { background-position: -648px 0px} 151 .dojoE2TBIcon_Undo { background-position: -666px 0px} 152 .dojoE2TBIcon_WikiWord { background-position: -684px 0px} 98 153 99 .sep { width: 5px; min-width: 5px; max-width: 5px; background-position: 0px 0px}100 .backcolor { background-position: -18px 0px}101 .bold { background-position: -36px 0px}102 .cancel { background-position: -54px 0px}103 .copy { background-position: -72px 0px}104 .createlink { background-position: -90px 0px}105 .cut { background-position: -108px 0px}106 .delete { background-position: -126px 0px}107 .forecolor { background-position: -144px 0px}108 .hilitecolor { background-position: -162px 0px}109 .indent { background-position: -180px 0px}110 .inserthorizontalrule { background-position: -198px 0px}111 .insertimage { background-position: -216px 0px}112 .insertorderedlist { background-position: -234px 0px}113 .inserttable { background-position: -252px 0px}114 .insertunorderedlist { background-position: -270px 0px}115 .italic { background-position: -288px 0px}116 .justifycenter { background-position: -306px 0px}117 .justifyfull { background-position: -324px 0px}118 .justifyleft { background-position: -342px 0px}119 .justifyright { background-position: -360px 0px}120 .left_to_right { background-position: -378px 0px}121 .list_bullet_indent { background-position: -396px 0px}122 .list_bullet_outdent { background-position: -414px 0px}123 .list_num_indent { background-position: -432px 0px}124 .list_num_outdent { background-position: -450px 0px}125 .outdent { background-position: -468px 0px}126 .paste { background-position: -486px 0px}127 .redo { background-position: -504px 0px}128 .removeformat { background-position: -522px 0px}129 .right_to_left { background-position: -540px 0px}130 .save { background-position: -558px 0px}131 .space { background-position: -576px 0px}132 .strikethrough { background-position: -594px 0px}133 .subscript { background-position: -612px 0px}134 .superscript { background-position: -630px 0px}135 .underline { background-position: -648px 0px}136 .undo { background-position: -666px 0px}137 .wikiword { background-position: -684px 0px}138 -
trunk/src/widget/templates/EditorToolbarOneline.html
r5163 r5306 1 <div class="EditorToolbarDomNode EditorToolbarSmallBg" 2 unselectable="on" dojoOnMouseDown="preventSelect"> 1 <div class="EditorToolbarDomNode EditorToolbarSmallBg"> 3 2 <table cellpadding="1" cellspacing="0" border="0"> 4 3 <!-- … … 27 26 --> 28 27 <tbody> 29 <tr valign="top" align="left" dojoAttachPoint="oneLineTr">28 <tr valign="top" align="left"> 30 29 <td> 31 30 <!-- htmltoggle --> 32 <span class="iconContainer" dojoAttachPoint="htmltoggleButton" 33 dojoOnClick="htmltoggleClick; buttonClick;" style="display: none;"> 34 <span title="Toggle Rich Text and HTML Markup Editing Modes" class="icon" 35 style="background-image: none; width: 30px;" 36 unselectable="on"><h></span> 37 </span> 38 </td> 39 <td> 40 <!-- wikiword --> 31 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="htmltoggle"> 32 <span title="Toggle Rich Text and HTML Markup Editing Modes" class="dojoE2TBIcon" 33 style="background-image: none; width: 30px;" ><h></span> 34 </span> 35 </td> 36 <!-- wikiword --> 37 <!--td> 41 38 <span class="iconContainer" dojoAttachPoint="wikiwordButton" 42 39 dojoOnClick="wikiwordClick; buttonClick;" style="display: none;"> 43 <span title="Toggle Wiki Word" class=" iconwikiword"40 <span title="Toggle Wiki Word" class="dojoE2TBIcon dojoE2TBIcon_wikiword" 44 41 unselectable="on"> </span> 45 42 </span> 43 </td--> 44 <td> 45 <!-- copy --> 46 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="copy"> 47 <span title="Copy (Ctrl-C)" class="dojoE2TBIcon dojoE2TBIcon_Copy"> </span> 48 </span> 46 49 </td> 47 50 <td> 48 51 <!-- paste --> 49 <span class="iconContainer" dojoAttachPoint="copyButton" 50 unselectable="on" dojoOnClick="copyClick; buttonClick;"> 51 <span title="Copy (Ctrl-C)" class="icon copy" unselectable="on"> </span> 52 </span> 53 </td> 54 <td> 55 <!-- copy --> 56 <span class="iconContainer" dojoAttachPoint="pasteButton" 57 dojoOnClick="pasteClick; buttonClick;" unselectable="on"> 58 <span title="Paste (Ctrl-V)" class="icon paste" unselectable="on"> </span> 52 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="paste"> 53 <span title="Paste (Ctrl-V)" class="dojoE2TBIcon dojoE2TBIcon_Paste"> </span> 59 54 </span> 60 55 </td> 61 56 <td> 62 57 <!-- undo --> 63 <span class="iconContainer" dojoAttachPoint="undoButton" 64 dojoOnClick="undoClick; buttonClick;" unselectable="on"> 58 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="undo"> 65 59 <!-- FIXME: should we have the text "undo" here? --> 66 <span title="Undo (Ctrl-Z)" class=" icon undo" unselectable="on"> </span>60 <span title="Undo (Ctrl-Z)" class="dojoE2TBIcon dojoE2TBIcon_Undo"> </span> 67 61 </span> 68 62 </td> 69 63 <td> 70 64 <!-- redo --> 71 <span class="iconContainer" dojoAttachPoint="redoButton" 72 dojoOnClick="redoClick; buttonClick;" unselectable="on"> 73 <span title="Redo (Ctrl-R)" class="icon redo" unselectable="on"> </span> 74 </span> 75 </td> 76 <td isSpacer="true"> 77 <!-- spacer --> 78 <span class="iconContainer"> 79 <span class="icon sep" unselectable="on" 65 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="redo"> 66 <span title="Redo (Ctrl-R)" class="dojoE2TBIcon dojoE2TBIcon_Redo"> </span> 67 </span> 68 </td> 69 <td isSpacer="true"> 70 <!-- spacer --> 71 <span class="iconContainer"> 72 <span class="dojoE2TBIcon dojoE2TBIcon_Sep" style="width: 5px; min-width: 5px;"></span> 73 </span> 74 </td> 75 <td> 76 <!-- link --> 77 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="createlink"> 78 <span title="Create Link" class="dojoE2TBIcon dojoE2TBIcon_Link"> </span> 79 </span> 80 </td> 81 <td> 82 <!-- insertimage --> 83 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="insertimage"> 84 <span title="Insert Image" class="dojoE2TBIcon dojoE2TBIcon_Image"> </span> 85 </span> 86 </td> 87 <td> 88 <!-- inserthorizontalrule --> 89 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="inserthorizontalrule"> 90 <span title="Insert Horizontal Rule" class="dojoE2TBIcon dojoE2TBIcon_HorizontalLine "> </span> 91 </span> 92 </td> 93 <td> 94 <!-- bold --> 95 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="bold"> 96 <span title="Toggle Bold (Ctrl-B)" class="dojoE2TBIcon dojoE2TBIcon_Bold"> </span> 97 </span> 98 </td> 99 <td> 100 <!-- italic --> 101 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="italic"> 102 <span title="Toggle Italic (Ctrl-I)" class="dojoE2TBIcon dojoE2TBIcon_Italic"> </span> 103 </span> 104 </td> 105 <td> 106 <!-- underline --> 107 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="underline"> 108 <span title="Toggle Underline (Ctrl-U)" class="dojoE2TBIcon dojoE2TBIcon_Underline"> </span> 109 </span> 110 </td> 111 <td> 112 <!-- strikethrough --> 113 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="strikethrough"> 114 <span title="Toggle Strike-Through" 115 class="dojoE2TBIcon dojoE2TBIcon_StrikeThrough"> </span> 116 </span> 117 </td> 118 <td isSpacer="true"> 119 <!-- spacer --> 120 <span class="iconContainer"> 121 <span class="dojoE2TBIcon dojoE2TBIcon_Sep" 80 122 style="width: 5px; min-width: 5px;"></span> 81 123 </span> 82 124 </td> 83 125 <td> 84 <!-- link -->85 <span class="iconContainer" dojoAttachPoint="linkButton"86 unselectable="on" dojoOnClick="linkClick; buttonClick;">87 <span title="Create Link" class="icon createlink" unselectable="on"> </span>88 </span>89 </td>90 <td>91 <!-- insertimage -->92 <span class="iconContainer"93 style="display: none;"94 dojoAttachPoint="insertimageButton"95 unselectable="on" dojoOnClick="insertimageClick; buttonClick;">96 <span title="Insert Image" class="icon insertimage" unselectable="on"> </span>97 </span>98 </td>99 <td>100 <!-- inserthorizontalrule -->101 <span class="iconContainer" dojoAttachPoint="inserthorizontalruleButton"102 unselectable="on" dojoOnClick="inserthorizontalruleClick; buttonClick;">103 <span title="Insert Horizontal Rule" class="icon inserthorizontalrule " unselectable="on"> </span>104 </span>105 </td>106 <td>107 <!-- bold -->108 <span class="iconContainer" dojoAttachPoint="boldButton"109 unselectable="on" dojoOnClick="boldClick; buttonClick;">110 <span title="Toggle Bold (Ctrl-B)" class="icon bold" unselectable="on"> </span>111 </span>112 </td>113 <td>114 <!-- italic -->115 <span class="iconContainer" dojoAttachPoint="italicButton"116 dojoOnClick="italicClick; buttonClick;">117 <span title="Toggle Italic (Ctrl-I)" class="icon italic" unselectable="on"> </span>118 </span>119 </td>120 <td>121 <!-- underline -->122 <span class="iconContainer" dojoAttachPoint="underlineButton"123 dojoOnClick="underlineClick; buttonClick;">124 <span title="Toggle Underline (Ctrl-U)" class="icon underline" unselectable="on"> </span>125 </span>126 </td>127 <td>128 <!-- strikethrough -->129 <span class="iconContainer" dojoAttachPoint="strikethroughButton"130 dojoOnClick="strikethroughClick; buttonClick;">131 <span title="Toggle Strike-Through"132 class="icon strikethrough" unselectable="on"> </span>133 </span>134 </td>135 <td isSpacer="true">136 <!-- spacer -->137 <span class="iconContainer">138 <span class="icon sep" unselectable="on"139 style="width: 5px; min-width: 5px;"></span>140 </span>141 </td>142 <td>143 126 <!-- insertunorderedlist --> 144 <span class="iconContainer" dojoAttachPoint="insertunorderedlistButton" 145 unselectable="on" 146 dojoOnClick="insertunorderedlistClick; buttonClick;"> 127 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="insertunorderedlist"> 147 128 <span title="Insert Bullet List" 148 class=" icon insertunorderedlist" unselectable="on"> </span>129 class="dojoE2TBIcon dojoE2TBIcon_BulletedList"> </span> 149 130 </span> 150 131 </td> 151 132 <td> 152 133 <!-- insertorderedlist --> 153 <span class="iconContainer" dojoAttachPoint="insertorderedlistButton" 154 unselectable="on" dojoOnClick="insertorderedlistClick; buttonClick;"> 134 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="insertorderedlist"> 155 135 <span title="Insert Numbered List" 156 class="icon insertorderedlist" unselectable="on"> </span> 157 </span> 158 </td> 159 <td isSpacer="true"> 160 <!-- spacer --> 161 <span class="iconContainer"> 162 <span class="icon sep" unselectable="on" 163 style="width: 5px; min-width: 5px;"></span> 136 class="dojoE2TBIcon dojoE2TBIcon_NumberedList"> </span> 137 </span> 138 </td> 139 <td isSpacer="true"> 140 <!-- spacer --> 141 <span class="iconContainer"> 142 <span class="dojoE2TBIcon dojoE2TBIcon_Sep" style="width: 5px; min-width: 5px;"></span> 164 143 </span> 165 144 </td> 166 145 <td> 167 146 <!-- indent --> 168 <span class="iconContainer" dojoAttachPoint="indentButton" 169 unselectable="on" dojoOnClick="indentClick; buttonClick;"> 170 <span title="Indent Selection" class="icon indent" 147 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="indent"> 148 <span title="Indent Selection" class="dojoE2TBIcon dojoE2TBIcon_Indent" 171 149 unselectable="on"> </span> 172 150 </span> … … 174 152 <td> 175 153 <!-- outdent --> 176 <span class="iconContainer" dojoAttachPoint="outdentButton" 177 unselectable="on" dojoOnClick="outdentClick; buttonClick;"> 178 <span title="Outdent Selection" class="icon outdent" 179 unselectable="on"> </span> 180 </span> 181 </td> 182 <td isSpacer="true"> 183 <!-- spacer --> 184 <span class="iconContainer"> 185 <span class="icon sep" unselectable="on" 186 style="width: 5px; min-width: 5px;"></span> 154 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="outdent"> 155 <span title="Outdent Selection" class="dojoE2TBIcon dojoE2TBIcon_Outdent" 156 unselectable="on"> </span> 157 </span> 158 </td> 159 <td isSpacer="true"> 160 <!-- spacer --> 161 <span class="iconContainer"> 162 <span class="dojoE2TBIcon dojoE2TBIcon_Sep" style="width: 5px; min-width: 5px;"></span> 187 163 </span> 188 164 </td> 189 165 <td> 190 166 <!-- forecolor --> 191 <span class="iconContainer" dojoAttachPoint="forecolorButton" 192 unselectable="on" dojoOnClick="forecolorClick; buttonClick;"> 193 <span title="Change Text Color" class="icon forecolor" 194 unselectable="on"> </span> 195 </span> 196 <div class="ColorDropdownContainer" 197 style="display: none; margin-top: 22px;" 198 dojoAttachPoint="forecolorDropDown"> 199 </div> 167 <span class="iconContainer dojoEditorToolbarItem" dojoETItemName="forecolor">