debian-django-ckeditor/ckeditor/static/ckeditor/ckeditor/_source/core/dom/domobject.js

259 lines
7.9 KiB
JavaScript

/*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
/**
* @fileOverview Defines the {@link CKEDITOR.editor} class, which is the base
* for other classes representing DOM objects.
*/
/**
* Represents a DOM object. This class is not intended to be used directly. It
* serves as the base class for other classes representing specific DOM
* objects.
* @constructor
* @param {Object} nativeDomObject A native DOM object.
* @augments CKEDITOR.event
* @example
*/
CKEDITOR.dom.domObject = function( nativeDomObject )
{
if ( nativeDomObject )
{
/**
* The native DOM object represented by this class instance.
* @type Object
* @example
* var element = new CKEDITOR.dom.element( 'span' );
* alert( element.$.nodeType ); // "1"
*/
this.$ = nativeDomObject;
}
};
CKEDITOR.dom.domObject.prototype = (function()
{
// Do not define other local variables here. We want to keep the native
// listener closures as clean as possible.
var getNativeListener = function( domObject, eventName )
{
return function( domEvent )
{
// In FF, when reloading the page with the editor focused, it may
// throw an error because the CKEDITOR global is not anymore
// available. So, we check it here first. (#2923)
if ( typeof CKEDITOR != 'undefined' )
domObject.fire( eventName, new CKEDITOR.dom.event( domEvent ) );
};
};
return /** @lends CKEDITOR.dom.domObject.prototype */ {
getPrivate : function()
{
var priv;
// Get the main private function from the custom data. Create it if not
// defined.
if ( !( priv = this.getCustomData( '_' ) ) )
this.setCustomData( '_', ( priv = {} ) );
return priv;
},
/** @ignore */
on : function( eventName )
{
// We customize the "on" function here. The basic idea is that we'll have
// only one listener for a native event, which will then call all listeners
// set to the event.
// Get the listeners holder object.
var nativeListeners = this.getCustomData( '_cke_nativeListeners' );
if ( !nativeListeners )
{
nativeListeners = {};
this.setCustomData( '_cke_nativeListeners', nativeListeners );
}
// Check if we have a listener for that event.
if ( !nativeListeners[ eventName ] )
{
var listener = nativeListeners[ eventName ] = getNativeListener( this, eventName );
if ( this.$.attachEvent )
this.$.attachEvent( 'on' + eventName, listener );
else if ( this.$.addEventListener )
this.$.addEventListener( eventName, listener, !!CKEDITOR.event.useCapture );
}
// Call the original implementation.
return CKEDITOR.event.prototype.on.apply( this, arguments );
},
/** @ignore */
removeListener : function( eventName )
{
// Call the original implementation.
CKEDITOR.event.prototype.removeListener.apply( this, arguments );
// If we don't have listeners for this event, clean the DOM up.
if ( !this.hasListeners( eventName ) )
{
var nativeListeners = this.getCustomData( '_cke_nativeListeners' );
var listener = nativeListeners && nativeListeners[ eventName ];
if ( listener )
{
if ( this.$.detachEvent )
this.$.detachEvent( 'on' + eventName, listener );
else if ( this.$.removeEventListener )
this.$.removeEventListener( eventName, listener, false );
delete nativeListeners[ eventName ];
}
}
},
/**
* Removes any listener set on this object.
* To avoid memory leaks we must assure that there are no
* references left after the object is no longer needed.
*/
removeAllListeners : function()
{
var nativeListeners = this.getCustomData( '_cke_nativeListeners' );
for ( var eventName in nativeListeners )
{
var listener = nativeListeners[ eventName ];
if ( this.$.detachEvent )
this.$.detachEvent( 'on' + eventName, listener );
else if ( this.$.removeEventListener )
this.$.removeEventListener( eventName, listener, false );
delete nativeListeners[ eventName ];
}
}
};
})();
(function( domObjectProto )
{
var customData = {};
CKEDITOR.on( 'reset', function()
{
customData = {};
});
/**
* Determines whether the specified object is equal to the current object.
* @name CKEDITOR.dom.domObject.prototype.equals
* @function
* @param {Object} object The object to compare with the current object.
* @returns {Boolean} "true" if the object is equal.
* @example
* var doc = new CKEDITOR.dom.document( document );
* alert( doc.equals( CKEDITOR.document ) ); // "true"
* alert( doc == CKEDITOR.document ); // "false"
*/
domObjectProto.equals = function( object )
{
return ( object && object.$ === this.$ );
};
/**
* Sets a data slot value for this object. These values are shared by all
* instances pointing to that same DOM object.
* <strong>Note:</strong> The created data slot is only guarantied to be available on this unique dom node,
* thus any wish to continue access it from other element clones (either created by clone node or from innerHtml)
* will fail, for such usage, please use {@link CKEDITOR.dom.element::setAttribute} instead.
* @name CKEDITOR.dom.domObject.prototype.setCustomData
* @function
* @param {String} key A key used to identify the data slot.
* @param {Object} value The value to set to the data slot.
* @returns {CKEDITOR.dom.domObject} This DOM object instance.
* @see CKEDITOR.dom.domObject.prototype.getCustomData
* @example
* var element = new CKEDITOR.dom.element( 'span' );
* element.setCustomData( 'hasCustomData', true );
*/
domObjectProto.setCustomData = function( key, value )
{
var expandoNumber = this.getUniqueId(),
dataSlot = customData[ expandoNumber ] || ( customData[ expandoNumber ] = {} );
dataSlot[ key ] = value;
return this;
};
/**
* Gets the value set to a data slot in this object.
* @name CKEDITOR.dom.domObject.prototype.getCustomData
* @function
* @param {String} key The key used to identify the data slot.
* @returns {Object} This value set to the data slot.
* @see CKEDITOR.dom.domObject.prototype.setCustomData
* @example
* var element = new CKEDITOR.dom.element( 'span' );
* alert( element.getCustomData( 'hasCustomData' ) ); // e.g. 'true'
*/
domObjectProto.getCustomData = function( key )
{
var expandoNumber = this.$[ 'data-cke-expando' ],
dataSlot = expandoNumber && customData[ expandoNumber ];
return dataSlot && dataSlot[ key ];
};
/**
* @name CKEDITOR.dom.domObject.prototype.removeCustomData
*/
domObjectProto.removeCustomData = function( key )
{
var expandoNumber = this.$[ 'data-cke-expando' ],
dataSlot = expandoNumber && customData[ expandoNumber ],
retval = dataSlot && dataSlot[ key ];
if ( typeof retval != 'undefined' )
delete dataSlot[ key ];
return retval || null;
};
/**
* Removes any data stored on this object.
* To avoid memory leaks we must assure that there are no
* references left after the object is no longer needed.
* @name CKEDITOR.dom.domObject.prototype.clearCustomData
* @function
*/
domObjectProto.clearCustomData = function()
{
// Clear all event listeners
this.removeAllListeners();
var expandoNumber = this.$[ 'data-cke-expando' ];
expandoNumber && delete customData[ expandoNumber ];
};
/**
* Gets an ID that can be used to identiquely identify this DOM object in
* the running session.
* @name CKEDITOR.dom.domObject.prototype.getUniqueId
* @function
* @returns {Number} A unique ID.
*/
domObjectProto.getUniqueId = function()
{
return this.$[ 'data-cke-expando' ] || ( this.$[ 'data-cke-expando' ] = CKEDITOR.tools.getNextNumber() );
};
// Implement CKEDITOR.event.
CKEDITOR.event.implementOn( domObjectProto );
})( CKEDITOR.dom.domObject.prototype );