Mimimum syndical pour en faire un produit zope / cmf.
[ckeditor.git] / skins / ckeditor / _source / core / event.js
diff --git a/skins/ckeditor/_source/core/event.js b/skins/ckeditor/_source/core/event.js
new file mode 100644 (file)
index 0000000..fa19060
--- /dev/null
@@ -0,0 +1,342 @@
+/*\r
+Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.\r
+For licensing, see LICENSE.html or http://ckeditor.com/license\r
+*/\r
+\r
+/**\r
+ * @fileOverview Defines the {@link CKEDITOR.event} class, which serves as the\r
+ *             base for classes and objects that require event handling features.\r
+ */\r
+\r
+if ( !CKEDITOR.event )\r
+{\r
+       /**\r
+        * Creates an event class instance. This constructor is rearely used, being\r
+        * the {@link #.implementOn} function used in class prototypes directly\r
+        * instead.\r
+        * @class This is a base class for classes and objects that require event\r
+        * handling features.<br />\r
+        * <br />\r
+        * Do not confuse this class with {@link CKEDITOR.dom.event} which is\r
+        * instead used for DOM events. The CKEDITOR.event class implements the\r
+        * internal event system used by the CKEditor to fire API related events.\r
+        * @example\r
+        */\r
+       CKEDITOR.event = function()\r
+       {};\r
+\r
+       /**\r
+        * Implements the {@link CKEDITOR.event} features in an object.\r
+        * @param {Object} targetObject The object into which implement the features.\r
+        * @example\r
+        * var myObject = { message : 'Example' };\r
+        * <b>CKEDITOR.event.implementOn( myObject }</b>;\r
+        * myObject.on( 'testEvent', function()\r
+        *     {\r
+        *         alert( this.message );  // "Example"\r
+        *     });\r
+        * myObject.fire( 'testEvent' );\r
+        */\r
+       CKEDITOR.event.implementOn = function( targetObject )\r
+       {\r
+               var eventProto = CKEDITOR.event.prototype;\r
+\r
+               for ( var prop in eventProto )\r
+               {\r
+                       if ( targetObject[ prop ] == undefined )\r
+                               targetObject[ prop ] = eventProto[ prop ];\r
+               }\r
+       };\r
+\r
+       CKEDITOR.event.prototype = (function()\r
+       {\r
+               // Returns the private events object for a given object.\r
+               var getPrivate = function( obj )\r
+               {\r
+                       var _ = ( obj.getPrivate && obj.getPrivate() ) || obj._ || ( obj._ = {} );\r
+                       return _.events || ( _.events = {} );\r
+               };\r
+\r
+               var eventEntry = function( eventName )\r
+               {\r
+                       this.name = eventName;\r
+                       this.listeners = [];\r
+               };\r
+\r
+               eventEntry.prototype =\r
+               {\r
+                       // Get the listener index for a specified function.\r
+                       // Returns -1 if not found.\r
+                       getListenerIndex : function( listenerFunction )\r
+                       {\r
+                               for ( var i = 0, listeners = this.listeners ; i < listeners.length ; i++ )\r
+                               {\r
+                                       if ( listeners[i].fn == listenerFunction )\r
+                                               return i;\r
+                               }\r
+                               return -1;\r
+                       }\r
+               };\r
+\r
+               return /** @lends CKEDITOR.event.prototype */ {\r
+                       /**\r
+                        * Registers a listener to a specific event in the current object.\r
+                        * @param {String} eventName The event name to which listen.\r
+                        * @param {Function} listenerFunction The function listening to the\r
+                        *              event. A single {@link CKEDITOR.eventInfo} object instanced\r
+                        *              is passed to this function containing all the event data.\r
+                        * @param {Object} [scopeObj] The object used to scope the listener\r
+                        *              call (the this object. If omitted, the current object is used.\r
+                        * @param {Object} [listenerData] Data to be sent as the\r
+                        *              {@link CKEDITOR.eventInfo#listenerData} when calling the\r
+                        *              listener.\r
+                        * @param {Number} [priority] The listener priority. Lower priority\r
+                        *              listeners are called first. Listeners with the same priority\r
+                        *              value are called in registration order. Defaults to 10.\r
+                        * @example\r
+                        * someObject.on( 'someEvent', function()\r
+                        *     {\r
+                        *         alert( this == someObject );  // "true"\r
+                        *     });\r
+                        * @example\r
+                        * someObject.on( 'someEvent', function()\r
+                        *     {\r
+                        *         alert( this == anotherObject );  // "true"\r
+                        *     }\r
+                        *     , anotherObject );\r
+                        * @example\r
+                        * someObject.on( 'someEvent', function( event )\r
+                        *     {\r
+                        *         alert( event.listenerData );  // "Example"\r
+                        *     }\r
+                        *     , null, 'Example' );\r
+                        * @example\r
+                        * someObject.on( 'someEvent', function() { ... } );                   // 2nd called\r
+                        * someObject.on( 'someEvent', function() { ... }, null, null, 100 );  // 3rd called\r
+                        * someObject.on( 'someEvent', function() { ... }, null, null, 1 );    // 1st called\r
+                        */\r
+                       on : function( eventName, listenerFunction, scopeObj, listenerData, priority )\r
+                       {\r
+                               // Get the event entry (create it if needed).\r
+                               var events = getPrivate( this ),\r
+                                       event = events[ eventName ] || ( events[ eventName ] = new eventEntry( eventName ) );\r
+\r
+                               if ( event.getListenerIndex( listenerFunction ) < 0 )\r
+                               {\r
+                                       // Get the listeners.\r
+                                       var listeners = event.listeners;\r
+\r
+                                       // Fill the scope.\r
+                                       if ( !scopeObj )\r
+                                               scopeObj = this;\r
+\r
+                                       // Default the priority, if needed.\r
+                                       if ( isNaN( priority ) )\r
+                                               priority = 10;\r
+\r
+                                       var me = this;\r
+\r
+                                       // Create the function to be fired for this listener.\r
+                                       var listenerFirer = function( editor, publisherData, stopFn, cancelFn )\r
+                                       {\r
+                                               var ev =\r
+                                               {\r
+                                                       name : eventName,\r
+                                                       sender : this,\r
+                                                       editor : editor,\r
+                                                       data : publisherData,\r
+                                                       listenerData : listenerData,\r
+                                                       stop : stopFn,\r
+                                                       cancel : cancelFn,\r
+                                                       removeListener : function()\r
+                                                       {\r
+                                                               me.removeListener( eventName, listenerFunction );\r
+                                                       }\r
+                                               };\r
+\r
+                                               listenerFunction.call( scopeObj, ev );\r
+\r
+                                               return ev.data;\r
+                                       };\r
+                                       listenerFirer.fn = listenerFunction;\r
+                                       listenerFirer.priority = priority;\r
+\r
+                                       // Search for the right position for this new listener, based on its\r
+                                       // priority.\r
+                                       for ( var i = listeners.length - 1 ; i >= 0 ; i-- )\r
+                                       {\r
+                                               // Find the item which should be before the new one.\r
+                                               if ( listeners[ i ].priority <= priority )\r
+                                               {\r
+                                                       // Insert the listener in the array.\r
+                                                       listeners.splice( i + 1, 0, listenerFirer );\r
+                                                       return;\r
+                                               }\r
+                                       }\r
+\r
+                                       // If no position has been found (or zero length), put it in\r
+                                       // the front of list.\r
+                                       listeners.unshift( listenerFirer );\r
+                               }\r
+                       },\r
+\r
+                       /**\r
+                        * Fires an specific event in the object. All registered listeners are\r
+                        * called at this point.\r
+                        * @function\r
+                        * @param {String} eventName The event name to fire.\r
+                        * @param {Object} [data] Data to be sent as the\r
+                        *              {@link CKEDITOR.eventInfo#data} when calling the\r
+                        *              listeners.\r
+                        * @param {CKEDITOR.editor} [editor] The editor instance to send as the\r
+                        *              {@link CKEDITOR.eventInfo#editor} when calling the\r
+                        *              listener.\r
+                        * @returns {Boolean|Object} A booloan indicating that the event is to be\r
+                        *              canceled, or data returned by one of the listeners.\r
+                        * @example\r
+                        * someObject.on( 'someEvent', function() { ... } );\r
+                        * someObject.on( 'someEvent', function() { ... } );\r
+                        * <b>someObject.fire( 'someEvent' )</b>;  // both listeners are called\r
+                        * @example\r
+                        * someObject.on( 'someEvent', function( event )\r
+                        *     {\r
+                        *         alert( event.data );  // "Example"\r
+                        *     });\r
+                        * <b>someObject.fire( 'someEvent', 'Example' )</b>;\r
+                        */\r
+                       fire : (function()\r
+                       {\r
+                               // Create the function that marks the event as stopped.\r
+                               var stopped = false;\r
+                               var stopEvent = function()\r
+                               {\r
+                                       stopped = true;\r
+                               };\r
+\r
+                               // Create the function that marks the event as canceled.\r
+                               var canceled = false;\r
+                               var cancelEvent = function()\r
+                               {\r
+                                       canceled = true;\r
+                               };\r
+\r
+                               return function( eventName, data, editor )\r
+                               {\r
+                                       // Get the event entry.\r
+                                       var event = getPrivate( this )[ eventName ];\r
+\r
+                                       // Save the previous stopped and cancelled states. We may\r
+                                       // be nesting fire() calls.\r
+                                       var previousStopped = stopped,\r
+                                               previousCancelled = canceled;\r
+\r
+                                       // Reset the stopped and canceled flags.\r
+                                       stopped = canceled = false;\r
+\r
+                                       if ( event )\r
+                                       {\r
+                                               var listeners = event.listeners;\r
+\r
+                                               if ( listeners.length )\r
+                                               {\r
+                                                       // As some listeners may remove themselves from the\r
+                                                       // event, the original array length is dinamic. So,\r
+                                                       // let's make a copy of all listeners, so we are\r
+                                                       // sure we'll call all of them.\r
+                                                       listeners = listeners.slice( 0 );\r
+\r
+                                                       // Loop through all listeners.\r
+                                                       for ( var i = 0 ; i < listeners.length ; i++ )\r
+                                                       {\r
+                                                               // Call the listener, passing the event data.\r
+                                                               var retData = listeners[i].call( this, editor, data, stopEvent, cancelEvent );\r
+\r
+                                                               if ( typeof retData != 'undefined' )\r
+                                                                       data = retData;\r
+\r
+                                                               // No further calls is stopped or canceled.\r
+                                                               if ( stopped || canceled )\r
+                                                                       break;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       var ret = canceled || ( typeof data == 'undefined' ? false : data );\r
+\r
+                                       // Restore the previous stopped and canceled states.\r
+                                       stopped = previousStopped;\r
+                                       canceled = previousCancelled;\r
+\r
+                                       return ret;\r
+                               };\r
+                       })(),\r
+\r
+                       /**\r
+                        * Fires an specific event in the object, releasing all listeners\r
+                        * registered to that event. The same listeners are not called again on\r
+                        * successive calls of it or of {@link #fire}.\r
+                        * @param {String} eventName The event name to fire.\r
+                        * @param {Object} [data] Data to be sent as the\r
+                        *              {@link CKEDITOR.eventInfo#data} when calling the\r
+                        *              listeners.\r
+                        * @param {CKEDITOR.editor} [editor] The editor instance to send as the\r
+                        *              {@link CKEDITOR.eventInfo#editor} when calling the\r
+                        *              listener.\r
+                        * @returns {Boolean|Object} A booloan indicating that the event is to be\r
+                        *              canceled, or data returned by one of the listeners.\r
+                        * @example\r
+                        * someObject.on( 'someEvent', function() { ... } );\r
+                        * someObject.fire( 'someEvent' );  // above listener called\r
+                        * <b>someObject.fireOnce( 'someEvent' )</b>;  // above listener called\r
+                        * someObject.fire( 'someEvent' );  // no listeners called\r
+                        */\r
+                       fireOnce : function( eventName, data, editor )\r
+                       {\r
+                               var ret = this.fire( eventName, data, editor );\r
+                               delete getPrivate( this )[ eventName ];\r
+                               return ret;\r
+                       },\r
+\r
+                       /**\r
+                        * Unregisters a listener function from being called at the specified\r
+                        *              event. No errors are thrown if the listener has not been\r
+                        *              registered previously.\r
+                        * @param {String} eventName The event name.\r
+                        * @param {Function} listenerFunction The listener function to unregister.\r
+                        * @example\r
+                        * var myListener = function() { ... };\r
+                        * someObject.on( 'someEvent', myListener );\r
+                        * someObject.fire( 'someEvent' );  // myListener called\r
+                        * <b>someObject.removeListener( 'someEvent', myListener )</b>;\r
+                        * someObject.fire( 'someEvent' );  // myListener not called\r
+                        */\r
+                       removeListener : function( eventName, listenerFunction )\r
+                       {\r
+                               // Get the event entry.\r
+                               var event = getPrivate( this )[ eventName ];\r
+\r
+                               if ( event )\r
+                               {\r
+                                       var index = event.getListenerIndex( listenerFunction );\r
+                                       if ( index >= 0 )\r
+                                               event.listeners.splice( index, 1 );\r
+                               }\r
+                       },\r
+\r
+                       /**\r
+                        * Checks if there is any listener registered to a given event.\r
+                        * @param {String} eventName The event name.\r
+                        * @example\r
+                        * var myListener = function() { ... };\r
+                        * someObject.on( 'someEvent', myListener );\r
+                        * alert( someObject.<b>hasListeners( 'someEvent' )</b> );  // "true"\r
+                        * alert( someObject.<b>hasListeners( 'noEvent' )</b> );    // "false"\r
+                        */\r
+                       hasListeners : function( eventName )\r
+                       {\r
+                               var event = getPrivate( this )[ eventName ];\r
+                               return ( event && event.listeners.length > 0 ) ;\r
+                       }\r
+               };\r
+       })();\r
+}\r