diff --git a/_source/core/config.js b/_source/core/config.js index e2ea7d01a4..e727cfd01b 100644 --- a/_source/core/config.js +++ b/_source/core/config.js @@ -146,7 +146,7 @@ CKEDITOR.config = { * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea'; */ - plugins: 'basicstyles,blockquote,button,clipboard,elementspath,find,flash,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,showblocks,sourcearea,table,specialchar,tab,templates,toolbar,undo,wysiwygarea', + plugins: 'basicstyles,blockquote,button,clipboard,elementspath,find,flash,format,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,showblocks,sourcearea,table,specialchar,tab,templates,toolbar,undo,wysiwygarea', /** * The theme to be used to build the UI. diff --git a/_source/core/dom/domobject.js b/_source/core/dom/domobject.js index 545c803ef9..65001ba9e8 100644 --- a/_source/core/dom/domobject.js +++ b/_source/core/dom/domobject.js @@ -133,7 +133,7 @@ CKEDITOR.dom.domObject.prototype = (function() { * element.setCustomData( 'hasCustomData', true ); */ domObjectProto.setCustomData = function( key, value ) { - var expandoNumber = this.$._cke_expando || ( this.$._cke_expando = CKEDITOR.tools.getNextNumber() ), + var expandoNumber = this.getUniqueId(), dataSlot = customData[ expandoNumber ] || ( customData[ expandoNumber ] = {} ); dataSlot[ key ] = value; @@ -170,6 +170,10 @@ CKEDITOR.dom.domObject.prototype = (function() { return retval || null; }; + domObjectProto.getUniqueId = function() { + return this.$._cke_expando || ( this.$._cke_expando = CKEDITOR.tools.getNextNumber() ); + }; + // Implement CKEDITOR.event. CKEDITOR.event.implementOn( domObjectProto ); diff --git a/_source/core/dom/element.js b/_source/core/dom/element.js index eec5f2ea0b..290fddc520 100644 --- a/_source/core/dom/element.js +++ b/_source/core/dom/element.js @@ -151,6 +151,11 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, } }, + hasClass: function( className ) { + var regex = new RegExp( '(?:^|\\s+)' + className + '(?=\\s|$)', '' ); + return regex.test( this.$.className ); + }, + /** * Append a node as a child of this element. * @param {CKEDITOR.dom.node|String} node The node or element name to be @@ -180,6 +185,12 @@ CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype, return node; }, + appendHtml: function( html ) { + var temp = new CKEDITOR.dom.element( 'div', this.getDocument() ); + temp.setHtml( html ); + temp.moveChildren( this ); + }, + /** * Append text to this element. * @param {String} text The text to be appended. diff --git a/_source/core/editor.js b/_source/core/editor.js index 52183535a9..361a5f8323 100644 --- a/_source/core/editor.js +++ b/_source/core/editor.js @@ -69,10 +69,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( instanceConfig ) CKEDITOR.tools.extend( editor.config, instanceConfig, true ); - // Fire the "configLoaded" event. - editor.fireOnce( 'configLoaded' ); - - loadLang( editor ); + onConfigLoaded( editor ); }); // The instance config may override the customConfig setting to avoid @@ -87,6 +84,19 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // ##### END: Config Privates + var onConfigLoaded = function( editor ) { + // Set config related properties. + + editor.skinPath = CKEDITOR.getUrl( '_source/' + // %REMOVE_LINE% + 'skins/' + editor.config.skin + '/' ); + + // Fire the "configLoaded" event. + editor.fireOnce( 'configLoaded' ); + + // Load language file. + loadLang( editor ); + }; + var loadLang = function( editor ) { CKEDITOR.lang.load( editor.config.defaultLanguage, editor.config.autoLanguage, function( languageCode, lang ) { editor.langCode = languageCode; diff --git a/_source/core/plugins.js b/_source/core/plugins.js index 724cc6c89d..e4dca0f059 100644 --- a/_source/core/plugins.js +++ b/_source/core/plugins.js @@ -40,8 +40,20 @@ CKEDITOR.plugins.load = CKEDITOR.tools.override( CKEDITOR.plugins.load, function if ( requiredPlugins.length ) loadPlugins.call( this, requiredPlugins ); - else if ( callback ) - callback.call( scope || window, allPlugins ); + else { + // Call the "onLoad" function for all plugins. + for ( pluginName in allPlugins ) { + plugin = allPlugins[ pluginName ]; + if ( plugin.onLoad && !plugin.onLoad._called ) { + plugin.onLoad(); + plugin.onLoad._called = 1; + } + } + + // Call the callback. + if ( callback ) + callback.call( scope || window, allPlugins ); + } }, this ); }; diff --git a/_source/core/tools.js b/_source/core/tools.js index b072c2d1b2..204a547024 100644 --- a/_source/core/tools.js +++ b/_source/core/tools.js @@ -8,307 +8,366 @@ For licensing, see LICENSE.html or http://ckeditor.com/license * utility functions. */ -/** - * Utility functions. - * @namespace - * @example - */ -CKEDITOR.tools = { - arrayCompare: function( arrayA, arrayB ) { - if ( !arrayA && !arrayB ) - return true; +(function() { + var functions = []; - if ( !arrayA || !arrayB || arrayA.length != arrayB.length ) - return false; + /** + * Utility functions. + * @namespace + * @example + */ + CKEDITOR.tools = { + arrayCompare: function( arrayA, arrayB ) { + if ( !arrayA && !arrayB ) + return true; - for ( var i = 0; i < arrayA.length; i++ ) { - if ( arrayA[ i ] != arrayB[ i ] ) + if ( !arrayA || !arrayB || arrayA.length != arrayB.length ) return false; - } - return true; - }, + for ( var i = 0; i < arrayA.length; i++ ) { + if ( arrayA[ i ] != arrayB[ i ] ) + return false; + } - /** - * Copy the properties from one object to another. By default, properties - * already present in the target object are not overwritten. - * @param {Object} target The object to be extended. - * @param {Object} source[,souce(n)] The objects from which copy - * properties. Any number of objects can be passed to this function. - * @param {Boolean} [overwrite] Indicates that properties already present - * in the target object must be overwritten. This must be the last - * parameter in the function call. - * @returns {Object} the extended object (target). - * @example - * // Create the sample object. - * var myObject = - * { - * prop1 : true - * }; - * - * // Extend the above object with two properties. - * CKEDITOR.tools.extend( myObject, - * { - * prop2 : true, - * prop3 : true - * } ); - * - * // Alert "prop1", "prop2" and "prop3". - * for ( var p in myObject ) - * alert( p ); - */ - extend: function( target ) { - var argsLength = arguments.length, - overwrite = arguments[ argsLength - 1 ]; + return true; + }, - if ( typeof overwrite == 'boolean' ) - argsLength--; - else - overwrite = false; + /** + * Copy the properties from one object to another. By default, properties + * already present in the target object are not overwritten. + * @param {Object} target The object to be extended. + * @param {Object} source[,souce(n)] The objects from which copy + * properties. Any number of objects can be passed to this function. + * @param {Boolean} [overwrite] Indicates that properties already present + * in the target object must be overwritten. This must be the last + * parameter in the function call. + * @returns {Object} the extended object (target). + * @example + * // Create the sample object. + * var myObject = + * { + * prop1 : true + * }; + * + * // Extend the above object with two properties. + * CKEDITOR.tools.extend( myObject, + * { + * prop2 : true, + * prop3 : true + * } ); + * + * // Alert "prop1", "prop2" and "prop3". + * for ( var p in myObject ) + * alert( p ); + */ + extend: function( target ) { + var argsLength = arguments.length, + overwrite = arguments[ argsLength - 1 ]; + + if ( typeof overwrite == 'boolean' ) + argsLength--; + else + overwrite = false; - for ( var i = 1; i < argsLength; i++ ) { - var source = arguments[ i ]; + for ( var i = 1; i < argsLength; i++ ) { + var source = arguments[ i ]; - for ( var propertyName in source ) { - if ( overwrite || target[ propertyName ] == undefined ) - target[ propertyName ] = source[ propertyName ]; + for ( var propertyName in source ) { + if ( overwrite || target[ propertyName ] == undefined ) + target[ propertyName ] = source[ propertyName ]; + } } - } - return target; - }, + return target; + }, - /** - * Creates an object which is an instance of a class which prototype is a - * predefined object. All properties defined in the source object are - * automatically inherited by the resulting object, including future - * changes to it. - * @param {Object} source The source object to be used as the prototype for - * the final object. - * @returns {Object} The resulting copy. - */ - prototypedCopy: function( source ) { - var copy = function() {}; - copy.prototype = source; - return new copy(); - }, + /** + * Creates an object which is an instance of a class which prototype is a + * predefined object. All properties defined in the source object are + * automatically inherited by the resulting object, including future + * changes to it. + * @param {Object} source The source object to be used as the prototype for + * the final object. + * @returns {Object} The resulting copy. + */ + prototypedCopy: function( source ) { + var copy = function() {}; + copy.prototype = source; + return new copy(); + }, - /** - * Checks if an object is an Array. - * @param {Object} object The object to be checked. - * @type Boolean - * @returns true if the object is an Array, otherwise false. - * @example - * alert( CKEDITOR.tools.isArray( [] ) ); // "true" - * alert( CKEDITOR.tools.isArray( 'Test' ) ); // "false" - */ - isArray: function( object ) { - return ( !!object && object instanceof Array ); - }, + /** + * Checks if an object is an Array. + * @param {Object} object The object to be checked. + * @type Boolean + * @returns true if the object is an Array, otherwise false. + * @example + * alert( CKEDITOR.tools.isArray( [] ) ); // "true" + * alert( CKEDITOR.tools.isArray( 'Test' ) ); // "false" + */ + isArray: function( object ) { + return ( !!object && object instanceof Array ); + }, - /** - * Transforms a CSS property name to its relative DOM style name. - * @param {String} cssName The CSS property name. - * @returns {String} The transformed name. - * @example - * alert( CKEDITOR.tools.cssStyleToDomStyle( 'background-color' ) ); // "backgroundColor" - * alert( CKEDITOR.tools.cssStyleToDomStyle( 'float' ) ); // "cssFloat" - */ - cssStyleToDomStyle: function( cssName ) { - if ( cssName == 'float' ) - return 'cssFloat'; - else { - return cssName.replace( /-./g, function( match ) { - return match.substr( 1 ).toUpperCase(); - }); - } - }, + /** + * Transforms a CSS property name to its relative DOM style name. + * @param {String} cssName The CSS property name. + * @returns {String} The transformed name. + * @example + * alert( CKEDITOR.tools.cssStyleToDomStyle( 'background-color' ) ); // "backgroundColor" + * alert( CKEDITOR.tools.cssStyleToDomStyle( 'float' ) ); // "cssFloat" + */ + cssStyleToDomStyle: function( cssName ) { + if ( cssName == 'float' ) + return 'cssFloat'; + else { + return cssName.replace( /-./g, function( match ) { + return match.substr( 1 ).toUpperCase(); + }); + } + }, - /** - * Replace special HTML characters in a string with their relative HTML - * entity values. - * @param {String} text The string to be encoded. - * @returns {String} The encode string. - * @example - * alert( CKEDITOR.tools.htmlEncode( 'A > B & C < D' ) ); // "A > B & C < D" - */ - htmlEncode: function( text ) { - var standard = function( text ) { - var span = new CKEDITOR.dom.element( 'span' ); - span.setText( text ); - return span.getHtml(); + /** + * Replace special HTML characters in a string with their relative HTML + * entity values. + * @param {String} text The string to be encoded. + * @returns {String} The encode string. + * @example + * alert( CKEDITOR.tools.htmlEncode( 'A > B & C < D' ) ); // "A > B & C < D" + */ + htmlEncode: function( text ) { + var standard = function( text ) { + var span = new CKEDITOR.dom.element( 'span' ); + span.setText( text ); + return span.getHtml(); + }; + + this.htmlEncode = ( standard( '>' ) == '>' ) ? + function( text ) { + // WebKit does't encode the ">" character, which makes sense, but + // it's different than other browsers. + return standard( text ).replace( />/g, '>' ); + } : standard; + + return this.htmlEncode( text ); + }, + + /** + * Gets a unique number for this CKEDITOR execution session. It returns + * progressive numbers starting at 1. + * @function + * @returns {Number} A unique number. + * @example + * alert( CKEDITOR.tools.getNextNumber() ); // "1" (e.g.) + * alert( CKEDITOR.tools.getNextNumber() ); // "2" + */ + getNextNumber: (function() { + var last = 0; + return function() { + return ++last; }; + })(), - this.htmlEncode = ( standard( '>' ) == '>' ) ? - function( text ) { - // WebKit does't encode the ">" character, which makes sense, but - // it's different than other browsers. - return standard( text ).replace( />/g, '>' ); - } : standard; + /** + * Creates a function override. + * @param {Function} originalFunction The function to be overridden. + * @param {Function} functionBuilder A function that returns the new + * function. The original function reference will be passed to this + * function. + * @returns {Function} The new function. + * @example + * var example = + * { + * myFunction : function( name ) + * { + * alert( 'Name: ' + name ); + * } + * }; + * + * example.myFunction = CKEDITOR.tools.override( example.myFunction, function( myFunctionOriginal ) + * { + * return function( name ) + * { + * alert( 'Override Name: ' + name ); + * myFunctionOriginal.call( this, name ); + * }; + * }); + */ + override: function( originalFunction, functionBuilder ) { + return functionBuilder( originalFunction ); + }, - return this.htmlEncode( text ); - }, + /** + * Executes a function after specified delay. + * @param {Function} func The function to be executed. + * @param {Number} [milliseconds] The amount of time (millisecods) to wait + * to fire the function execution. Defaults to zero. + * @param {Object} [scope] The object to hold the function execution scope + * (the "this" object). By default the "window" object. + * @param {Object|Array} [args] A single object, or an array of objects, to + * pass as arguments to the function. + * @param {Object} [ownerWindow] The window that will be used to set the + * timeout. By default the current "window". + * @returns {Object} A value that can be used to cancel the function execution. + * @example + * CKEDITOR.tools.setTimeout( + * function() + * { + * alert( 'Executed after 2 seconds' ); + * }, + * 2000 ); + */ + setTimeout: function( func, milliseconds, scope, args, ownerWindow ) { + if ( !ownerWindow ) + ownerWindow = window; - /** - * Gets a unique number for this CKEDITOR execution session. It returns - * progressive numbers starting at 1. - * @function - * @returns {Number} A unique number. - * @example - * alert( CKEDITOR.tools.getNextNumber() ); // "1" (e.g.) - * alert( CKEDITOR.tools.getNextNumber() ); // "2" - */ - getNextNumber: (function() { - var last = 0; - return function() { - return ++last; - }; - })(), + if ( !scope ) + scope = ownerWindow; - /** - * Creates a function override. - * @param {Function} originalFunction The function to be overridden. - * @param {Function} functionBuilder A function that returns the new - * function. The original function reference will be passed to this - * function. - * @returns {Function} The new function. - * @example - * var example = - * { - * myFunction : function( name ) - * { - * alert( 'Name: ' + name ); - * } - * }; - * - * example.myFunction = CKEDITOR.tools.override( example.myFunction, function( myFunctionOriginal ) - * { - * return function( name ) - * { - * alert( 'Override Name: ' + name ); - * myFunctionOriginal.call( this, name ); - * }; - * }); - */ - override: function( originalFunction, functionBuilder ) { - return functionBuilder( originalFunction ); - }, + return ownerWindow.setTimeout( function() { + if ( args ) + func.apply( scope, [].concat( args ) ); + else + func.apply( scope ); + }, milliseconds || 0 ); + }, - /** - * Executes a function after specified delay. - * @param {Function} func The function to be executed. - * @param {Number} [milliseconds] The amount of time (millisecods) to wait - * to fire the function execution. Defaults to zero. - * @param {Object} [scope] The object to hold the function execution scope - * (the "this" object). By default the "window" object. - * @param {Object|Array} [args] A single object, or an array of objects, to - * pass as arguments to the function. - * @param {Object} [ownerWindow] The window that will be used to set the - * timeout. By default the current "window". - * @returns {Object} A value that can be used to cancel the function execution. - * @example - * CKEDITOR.tools.setTimeout( - * function() - * { - * alert( 'Executed after 2 seconds' ); - * }, - * 2000 ); - */ - setTimeout: function( func, milliseconds, scope, args, ownerWindow ) { - if ( !ownerWindow ) - ownerWindow = window; + /** + * Remove spaces from the start and the end of a string. The following + * characters are removed: space, tab, line break, line feed. + * @function + * @param {String} str The text from which remove the spaces. + * @returns {String} The modified string without the boundary spaces. + * @example + * alert( CKEDITOR.tools.trim( ' example ' ); // "example" + */ + trim: (function() { + // We are not using \s because we don't want "non-breaking spaces" to be caught. + var trimRegex = /(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g; + return function( str ) { + return str.replace( trimRegex, '' ); + }; + })(), - if ( !scope ) - scope = ownerWindow; + /** + * Remove spaces from the start (left) of a string. The following + * characters are removed: space, tab, line break, line feed. + * @function + * @param {String} str The text from which remove the spaces. + * @returns {String} The modified string excluding the removed spaces. + * @example + * alert( CKEDITOR.tools.ltrim( ' example ' ); // "example " + */ + ltrim: (function() { + // We are not using \s because we don't want "non-breaking spaces" to be caught. + var trimRegex = /^[ \t\n\r]+/g; + return function( str ) { + return str.replace( trimRegex, '' ); + }; + })(), - return ownerWindow.setTimeout( function() { - if ( args ) - func.apply( scope, [].concat( args ) ); - else - func.apply( scope ); - }, milliseconds || 0 ); - }, + /** + * Remove spaces from the end (right) of a string. The following + * characters are removed: space, tab, line break, line feed. + * @function + * @param {String} str The text from which remove the spaces. + * @returns {String} The modified string excluding the removed spaces. + * @example + * alert( CKEDITOR.tools.ltrim( ' example ' ); // " example" + */ + rtrim: (function() { + // We are not using \s because we don't want "non-breaking spaces" to be caught. + var trimRegex = /[ \t\n\r]+$/g; + return function( str ) { + return str.replace( trimRegex, '' ); + }; + })(), - /** - * Remove spaces from the start and the end of a string. The following - * characters are removed: space, tab, line break, line feed. - * @function - * @param {String} str The text from which remove the spaces. - * @returns {String} The modified string without the boundary spaces. - * @example - * alert( CKEDITOR.tools.trim( ' example ' ); // "example" - */ - trim: (function() { - // We are not using \s because we don't want "non-breaking spaces" to be caught. - var trimRegex = /(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g; - return function( str ) { - return str.replace( trimRegex, '' ); - }; - })(), + /** + * Returns the index of an element in an array. + * @param {Array} array The array to be searched. + * @param {Object} entry The element to be found. + * @returns {Number} The (zero based) index of the first entry that matches + * the entry, or -1 if not found. + * @example + * var letters = [ 'a', 'b', 0, 'c', false ]; + * alert( CKEDITOR.tools.indexOf( letters, '0' ) ); "-1" because 0 !== '0' + * alert( CKEDITOR.tools.indexOf( letters, false ) ); "4" because 0 !== false + */ + indexOf: + // #2514: We should try to use Array.indexOf if it does exist. + ( Array.prototype.indexOf ) ? + function( array, entry ) { + return array.indexOf( entry ); + } : function( array, entry ) { + for ( var i = 0, len = array.length; i < len; i++ ) { + if ( array[ i ] === entry ) + return i; + } + return -1; + }, - /** - * Remove spaces from the start (left) of a string. The following - * characters are removed: space, tab, line break, line feed. - * @function - * @param {String} str The text from which remove the spaces. - * @returns {String} The modified string excluding the removed spaces. - * @example - * alert( CKEDITOR.tools.ltrim( ' example ' ); // "example " - */ - ltrim: (function() { - // We are not using \s because we don't want "non-breaking spaces" to be caught. - var trimRegex = /^[ \t\n\r]+/g; - return function( str ) { - return str.replace( trimRegex, '' ); - }; - })(), + bind: function( func, obj ) { + return function() { + return func.apply( obj, arguments ); + }; + }, - /** - * Remove spaces from the end (right) of a string. The following - * characters are removed: space, tab, line break, line feed. - * @function - * @param {String} str The text from which remove the spaces. - * @returns {String} The modified string excluding the removed spaces. - * @example - * alert( CKEDITOR.tools.ltrim( ' example ' ); // " example" - */ - rtrim: (function() { - // We are not using \s because we don't want "non-breaking spaces" to be caught. - var trimRegex = /[ \t\n\r]+$/g; - return function( str ) { - return str.replace( trimRegex, '' ); - }; - })(), + createClass: function( definition ) { + var $ = definition.$, + baseClass = definition.base, + privates = definition.privates || definition._, + proto = definition.proto, + statics = definition.statics; - /** - * Returns the index of an element in an array. - * @param {Array} array The array to be searched. - * @param {Object} entry The element to be found. - * @returns {Number} The (zero based) index of the first entry that matches - * the entry, or -1 if not found. - * @example - * var letters = [ 'a', 'b', 0, 'c', false ]; - * alert( CKEDITOR.tools.indexOf( letters, '0' ) ); "-1" because 0 !== '0' - * alert( CKEDITOR.tools.indexOf( letters, false ) ); "4" because 0 !== false - */ - indexOf: - // #2514: We should try to use Array.indexOf if it does exist. - ( Array.prototype.indexOf ) ? - function( array, entry ) { - return array.indexOf( entry ); - } : function( array, entry ) { - for ( var i = 0, len = array.length; i < len; i++ ) { - if ( array[ i ] === entry ) - return i; + if ( privates ) { + var originalConstructor = $; + $ = function() { + originalConstructor.apply( this, arguments ); + + // Create (and get) the private namespace. + var _ = this._ || ( this._ = {} ); + + // Make some magic so "this" will refer to the main + // instance when coding private functions. + for ( var privateName in privates ) { + var priv = privates[ privateName ]; + + _[ privateName ] = ( typeof priv == 'function' ) ? CKEDITOR.tools.bind( priv, this ) : priv; + } + }; + } + + if ( baseClass ) { + $.prototype = this.prototypedCopy( baseClass.prototype ); + + $.prototype.base = function() { + this.base = baseClass.prototype.base; + baseClass.apply( this, arguments ); + this.base = arguments.callee; + }; + } + + if ( proto ) + this.extend( $.prototype, proto, true ); + + if ( statics ) + this.extend( $, statics, true ); + + return $; + }, + + addFunction: function( fn, scope ) { + return functions.push( function() { + fn.apply( scope || this, arguments ); + }) - 1; + }, + + callFunction: function( index ) { + var fn = functions[ index ]; + return fn.apply( window, Array.prototype.slice.call( arguments, 1 ) ); } - return -1; - }, - - bind: function( func, obj ) { - return function() { - return func.apply( obj, arguments ); - }; - } -}; + }; +})(); // PACKAGER_RENAME( CKEDITOR.tools ) diff --git a/_source/core/ui.js b/_source/core/ui.js index 69036f6c25..54e4bbefcd 100644 --- a/_source/core/ui.js +++ b/_source/core/ui.js @@ -44,9 +44,10 @@ CKEDITOR.ui.prototype = { * }); */ add: function( name, type, definition ) { - var item = this._.handlers[ type ].create( definition ); - item.name = name; - this._.items[ name ] = item; + this._.items[ name ] = { + type: type, + args: Array.prototype.slice.call( arguments, 2 ) + }; }, /** @@ -54,8 +55,11 @@ CKEDITOR.ui.prototype = { * @param {String} name The UI item hame. * @example */ - get: function( name ) { - return this._.items[ name ] || null; + create: function( name ) { + var item = this._.items[ name ], + handler = item && this._.handlers[ item.type ]; + + return handler && handler.create.apply( this, item.args ); }, /** diff --git a/_source/lang/en.js b/_source/lang/en.js index 750895f17c..3d063f0497 100644 --- a/_source/lang/en.js +++ b/_source/lang/en.js @@ -413,5 +413,21 @@ CKEDITOR.lang[ 'en' ] = { emptyListMsg: '(No templates defined)' }, - showBlocks: 'Show Blocks' + showBlocks: 'Show Blocks', + + format: { + label: 'Format', + panelTitle: 'Paragraph Format', + + tag_p: 'Normal', + tag_pre: 'Formatted', + tag_address: 'Address', + tag_h1: 'Heading 1', + tag_h2: 'Heading 2', + tag_h3: 'Heading 3', + tag_h4: 'Heading 4', + tag_h5: 'Heading 5', + tag_h6: 'Heading 6', + tag_div: 'Normal (DIV)' + } }; diff --git a/_source/plugins/floatpanel/plugin.js b/_source/plugins/floatpanel/plugin.js new file mode 100644 index 0000000000..508b6f84f0 --- /dev/null +++ b/_source/plugins/floatpanel/plugin.js @@ -0,0 +1,108 @@ +/* +Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +CKEDITOR.plugins.add( 'floatpanel', { + requires: [ 'panel' ] +}); + +(function() { + var panels = {}; + + function getPanel( doc, parentElement, definition ) { + // Generates the panel key: docId-eleId-CSSs + var key = doc.getUniqueId() + '-' + parentElement.getUniqueId() + + ( ( definition.css && ( '-' + definition.css ) ) || '' ); + + var panel = panels[ key ]; + + if ( !panel ) { + panel = panels[ key ] = new CKEDITOR.ui.panel( doc, definition ); + panel.element = parentElement.append( CKEDITOR.dom.element.createFromHtml( panel.renderHtml(), doc ) ); + + panel.element.setStyles({ + display: 'none', + position: 'absolute' + }); + } + + return panel; + } + + CKEDITOR.ui.floatPanel = CKEDITOR.tools.createClass({ + $: function( parentElement, definition ) { + definition.forceIFrame = true; + + var doc = parentElement.getDocument(), + panel = getPanel( doc, parentElement, definition ), + element = panel.element, + iframe = element.getFirst(); + + this.element = element; + + this._ = { + // The panel that will be floating. + panel: panel, + document: doc, + iframe: iframe + } + }, + + proto: { + addBlock: function( name, block ) { + return this._.panel.addBlock( name, block ); + }, + + addListBlock: function( name, multiSelect ) { + return this._.panel.addListBlock( name, multiSelect ); + }, + + showBlock: function( name, offsetParent, corner, offsetX, offsetY ) { + this._.panel.showBlock( name ); + + var element = this.element, + iframe = this._.iframe, + position = offsetParent.getDocumentPosition(); + + var left = position.x + ( offsetX || 0 ), + top = position.y + ( offsetY || 0 ); + + if ( corner == 2 || corner == 3 ) + left += offsetParent.$.offsetWidth - 1; + + if ( corner == 3 || corner == 4 ) + top += offsetParent.$.offsetHeight - 1; + + element.setStyles({ + left: left + 'px', + top: top + 'px', + display: '' + }); + + // Configure the IFrame blur event. Do that only once. + if ( !this._.blurSet ) { + // Non IE prefer the event into a window object. + var focused = CKEDITOR.env.ie ? iframe : new CKEDITOR.dom.window( iframe.$.contentWindow ); + + focused.on( 'blur', CKEDITOR.tools.bind( this.hide, this ) ); + + this._.blurSet = 1; + } + + // Set the IFrame focus, so the blur event gets fired. + setTimeout( function() { + iframe.$.contentWindow.focus(); + }, 0 ); + + if ( this.onShow ) + this.onShow.call( this ); + }, + + hide: function() { + if ( !this.onHide || this.onHide.call( this ) !== true ) + this.element.setStyle( 'display', 'none' ); + } + } + }); +})(); diff --git a/_source/plugins/format/plugin.js b/_source/plugins/format/plugin.js new file mode 100644 index 0000000000..d18ed4bc4c --- /dev/null +++ b/_source/plugins/format/plugin.js @@ -0,0 +1,102 @@ +/* +Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +CKEDITOR.plugins.add( 'format', { + requires: [ 'richcombo' ], + + init: function( editor ) { + var config = editor.config, + lang = editor.lang.format; + + var saveRanges; + + // Gets the list of tags from the settings. + var tags = config.format_tags.split( ',' ); + + // Create style objects for all defined styles. + var styles = {}; + for ( var i = 0; i < tags.length; i++ ) { + var tag = tags[ i ]; + styles[ tag ] = new CKEDITOR.style( config[ 'format_' + tag ] ); + } + + editor.ui.addRichCombo( 'Format', { + label: lang.label, + title: lang.panelTitle, + className: 'cke_format', + multiSelect: false, + + panel: { + css: [ config.contentsCss, editor.skinPath + 'editor.css' ], + className: 'cke_skin_default' + }, + + init: function() { + this.startGroup( lang.panelTitle ); + + for ( var tag in styles ) { + var label = lang[ 'tag_' + tag ]; + + // Add the tag entry to the panel list. + this.add( tag, '<' + tag + '>' + label + '' + tag + '>', label ); + } + }, + + onClick: function( value ) { + editor.focus(); + + if ( saveRanges ) { + editor.getSelection().selectRanges( saveRanges ); + saveRanges = false; + } + + styles[ value ].apply( editor.document ); + }, + + onRender: function() { + editor.on( 'selectionChange', function( ev ) { + var currentTag = this.getValue(); + + var elementPath = ev.data.path; + + for ( var tag in styles ) { + if ( styles[ tag ].checkActive( elementPath ) ) { + if ( tag != currentTag ) + this.setValue( tag, editor.lang.format[ 'tag_' + tag ] ); + return; + } + } + + // If no styles match, just empty it. + this.setValue( '' ); + }, this ); + }, + + onOpen: function() { + if ( CKEDITOR.env.ie ) { + editor.focus(); + saveRanges = editor.getSelection().getRanges(); + } + }, + + onClose: function() { + saveRanges = null; + } + }); + } +}); + +CKEDITOR.config.format_tags = 'p,h1,h2,h3,h4,h5,h6,pre,address,div'; + +CKEDITOR.config.format_p = { element: 'p' }; +CKEDITOR.config.format_div = { element: 'div' }; +CKEDITOR.config.format_pre = { element: 'pre' }; +CKEDITOR.config.format_address = { element: 'address' }; +CKEDITOR.config.format_h1 = { element: 'h1' }; +CKEDITOR.config.format_h2 = { element: 'h2' }; +CKEDITOR.config.format_h3 = { element: 'h3' }; +CKEDITOR.config.format_h4 = { element: 'h4' }; +CKEDITOR.config.format_h5 = { element: 'h5' }; +CKEDITOR.config.format_h6 = { element: 'h6' }; diff --git a/_source/plugins/listblock/plugin.js b/_source/plugins/listblock/plugin.js new file mode 100644 index 0000000000..4b06271adb --- /dev/null +++ b/_source/plugins/listblock/plugin.js @@ -0,0 +1,117 @@ +/* +Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +CKEDITOR.plugins.add( 'listblock', { + requires: [ 'panel' ], + + onLoad: function() { + CKEDITOR.ui.panel.prototype.addListBlock = function( name, multiSelect ) { + return this.addBlock( name, new CKEDITOR.ui.listBlock( this.getHolderElement(), multiSelect ) ); + }; + + CKEDITOR.ui.listBlock = CKEDITOR.tools.createClass({ + base: CKEDITOR.ui.panel.block, + + $: function( blockHolder, multiSelect ) { + // Call the base contructor. + this.base( blockHolder ); + + this.multiSelect = !!multiSelect; + + this._ = { + pendingHtml: [], + items: {} + }; + }, + + _: { + close: function() { + if ( this._.started ) { + this._.pendingHtml.push( '' ); + delete this._.started; + } + }, + + getClick: function() { + if ( !this._.click ) { + this._.click = CKEDITOR.tools.addFunction( function( value ) { + var marked = true; + + if ( this.multiSelect ) + marked = this.toggle( value ); + else + this.mark( value ); + + if ( this.onClick ) + this.onClick( value, marked ); + }, this ); + } + return this._.click; + } + }, + + proto: { + add: function( value, html ) { + var pendingHtml = this._.pendingHtml, + id = CKEDITOR.tools.getNextNumber(); + + if ( !this._.started ) { + pendingHtml.push( '
. + // var newBlockIsPre = newBlock.nodeName.IEquals( 'pre' ); + // var blockIsPre = block.nodeName.IEquals( 'pre' ); + + // var toPre = newBlockIsPre && !blockIsPre; + // var fromPre = !newBlockIsPre && blockIsPre; + + // Move everything from the current node to the new one. + // if ( toPre ) + // newBlock = this._ToPre( doc, block, newBlock ); + // else if ( fromPre ) + // newBlock = this._FromPre( doc, block, newBlock ); + // else // Convering from a regular block to another regular block. + block.moveChildren( newBlock ); + + // Replace the current block. + newBlock.insertBefore( block ); + block.remove(); + + // Complete other tasks after inserting the node in the DOM. + // if ( newBlockIsPre ) + // { + // if ( previousPreBlock ) + // this._CheckAndMergePre( previousPreBlock, newBlock ) ; // Merge successiveblocks. + // previousPreBlock = newBlock; + // } + // else if ( fromPre ) + // this._CheckAndSplitPre( newBlock ) ; // Split
in successives. + } + + range.moveToBookmark( bookmark ); + }; // Removes a style from an element itself, don't care about its subtree. var removeFromElement = function( style, element ) { diff --git a/_source/plugins/toolbar/plugin.js b/_source/plugins/toolbar/plugin.js index d3d814ca39..3826d9a005 100644 --- a/_source/plugins/toolbar/plugin.js +++ b/_source/plugins/toolbar/plugin.js @@ -117,7 +117,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( itemName == '-' ) item = CKEDITOR.ui.separator; else - item = editor.ui.get( itemName ); + item = editor.ui.create( itemName ); if ( item ) { var itemObj = item.render( editor, output ); @@ -198,6 +198,7 @@ CKEDITOR.config.toolbar = [ 'Link', 'Unlink', 'Anchor', '-', 'Image', 'Flash', '-', 'Table', 'Smiley', 'HorizontalRule', 'SpecialChar', 'PageBreak', '-', - 'ShowBlocks' + 'ShowBlocks', '-', + 'Format' ] ]; diff --git a/_source/skins/default/editor.css b/_source/skins/default/editor.css index fcb52f21e0..261a28829f 100644 --- a/_source/skins/default/editor.css +++ b/_source/skins/default/editor.css @@ -6,6 +6,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license @import url("reset.css"); @import url("mainui.css"); @import url("toolbar.css"); +@import url("panel.css"); +@import url("richcombo.css"); @import url("elementspath.css"); /* Restore the container visibility */ diff --git a/_source/skins/default/panel.css b/_source/skins/default/panel.css new file mode 100644 index 0000000000..0db56f9ef4 --- /dev/null +++ b/_source/skins/default/panel.css @@ -0,0 +1,262 @@ +/* +Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +.cke_skin_default.cke_panel +{ + border: 1px solid #316ac5; + background-color: #fff; + + width: 120px; + height: 100px; + + overflow:hidden; + + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -moz-border-radius-topright: 3px; + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; +} + +.cke_skin_default.cke_panel.cke_format +{ + width: 150px; + height: 170px; +} + +/* Ideally we would use "inherit here"... but you know... IE :( */ +.cke_skin_default.cke_panel iframe +{ + width: 100%; + height: 100%; +} + +/* + * All the following styles are to be used inside the iframe that holds panel + * contents. We don't use the cke_skin_default there to avoid the reset to be + * active. + * This is not an issue as we'll never have two skins running inside the same + * panel iframe. + */ + +body.cke_panel_frame +{ + overflow: auto; + overflow-x: hidden; +} + +ul.cke_panel_list +{ + list-style-type: none; + margin: 3px; + padding: 0px; + white-space: nowrap; +} + +li.cke_panel_listItem +{ + margin: 0px; +} + +.cke_panel_listItem a +{ + padding: 2px; + display: block; + border: 1px solid #fff; + color: inherit; + text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; +} + +/* IE6 */ +* html .cke_panel_listItem a +{ + width : 100%; + + /* IE is not able to inherit the color, so we must force it to black */ + color: #000; +} + +/* IE7 */ +*:first-child+html .cke_panel_listItem a +{ + /* IE is not able to inherit the color, so we must force it to black */ + color: #000; +} + +.cke_panel_listItem.cke_selected a +{ + border: 1px solid #ccc; + background-color: #e9f5ff; +} + +.cke_panel_listItem a:hover, +.cke_panel_listItem a:focus, +.cke_panel_listItem a:active +{ + border-color: #316ac5; + background-color: #dff1ff; +} + +.cke_panel_grouptitle +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; + font-weight: bold; + white-space: nowrap; + background-color: #dcdcdc; + color: #000; + margin:0px; + padding:3px; +} + +.cke_panel_listItem p, +.cke_panel_listItem h1, +.cke_panel_listItem h2, +.cke_panel_listItem h3, +.cke_panel_listItem h4, +.cke_panel_listItem h5, +.cke_panel_listItem h6, +.cke_panel_listItem pre +{ + margin-top: 3px; + margin-bottom: 3px; +} +/* +Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +.cke_skin_default.cke_panel +{ + border: 1px solid #316ac5; + background-color: #fff; + + width: 120px; + height: 100px; + + overflow:hidden; + + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -moz-border-radius-topright: 3px; + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; +} + +.cke_skin_default.cke_panel.cke_format +{ + width: 150px; + height: 170px; +} + +/* Ideally we would use "inherit here"... but you know... IE :( */ +.cke_skin_default.cke_panel iframe +{ + width: 100%; + height: 100%; +} + +/* + * All the following styles are to be used inside the iframe that holds panel + * contents. We don't use the cke_skin_default there to avoid the reset to be + * active. + * This is not an issue as we'll never have two skins running inside the same + * panel iframe. + */ + +body.cke_panel_frame +{ + overflow: auto; + overflow-x: hidden; +} + +ul.cke_panel_list +{ + list-style-type: none; + margin: 3px; + padding: 0px; + white-space: nowrap; +} + +li.cke_panel_listItem +{ + margin: 0px; +} + +.cke_panel_listItem a +{ + padding: 2px; + display: block; + border: 1px solid #fff; + color: inherit; + text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; +} + +/* IE6 */ +* html .cke_panel_listItem a +{ + width : 100%; + + /* IE is not able to inherit the color, so we must force it to black */ + color: #000; +} + +/* IE7 */ +*:first-child+html .cke_panel_listItem a +{ + /* IE is not able to inherit the color, so we must force it to black */ + color: #000; +} + +.cke_panel_listItem.cke_selected a +{ + border: 1px solid #ccc; + background-color: #e9f5ff; +} + +.cke_panel_listItem a:hover, +.cke_panel_listItem a:focus, +.cke_panel_listItem a:active +{ + border-color: #316ac5; + background-color: #dff1ff; +} + +.cke_panel_grouptitle +{ + font-size: 11px; + font-family: 'Microsoft Sans Serif' , Tahoma, Arial, Verdana, Sans-Serif; + font-weight: bold; + white-space: nowrap; + background-color: #dcdcdc; + color: #000; + margin:0px; + padding:3px; +} + +.cke_panel_listItem p, +.cke_panel_listItem h1, +.cke_panel_listItem h2, +.cke_panel_listItem h3, +.cke_panel_listItem h4, +.cke_panel_listItem h5, +.cke_panel_listItem h6, +.cke_panel_listItem pre +{ + margin-top: 3px; + margin-bottom: 3px; +} diff --git a/_source/skins/default/richcombo.css b/_source/skins/default/richcombo.css new file mode 100644 index 0000000000..7dc0dc457b --- /dev/null +++ b/_source/skins/default/richcombo.css @@ -0,0 +1,226 @@ +/* Special Combo */ + +.cke_skin_default .cke_rcombo +{ + padding-right: 4px; + float: left; +} + +/* IE6 only */ +/*\*/ +* html .cke_skin_default .cke_rcombo +{ + float: none; +} +/**/ + +.cke_skin_default .cke_rcombo a +{ + filter: alpha(opacity=70); /* IE */ + opacity: 0.70; /* Safari, Opera and Mozilla */ +} + +.cke_skin_default .cke_rcombo .cke_label +{ + padding-top: 6px; + padding-left: 4px; + padding-right: 5px; + float: left; + filter: alpha(opacity=70); /* IE */ + opacity: 0.70; /* Safari, Opera and Mozilla */ + background-color: #f1f1e3; /* Because of IE6+ClearType */ +} + +.cke_skin_default .cke_rcombo .cke_text +{ + border: 1px solid #8f8f73; + background-color: #fff; + float: left; + height: 14px; + width:60px; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 5px; + padding-right: 5px; + text-overflow: ellipsis; + overflow: hidden; + -moz-border-radius-topleft: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +.cke_skin_default .cke_rcombo .cke_openbutton +{ + background-position: center center; + background-image: url(images/toolbar.buttonarrow.gif); + border-right: 1px solid #8f8f73; + border-top: 1px solid #8f8f73; + border-bottom: 1px solid #8f8f73; + display: block; + float: left; + width: 14px; + height: 22px; + background-repeat: no-repeat; + -moz-border-radius-topright: 3px; + -webkit-border-top-right-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.cke_skin_default .cke_rcombo a:hover, +.cke_skin_default .cke_rcombo a:focus, +.cke_skin_default .cke_rcombo a:active, +.cke_skin_default .cke_rcombo.cke_on a +{ + filter: alpha(opacity=100); /* IE */ + opacity: 1; /* Safari, Opera and Mozilla */ +} + +.cke_skin_default .cke_rcombo a:hover .cke_text, +.cke_skin_default .cke_rcombo a:focus .cke_text, +.cke_skin_default .cke_rcombo a:active .cke_text, +.cke_skin_default .cke_rcombo.cke_on .cke_text +{ + border-color: #316ac5; +} + +.cke_skin_default .cke_rcombo a:hover .cke_openbutton, +.cke_skin_default .cke_rcombo a:focus .cke_openbutton, +.cke_skin_default .cke_rcombo a:active .cke_openbutton, +.cke_skin_default .cke_rcombo.cke_on .cke_openbutton +{ + border-color: #316ac5; + background-color: #dff1ff; +} + +.cke_skin_default .cke_rcombo.cke_on .cke_text +{ + -moz-border-radius-bottomleft: 0px; + -webkit-border-bottom-left-radius: 0px; + border-bottom-left-radius: 0px; +} + +.cke_skin_default .cke_rcombo.cke_on .cke_openbutton +{ + -moz-border-radius-bottomright: 0px; + -webkit-border-bottom-right-radius: 0px; + border-bottom-right-radius: 0px; +} +/* Special Combo */ + +.cke_skin_default .cke_rcombo +{ + padding-right: 4px; + float: left; +} + +/* IE6 only */ +/*\*/ +* html .cke_skin_default .cke_rcombo +{ + float: none; +} +/**/ + +.cke_skin_default .cke_rcombo a +{ + filter: alpha(opacity=70); /* IE */ + opacity: 0.70; /* Safari, Opera and Mozilla */ +} + +.cke_skin_default .cke_rcombo .cke_label +{ + padding-top: 6px; + padding-left: 4px; + padding-right: 5px; + float: left; + filter: alpha(opacity=70); /* IE */ + opacity: 0.70; /* Safari, Opera and Mozilla */ + background-color: #f1f1e3; /* Because of IE6+ClearType */ +} + +.cke_skin_default .cke_rcombo .cke_text +{ + border: 1px solid #8f8f73; + background-color: #fff; + float: left; + height: 14px; + width:60px; + padding-top: 4px; + padding-bottom: 4px; + padding-left: 5px; + padding-right: 5px; + text-overflow: ellipsis; + overflow: hidden; + -moz-border-radius-topleft: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +.cke_skin_default .cke_rcombo .cke_openbutton +{ + background-position: center center; + background-image: url(images/toolbar.buttonarrow.gif); + border-right: 1px solid #8f8f73; + border-top: 1px solid #8f8f73; + border-bottom: 1px solid #8f8f73; + display: block; + float: left; + width: 14px; + height: 22px; + background-repeat: no-repeat; + -moz-border-radius-topright: 3px; + -webkit-border-top-right-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.cke_skin_default .cke_rcombo a:hover, +.cke_skin_default .cke_rcombo a:focus, +.cke_skin_default .cke_rcombo a:active, +.cke_skin_default .cke_rcombo.cke_on a +{ + filter: alpha(opacity=100); /* IE */ + opacity: 1; /* Safari, Opera and Mozilla */ +} + +.cke_skin_default .cke_rcombo a:hover .cke_text, +.cke_skin_default .cke_rcombo a:focus .cke_text, +.cke_skin_default .cke_rcombo a:active .cke_text, +.cke_skin_default .cke_rcombo.cke_on .cke_text +{ + border-color: #316ac5; +} + +.cke_skin_default .cke_rcombo a:hover .cke_openbutton, +.cke_skin_default .cke_rcombo a:focus .cke_openbutton, +.cke_skin_default .cke_rcombo a:active .cke_openbutton, +.cke_skin_default .cke_rcombo.cke_on .cke_openbutton +{ + border-color: #316ac5; + background-color: #dff1ff; +} + +.cke_skin_default .cke_rcombo.cke_on .cke_text +{ + -moz-border-radius-bottomleft: 0px; + -webkit-border-bottom-left-radius: 0px; + border-bottom-left-radius: 0px; +} + +.cke_skin_default .cke_rcombo.cke_on .cke_openbutton +{ + -moz-border-radius-bottomright: 0px; + -webkit-border-bottom-right-radius: 0px; + border-bottom-right-radius: 0px; +} diff --git a/_source/tests/core/event.html b/_source/tests/core/event.html index 4d7f1422fc..5b6b403aae 100644 --- a/_source/tests/core/event.html +++ b/_source/tests/core/event.html @@ -449,6 +449,34 @@ assert.areSame( false, isCanceledC, 'event C must not be canceled' ); }, + test_event_removeListener : function() + { + // Create a testObject and implement CKEDITOR.event on it. + var testObject = {}; + CKEDITOR.event.implementOn( testObject ); + + var counter = 0; + + // Add two listeners for the same event "A". + + testObject.on( 'A', function( ev ) + { + counter++; + ev.removeListener(); + }); + + testObject.on( 'A', function( ev ) + { + counter++; + }); + + // Fire the event twice. + testObject.fire( 'A' ); + testObject.fire( 'A' ); + + assert.areSame( 3, counter ); + }, + name : document.title }; })() ); diff --git a/_source/themes/default/theme.js b/_source/themes/default/theme.js index 3600ed29ea..f08a9341ed 100644 --- a/_source/themes/default/theme.js +++ b/_source/themes/default/theme.js @@ -48,7 +48,7 @@ CKEDITOR.themes.add( 'default', ( function() { // differently by the browsers ("semi-inline"). var container = CKEDITOR.dom.element.createFromHtml( [ '' + + ' cke_', editor.lang.dir, '" dir="', editor.lang.dir, '" title="', ( CKEDITOR.env.gecko ? ' ' : '' ), '">' + '
' + '
' + ' ' + diff --git a/ckeditor.pack b/ckeditor.pack index 3127c3b239..a5b8c016a2 100644 --- a/ckeditor.pack +++ b/ckeditor.pack @@ -46,12 +46,14 @@ constants : 'CKEDITOR.SELECTION_NONE' : 1, 'CKEDITOR.SELECTION_TEXT' : 2, 'CKEDITOR.SELECTION_ELEMENT' : 3, + 'CKEDITOR.UI_RICHCOMBO' : 3, 'CKEDITOR.DIALOG_RESIZE_NONE' : 0, 'CKEDITOR.DIALOG_RESIZE_WIDTH' : 1, 'CKEDITOR.DIALOG_RESIZE_HEIGHT' : 2, 'CKEDITOR.DIALOG_RESIZE_BOTH' : 3, 'CKEDITOR.VALIDATE_OR' : 1, - 'CKEDITOR.VALIDATE_AND' : 2 + 'CKEDITOR.VALIDATE_AND' : 2, + 'CKEDITOR.UI_PANEL' : 2 }, packages : @@ -120,6 +122,8 @@ packages : '_source/plugins/clipboard/plugin.js', '_source/plugins/elementspath/plugin.js', '_source/plugins/find/plugin.js', + '_source/plugins/flash/plugin.js', + '_source/plugins/format/plugin.js', '_source/plugins/horizontalrule/plugin.js', '_source/plugins/htmldataprocessor/plugin.js', '_source/plugins/image/plugin.js', @@ -136,6 +140,7 @@ packages : '_source/plugins/print/plugin.js', '_source/plugins/removeformat/plugin.js', '_source/plugins/smiley/plugin.js', + '_source/plugins/showblocks/plugin.js', '_source/plugins/sourcearea/plugin.js', '_source/plugins/table/plugin.js', '_source/plugins/specialchar/plugin.js', @@ -147,11 +152,15 @@ packages : '_source/plugins/styles/plugin.js', '_source/plugins/domiterator/plugin.js', '_source/plugins/selection/plugin.js', - '_source/plugins/htmlwriter/plugin.js', '_source/plugins/fakeobjects/plugin.js', + '_source/plugins/richcombo/plugin.js', + '_source/plugins/htmlwriter/plugin.js', '_source/plugins/dialog/plugin.js', '_source/plugins/editingblock/plugin.js', + '_source/plugins/floatpanel/plugin.js', + '_source/plugins/listblock/plugin.js', '_source/plugins/dialogui/plugin.js', + '_source/plugins/panel/plugin.js', '_source/skins/default/skin.js', '_source/themes/default/theme.js' ] diff --git a/contents.css b/contents.css index 51686f3883..3f2aba54ac 100644 --- a/contents.css +++ b/contents.css @@ -9,6 +9,9 @@ body font-family: Arial, Verdana, sans-serif; font-size: 12px; + /* Text color */ + color: #222; + /* Remove the background color to make it transparent */ background-color: #fff; }