307 lines
8.9 KiB
JavaScript
307 lines
8.9 KiB
JavaScript
|
/*
|
|||
|
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
|
|||
|
For licensing, see LICENSE.html or http://ckeditor.com/license
|
|||
|
*/
|
|||
|
|
|||
|
/**
|
|||
|
* @fileOverview jQuery adapter provides easy use of basic CKEditor functions
|
|||
|
* and access to internal API. It also integrates some aspects of CKEditor with
|
|||
|
* jQuery framework.
|
|||
|
*
|
|||
|
* Every TEXTAREA, DIV and P elements can be converted to working editor.
|
|||
|
*
|
|||
|
* Plugin exposes some of editor's event to jQuery event system. All of those are namespaces inside
|
|||
|
* ".ckeditor" namespace and can be binded/listened on supported textarea, div and p nodes.
|
|||
|
*
|
|||
|
* Available jQuery events:
|
|||
|
* - instanceReady.ckeditor( editor, rootNode )
|
|||
|
* Triggered when new instance is ready.
|
|||
|
* - destroy.ckeditor( editor )
|
|||
|
* Triggered when instance is destroyed.
|
|||
|
* - getData.ckeditor( editor, eventData )
|
|||
|
* Triggered when getData event is fired inside editor. It can change returned data using eventData reference.
|
|||
|
* - setData.ckeditor( editor )
|
|||
|
* Triggered when getData event is fired inside editor.
|
|||
|
*
|
|||
|
* @example
|
|||
|
* <script src="jquery.js"></script>
|
|||
|
* <script src="ckeditor.js"></script>
|
|||
|
* <script src="adapters/jquery/adapter.js"></script>
|
|||
|
*/
|
|||
|
|
|||
|
(function()
|
|||
|
{
|
|||
|
/**
|
|||
|
* Allows CKEditor to override jQuery.fn.val(), making it possible to use the val()
|
|||
|
* function on textareas, as usual, having it synchronized with CKEditor.<br>
|
|||
|
* <br>
|
|||
|
* This configuration option is global and executed during the jQuery Adapter loading.
|
|||
|
* It can't be customized across editor instances.
|
|||
|
* @type Boolean
|
|||
|
* @example
|
|||
|
* <script>
|
|||
|
* CKEDITOR.config.jqueryOverrideVal = true;
|
|||
|
* </script>
|
|||
|
* <!-- Important: The JQuery adapter is loaded *after* setting jqueryOverrideVal -->
|
|||
|
* <script src="/ckeditor/adapters/jquery.js"></script>
|
|||
|
* @example
|
|||
|
* // ... then later in the code ...
|
|||
|
*
|
|||
|
* $( 'textarea' ).ckeditor();
|
|||
|
* // ...
|
|||
|
* $( 'textarea' ).val( 'New content' );
|
|||
|
*/
|
|||
|
CKEDITOR.config.jqueryOverrideVal = typeof CKEDITOR.config.jqueryOverrideVal == 'undefined'
|
|||
|
? true : CKEDITOR.config.jqueryOverrideVal;
|
|||
|
|
|||
|
var jQuery = window.jQuery;
|
|||
|
|
|||
|
if ( typeof jQuery == 'undefined' )
|
|||
|
return;
|
|||
|
|
|||
|
// jQuery object methods.
|
|||
|
jQuery.extend( jQuery.fn,
|
|||
|
/** @lends jQuery.fn */
|
|||
|
{
|
|||
|
/**
|
|||
|
* Return existing CKEditor instance for first matched element.
|
|||
|
* Allows to easily use internal API. Doesn't return jQuery object.
|
|||
|
*
|
|||
|
* Raised exception if editor doesn't exist or isn't ready yet.
|
|||
|
*
|
|||
|
* @name jQuery.ckeditorGet
|
|||
|
* @return CKEDITOR.editor
|
|||
|
* @see CKEDITOR.editor
|
|||
|
*/
|
|||
|
ckeditorGet: function()
|
|||
|
{
|
|||
|
var instance = this.eq( 0 ).data( 'ckeditorInstance' );
|
|||
|
if ( !instance )
|
|||
|
throw "CKEditor not yet initialized, use ckeditor() with callback.";
|
|||
|
return instance;
|
|||
|
},
|
|||
|
/**
|
|||
|
* Triggers creation of CKEditor in all matched elements (reduced to DIV, P and TEXTAREAs).
|
|||
|
* Binds callback to instanceReady event of all instances. If editor is already created, than
|
|||
|
* callback is fired right away.
|
|||
|
*
|
|||
|
* Mixed parameter order allowed.
|
|||
|
*
|
|||
|
* @param callback Function to be run on editor instance. Passed parameters: [ textarea ].
|
|||
|
* Callback is fiered in "this" scope being ckeditor instance and having source textarea as first param.
|
|||
|
*
|
|||
|
* @param config Configuration options for new instance(s) if not already created.
|
|||
|
* See URL
|
|||
|
*
|
|||
|
* @example
|
|||
|
* $( 'textarea' ).ckeditor( function( textarea ) {
|
|||
|
* $( textarea ).val( this.getData() )
|
|||
|
* } );
|
|||
|
*
|
|||
|
* @name jQuery.fn.ckeditor
|
|||
|
* @return jQuery.fn
|
|||
|
*/
|
|||
|
ckeditor: function( callback, config )
|
|||
|
{
|
|||
|
if ( !CKEDITOR.env.isCompatible )
|
|||
|
return this;
|
|||
|
|
|||
|
if ( !jQuery.isFunction( callback ))
|
|||
|
{
|
|||
|
var tmp = config;
|
|||
|
config = callback;
|
|||
|
callback = tmp;
|
|||
|
}
|
|||
|
config = config || {};
|
|||
|
|
|||
|
this.filter( 'textarea, div, p' ).each( function()
|
|||
|
{
|
|||
|
var $element = jQuery( this ),
|
|||
|
editor = $element.data( 'ckeditorInstance' ),
|
|||
|
instanceLock = $element.data( '_ckeditorInstanceLock' ),
|
|||
|
element = this;
|
|||
|
|
|||
|
if ( editor && !instanceLock )
|
|||
|
{
|
|||
|
if ( callback )
|
|||
|
callback.apply( editor, [ this ] );
|
|||
|
}
|
|||
|
else if ( !instanceLock )
|
|||
|
{
|
|||
|
// CREATE NEW INSTANCE
|
|||
|
|
|||
|
// Handle config.autoUpdateElement inside this plugin if desired.
|
|||
|
if ( config.autoUpdateElement
|
|||
|
|| ( typeof config.autoUpdateElement == 'undefined' && CKEDITOR.config.autoUpdateElement ) )
|
|||
|
{
|
|||
|
config.autoUpdateElementJquery = true;
|
|||
|
}
|
|||
|
|
|||
|
// Always disable config.autoUpdateElement.
|
|||
|
config.autoUpdateElement = false;
|
|||
|
$element.data( '_ckeditorInstanceLock', true );
|
|||
|
|
|||
|
// Set instance reference in element's data.
|
|||
|
editor = CKEDITOR.replace( element, config );
|
|||
|
$element.data( 'ckeditorInstance', editor );
|
|||
|
|
|||
|
// Register callback.
|
|||
|
editor.on( 'instanceReady', function( event )
|
|||
|
{
|
|||
|
var editor = event.editor;
|
|||
|
setTimeout( function()
|
|||
|
{
|
|||
|
// Delay bit more if editor is still not ready.
|
|||
|
if ( !editor.element )
|
|||
|
{
|
|||
|
setTimeout( arguments.callee, 100 );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Remove this listener.
|
|||
|
event.removeListener( 'instanceReady', this.callee );
|
|||
|
|
|||
|
// Forward setData on dataReady.
|
|||
|
editor.on( 'dataReady', function()
|
|||
|
{
|
|||
|
$element.trigger( 'setData' + '.ckeditor', [ editor ] );
|
|||
|
});
|
|||
|
|
|||
|
// Forward getData.
|
|||
|
editor.on( 'getData', function( event ) {
|
|||
|
$element.trigger( 'getData' + '.ckeditor', [ editor, event.data ] );
|
|||
|
}, 999 );
|
|||
|
|
|||
|
// Forward destroy event.
|
|||
|
editor.on( 'destroy', function()
|
|||
|
{
|
|||
|
$element.trigger( 'destroy.ckeditor', [ editor ] );
|
|||
|
});
|
|||
|
|
|||
|
// Integrate with form submit.
|
|||
|
if ( editor.config.autoUpdateElementJquery && $element.is( 'textarea' ) && $element.parents( 'form' ).length )
|
|||
|
{
|
|||
|
var onSubmit = function()
|
|||
|
{
|
|||
|
$element.ckeditor( function()
|
|||
|
{
|
|||
|
editor.updateElement();
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// Bind to submit event.
|
|||
|
$element.parents( 'form' ).submit( onSubmit );
|
|||
|
|
|||
|
// Bind to form-pre-serialize from jQuery Forms plugin.
|
|||
|
$element.parents( 'form' ).bind( 'form-pre-serialize', onSubmit );
|
|||
|
|
|||
|
// Unbind when editor destroyed.
|
|||
|
$element.bind( 'destroy.ckeditor', function()
|
|||
|
{
|
|||
|
$element.parents( 'form' ).unbind( 'submit', onSubmit );
|
|||
|
$element.parents( 'form' ).unbind( 'form-pre-serialize', onSubmit );
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
// Garbage collect on destroy.
|
|||
|
editor.on( 'destroy', function()
|
|||
|
{
|
|||
|
$element.data( 'ckeditorInstance', null );
|
|||
|
});
|
|||
|
|
|||
|
// Remove lock.
|
|||
|
$element.data( '_ckeditorInstanceLock', null );
|
|||
|
|
|||
|
// Fire instanceReady event.
|
|||
|
$element.trigger( 'instanceReady.ckeditor', [ editor ] );
|
|||
|
|
|||
|
// Run given (first) code.
|
|||
|
if ( callback )
|
|||
|
callback.apply( editor, [ element ] );
|
|||
|
}, 0 );
|
|||
|
}, null, null, 9999);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Editor is already during creation process, bind our code to the event.
|
|||
|
CKEDITOR.on( 'instanceReady', function( event )
|
|||
|
{
|
|||
|
var editor = event.editor;
|
|||
|
setTimeout( function()
|
|||
|
{
|
|||
|
// Delay bit more if editor is still not ready.
|
|||
|
if ( !editor.element )
|
|||
|
{
|
|||
|
setTimeout( arguments.callee, 100 );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( editor.element.$ == element )
|
|||
|
{
|
|||
|
// Run given code.
|
|||
|
if ( callback )
|
|||
|
callback.apply( editor, [ element ] );
|
|||
|
}
|
|||
|
}, 0 );
|
|||
|
}, null, null, 9999);
|
|||
|
}
|
|||
|
});
|
|||
|
return this;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// New val() method for objects.
|
|||
|
if ( CKEDITOR.config.jqueryOverrideVal )
|
|||
|
{
|
|||
|
jQuery.fn.val = CKEDITOR.tools.override( jQuery.fn.val, function( oldValMethod )
|
|||
|
{
|
|||
|
/**
|
|||
|
* CKEditor-aware val() method.
|
|||
|
*
|
|||
|
* Acts same as original jQuery val(), but for textareas which have CKEditor instances binded to them, method
|
|||
|
* returns editor's content. It also works for settings values.
|
|||
|
*
|
|||
|
* @param oldValMethod
|
|||
|
* @name jQuery.fn.val
|
|||
|
*/
|
|||
|
return function( newValue, forceNative )
|
|||
|
{
|
|||
|
var isSetter = typeof newValue != 'undefined',
|
|||
|
result;
|
|||
|
|
|||
|
this.each( function()
|
|||
|
{
|
|||
|
var $this = jQuery( this ),
|
|||
|
editor = $this.data( 'ckeditorInstance' );
|
|||
|
|
|||
|
if ( !forceNative && $this.is( 'textarea' ) && editor )
|
|||
|
{
|
|||
|
if ( isSetter )
|
|||
|
editor.setData( newValue );
|
|||
|
else
|
|||
|
{
|
|||
|
result = editor.getData();
|
|||
|
// break;
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ( isSetter )
|
|||
|
oldValMethod.call( $this, newValue );
|
|||
|
else
|
|||
|
{
|
|||
|
result = oldValMethod.call( $this );
|
|||
|
// break;
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
});
|
|||
|
return isSetter ? this : result;
|
|||
|
};
|
|||
|
});
|
|||
|
}
|
|||
|
})();
|