X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fcore%2Feditor.js;h=352c4b22826f0fcb450c948f345cd3967462bc9a;hb=4e90e78dc97789709ee7404359a5517540c27553;hp=e21477830c15f7afe7d2dc92dfeaf656b61189c4;hpb=7cd80714081a8ffdf4a1a8d2c72f120ed5ef3d6d;p=ckeditor.git diff --git a/_source/core/editor.js b/_source/core/editor.js index e214778..352c4b2 100644 --- a/_source/core/editor.js +++ b/_source/core/editor.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ @@ -33,6 +33,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( !customConfig ) return false; + customConfig = CKEDITOR.getUrl( customConfig ); + var loadedConfig = loadConfigLoaded[ customConfig ] || ( loadConfigLoaded[ customConfig ] = {} ); // If the custom config has already been downloaded, reuse it. @@ -44,7 +46,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // If there is no other customConfig in the chain, fire the // "configLoaded" event. - if ( editor.config.customConfig == customConfig || !loadConfig( editor ) ) + if ( CKEDITOR.getUrl( editor.config.customConfig ) == customConfig || !loadConfig( editor ) ) editor.fireOnce( 'customConfigLoaded' ); } else @@ -116,23 +118,77 @@ For licensing, see LICENSE.html or http://ckeditor.com/license '_source/' + // @Packager.RemoveLine 'skins/' + skinName + '/' ) ); + /** + * The name of the skin used by this editor instance. The skin name can + * be set though the {@link CKEDITOR.config.skin} setting. + * @name CKEDITOR.editor.prototype.skinName + * @type String + * @example + * alert( editor.skinName ); // "kama" (e.g.) + */ editor.skinName = skinName; + + /** + * The full URL of the skin directory. + * @name CKEDITOR.editor.prototype.skinPath + * @type String + * @example + * alert( editor.skinPath ); // "http://example.com/ckeditor/skins/kama/" (e.g.) + */ editor.skinPath = skinPath; + + /** + * The CSS class name used for skin identification purposes. + * @name CKEDITOR.editor.prototype.skinClass + * @type String + * @example + * alert( editor.skinClass ); // "cke_skin_kama" (e.g.) + */ editor.skinClass = 'cke_skin_' + skinName; + /** + * The tabbing + * navigation order that has been calculated for this editor + * instance. This can be set by the {@link CKEDITOR.config.tabIndex} + * setting or taken from the "tabindex" attribute of the + * {@link #element} associated to the editor. + * @name CKEDITOR.editor.prototype.tabIndex + * @type Number + * @default 0 (zero) + * @example + * alert( editor.tabIndex ); // "0" (e.g.) + */ + editor.tabIndex = editor.config.tabIndex || editor.element.getAttribute( 'tabindex' ) || 0; + // Fire the "configLoaded" event. editor.fireOnce( 'configLoaded' ); // Load language file. - loadLang( editor ); + loadSkin( editor ); }; var loadLang = function( editor ) { CKEDITOR.lang.load( editor.config.language, editor.config.defaultLanguage, function( languageCode, lang ) { + /** + * The code for the language resources that have been loaded + * for the user internface elements of this editor instance. + * @name CKEDITOR.editor.prototype.langCode + * @type String + * @example + * alert( editor.langCode ); // "en" (e.g.) + */ editor.langCode = languageCode; + /** + * An object holding all language strings used by the editor + * interface. + * @name CKEDITOR.editor.prototype.lang + * @type CKEDITOR.lang + * @example + * alert( editor.lang.bold ); // "Negrito" (e.g. if language is Portuguese) + */ // As we'll be adding plugin specific entries that could come // from different language code files, we need a copy of lang, // not a direct reference to it. @@ -142,6 +198,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 && editor.lang.dir == 'rtl' ) editor.lang.dir = 'ltr'; + var config = editor.config; + config.contentsLangDirection == 'ui' && ( config.contentsLangDirection = editor.lang.dir ); + loadPlugins( editor ); }); }; @@ -168,6 +227,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license plugins = plugins.replace( removeRegex, '' ); } + // Load the Adobe AIR plugin conditionally. + CKEDITOR.env.air && ( plugins += ',adobeair' ); + // Load all plugins defined in the "plugins" setting. CKEDITOR.plugins.load( plugins.split( ',' ), function( plugins ) { @@ -181,7 +243,14 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // The list of URLs to language files. var languageFiles = []; - // Cache the loaded plugin names. + /** + * And object holding references to all plugins used by this + * editor istance. + * @name CKEDITOR.editor.prototype.plugins + * @type Object + * @example + * alert( editor.plugins.dialog.path ); // "http://example.com/ckeditor/plugins/dialog/" (e.g.) + */ editor.plugins = plugins; // Loop through all plugins, to build the list of language @@ -203,7 +272,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // is not available, get the first one (default one). lang = ( CKEDITOR.tools.indexOf( pluginLangs, editor.langCode ) >= 0 ? editor.langCode : pluginLangs[ 0 ] ); - if ( !plugin.lang[ lang ] ) + if ( !plugin.langEntries || !plugin.langEntries[ lang ] ) { // Put the language file URL into the list of files to // get downloaded. @@ -211,7 +280,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license } else { - CKEDITOR.tools.extend( editor.lang, plugin.lang[ lang ] ); + CKEDITOR.tools.extend( editor.lang, plugin.langEntries[ lang ] ); lang = null; } } @@ -236,7 +305,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Uses the first loop to update the language entries also. if ( m === 0 && languageCodes[ i ] && plugin.lang ) - CKEDITOR.tools.extend( editor.lang, plugin.lang[ languageCodes[ i ] ] ); + CKEDITOR.tools.extend( editor.lang, plugin.langEntries[ languageCodes[ i ] ] ); // Call the plugin method (beforeInit and init). if ( plugin[ methods[ m ] ] ) @@ -246,7 +315,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Load the editor skin. editor.fire( 'pluginsLoaded' ); - loadSkin( editor ); + loadTheme( editor ); }); }); }; @@ -255,7 +324,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { CKEDITOR.skins.load( editor, 'editor', function() { - loadTheme( editor ); + loadLang( editor ); }); }; @@ -264,6 +333,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license var theme = editor.config.theme; CKEDITOR.themes.load( theme, function() { + /** + * The theme used by this editor instance. + * @name CKEDITOR.editor.prototype.theme + * @type CKEDITOR.theme + * @example + * alert( editor.theme ); "http://example.com/ckeditor/themes/default/" (e.g.) + */ var editorTheme = editor.theme = CKEDITOR.themes.get( theme ); editorTheme.path = CKEDITOR.themes.getPath( theme ); editorTheme.build( editor ); @@ -291,7 +367,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Setup the submit function because it doesn't fire the // "submit" event. - if ( !form.$.submit.nodeName ) + if ( !form.$.submit.nodeName && !form.$.submit.length ) { form.$.submit = CKEDITOR.tools.override( form.$.submit, function( originalSubmit ) { @@ -327,7 +403,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license for ( var name in commands ) { command = commands[ name ]; - command[ command.modes[ mode ] ? 'enable' : 'disable' ](); + command[ command.startDisabled ? 'disable' : command.modes[ mode ] ? 'enable' : 'disable' ](); } } @@ -376,6 +452,13 @@ For licensing, see LICENSE.html or http://ckeditor.com/license throw '[CKEDITOR.editor] The instance "' + this.name + '" already exists.'; /** + * A unique random string assigned to each editor instance in the page. + * @name CKEDITOR.editor.prototype.id + * @type String + */ + this.id = CKEDITOR.tools.getNextId(); + + /** * The configurations for this editor instance. It inherits all * settings defined in (@link CKEDITOR.config}, combined with settings * loaded from custom configuration files and those defined inline in @@ -464,8 +547,9 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, if ( !noUpdate ) this.updateElement(); - this.theme.destroy( this ); this.fire( 'destroy' ); + this.theme && this.theme.destroy( this ); + CKEDITOR.remove( this ); CKEDITOR.fire( 'instanceDestroyed', null, this ); }, @@ -553,6 +637,16 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, return eventData.dataValue; }, + /** + * Gets the "raw data" currently available in the editor. This is a + * fast method which return the data as is, without processing, so it's + * not recommended to use it on resulting pages. It can be used instead + * combined with the {@link #loadSnapshot} so one can automatic save + * the editor data from time to time while the user is using the + * editor, to avoid data loss, without risking performance issues. + * @example + * alert( editor.getSnapshot() ); + */ getSnapshot : function() { var data = this.fire( 'getSnapshot' ); @@ -567,23 +661,39 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, return data; }, + /** + * Loads "raw data" in the editor. This data is loaded with processing + * straight to the editing area. It should not be used as a way to load + * any kind of data, but instead in combination with + * {@link #getSnapshot} produced data. + * @example + * var data = editor.getSnapshot(); + * editor.loadSnapshot( data ); + */ loadSnapshot : function( snapshot ) { this.fire( 'loadSnapshot', snapshot ); }, /** - * Sets the editor data. The data must be provided in raw format. - * @param {String} data HTML code to replace the curent content in the editor. - * @param {Function} callback Function to be called after the setData is completed. + * Sets the editor data. The data must be provided in raw format (HTML).
+ *
+ * Note that this menthod is asynchronous. The "callback" parameter must + * be used if interaction with the editor is needed after setting the data. + * @param {String} data HTML code to replace the curent content in the + * editor. + * @param {Function} callback Function to be called after the setData + * is completed. + *@param {Boolean} internal Whether suppress any event firing when copying data internally inside editor. * @example - * CKEDITOR.instances.editor1.setData( '<p>This is the editor data.</p>' ); - * CKEDITOR.instances.editor1.setData( '<p>Some other editor data.</p>', function() - * { - * CKEDITOR.instances.editor1.checkDirty(); // true - * } ); + * CKEDITOR.instances.editor1.setData( '<p>This is the editor data.</p>' ); + * @example + * CKEDITOR.instances.editor1.setData( '<p>Some other editor data.</p>', function() + * { + * this.checkDirty(); // true + * }); */ - setData : function( data , callback ) + setData : function( data , callback, internal ) { if( callback ) { @@ -593,13 +703,14 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, callback.call( evt.editor ); } ); } + // Fire "setData" so data manipulation may happen. var eventData = { dataValue : data }; - this.fire( 'setData', eventData ); + !internal && this.fire( 'setData', eventData ); this._.data = eventData.dataValue; - this.fire( 'afterSetData', eventData ); + !internal && this.fire( 'afterSetData', eventData ); }, /** @@ -614,6 +725,22 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, }, /** + * Insert text content into the currently selected position in the + * editor, in WYSIWYG mode, styles of the selected element will be applied to the inserted text, + * spaces around the text will be leaving untouched. + * Note: two subsequent line-breaks will introduce one paragraph, which element depends on {@link CKEDITOR.config.enterMode}; + * A single line-break will be instead translated into one <br />. + * @since 3.5 + * @param {String} text Text to be inserted into the editor. + * @example + * CKEDITOR.instances.editor1.insertText( ' line1 \n\n line2' ); + */ + insertText : function( text ) + { + this.fire( 'insertText', text ); + }, + + /** * Inserts an element into the currently selected position in the * editor. * @param {CKEDITOR.dom.element} element The element to be inserted @@ -627,11 +754,38 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, this.fire( 'insertElement', element ); }, + /** + * Checks whether the current editor contents present changes when + * compared to the contents loaded into the editor at startup, or to + * the contents available in the editor when {@link #resetDirty} has + * been called. + * @returns {Boolean} "true" is the contents present changes. + * @example + * function beforeUnload( e ) + * { + * if ( CKEDITOR.instances.editor1.checkDirty() ) + * return e.returnValue = "You'll loose the changes made in the editor."; + * } + * + * if ( window.addEventListener ) + * window.addEventListener( 'beforeunload', beforeUnload, false ); + * else + * window.attachEvent( 'onbeforeunload', beforeUnload ); + */ checkDirty : function() { return ( this.mayBeDirty && this._.previousValue !== this.getSnapshot() ); }, + /** + * Resets the "dirty state" of the editor so subsequent calls to + * {@link #checkDirty} will return "false" if the user will not make + * further changes to the contents. + * @example + * alert( editor.checkDirty() ); // "true" (e.g.) + * editor.resetDirty(); + * alert( editor.checkDirty() ); // "false" + */ resetDirty : function() { if ( this.mayBeDirty ) @@ -650,10 +804,15 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype, var element = this.element; if ( element && this.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) { + var data = this.getData(); + + if ( this.config.htmlEncodeOutput ) + data = CKEDITOR.tools.htmlEncode( data ); + if ( element.is( 'textarea' ) ) - element.setValue( this.getData() ); + element.setValue( data ); else - element.setHtml( this.getData() ); + element.setHtml( data ); } } }); @@ -670,3 +829,157 @@ CKEDITOR.on( 'loaded', function() pending[ i ]._init(); } }); + +/** + * Whether escape HTML when editor update original input element. + * @name CKEDITOR.config.htmlEncodeOutput + * @since 3.1 + * @type Boolean + * @default false + * @example + * config.htmlEncodeOutput = true; + */ + +/** + * Fired when a CKEDITOR instance is created, but still before initializing it. + * To interact with a fully initialized instance, use the + * {@link CKEDITOR#instanceReady} event instead. + * @name CKEDITOR#instanceCreated + * @event + * @param {CKEDITOR.editor} editor The editor instance that has been created. + */ + +/** + * Fired when a CKEDITOR instance is destroyed. + * @name CKEDITOR#instanceDestroyed + * @event + * @param {CKEDITOR.editor} editor The editor instance that has been destroyed. + */ + +/** + * Fired when all plugins are loaded and initialized into the editor instance. + * @name CKEDITOR.editor#pluginsLoaded + * @event + * @param {CKEDITOR.editor} editor This editor instance. + */ + +/** + * Fired before the command execution when {@link #execCommand} is called. + * @name CKEDITOR.editor#beforeCommandExec + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {String} data.name The command name. + * @param {Object} data.commandData The data to be sent to the command. This + * can be manipulated by the event listener. + * @param {CKEDITOR.command} data.command The command itself. + */ + +/** + * Fired after the command execution when {@link #execCommand} is called. + * @name CKEDITOR.editor#afterCommandExec + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {String} data.name The command name. + * @param {Object} data.commandData The data sent to the command. + * @param {CKEDITOR.command} data.command The command itself. + * @param {Object} data.returnValue The value returned by the command execution. + */ + +/** + * Fired every custom configuration file is loaded, before the final + * configurations initialization.
+ *
+ * Custom configuration files can be loaded thorugh the + * {@link CKEDITOR.config.customConfig} setting. Several files can be loading + * by chaning this setting. + * @name CKEDITOR.editor#customConfigLoaded + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @example + */ + +/** + * Fired once the editor configuration is ready (loaded and processed). + * @name CKEDITOR.editor#configLoaded + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @example + * if( editor.config.fullPage ) + * alert( 'This is a full page editor' ); + */ + +/** + * Fired when this editor instance is destroyed. The editor at this + * point isn't usable and this event should be used to perform clean up + * in any plugin. + * @name CKEDITOR.editor#destroy + * @event + */ + +/** + * Internal event to get the current data. + * @name CKEDITOR.editor#beforeGetData + * @event + */ + +/** + * Internal event to perform the #getSnapshot call. + * @name CKEDITOR.editor#getSnapshot + * @event + */ + +/** + * Internal event to perform the #loadSnapshot call. + * @name CKEDITOR.editor#loadSnapshot + * @event + */ + + +/** + * Event fired before the #getData call returns allowing additional manipulation. + * @name CKEDITOR.editor#getData + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {String} data.dataValue The data that will be returned. + */ + +/** + * Event fired before the #setData call is executed allowing additional manipulation. + * @name CKEDITOR.editor#setData + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {String} data.dataValue The data that will be used. + */ + +/** + * Event fired at the end of the #setData call is executed. Usually it's better to use the + * {@link CKEDITOR.editor.prototype.dataReady} event. + * @name CKEDITOR.editor#afterSetData + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {String} data.dataValue The data that has been set. + */ + +/** + * Internal event to perform the #insertHtml call + * @name CKEDITOR.editor#insertHtml + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {String} data The HTML to insert. + */ + +/** + * Internal event to perform the #insertText call + * @name CKEDITOR.editor#insertText + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {String} text The text to insert. + */ + +/** + * Internal event to perform the #insertElement call + * @name CKEDITOR.editor#insertElement + * @event + * @param {CKEDITOR.editor} editor This editor instance. + * @param {Object} element The element to insert. + */