* @description <p>Creates a basic custom Toolbar Button. Primarily used with the Rich Text Editor's Toolbar</p><p>Provides a toolbar button based on the button and menu widgets, <select> elements are used in place of menu's.</p>
* @class ToolbarButton
* @namespace YAHOO.widget
* @requires yahoo, dom, element, event
* @extends YAHOO.util.Element
*
*
* @constructor
* @param {String/HTMLElement} el The element to turn into a button.
* @param {Object} o The object passed to this handler is the button config used to create the button.
* @description Fires when any botton receives a click event. Passes back a single object representing the buttons config object. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event valueClick
* @param {Object} o The object passed to this handler is the button config used to create the button.
* @description This is a special dynamic event that is created and dispatched based on the value property
* of the button config. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @description Fires when the toolbar is expanded via the collapse button. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event toolbarCollapsed
* @description Fires when the toolbar is collapsed via the collapse button. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
})();
/**
* @module editor
* @description <p>The Rich Text Editor is a UI control that replaces a standard HTML textarea; it allows for the rich formatting of text content, including common structural treatments like lists, formatting treatments like bold and italic text, and drag-and-drop inclusion and sizing of images. The Rich Text Editor's toolbar is extensible via a plugin architecture so that advanced implementations can achieve a high degree of customization.</p>
* The Rich Text Editor is a UI control that replaces a standard HTML textarea; it allows for the rich formatting of text content, including common structural treatments like lists, formatting treatments like bold and italic text, and drag-and-drop inclusion and sizing of images. The Rich Text Editor's toolbar is extensible via a plugin architecture so that advanced implementations can achieve a high degree of customization.
* @constructor
* @class SimpleEditor
* @extends YAHOO.util.Element
* @param {String/HTMLElement} el The textarea element to turn into an editor.
* @description Named key maps for various actions in the Editor. Example: <code>CLOSE_WINDOW: { key: 87, mods: ['shift', 'ctrl'] }</code>.
* This entry shows that when key 87 (W) is found with the modifiers of shift and control, the window will close. You can customize this object to tweak keyboard shortcuts.
* @type {Object/Mixed}
*/
_keyMap: {
SELECT_ALL: {
key: 65, //A key
mods: ['ctrl']
},
CLOSE_WINDOW: {
key: 87, //W key
mods: ['shift', 'ctrl']
},
FOCUS_TOOLBAR: {
key: 27,
mods: ['shift']
},
FOCUS_AFTER: {
key: 27
},
FONT_SIZE_UP: {
key: 38,
mods: ['shift', 'ctrl']
},
FONT_SIZE_DOWN: {
key: 40,
mods: ['shift', 'ctrl']
},
CREATE_LINK: {
key: 76,
mods: ['shift', 'ctrl']
},
BOLD: {
key: 66,
mods: ['shift', 'ctrl']
},
ITALIC: {
key: 73,
mods: ['shift', 'ctrl']
},
UNDERLINE: {
key: 85,
mods: ['shift', 'ctrl']
},
UNDO: {
key: 90,
mods: ['ctrl']
},
REDO: {
key: 90,
mods: ['shift', 'ctrl']
},
JUSTIFY_LEFT: {
key: 219,
mods: ['shift', 'ctrl']
},
JUSTIFY_CENTER: {
key: 220,
mods: ['shift', 'ctrl']
},
JUSTIFY_RIGHT: {
key: 221,
mods: ['shift', 'ctrl']
}
},
/**
* @private
* @method _cleanClassName
* @description Makes a useable classname from dynamic data, by dropping it to lowercase and replacing spaces with -'s.
* @param {String} str The classname to clean up
* @return {String}
*/
_cleanClassName: function(str) {
return str.replace(/ /g, '-').toLowerCase();
},
/**
* @property _textarea
* @description Flag to determine if we are using a textarea or an HTML Node.
* @type Boolean
*/
_textarea: null,
/**
* @property _docType
* @description The DOCTYPE to use in the editable container.
* @type String
*/
_docType: '<!DOCTYPE HTML PUBLIC "-/'+'/W3C/'+'/DTD HTML 4.01/'+'/EN" "http:/'+'/www.w3.org/TR/html4/strict.dtd">',
/**
* @property editorDirty
* @description This flag will be set when certain things in the Editor happen. It is to be used by the developer to check to see if content has changed.
* @type Boolean
*/
editorDirty: null,
/**
* @property _defaultCSS
* @description The default CSS used in the config for 'css'. This way you can add to the config like this: { css: YAHOO.widget.SimpleEditor.prototype._defaultCSS + 'ADD MYY CSS HERE' }
* @description Safari reference for the last image selected (for styling as selected).
* @type HTMLElement
*/
_lastImage: null,
/**
* @property _blankImageLoaded
* @private
* @description Don't load the blank image more than once..
* @type Boolean
*/
_blankImageLoaded: null,
/**
* @property _fixNodesTimer
* @private
* @description Holder for the fixNodes timer
* @type Date
*/
_fixNodesTimer: null,
/**
* @property _nodeChangeTimer
* @private
* @description Holds a reference to the nodeChange setTimeout call
* @type Number
*/
_nodeChangeTimer: null,
/**
* @property _nodeChangeDelayTimer
* @private
* @description Holds a reference to the nodeChangeDelay setTimeout call
* @type Number
*/
_nodeChangeDelayTimer: null,
/**
* @property _lastNodeChangeEvent
* @private
* @description Flag to determine the last event that fired a node change
* @type Event
*/
_lastNodeChangeEvent: null,
/**
* @property _lastNodeChange
* @private
* @description Flag to determine when the last node change was fired
* @type Date
*/
_lastNodeChange: 0,
/**
* @property _rendered
* @private
* @description Flag to determine if editor has been rendered or not
* @type Boolean
*/
_rendered: null,
/**
* @property DOMReady
* @private
* @description Flag to determine if DOM is ready or not
* @type Boolean
*/
DOMReady: null,
/**
* @property _selection
* @private
* @description Holder for caching iframe selections
* @type Object
*/
_selection: null,
/**
* @property _mask
* @private
* @description DOM Element holder for the editor Mask when disabled
* @type Object
*/
_mask: null,
/**
* @property _showingHiddenElements
* @private
* @description Status of the hidden elements button
* @type Boolean
*/
_showingHiddenElements: null,
/**
* @property currentWindow
* @description A reference to the currently open EditorWindow
* @type Object
*/
currentWindow: null,
/**
* @property currentEvent
* @description A reference to the current editor event
* @type Event
*/
currentEvent: null,
/**
* @property operaEvent
* @private
* @description setTimeout holder for Opera and Image DoubleClick event..
* @type Object
*/
operaEvent: null,
/**
* @property currentFont
* @description A reference to the last font selected from the Toolbar
* @type HTMLElement
*/
currentFont: null,
/**
* @property currentElement
* @description A reference to the current working element in the editor
* @type Array
*/
currentElement: null,
/**
* @property dompath
* @description A reference to the dompath container for writing the current working dom path to.
* @type HTMLElement
*/
dompath: null,
/**
* @property beforeElement
* @description A reference to the H2 placed before the editor for Accessibilty.
* @type HTMLElement
*/
beforeElement: null,
/**
* @property afterElement
* @description A reference to the H2 placed after the editor for Accessibilty.
* @type HTMLElement
*/
afterElement: null,
/**
* @property invalidHTML
* @description Contains a list of HTML elements that are invalid inside the editor. They will be removed when they are found. If you set the value of a key to "{ keepContents: true }", then the element will be replaced with a yui-non span to be filtered out when cleanHTML is called. The only tag that is ignored here is the span tag as it will force the Editor into a loop and freeze the browser. However.. all of these tags will be removed in the cleanHTML routine.
* @type Object
*/
invalidHTML: {
form: true,
input: true,
button: true,
select: true,
link: true,
html: true,
body: true,
iframe: true,
script: true,
style: true,
textarea: true
},
/**
* @property toolbar
* @description Local property containing the <a href="YAHOO.widget.Toolbar.html">YAHOO.widget.Toolbar</a> instance
var str = pathArr.join(' ' + this.SEP_DOMPATH + ' ');
//Prevent flickering
if (this.dompath.innerHTML != str) {
this.dompath.innerHTML = str;
}
},
/**
* @private
* @method _fixNodes
* @description Fix href and imgs as well as remove invalid HTML.
*/
_fixNodes: function() {
try {
var doc = this._getDoc(),
els = [];
for (var v in this.invalidHTML) {
if (YAHOO.lang.hasOwnProperty(this.invalidHTML, v)) {
if (v.toLowerCase() != 'span') {
var tags = doc.body.getElementsByTagName(v);
if (tags.length) {
for (var i = 0; i < tags.length; i++) {
els.push(tags[i]);
}
}
}
}
}
for (var h = 0; h < els.length; h++) {
if (els[h].parentNode) {
if (Lang.isObject(this.invalidHTML[els[h].tagName.toLowerCase()]) && this.invalidHTML[els[h].tagName.toLowerCase()].keepContents) {
this._swapEl(els[h], 'span', function(el) {
el.className = 'yui-non';
});
} else {
els[h].parentNode.removeChild(els[h]);
}
}
}
var imgs = this._getDoc().getElementsByTagName('img');
Dom.addClass(imgs, 'yui-img');
} catch(e) {}
},
/**
* @private
* @method _isNonEditable
* @param Event ev The Dom event being checked
* @description Method is called at the beginning of all event handlers to check if this element or a parent element has the class yui-noedit (this.CLASS_NOEDIT) applied.
* If it does, then this method will stop the event and return true. The event handlers will then return false and stop the nodeChange from occuring. This method will also
* disable and enable the Editor's toolbar based on the noedit state.
* @description Handles all click events inside the iFrame document.
*/
_handleClick: function(ev) {
var ret = this.fireEvent('beforeEditorClick', { type: 'beforeEditorClick', target: this, ev: ev });
if (ret === false) {
return false;
}
if (this._isNonEditable(ev)) {
return false;
}
this._setCurrentEvent(ev);
if (this.currentWindow) {
this.closeWindow();
}
if (this.currentWindow) {
this.closeWindow();
}
if (this.browser.webkit) {
var tar =Event.getTarget(ev);
if (this._isElement(tar, 'a') || this._isElement(tar.parentNode, 'a')) {
Event.stopEvent(ev);
this.nodeChange();
}
} else {
this.nodeChange();
}
this.fireEvent('editorClick', { type: 'editorClick', target: this, ev: ev });
},
/**
* @private
* @method _handleMouseUp
* @param {Event} ev The event we are working on.
* @description Handles all mouseup events inside the iFrame document.
*/
_handleMouseUp: function(ev) {
var ret = this.fireEvent('beforeEditorMouseUp', { type: 'beforeEditorMouseUp', target: this, ev: ev });
if (ret === false) {
return false;
}
if (this._isNonEditable(ev)) {
return false;
}
//Don't set current event for mouseup.
//It get's fired after a menu is closed and gives up a bogus event to work with
//this._setCurrentEvent(ev);
var self = this;
if (this.browser.opera) {
/*
* @knownissue Opera appears to stop the MouseDown, Click and DoubleClick events on an image inside of a document with designMode on..
* @browser Opera
* @description This work around traps the MouseUp event and sets a timer to check if another MouseUp event fires in so many seconds. If another event is fired, they we internally fire the DoubleClick event.
*/
var sel = Event.getTarget(ev);
if (this._isElement(sel, 'img')) {
this.nodeChange();
if (this.operaEvent) {
clearTimeout(this.operaEvent);
this.operaEvent = null;
this._handleDoubleClick(ev);
} else {
this.operaEvent = window.setTimeout(function() {
self.operaEvent = false;
}, 700);
}
}
}
//This will stop Safari from selecting the entire document if you select all the text in the editor
if (this.browser.webkit || this.browser.opera) {
if (this.browser.webkit) {
Event.stopEvent(ev);
}
}
this.nodeChange();
this.fireEvent('editorMouseUp', { type: 'editorMouseUp', target: this, ev: ev });
},
/**
* @private
* @method _handleMouseDown
* @param {Event} ev The event we are working on.
* @description Handles all mousedown events inside the iFrame document.
*/
_handleMouseDown: function(ev) {
var ret = this.fireEvent('beforeEditorMouseDown', { type: 'beforeEditorMouseDown', target: this, ev: ev });
if (ret === false) {
return false;
}
if (this._isNonEditable(ev)) {
return false;
}
this._setCurrentEvent(ev);
var sel = Event.getTarget(ev);
if (this.browser.webkit && this._hasSelection()) {
var _sel = this._getSelection();
if (!this.browser.webkit3) {
_sel.collapse(true);
} else {
_sel.collapseToStart();
}
}
if (this.browser.webkit && this._lastImage) {
Dom.removeClass(this._lastImage, 'selected');
this._lastImage = null;
}
if (this._isElement(sel, 'img') || this._isElement(sel, 'a')) {
if (this.browser.webkit) {
Event.stopEvent(ev);
if (this._isElement(sel, 'img')) {
Dom.addClass(sel, 'selected');
this._lastImage = sel;
}
}
if (this.currentWindow) {
this.closeWindow();
}
this.nodeChange();
}
this.fireEvent('editorMouseDown', { type: 'editorMouseDown', target: this, ev: ev });
},
/**
* @private
* @method _handleDoubleClick
* @param {Event} ev The event we are working on.
* @description Handles all doubleclick events inside the iFrame document.
*/
_handleDoubleClick: function(ev) {
var ret = this.fireEvent('beforeEditorDoubleClick', { type: 'beforeEditorDoubleClick', target: this, ev: ev });
var img_button = this.toolbar.getButtonByValue('insertimage');
if (img_button && this.currentWindow && (this.currentWindow.name == 'insertimage')) {
this.toolbar.disableButton(img_button);
}
if (this._lastButton && this._lastButton.isSelected) {
this.toolbar.deselectButton(this._lastButton.id);
}
this._undoNodeChange();
}
}
this.fireEvent('afterNodeChange', { type: 'afterNodeChange', target: this });
},
/**
* @private
* @method _updateMenuChecked
* @param {Object} button The command identifier of the button you want to check
* @param {String} value The value of the menu item you want to check
* @param {<a href="YAHOO.widget.Toolbar.html">YAHOO.widget.Toolbar</a>} The Toolbar instance the button belongs to (defaults to this.toolbar)
* @description Gets the menu from a button instance, if the menu is not rendered it will render it. It will then search the menu for the specified value, unchecking all other items and checking the specified on.
* @param {Event} ev The event that triggered the button click
* @description This is an event handler attached to the Toolbar's buttonClick event. It will fire execCommand with the command identifier from the Toolbar Button.
*/
_handleToolbarClick: function(ev) {
var value = '';
var str = '';
var cmd = ev.button.value;
if (ev.button.menucmd) {
value = cmd;
cmd = ev.button.menucmd;
}
this._lastButton = ev.button;
if (this.STOP_EXEC_COMMAND) {
YAHOO.log('execCommand skipped because we found the STOP_EXEC_COMMAND flag set to true', 'warn', 'SimpleEditor');
* @description The value to place in between the Dom path items
* @type String
*/
SEP_DOMPATH: '<',
/**
* @property STR_LEAVE_EDITOR
* @description The accessibility string for the element after the iFrame
* @type String
*/
STR_LEAVE_EDITOR: 'You have left the Rich Text Editor.',
/**
* @property STR_BEFORE_EDITOR
* @description The accessibility string for the element before the iFrame
* @type String
*/
STR_BEFORE_EDITOR: 'This text field can contain stylized text and graphics. To cycle through all formatting options, use the keyboard shortcut Shift + Escape to place focus on the toolbar and navigate between options with your arrow keys. To exit this text editor use the Escape key and continue tabbing. <h4>Common formatting keyboard shortcuts:</h4><ul><li>Control Shift B sets text to bold</li> <li>Control Shift I sets text to italic</li> <li>Control Shift U underlines text</li> <li>Control Shift L adds an HTML link</li></ul>',
/**
* @property STR_TITLE
* @description The Title of the HTML document that is created in the iFrame
* @type String
*/
STR_TITLE: 'Rich Text Area.',
/**
* @property STR_IMAGE_HERE
* @description The text to place in the URL textbox when using the blankimage.
* @type String
*/
STR_IMAGE_HERE: 'Image URL Here',
/**
* @property STR_IMAGE_URL
* @description The label string for Image URL
* @type String
*/
STR_IMAGE_URL: 'Image URL',
/**
* @property STR_LINK_URL
* @description The label string for the Link URL.
* @type String
*/
STR_LINK_URL: 'Link URL',
/**
* @protected
* @property STOP_EXEC_COMMAND
* @description Set to true when you want the default execCommand function to not process anything
* @type Boolean
*/
STOP_EXEC_COMMAND: false,
/**
* @protected
* @property STOP_NODE_CHANGE
* @description Set to true when you want the default nodeChange function to not process anything
* @type Boolean
*/
STOP_NODE_CHANGE: false,
/**
* @protected
* @property CLASS_NOEDIT
* @description CSS class applied to elements that are not editable.
* @type String
*/
CLASS_NOEDIT: 'yui-noedit',
/**
* @protected
* @property CLASS_CONTAINER
* @description Default CSS class to apply to the editors container element
* @type String
*/
CLASS_CONTAINER: 'yui-editor-container',
/**
* @protected
* @property CLASS_EDITABLE
* @description Default CSS class to apply to the editors iframe element
* @type String
*/
CLASS_EDITABLE: 'yui-editor-editable',
/**
* @protected
* @property CLASS_EDITABLE_CONT
* @description Default CSS class to apply to the editors iframe's parent element
* @description The max number of undo levels to store.
* @default 30
* @type Number
*/
this.setAttributeConfig('maxUndo', {
writeOnce: true,
value: attr.maxUndo || 30
});
/**
* @config ptags
* @description If true, the editor uses <P> tags instead of <br> tags. (Use Shift + Enter to get a <br>)
* @default false
* @type Boolean
*/
this.setAttributeConfig('ptags', {
writeOnce: true,
value: attr.ptags || false
});
/**
* @config insert
* @description If true, selection is not required for: fontname, fontsize, forecolor, backcolor.
* @default false
* @type Boolean
*/
this.setAttributeConfig('insert', {
writeOnce: true,
value: attr.insert || false,
method: function(insert) {
if (insert) {
var buttons = {
fontname: true,
fontsize: true,
forecolor: true,
backcolor: true
};
var tmp = this._defaultToolbar.buttons;
for (var i = 0; i < tmp.length; i++) {
if (tmp[i].buttons) {
for (var a = 0; a < tmp[i].buttons.length; a++) {
if (tmp[i].buttons[a].value) {
if (buttons[tmp[i].buttons[a].value]) {
delete tmp[i].buttons[a].disabled;
}
}
}
}
}
}
}
});
/**
* @config container
* @description Used when dynamically creating the Editor from Javascript with no default textarea.
* We will create one and place it in this container. If no container is passed we will append to document.body.
* @default false
* @type HTMLElement
*/
this.setAttributeConfig('container', {
writeOnce: true,
value: attr.container || false
});
/**
* @config plainText
* @description Process the inital textarea data as if it was plain text. Accounting for spaces, tabs and line feeds.
* @default false
* @type Boolean
*/
this.setAttributeConfig('plainText', {
writeOnce: true,
value: attr.plainText || false
});
/**
* @private
* @config iframe
* @description Internal config for holding the iframe element.
* @default null
* @type HTMLElement
*/
this.setAttributeConfig('iframe', {
value: null
});
/**
* @private
* @config disabled_iframe
* @description Internal config for holding the iframe element used when disabling the Editor.
* @default null
* @type HTMLElement
*/
this.setAttributeConfig('disabled_iframe', {
value: null
});
/**
* @private
* @depreciated - No longer used, should use this.get('element')
* @config textarea
* @description Internal config for holding the textarea element (replaced with element).
* @default null
* @type HTMLElement
*/
this.setAttributeConfig('textarea', {
value: null,
writeOnce: true
});
/**
* @config nodeChangeThreshold
* @description The number of seconds that need to be in between nodeChange processing
* @default 3
* @type Number
*/
this.setAttributeConfig('nodeChangeThreshold', {
value: attr.nodeChangeThreshold || 3,
validator: YAHOO.lang.isNumber
});
/**
* @config allowNoEdit
* @description Should the editor check for non-edit fields. It should be noted that this technique is not perfect. If the user does the right things, they will still be able to make changes.
* Such as highlighting an element below and above the content and hitting a toolbar button or a shortcut key.
* @default false
* @type Boolean
*/
this.setAttributeConfig('allowNoEdit', {
value: attr.allowNoEdit || false,
validator: YAHOO.lang.isBoolean
});
/**
* @config limitCommands
* @description Should the Editor limit the allowed execCommands to the ones available in the toolbar. If true, then execCommand and keyboard shortcuts will fail if they are not defined in the toolbar.
* @default false
* @type Boolean
*/
this.setAttributeConfig('limitCommands', {
value: attr.limitCommands || false,
validator: YAHOO.lang.isBoolean
});
/**
* @config element_cont
* @description Internal config for the editors container
* @default false
* @type HTMLElement
*/
this.setAttributeConfig('element_cont', {
value: attr.element_cont
});
/**
* @private
* @config editor_wrapper
* @description The outter wrapper for the entire editor.
* @default null
* @type HTMLElement
*/
this.setAttributeConfig('editor_wrapper', {
value: attr.editor_wrapper || null,
writeOnce: true
});
/**
* @attribute height
* @description The height of the editor iframe container, not including the toolbar..
* @default Best guessed size of the textarea, for best results use CSS to style the height of the textarea or pass it in as an argument
* @description The default HTML to be written to the iframe document before the contents are loaded (Note that the DOCTYPE attr will be added at render item)
* @default This HTML requires a few things if you are to override:
<p><code>{TITLE}, {CSS}, {HIDDEN_CSS}, {EXTRA_CSS}</code> and <code>{CONTENT}</code> need to be there, they are passed to YAHOO.lang.substitute to be replace with other strings.<p>
<p><code>onload="document.body._rteLoaded = true;"</code> : the onload statement must be there or the editor will not finish loading.</p>
* @description This will toggle the editor's disabled state. When the editor is disabled, designMode is turned off and a mask is placed over the iframe so no interaction can take place.
All Toolbar buttons are also disabled so they cannot be used.
* @default false
* @type Boolean
*/
this.setAttributeConfig('disabled', {
value: false,
method: function(disabled) {
if (this._rendered) {
this._disableEditor(disabled);
}
}
});
/**
* @config saveEl
* @description When save HTML is called, this element will be updated as well as the source of data.
* @default element
* @type HTMLElement
*/
this.setAttributeConfig('saveEl', {
value: this.get('element')
});
/**
* @config toolbar_cont
* @description Internal config for the toolbars container
* @param {HTMLElement} el The element to swap with
* @param {String} tagName The tagname of the element that you wish to create
* @param {Function} callback (optional) A function to run on the element after it is created, but before it is replaced. An element reference is passed to this function.
* @description This function will create a new element in the DOM and populate it with the contents of another element. Then it will assume it's place.
*/
_swapEl: function(el, tagName, callback) {
var _el = this._getDoc().createElement(tagName);
if (el) {
_el.innerHTML = el.innerHTML;
}
if (typeof callback == 'function') {
callback.call(this, _el);
}
if (el) {
el.parentNode.replaceChild(_el, el);
}
return _el;
},
/**
* @private
* @method _createInsertElement
* @description Creates a new "currentElement" then adds some text (and other things) to make it selectable and stylable. Then the user can continue typing.
* @param {Object} css (optional) Object literal containing styles to apply to the new element.
this._getSelection().setBaseAndExtent(el, 1, el, el.innerText.length);
} else if (this.browser.ie || this.browser.opera) {
el.innerHTML = ' ';
}
this.focus();
this._selectNode(el, true);
return el;
},
/**
* @private
* @method _createCurrentElement
* @param {String} tagName (optional defaults to a) The tagname of the element that you wish to create
* @param {Object} tagStyle (optional) Object literal containing styles to apply to the new element.
* @description This is a work around for the various browser issues with execCommand. This method will run <code>execCommand('fontname', false, 'yui-tmp')</code> on the given selection.
* It will then search the document for an element with the font-family set to <strong>yui-tmp</strong> and replace that with another span that has other information in it, then assign the new span to the
* <code>this.currentElement</code> array, so we now have element references to the elements that were just modified. At this point we can use standard DOM manipulation to change them as we see fit.
* @description Cleans the HTML with the cleanHTML method then places that string back into the textarea.
* @return String
*/
saveHTML: function() {
var html = this.cleanHTML();
if (this._textarea) {
this.get('element').value = html;
} else {
this.get('element').innerHTML = html;
}
if (this.get('saveEl') !== this.get('element')) {
var out = this.get('saveEl');
if (Lang.isString(out)) {
out = Dom.get(out);
}
if (out) {
if (out.tagName.toLowerCase() === 'textarea') {
out.value = html;
} else {
out.innerHTML = html;
}
}
}
return html;
},
/**
* @method setEditorHTML
* @param {String} incomingHTML The html content to load into the editor
* @description Loads HTML into the editors body
*/
setEditorHTML: function(incomingHTML) {
var html = this._cleanIncomingHTML(incomingHTML);
html = html.replace(/RIGHT_BRACKET/gi, '{');
html = html.replace(/LEFT_BRACKET/gi, '}');
this._getDoc().body.innerHTML = html;
this.nodeChange();
},
/**
* @method getEditorHTML
* @description Gets the unprocessed/unfiltered HTML from the editor
*/
getEditorHTML: function() {
try {
var b = this._getDoc().body;
if (b === null) {
YAHOO.log('Body is null, returning null.', 'error', 'SimpleEditor');
return null;
}
return this._getDoc().body.innerHTML;
} catch (e) {
return '';
}
},
/**
* @method show
* @description This method needs to be called if the Editor was hidden (like in a TabView or Panel). It is used to reset the editor after being in a container that was set to display none.
*/
show: function() {
if (this.browser.gecko) {
this._setDesignMode('on');
this.focus();
}
if (this.browser.webkit) {
var self = this;
window.setTimeout(function() {
self._setInitialContent.call(self);
}, 10);
}
//Adding this will close all other Editor window's when showing this one.
* @description This method needs to be called if the Editor is to be hidden (like in a TabView or Panel). It should be called to clear timeouts and close open editor windows.
*/
hide: function() {
//Adding this will close all other Editor window's.
if (this.currentWindow) {
this.closeWindow();
}
if (this._fixNodesTimer) {
clearTimeout(this._fixNodesTimer);
this._fixNodesTimer = null;
}
if (this._nodeChangeTimer) {
clearTimeout(this._nodeChangeTimer);
this._nodeChangeTimer = null;
}
this._lastNodeChange = 0;
//Move the iframe off of the screen, so that in containers with visiblity hidden, IE will not cover other elements.
html = html.replace(/<span class="Apple-tab-span" style="white-space:pre">([^>])<\/span>/gi, ' ');
html = html.replace(/Apple-style-span/gi, '');
html = html.replace(/style="line-height: normal;"/gi, '');
html = html.replace(/yui-wk-div/gi, '');
html = html.replace(/yui-wk-p/gi, '');
//Remove bogus LI's
html = html.replace(/<li><\/li>/gi, '');
html = html.replace(/<li> <\/li>/gi, '');
html = html.replace(/<li> <\/li>/gi, '');
//Remove bogus DIV's - updated from just removing the div's to replacing /div with a break
if (this.get('ptags')) {
html = html.replace(/<div([^>]*)>/g, '<p$1>');
html = html.replace(/<\/div>/gi, '</p>');
} else {
//html = html.replace(/<div>/gi, '<br>');
html = html.replace(/<div([^>]*)>([ tnr]*)<\/div>/gi, '<br>');
html = html.replace(/<\/div>/gi, '');
}
}
return html;
},
/**
* @method filter_internals
* @param String html The HTML string to filter
* @description Filters internal RTE strings and bogus attrs we don't want
* @return String
*/
filter_internals: function(html) {
html = html.replace(/\r/g, '');
//Fix stuff we don't want
html = html.replace(/<\/?(body|head|html)[^>]*>/gi, '');
//Fix last BR in LI
html = html.replace(/<YUI_BR><\/li>/gi, '</li>');
html = html.replace(/yui-tag-span/gi, '');
html = html.replace(/yui-tag/gi, '');
html = html.replace(/yui-non/gi, '');
html = html.replace(/yui-img/gi, '');
html = html.replace(/ tag="span"/gi, '');
html = html.replace(/ class=""/gi, '');
html = html.replace(/ style=""/gi, '');
html = html.replace(/ class=" "/gi, '');
html = html.replace(/ class=" "/gi, '');
html = html.replace(/ target=""/gi, '');
html = html.replace(/ title=""/gi, '');
if (this.browser.ie) {
html = html.replace(/ class= /gi, '');
html = html.replace(/ class= >/gi, '');
}
return html;
},
/**
* @method filter_all_rgb
* @param String str The HTML string to filter
* @description Converts all RGB color strings found in passed string to a hex color, example: style="color: rgb(0, 255, 0)" converts to style="color: #00ff00"
* @return String
*/
filter_all_rgb: function(str) {
var exp = new RegExp("rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)", "gi");
var arr = str.match(exp);
if (Lang.isArray(arr)) {
for (var i = 0; i < arr.length; i++) {
var color = this.filter_rgb(arr[i]);
str = str.replace(arr[i].toString(), color);
}
}
return str;
},
/**
* @method filter_rgb
* @param String css The CSS string containing rgb(#,#,#);
* @description Converts an RGB color string to a hex color, example: rgb(0, 255, 0) converts to #00ff00
* @return String
*/
filter_rgb: function(css) {
if (css.toLowerCase().indexOf('rgb') != -1) {
var exp = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");
var rgb = css.replace(exp, "$1,$2,$3,$4,$5").split(',');
if (rgb.length == 5) {
var r = parseInt(rgb[1], 10).toString(16);
var g = parseInt(rgb[2], 10).toString(16);
var b = parseInt(rgb[3], 10).toString(16);
r = r.length == 1 ? '0' + r : r;
g = g.length == 1 ? '0' + g : g;
b = b.length == 1 ? '0' + b : b;
css = "#" + r + g + b;
}
}
return css;
},
/**
* @method pre_filter_linebreaks
* @param String html The HTML to filter
* @param String markup The markup type to filter to
* @description HTML Pre Filter
* @return String
*/
pre_filter_linebreaks: function(html, markup) {
if (this.browser.webkit) {
html = html.replace(/<br class="khtml-block-placeholder">/gi, '<YUI_BR>');
html = html.replace(/<br class="webkit-block-placeholder">/gi, '<YUI_BR>');
}
html = html.replace(/<br>/gi, '<YUI_BR>');
html = html.replace(/<br (.*?)>/gi, '<YUI_BR>');
html = html.replace(/<br\/>/gi, '<YUI_BR>');
html = html.replace(/<br \/>/gi, '<YUI_BR>');
html = html.replace(/<div><YUI_BR><\/div>/gi, '<YUI_BR>');
html = html.replace(/<p>( | )<\/p>/g, '<YUI_BR>');
html = html.replace(/<p><br> <\/p>/gi, '<YUI_BR>');
html = html.replace(/<p> <\/p>/gi, '<YUI_BR>');
//Fix last BR
html = html.replace(/<YUI_BR>$/, '');
//Fix last BR in P
html = html.replace(/<YUI_BR><\/p>/g, '</p>');
if (this.browser.ie) {
html = html.replace(/ /g, '\t');
}
return html;
},
/**
* @method post_filter_linebreaks
* @param String html The HTML to filter
* @param String markup The markup type to filter to
* @description HTML Pre Filter
* @return String
*/
post_filter_linebreaks: function(html, markup) {
if (markup == 'xhtml') {
html = html.replace(/<YUI_BR>/g, '<br />');
} else {
html = html.replace(/<YUI_BR>/g, '<br>');
}
return html;
},
/**
* @method clearEditorDoc
* @description Clear the doc of the Editor
*/
clearEditorDoc: function() {
this._getDoc().body.innerHTML = ' ';
},
/**
* @method openWindow
* @description Override Method for Advanced Editor
*/
openWindow: function(win) {
},
/**
* @method moveWindow
* @description Override Method for Advanced Editor
*/
moveWindow: function() {
},
/**
* @private
* @method _closeWindow
* @description Override Method for Advanced Editor
*/
_closeWindow: function() {
},
/**
* @method closeWindow
* @description Override Method for Advanced Editor
*/
closeWindow: function() {
//this.unsubscribeAll('afterExecCommand');
this.toolbar.resetAllButtons();
this.focus();
},
/**
* @method destroy
* @description Destroys the editor, all of it's elements and objects.
* @description Event is fired during the render process directly after the Toolbar is loaded. Allowing you to attach events to the toolbar. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event cleanHTML
* @description Event is fired after the cleanHTML method is called.
* @type YAHOO.util.CustomEvent
*/
/**
* @event afterRender
* @description Event is fired after the render process finishes. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorContentLoaded
* @description Event is fired after the editor iframe's document fully loads and fires it's onload event. From here you can start injecting your own things into the document. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeNodeChange
* @description Event fires at the beginning of the nodeChange process. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event afterNodeChange
* @description Event fires at the end of the nodeChange process. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeExecCommand
* @description Event fires at the beginning of the execCommand process. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event afterExecCommand
* @description Event fires at the end of the execCommand process. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorMouseUp
* @param {Event} ev The DOM Event that occured
* @description Passed through HTML Event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorMouseDown
* @param {Event} ev The DOM Event that occured
* @description Passed through HTML Event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorDoubleClick
* @param {Event} ev The DOM Event that occured
* @description Passed through HTML Event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorClick
* @param {Event} ev The DOM Event that occured
* @description Passed through HTML Event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorKeyUp
* @param {Event} ev The DOM Event that occured
* @description Passed through HTML Event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorKeyPress
* @param {Event} ev The DOM Event that occured
* @description Passed through HTML Event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorKeyDown
* @param {Event} ev The DOM Event that occured
* @description Passed through HTML Event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeEditorMouseUp
* @param {Event} ev The DOM Event that occured
* @description Fires before editor event, returning false will stop the internal processing.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeEditorMouseDown
* @param {Event} ev The DOM Event that occured
* @description Fires before editor event, returning false will stop the internal processing.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeEditorDoubleClick
* @param {Event} ev The DOM Event that occured
* @description Fires before editor event, returning false will stop the internal processing.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeEditorClick
* @param {Event} ev The DOM Event that occured
* @description Fires before editor event, returning false will stop the internal processing.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeEditorKeyUp
* @param {Event} ev The DOM Event that occured
* @description Fires before editor event, returning false will stop the internal processing.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeEditorKeyPress
* @param {Event} ev The DOM Event that occured
* @description Fires before editor event, returning false will stop the internal processing.
* @type YAHOO.util.CustomEvent
*/
/**
* @event beforeEditorKeyDown
* @param {Event} ev The DOM Event that occured
* @description Fires before editor event, returning false will stop the internal processing.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorWindowFocus
* @description Fires when the iframe is focused. Note, this is window focus event, not an Editor focus event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event editorWindowBlur
* @description Fires when the iframe is blurred. Note, this is window blur event, not an Editor blur event.
* @type YAHOO.util.CustomEvent
*/
/**
* @description Singleton object used to track the open window objects and panels across the various open editors
* @class EditorInfo
* @static
*/
YAHOO.widget.EditorInfo = {
/**
* @private
* @property _instances
* @description A reference to all editors on the page.
* @type Object
*/
_instances: {},
/**
* @private
* @property blankImage
* @description A reference to the blankImage url
* @type String
*/
blankImage: '',
/**
* @private
* @property window
* @description A reference to the currently open window object in any editor on the page.
* @description Saves all Editor instances on the page. If a form reference is passed, only Editor's bound to this form will be saved.
* @param {HTMLElement} form The form to check if this Editor instance belongs to
*/
saveAll: function(form) {
var i, e, items = YAHOO.widget.EditorInfo._instances;
if (form) {
for (i in items) {
if (Lang.hasOwnProperty(items, i)) {
e = items[i];
if (e.get('element').form && (e.get('element').form == form)) {
e.saveHTML();
}
}
}
} else {
for (i in items) {
if (Lang.hasOwnProperty(items, i)) {
items[i].saveHTML();
}
}
}
},
/**
* @method toString
* @description Returns a string representing the EditorInfo.
* @return {String}
*/
toString: function() {
var len = 0;
for (var i in this._instances) {
if (Lang.hasOwnProperty(this._instances, i)) {
len++;
}
}
return 'Editor Info (' + len + ' registered intance' + ((len > 1) ? 's' : '') + ')';
}
};
})();
/**
* @module editor
* @description <p>The Rich Text Editor is a UI control that replaces a standard HTML textarea; it allows for the rich formatting of text content, including common structural treatments like lists, formatting treatments like bold and italic text, and drag-and-drop inclusion and sizing of images. The Rich Text Editor's toolbar is extensible via a plugin architecture so that advanced implementations can achieve a high degree of customization.</p>
* The Rich Text Editor is a UI control that replaces a standard HTML textarea; it allows for the rich formatting of text content, including common structural treatments like lists, formatting treatments like bold and italic text, and drag-and-drop inclusion and sizing of images. The Rich Text Editor's toolbar is extensible via a plugin architecture so that advanced implementations can achieve a high degree of customization.
* @constructor
* @class Editor
* @extends YAHOO.widget.SimpleEditor
* @param {String/HTMLElement} el The textarea element to turn into an editor.
* @description The accessibility string for the element before the iFrame
* @type String
*/
STR_BEFORE_EDITOR: 'This text field can contain stylized text and graphics. To cycle through all formatting options, use the keyboard shortcut Control + Shift + T to place focus on the toolbar and navigate between option heading names. <h4>Common formatting keyboard shortcuts:</h4><ul><li>Control Shift B sets text to bold</li> <li>Control Shift I sets text to italic</li> <li>Control Shift U underlines text</li> <li>Control Shift [ aligns text left</li> <li>Control Shift | centers text</li> <li>Control Shift ] aligns text right</li> <li>Control Shift L adds an HTML link</li> <li>To exit this text editor use the keyboard shortcut Control + Shift + ESC.</li></ul>',
/**
* @property STR_CLOSE_WINDOW
* @description The Title of the close button in the Editor Window
* @type String
*/
STR_CLOSE_WINDOW: 'Close Window',
/**
* @property STR_CLOSE_WINDOW_NOTE
* @description A note appearing in the Editor Window to tell the user that the Escape key will close the window
* @type String
*/
STR_CLOSE_WINDOW_NOTE: 'To close this window use the Control + Shift + W key',
/**
* @property STR_IMAGE_PROP_TITLE
* @description The title for the Image Property Editor Window
* @type String
*/
STR_IMAGE_PROP_TITLE: 'Image Options',
/**
* @property STR_IMAGE_TITLE
* @description The label string for Image Description
* @type String
*/
STR_IMAGE_TITLE: 'Description',
/**
* @property STR_IMAGE_SIZE
* @description The label string for Image Size
* @type String
*/
STR_IMAGE_SIZE: 'Size',
/**
* @property STR_IMAGE_ORIG_SIZE
* @description The label string for Original Image Size
* @type String
*/
STR_IMAGE_ORIG_SIZE: 'Original Size',
/**
* @property STR_IMAGE_COPY
* @description The label string for the image copy and paste message for Opera and Safari
* @type String
*/
STR_IMAGE_COPY: '<span class="tip"><span class="icon icon-info"></span><strong>Note:</strong>To move this image just highlight it, cut, and paste where ever you\'d like.</span>',
/**
* @property STR_IMAGE_PADDING
* @description The label string for the image padding.
* @type String
*/
STR_IMAGE_PADDING: 'Padding',
/**
* @property STR_IMAGE_BORDER
* @description The label string for the image border.
* @type String
*/
STR_IMAGE_BORDER: 'Border',
/**
* @property STR_IMAGE_BORDER_SIZE
* @description The label string for the image border size.
* @type String
*/
STR_IMAGE_BORDER_SIZE: 'Border Size',
/**
* @property STR_IMAGE_BORDER_TYPE
* @description The label string for the image border type.
* @type String
*/
STR_IMAGE_BORDER_TYPE: 'Border Type',
/**
* @property STR_IMAGE_TEXTFLOW
* @description The label string for the image text flow.
* @type String
*/
STR_IMAGE_TEXTFLOW: 'Text Flow',
/**
* @property STR_LOCAL_FILE_WARNING
* @description The label string for the local file warning.
* @type String
*/
STR_LOCAL_FILE_WARNING: '<span class="tip"><span class="icon icon-warn"></span><strong>Note:</strong>This image/link points to a file on your computer and will not be accessible to others on the internet.</span>',
/**
* @property STR_LINK_PROP_TITLE
* @description The label string for the Link Property Editor Window.
* @type String
*/
STR_LINK_PROP_TITLE: 'Link Options',
/**
* @property STR_LINK_PROP_REMOVE
* @description The label string for the Remove link from text link inside the property editor.
* @type String
*/
STR_LINK_PROP_REMOVE: 'Remove link from text',
/**
* @property STR_LINK_NEW_WINDOW
* @description The string for the open in a new window label.
* @type String
*/
STR_LINK_NEW_WINDOW: 'Open in a new window.',
/**
* @property STR_LINK_TITLE
* @description The string for the link description.
* @type String
*/
STR_LINK_TITLE: 'Description',
/**
* @property STR_NONE
* @description The string for the word none.
* @type String
*/
STR_NONE: 'none',
/**
* @protected
* @property CLASS_LOCAL_FILE
* @description CSS class applied to an element when it's found to have a local url.
* @type String
*/
CLASS_LOCAL_FILE: 'warning-localfile',
/**
* @protected
* @property CLASS_HIDDEN
* @description CSS class applied to the body when the hiddenelements button is pressed.
* @type String
*/
CLASS_HIDDEN: 'yui-hidden',
/**
* @method init
* @description The Editor class' initialization method
*/
init: function(p_oElement, p_oAttributes) {
YAHOO.log('init', 'info', 'Editor');
this._windows = {};
if (!this._defaultToolbar) {
this._defaultToolbar = {
collapse: true,
titlebar: 'Text Editing Tools',
draggable: false,
buttonType: 'advanced',
buttons: [
{ group: 'fontstyle', label: 'Font Name and Size',
* @description Should we throw the warning if we detect a file that is local to their machine?
* @default true
* @type Boolean
*/
this.setAttributeConfig('localFileWarning', {
value: attr.locaFileWarning || true
});
/**
* @attribute hiddencss
* @description The CSS used to show/hide hidden elements on the page, these rules must be prefixed with the class provided in <code>this.CLASS_HIDDEN</code>
* @default <code><pre>
.yui-hidden font, .yui-hidden strong, .yui-hidden b, .yui-hidden em, .yui-hidden i, .yui-hidden u,
* @param {Boolean} disable The state to set all inputs in all Editor windows to. Defaults to: false.
* @description Disables/Enables all fields inside Editor windows. Used in show/hide events to keep window fields from submitting when the parent form is submitted.
*/
_handleWindowInputs: function(disable) {
if (!Lang.isBoolean(disable)) {
disable = false;
}
var inputs = this.get('panel').element.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
try {
inputs[i].disabled = disable;
} catch (e) {}
}
},
/**
* @method openWindow
* @param {<a href="YAHOO.widget.EditorWindow.html">YAHOO.widget.EditorWindow</a>} win A <a href="YAHOO.widget.EditorWindow.html">YAHOO.widget.EditorWindow</a> instance
* @param {<a href="YAHOO.widget.EditorWindow.html">EditorWindow</a>} win The EditorWindow object
* @param {Overlay} panel The Overlay object that is used to create the window.
* @description Event fires before an Editor Window is opened. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event afterOpenWindow
* @param {<a href="YAHOO.widget.EditorWindow.html">EditorWindow</a>} win The EditorWindow object
* @param {Overlay} panel The Overlay object that is used to create the window.
* @description Event fires after an Editor Window is opened. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event closeWindow
* @param {<a href="YAHOO.widget.EditorWindow.html">EditorWindow</a>} win The EditorWindow object
* @description Event fires after an Editor Window is closed. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event windowCMDOpen
* @param {<a href="YAHOO.widget.EditorWindow.html">EditorWindow</a>} win The EditorWindow object
* @param {Overlay} panel The Overlay object that is used to create the window.
* @description Dynamic event fired when an <a href="YAHOO.widget.EditorWindow.html">EditorWindow</a> is opened.. The dynamic event is based on the name of the window. Example Window: createlink, opening this window would fire the windowcreatelinkOpen event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event windowCMDClose
* @param {<a href="YAHOO.widget.EditorWindow.html">EditorWindow</a>} win The EditorWindow object
* @param {Overlay} panel The Overlay object that is used to create the window.
* @description Dynamic event fired when an <a href="YAHOO.widget.EditorWindow.html">EditorWindow</a> is closed.. The dynamic event is based on the name of the window. Example Window: createlink, opening this window would fire the windowcreatelinkClose event. See <a href="YAHOO.util.Element.html#addListener">Element.addListener</a> for more information on listening for this event.
* @type YAHOO.util.CustomEvent
*/
/**
* @event windowRender
* @param {<a href="YAHOO.widget.EditorWindow.html">EditorWindow</a>} win The EditorWindow object
* @param {Overlay} panel The Overlay object that is used to create the window.
* @description Event fired when the initial Overlay is rendered. Can be used to manipulate the content of the panel.
* @type YAHOO.util.CustomEvent
*/
/**
* @event windowInsertImageRender
* @param {Overlay} panel The Overlay object that is used to create the window.
* @param {HTMLElement} body The HTML element used as the body of the window..
* @param {Toolbar} toolbar A reference to the toolbar object used inside this window.
* @description Event fired when the pre render of the Insert Image window has finished.
* @type YAHOO.util.CustomEvent
*/
/**
* @event windowCreateLinkRender
* @param {Overlay} panel The Overlay object that is used to create the window.
* @param {HTMLElement} body The HTML element used as the body of the window..
* @description Event fired when the pre render of the Create Link window has finished.
* @type YAHOO.util.CustomEvent
*/
/**
* @description Class to hold Window information between uses. We use the same panel to show the windows, so using this will allow you to configure a window before it is shown.
* This is what you pass to Editor.openWindow();. These parameters will not take effect until the openWindow() is called in the editor.
* @class EditorWindow
* @param {String} name The name of the window.
* @param {Object} attrs Attributes for the window. Current attributes used are : height and width