Index: /CKEditor/branches/versions/3.1.x/CHANGES.html
===================================================================
--- /CKEditor/branches/versions/3.1.x/CHANGES.html	(revision 4622)
+++ /CKEditor/branches/versions/3.1.x/CHANGES.html	(revision 4623)
@@ -48,4 +48,5 @@
 		<li><a href="http://dev.fckeditor.net/ticket/4574">#4574</a> : Added the table merging tools and corresponding context menu options.</li>
 		<li><a href="http://dev.fckeditor.net/ticket/4340">#4340</a> : Added the email protection option for link dialog.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4210">#4210</a> : Added CKEditor plugin for jQuery.</li>
 	</ul>
 	<p>
Index: /CKEditor/branches/versions/3.1.x/_samples/index.html
===================================================================
--- /CKEditor/branches/versions/3.1.x/_samples/index.html	(revision 4622)
+++ /CKEditor/branches/versions/3.1.x/_samples/index.html	(revision 4623)
@@ -37,4 +37,5 @@
 		<li><a href="api_dialog.html">Using the JavaScript API to customize dialogs</a></li>
 		<li><a href="enterkey.html">Using the "Enter" key in CKEditor</a></li>
+		<li><a href="jqueryadapter.html">jQuery adapter example</a></li>
 	</ul>
 	<div id="footer">
Index: /CKEditor/branches/versions/3.1.x/_samples/jqueryadapter.html
===================================================================
--- /CKEditor/branches/versions/3.1.x/_samples/jqueryadapter.html	(revision 4623)
+++ /CKEditor/branches/versions/3.1.x/_samples/jqueryadapter.html	(revision 4623)
@@ -0,0 +1,68 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>jQuery adapter - CKEditor Sample</title>
+	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
+<!-- CKReleaser %REMOVE_LINE%
+	<script type="text/javascript" src="../ckeditor.js"></script>
+	<script type="text/javascript" src="../adapters/jquery.js"></script>
+CKReleaser %REMOVE_START% -->
+	<script type="text/javascript" src="../ckeditor_source.js"></script>
+	<script type="text/javascript" src="../_source/adapters/jquery.js"></script>
+<!-- CKReleaser %REMOVE_END% -->
+	<script type="text/javascript">
+		$( function()
+		{
+			var config = {
+				toolbar :
+				[
+					[ 'Bold', 'Italic', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink' ],
+					[ 'UIColor' ]
+				]
+			};
+
+			// Initialize the editor.
+			// Callback function can be passed and executed after full instance creation.
+			$( '.jquery_ckeditor' ).ckeditor( config );
+		} );
+	</script>
+</head>
+<body>
+	<div id="html">
+		<form action="sample_posteddata.php" method="post">
+			<p>
+				<label for="editor1">
+					Editor 1:</label><br />
+				<textarea id="editor1" name="editor1" class="jquery_ckeditor" rows="10" cols="80">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://www.fckeditor.net/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;</textarea>
+			</p>
+			<p>
+				<input type="submit" value="Submit" />
+			</p>
+		</form>
+	</div>
+	<div id="code">
+		<pre>
+&lt;script type=&quot;text/javascript&quot;&gt;
+	$( function()
+	{
+		$( '.jquery_ckeditor' ).<b>ckeditor()</b>;
+	} );
+&lt;/script&gt;
+		</pre>
+		<pre>
+&lt;form action=""&gt;
+  &lt;p&gt;
+    &lt;label for="editor1"&gt;
+      Editor 1:&lt;/label&gt;&lt;br /&gt;
+    &lt;textarea id="editor1" name="editor1" <b>class="jquery_ckeditor"</b> rows="10" cols="80"&gt;&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://www.fckeditor.net/"&gt;CKEditor&lt;/a&gt;.&lt;/p&gt;&lt;/textarea&gt;
+  &lt;/p&gt;
+  &lt;p&gt;
+&lt;/form&gt;
+</pre>
+	</div>
+</body>
+</html>
Index: /CKEditor/branches/versions/3.1.x/_source/adapters/jquery.js
===================================================================
--- /CKEditor/branches/versions/3.1.x/_source/adapters/jquery.js	(revision 4623)
+++ /CKEditor/branches/versions/3.1.x/_source/adapters/jquery.js	(revision 4623)
@@ -0,0 +1,283 @@
+/*
+Copyright (c) 2003-2009, 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()
+{
+	/**
+	 * Allow CKEditor to override jQuery.fn.val(). This results in ability to use val()
+	 * function on textareas as usual and having those calls synchronized with CKEditor
+	 * Rich Text Editor component.
+	 *
+	 * This config option is global and executed during plugin load.
+	 * Can't be customized across editor instances.
+	 *
+	 * @type Boolean
+	 * @example
+	 * $( 'textarea' ).ckeditor();
+	 * // ...
+	 * $( 'textarea' ).val( 'New content' );
+	 */
+	CKEDITOR.config.jqueryOverrideVal = typeof CKEDITOR.config.jqueryOverrideVal == 'undefined'
+		? true : CKEDITOR.config.jqueryOverrideVal;
+
+	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 ( !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 )
+								return setTimeout( arguments.callee, 100 );
+
+							// 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 );
+
+								// Unbind when editor destroyed.
+								$element.bind( 'destroy.ckeditor', function()
+								{
+									$element.parents( 'form' ).unbind( 'submit', 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 )
+								return setTimeout( arguments.callee, 100 );
+
+							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 isSetter ? this : result;
+			};
+		});
+	}
+})();
