define("dijit/Editor", ["dojo", "dijit", "dijit/_editor/RichText", "dijit/Toolbar", "dijit/ToolbarSeparator", "dijit/_editor/_Plugin", "dijit/_editor/plugins/EnterKeyHandling", "dijit/_editor/range", "dijit/_Container", "dojo/i18n", "dijit/layout/_LayoutWidget", "i18n!dijit/_editor/nls/commands"], function(dojo, dijit) {
dojo.declare(
"dijit.Editor",
dijit._editor.RichText,
{
// summary:
// A rich text Editing widget
//
// description:
// This widget provides basic WYSIWYG editing features, based on the browser's
// underlying rich text editing capability, accompanied by a toolbar (`dijit.Toolbar`).
// A plugin model is available to extend the editor's capabilities as well as the
// the options available in the toolbar. Content generation may vary across
// browsers, and clipboard operations may have different results, to name
// a few limitations. Note: this widget should not be used with the HTML
// <TEXTAREA> tag -- see dijit._editor.RichText for details.
// plugins: [const] Object[]
// A list of plugin names (as strings) or instances (as objects)
// for this widget.
//
// When declared in markup, it might look like:
// | plugins="['bold',{name:'dijit._editor.plugins.FontChoice', command:'fontName', generic:true}]"
plugins: null,
// extraPlugins: [const] Object[]
// A list of extra plugin names which will be appended to plugins array
extraPlugins: null,
constructor: function(){
// summary:
// Runs on widget initialization to setup arrays etc.
// tags:
// private
if(!dojo.isArray(this.plugins)){
this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|",
"insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull",
"dijit._editor.plugins.EnterKeyHandling" /*, "createLink"*/];
}
this._plugins=[];
this._editInterval = this.editActionInterval * 1000;
//IE will always lose focus when other element gets focus, while for FF and safari,
//when no iframe is used, focus will be lost whenever another element gets focus.
//For IE, we can connect to onBeforeDeactivate, which will be called right before
//the focus is lost, so we can obtain the selected range. For other browsers,
//no equivelent of onBeforeDeactivate, so we need to do two things to make sure
//selection is properly saved before focus is lost: 1) when user clicks another
//element in the page, in which case we listen to mousedown on the entire page and
//see whether user clicks out of a focus editor, if so, save selection (focus will
//only lost after onmousedown event is fired, so we can obtain correct caret pos.)
//2) when user tabs away from the editor, which is handled in onKeyDown below.
if(dojo.isIE){
this.events.push("onBeforeDeactivate");
this.events.push("onBeforeActivate");
}
},
postMixInProperties: function() {
// summary:
// Extension to make sure a deferred is in place before certain functions
// execute, like making sure all the plugins are properly inserted.
// Set up a deferred so that the value isn't applied to the editor
// until all the plugins load, needed to avoid timing condition
// reported in #10537.
this.setValueDeferred = new dojo.Deferred();
this.inherited(arguments);
},
postCreate: function(){
//for custom undo/redo, if enabled.
this._steps=this._steps.slice(0);
this._undoedSteps=this._undoedSteps.slice(0);
if(dojo.isArray(this.extraPlugins)){
this.plugins=this.plugins.concat(this.extraPlugins);
}
this.inherited(arguments);
this.commands = dojo.i18n.getLocalization("dijit._editor", "commands", this.lang);
if(!this.toolbar){
// if we haven't been assigned a toolbar, create one
this.toolbar = new dijit.Toolbar({
dir: this.dir,
lang: this.lang
});
this.header.appendChild(this.toolbar.domNode);
}
dojo.forEach(this.plugins, this.addPlugin, this);
// Okay, denote the value can now be set.
this.setValueDeferred.callback(true);
dojo.addClass(this.iframe.parentNode, "dijitEditorIFrameContainer");
dojo.addClass(this.iframe, "dijitEditorIFrame");
dojo.attr(this.iframe, "allowTransparency", true);
if(dojo.isWebKit){
// Disable selecting the entire editor by inadvertant double-clicks.
// on buttons, title bar, etc. Otherwise clicking too fast on
// a button such as undo/redo selects the entire editor.
dojo.style(this.domNode, "KhtmlUserSelect", "none");
}
this.toolbar.startup();
this.onNormalizedDisplayChanged(); //update toolbar button status
},
destroy: function(){
dojo.forEach(this._plugins, function(p){
if(p && p.destroy){
p.destroy();
}
});
this._plugins=[];
this.toolbar.destroyRecursive();
delete this.toolbar;
this.inherited(arguments);
},
addPlugin: function(/*String||Object*/plugin, /*Integer?*/index){
// summary:
// takes a plugin name as a string or a plugin instance and
// adds it to the toolbar and associates it with this editor
// instance. The resulting plugin is added to the Editor's
// plugins array. If index is passed, it's placed in the plugins
// array at that index. No big magic, but a nice helper for
// passing in plugin names via markup.
//
// plugin: String, args object or plugin instance
//
// args:
// This object will be passed to the plugin constructor
//
// index: Integer
// Used when creating an instance from
// something already in this.plugins. Ensures that the new
// instance is assigned to this.plugins at that index.
var args=dojo.isString(plugin)?{name:plugin}:plugin;
if(!args.setEditor){
var o={"args":args,"plugin":null,"editor":this};
dojo.publish(dijit._scopeName + ".Editor.getPlugin",[o]);
if(!o.plugin){
var pc = dojo.getObject(args.name);
if(pc){
o.plugin=new pc(args);
}
}
if(!o.plugin){
console.warn('Cannot find plugin',plugin);
return;
}
plugin=o.plugin;
}
if(arguments.length > 1){
this._plugins[index] = plugin;
}else{
this._plugins.push(plugin);
}
plugin.setEditor(this);
if(dojo.isFunction(plugin.setToolbar)){
plugin.setToolbar(this.toolbar);
}
},
//the following 3 functions are required to make the editor play nice under a layout widget, see #4070
startup: function(){
// summary:
// Exists to make Editor work as a child of a layout widget.
// Developers don't need to call this method.
// tags:
// protected
//console.log('startup',arguments);
},
resize: function(size){
// summary:
// Resize the editor to the specified size, see `dijit.layout._LayoutWidget.resize`
if(size){
// we've been given a height/width for the entire editor (toolbar + contents), calls layout()
// to split the allocated size between the toolbar and the contents
dijit.layout._LayoutWidget.prototype.resize.apply(this, arguments);
}
/*
else{
// do nothing, the editor is already laid out correctly. The user has probably specified
// the height parameter, which was used to set a size on the iframe
}
*/
},
layout: function(){
// summary:
// Called from `dijit.layout._LayoutWidget.resize`. This shouldn't be called directly
// tags:
// protected
// Converts the iframe (or rather the
surrounding it) to take all the available space
// except what's needed for the header (toolbars) and footer (breadcrumbs, etc).
// A class was added to the iframe container and some themes style it, so we have to
// calc off the added margins and padding too. See tracker: #10662
var areaHeight = (this._contentBox.h -
(this.getHeaderHeight() + this.getFooterHeight() +
dojo._getPadBorderExtents(this.iframe.parentNode).h +
dojo._getMarginExtents(this.iframe.parentNode).h));
this.editingArea.style.height = areaHeight + "px";
if(this.iframe){
this.iframe.style.height="100%";
}
this._layoutMode = true;
summaryCalled from `dijit.layout._LayoutWidget.resize`. This shouldn't be called directly
dijit.Editor._onIEMouseDown
- type
- parameters:
- source: [view]
var outsideClientArea;
// IE 8's componentFromPoint is broken, which is a shame since it
// was smaller code, but oh well. We have to do this brute force
// to detect if the click was scroller or not.
var b = this.document.body;
var clientWidth = b.clientWidth;
var clientHeight = b.clientHeight;
var clientLeft = b.clientLeft;
var offsetWidth = b.offsetWidth;
var offsetHeight = b.offsetHeight;
var offsetLeft = b.offsetLeft;
//Check for vertical scroller click.
bodyDir = b.dir ? b.dir.toLowerCase() : "";
if(bodyDir != "rtl"){
if(clientWidth < offsetWidth && e.x > clientWidth && e.x < offsetWidth){
// Check the click was between width and offset width, if so, scroller
outsideClientArea = true;
}
}else{
// RTL mode, we have to go by the left offsets.
if(e.x < clientLeft && e.x > offsetLeft){
// Check the click was between width and offset width, if so, scroller
outsideClientArea = true;
}
}
if(!outsideClientArea){
// Okay, might be horiz scroller, check that.
if(clientHeight < offsetHeight && e.y > clientHeight && e.y < offsetHeight){
// Horizontal scroller.
outsideClientArea = true;
}
}
if(!outsideClientArea){
delete this._cursorToStart; // Remove the force to cursor to start position.
delete this._savedSelection; // new mouse position overrides old selection
if(e.target.tagName == "BODY"){
setTimeout(dojo.hitch(this, "placeCursorAtEnd"), 0);
}
this.inherited(arguments);
}
- summary
IE only to prevent 2 clicks to focus
- tags:
dijit.Editor.onBeforeActivate
dijit.Editor.onBeforeDeactivate
- type
- parameters:
- source: [view]
if(this.customUndo){
this.endEditing(true);
}
//in IE, the selection will be lost when other elements get focus,
//let's save focus before the editor is deactivated
if(e.target.tagName != "BODY"){
this._saveSelection();
}
//console.log('onBeforeDeactivate',this);
- summary
Called on IE right before focus is lost. Saves the selected range.
- tags:
dijit.Editor.customUndo
- type
- summary
Whether we shall use custom undo/redo support instead of the native
browser support. By default, we now use custom undo. It works better
than native browser support and provides a consistent behavior across
browsers with a minimal performance hit. We already had the hit on
the slowest browser, IE, anyway.
dijit.Editor.editActionInterval
- type
- summary
When using customUndo, not every keystroke will be saved as a step.
Instead typing (including delete) will be grouped together: after
a user stops typing for editActionInterval seconds, a step will be
saved; if a user resume typing within editActionInterval seconds,
the timeout will be restarted. By default, editActionInterval is 3
seconds.
dijit.Editor.beginEditing
- type
- parameters:
- source: [view]
if(!this._inEditing){
this._inEditing=true;
this._beginEditing(cmd);
}
if(this.editActionInterval>0){
if(this._editTimer){
clearTimeout(this._editTimer);
}
this._editTimer = setTimeout(dojo.hitch(this, this.endEditing), this._editInterval);
}
- summary
Called to note that the user has started typing alphanumeric characters, if it's not already noted.
Deals with saving undo; see editActionInterval parameter.
- tags:
dijit.Editor._steps
dijit.Editor.setValueDeferred
dijit.Editor._undoedSteps
dijit.Editor.commands
dijit.Editor.toolbar
dijit.Editor._plugins
dijit.Editor.editingArea.style.height
dijit.Editor.iframe.style.height
dijit.Editor._layoutMode
dijit.Editor._inEditing
dijit.Editor._editTimer
dijit.Editor._editInterval
args
_p
name
p
o.plugin
dijit