2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license
\r
7 * @fileOverview Defines the {@link CKEDITOR.editor} class, which is the base
\r
8 * for other classes representing DOM objects.
\r
12 * Represents a DOM object. This class is not intended to be used directly. It
\r
13 * serves as the base class for other classes representing specific DOM
\r
16 * @param {Object} nativeDomObject A native DOM object.
\r
17 * @augments CKEDITOR.event
\r
20 CKEDITOR.dom.domObject = function( nativeDomObject )
\r
22 if ( nativeDomObject )
\r
25 * The native DOM object represented by this class instance.
\r
28 * var element = new CKEDITOR.dom.element( 'span' );
\r
29 * alert( element.$.nodeType ); // "1"
\r
31 this.$ = nativeDomObject;
\r
35 CKEDITOR.dom.domObject.prototype = (function()
\r
37 // Do not define other local variables here. We want to keep the native
\r
38 // listener closures as clean as possible.
\r
40 var getNativeListener = function( domObject, eventName )
\r
42 return function( domEvent )
\r
44 // In FF, when reloading the page with the editor focused, it may
\r
45 // throw an error because the CKEDITOR global is not anymore
\r
46 // available. So, we check it here first. (#2923)
\r
47 if ( typeof CKEDITOR != 'undefined' )
\r
48 domObject.fire( eventName, new CKEDITOR.dom.event( domEvent ) );
\r
52 return /** @lends CKEDITOR.dom.domObject.prototype */ {
\r
54 getPrivate : function()
\r
58 // Get the main private function from the custom data. Create it if not
\r
60 if ( !( priv = this.getCustomData( '_' ) ) )
\r
61 this.setCustomData( '_', ( priv = {} ) );
\r
67 on : function( eventName )
\r
69 // We customize the "on" function here. The basic idea is that we'll have
\r
70 // only one listener for a native event, which will then call all listeners
\r
71 // set to the event.
\r
73 // Get the listeners holder object.
\r
74 var nativeListeners = this.getCustomData( '_cke_nativeListeners' );
\r
76 if ( !nativeListeners )
\r
78 nativeListeners = {};
\r
79 this.setCustomData( '_cke_nativeListeners', nativeListeners );
\r
82 // Check if we have a listener for that event.
\r
83 if ( !nativeListeners[ eventName ] )
\r
85 var listener = nativeListeners[ eventName ] = getNativeListener( this, eventName );
\r
87 if ( this.$.addEventListener )
\r
88 this.$.addEventListener( eventName, listener, !!CKEDITOR.event.useCapture );
\r
89 else if ( this.$.attachEvent )
\r
90 this.$.attachEvent( 'on' + eventName, listener );
\r
93 // Call the original implementation.
\r
94 return CKEDITOR.event.prototype.on.apply( this, arguments );
\r
98 removeListener : function( eventName )
\r
100 // Call the original implementation.
\r
101 CKEDITOR.event.prototype.removeListener.apply( this, arguments );
\r
103 // If we don't have listeners for this event, clean the DOM up.
\r
104 if ( !this.hasListeners( eventName ) )
\r
106 var nativeListeners = this.getCustomData( '_cke_nativeListeners' );
\r
107 var listener = nativeListeners && nativeListeners[ eventName ];
\r
110 if ( this.$.removeEventListener )
\r
111 this.$.removeEventListener( eventName, listener, false );
\r
112 else if ( this.$.detachEvent )
\r
113 this.$.detachEvent( 'on' + eventName, listener );
\r
115 delete nativeListeners[ eventName ];
\r
122 (function( domObjectProto )
\r
124 var customData = {};
\r
127 * Determines whether the specified object is equal to the current object.
\r
128 * @name CKEDITOR.dom.domObject.prototype.equals
\r
130 * @param {Object} object The object to compare with the current object.
\r
131 * @returns {Boolean} "true" if the object is equal.
\r
133 * var doc = new CKEDITOR.dom.document( document );
\r
134 * alert( doc.equals( CKEDITOR.document ) ); // "true"
\r
135 * alert( doc == CKEDITOR.document ); // "false"
\r
137 domObjectProto.equals = function( object )
\r
139 return ( object && object.$ === this.$ );
\r
143 * Sets a data slot value for this object. These values are shared by all
\r
144 * instances pointing to that same DOM object.
\r
145 * @name CKEDITOR.dom.domObject.prototype.setCustomData
\r
147 * @param {String} key A key used to identify the data slot.
\r
148 * @param {Object} value The value to set to the data slot.
\r
149 * @returns {CKEDITOR.dom.domObject} This DOM object instance.
\r
150 * @see CKEDITOR.dom.domObject.prototype.getCustomData
\r
152 * var element = new CKEDITOR.dom.element( 'span' );
\r
153 * element.setCustomData( 'hasCustomData', true );
\r
155 domObjectProto.setCustomData = function( key, value )
\r
157 var expandoNumber = this.getUniqueId(),
\r
158 dataSlot = customData[ expandoNumber ] || ( customData[ expandoNumber ] = {} );
\r
160 dataSlot[ key ] = value;
\r
166 * Gets the value set to a data slot in this object.
\r
167 * @name CKEDITOR.dom.domObject.prototype.getCustomData
\r
169 * @param {String} key The key used to identify the data slot.
\r
170 * @returns {Object} This value set to the data slot.
\r
171 * @see CKEDITOR.dom.domObject.prototype.setCustomData
\r
173 * var element = new CKEDITOR.dom.element( 'span' );
\r
174 * alert( element.getCustomData( 'hasCustomData' ) ); // e.g. 'true'
\r
176 domObjectProto.getCustomData = function( key )
\r
178 var expandoNumber = this.$._cke_expando,
\r
179 dataSlot = expandoNumber && customData[ expandoNumber ];
\r
181 return dataSlot && dataSlot[ key ];
\r
185 * @name CKEDITOR.dom.domObject.prototype.removeCustomData
\r
187 domObjectProto.removeCustomData = function( key )
\r
189 var expandoNumber = this.$._cke_expando,
\r
190 dataSlot = expandoNumber && customData[ expandoNumber ],
\r
191 retval = dataSlot && dataSlot[ key ];
\r
193 if ( typeof retval != 'undefined' )
\r
194 delete dataSlot[ key ];
\r
196 return retval || null;
\r
200 * @name CKEDITOR.dom.domObject.prototype.getCustomData
\r
202 domObjectProto.getUniqueId = function()
\r
204 return this.$._cke_expando || ( this.$._cke_expando = CKEDITOR.tools.getNextNumber() );
\r
207 // Implement CKEDITOR.event.
\r
208 CKEDITOR.event.implementOn( domObjectProto );
\r
210 })( CKEDITOR.dom.domObject.prototype );
\r