Index: /CKEditor/branches/tests/editor/plugins/jquery/jquery.html
===================================================================
--- /CKEditor/branches/tests/editor/plugins/jquery/jquery.html	(revision 4094)
+++ /CKEditor/branches/tests/editor/plugins/jquery/jquery.html	(revision 4094)
@@ -0,0 +1,430 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Plugin: jquery</title>
+	<script type="text/javascript" src="../../../cktester/cell.js"></script>
+	<script type="text/javascript">
+	//<![CDATA[
+
+// Load the required plugins and launch the runner.
+CKEDITOR.test.runner.defer = true;
+
+$( window ).bind( 'load', function()
+{
+	CKEDITOR.plugins.load( 'jquery' , function()
+	{
+		CKEDITOR.test.runner.run();
+	} );
+} );
+
+CKEDITOR.test.addTestCase( ( function()
+{
+	// Local references.
+	var assert = CKEDITOR.test.assert,
+		doc = CKEDITOR.document,
+		action = YAHOO.util.UserAction,
+		selector = YAHOO.util.Selector;
+
+	function cleanup( id )
+	{
+		var instance = jQuery( '#' + id ).ckeditorGet();
+		if ( instance )
+			instance.destroy();
+	}
+
+	// Maximum time per each test. If test will take longer, failure will be thrown.
+	var testTimeout = 10000;
+
+	jQuery( 'textarea, input' ).val( 'default' );
+
+	return {
+		test_create : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery( 'textarea#create' ).ckeditor( function( textarea )
+			{
+				var editor = this;
+				testSelf.resume( function()
+				{
+					assert.isTrue( editor instanceof CKEDITOR.editor, 'editor instanceof CKEDITOR.editor' );
+					testFinished = true;
+					cleanup( 'create' );
+				});
+			});
+			testSelf.wait( function() {
+				cleanup( 'create' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout + 5000);
+		},
+
+		test_config : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			CKEDITOR.config.test_config = false;
+			jQuery( 'textarea#config' ).ckeditor(
+				{ test_config: true },
+				function( textarea )
+				{
+					var editor = this;
+					testSelf.resume( function()
+					{
+						assert.isTrue( editor.config.test_config );
+						testFinished = true;
+						cleanup( 'config' );
+					});
+				}
+			);
+			testSelf.wait(function(){
+				cleanup( 'config' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_config_no_order : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			CKEDITOR.config.test_config_no_order = false;
+			jQuery('textarea#config_no_order').ckeditor(
+				function( textarea )
+				{
+					var editor = this;
+					testSelf.resume( function()
+					{
+						assert.isTrue( editor.config.test_config_no_order );
+						testFinished = true;
+						cleanup( 'config_no_order' );
+					});
+				},
+				{ test_config_no_order: true }
+			);
+			testSelf.wait(function(){
+				cleanup( 'config_no_order' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_config_global : function()
+		{
+			CKEDITOR.config.test_config_global = false;
+			$.ckeditorConfig( { test_config_global: true } );
+			assert.isTrue( CKEDITOR.config.test_config_global );
+		},
+
+		test_val_get_without_timeout : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery('textarea#val_get_without_timeout').ckeditor(function( textarea )
+			{
+				var editor = this;
+				editor.dataProcessor.writer._.rules = {};
+				testSelf.resume( function()
+				{
+					// editor.setData is async, which creates the test failure
+					editor.setData( 'foo bar' );
+					assert.areSame( '<p>foo bar</p>', jQuery( textarea ).val() );
+					testFinished = true;
+					cleanup( 'val_get_without_timeout' );
+				});
+			});
+			testSelf.wait( function() {
+				cleanup( 'val_get_without_timeout' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_val_get_with_timeout : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery('textarea#val_get_with_timeout').ckeditor(function( textarea )
+			{
+				var editor = this;
+				editor.dataProcessor.writer._.rules = {};
+				editor.setData( 'foo bar' );
+				setTimeout(function()
+				{
+					testSelf.resume( function()
+					{
+						assert.areSame( '<p>foo bar</p>', jQuery( textarea ).val() );
+						testFinished = true;
+						cleanup( 'val_get_with_timeout' );
+					});
+				}, 1000);
+			});
+			testSelf.wait( function() {
+				cleanup( 'val_get_with_timeout' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_val_set_with_timeout : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery('textarea#val_set_with_timeout').ckeditor(function( textarea )
+			{
+				var editor = this;
+				editor.dataProcessor.writer._.rules = {};
+				jQuery( textarea ).val( 'foo bar' );
+				setTimeout( function()
+				{
+					testSelf.resume( function()
+					{
+						assert.areSame( '<p>foo bar</p>', editor.getData() );
+						testFinished = true;
+						cleanup( 'val_set_with_timeout' );
+					});
+				}, 1000);
+			});
+			testSelf.wait( function() {
+				cleanup( 'val_set_with_timeout' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_ckeditor_get : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery('#ckeditor_get').ckeditor(function( textarea )
+			{
+				var editor = this;
+				editor.dataProcessor.writer._.rules = {};
+				editor.setData( 'foo bar' );
+				setTimeout(function()
+				{
+					testSelf.resume( function()
+					{
+						var editor = jQuery( textarea ).ckeditorGet();
+						assert.isObject( editor );
+						testFinished = true;
+						cleanup( 'ckeditor_get' );
+					});
+				// longer timeout may be needed
+				}, 1000);
+			});
+			testSelf.wait( function() {
+				cleanup( 'ckeditor_get' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_destroy : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery('textarea#destroy').ckeditor(function( textarea )
+			{
+				var editor = this;
+				try
+				{
+					editor.destroy();
+				}
+				catch (e){}
+				setTimeout(function()
+				{
+					testSelf.resume( function()
+					{
+							assert.isUndefined( CKEDITOR.instances.destroy );
+							testFinished = true;
+					});
+				}, 0);
+			});
+			testSelf.wait(function(){
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_val_input_get : function()
+		{
+			assert.areSame( 'default', jQuery( '#val_input_get' ).val() );
+		},
+
+		test_val_input_set : function()
+		{
+			jQuery( '#val_input_set' ).val( 'new' );
+			assert.areSame( 'new', jQuery('#val_input_set').get( 0 ).value );
+		},
+
+		test_submit : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			// Synchronize textarea content on form submit
+			jQuery( '#submit textarea' ).ckeditor(
+				{ jquerySyncTextareaOnSubmit: true },
+				function( textarea )
+				{
+					var editor = this;
+					editor.dataProcessor.writer._.rules = {};
+					editor.setData( 'foo bar' );
+					jQuery('#submit').submit( function()
+					{
+						testSelf.resume( function()
+						{
+							assert.areSame( '<p>foo bar</p>', editor.getData(), '1' );
+							assert.areSame( editor.getData(), jQuery( '#submit textarea' ).get( 0 ).value, '2' );
+							testFinished = true;
+							cleanup( 'submit_textarea' );
+						});
+						return false;
+					});
+					setTimeout(function()
+					{
+						jQuery( '#submit' ).submit();
+					}, 1000 );
+				}
+			);
+			testSelf.wait( function() {
+				cleanup( 'submit_textarea' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_ajax_submit : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery( '#ajax_submit textarea' ).ckeditor(
+				{ jquerySyncTextareaOnSubmit: true },
+				function( textarea )
+				{
+					var editor = this;
+					editor.dataProcessor.writer._.rules = {};
+					editor.setData( 'foo bar' );
+					jQuery('#ajax_submit').ajaxForm(
+					{
+						beforeSubmit: function( formData )
+						{
+							testSelf.resume( function()
+							{
+								assert.areSame( '<p>foo bar</p>', editor.getData(), '1' );
+								assert.areSame( editor.getData(), formData[ 0 ][ 'value' ], '2' );
+								testFinished = true;
+								cleanup( 'ajax_submit_textarea' );
+							});
+							return false;
+						}
+					});
+					setTimeout(function()
+					{
+						jQuery('#ajax_submit').submit();
+					}, 1000 );
+				});
+			testSelf.wait(function(){
+				cleanup( 'ajax_submit_textarea' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_global_event : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery( document ).bind( 'instanceReady.ckeditor', function( event, editor )
+			{
+				if ( !jQuery( event.target ).is( '#global_event' ) )
+					return;
+				jQuery( this ).unbind( 'instanceReady.ckeditor', arguments.callee );
+				testSelf.resume( function()
+				{
+					assert.isTrue( editor instanceof CKEDITOR.editor, 'editor instanceof CKEDITOR.editor' );
+					testFinished = true;
+					cleanup( 'global_event' );
+				});
+			});
+			jQuery( 'textarea#global_event' ).ckeditor();
+			testSelf.wait( function(){
+				cleanup( 'global_event' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout );
+		},
+
+		test_setData_event : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery( 'textarea#setData_event' )
+				.one( 'setData.ckeditor', function( event, editor, data )
+				{
+					testSelf.resume( function()
+					{
+//								console.log('test_setData_event', data, editor.getData());
+						assert.areSame( 'foo bar', data );
+						assert.isTrue( editor instanceof CKEDITOR.editor, 'editor instanceof CKEDITOR.editor' );
+						testFinished = true;
+						cleanup( 'setData_event' );
+					});
+				})
+				.ckeditor( function()
+				{
+					var editor = this;
+					// Delay it a bit.
+					setTimeout( function()
+					{
+						editor.setData('foo bar');
+					}, 300 );
+				});
+//					testSelf.wait();
+			testSelf.wait( function() {
+				cleanup( 'setData_event' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		test_div_replace : function()
+		{
+			var testSelf = this,
+				testFinished = false;
+			jQuery( '#div_replace' ).ckeditor( function() {
+				var editor = this;
+				testSelf.resume( function()
+				{
+					assert.isTrue( editor instanceof CKEDITOR.editor, 'editor instanceof CKEDITOR.editor' );
+					testFinished = true;
+					cleanup( 'div_replace' );
+				});
+			});
+			testSelf.wait( function() {
+				cleanup( 'div_replace' );
+				assert.isTrue( testFinished, 'Test not finished.' );
+			}, testTimeout);
+		},
+
+		name :document.title
+	};
+} )() );
+	</script>
+</head>
+<body>
+		<form>
+			<textarea rows="10" cols="30" id="create">default</textarea>
+			<textarea rows="10" cols="30" id="config">default</textarea>
+			<textarea rows="10" cols="30" id="config_no_order">default</textarea>
+			<textarea rows="10" cols="30" id="val_get_without_timeout">default</textarea>
+			<textarea rows="10" cols="30" id="val_get_with_timeout">default</textarea>
+			<textarea rows="10" cols="30" id="val_set_with_timeout">default</textarea>
+			<textarea rows="10" cols="30" id="ckeditor_get">default</textarea>
+			<textarea rows="10" cols="30" id="destroy">default</textarea>
+			<input id="val_input_get" value="default" />
+			<input id="val_input_set" value="default" />
+			<textarea rows="10" cols="30" id="global_event">default</textarea>
+			<textarea rows="10" cols="30" id="setData_event">default</textarea>
+		</form>
+		<form action="./" method="post" id="submit">
+			<textarea rows="10" cols="30" name="submit_textarea" id="submit_textarea">default</textarea>
+			<input type="submit" value="Submit" />
+		</form>
+		<form action="/" method="post" id="ajax_submit">
+			<textarea rows="10" cols="30" name="ajax_submit_textarea" id="ajax_submit_textarea">default</textarea>
+			<input type="submit" value="Submit" />
+		</form>
+		<div style="padding: 15px; background-color: lightblue;">
+			<div id="div_replace" style="width: 200px; height: 300px; background-color: black;">default</div>
+		</div>
+</body>
+</html>
Index: /CKEditor/branches/tests/editor/tt/3978/3978.html
===================================================================
--- /CKEditor/branches/tests/editor/tt/3978/3978.html	(revision 4094)
+++ /CKEditor/branches/tests/editor/tt/3978/3978.html	(revision 4094)
@@ -0,0 +1,43 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Ticket: #3978</title>
+	<script type="text/javascript" src="../../../cktester/cell.js"></script>
+	<script type="text/javascript">
+	//<![CDATA[
+
+CKEDITOR.test.addTestCase( ( function()
+	{
+
+		// Local references.
+		var assert = CKEDITOR.test.assert,
+			doc = CKEDITOR.document,
+			action = YAHOO.util.UserAction,
+			selector = YAHOO.util.Selector;
+
+		return	{
+
+			test_ticket_3978 : function()
+			{
+				var div = new CKEDITOR.dom.element( 'div' );
+				div.setStyle( 'float', 'left' );
+				assert.areSame( 'float', div.getAttribute( 'style' ).split( ':' )[ 0 ] );
+			},
+
+			name :document.title
+		};
+	} )() );
+	
+//]]>
+	</script>
+</head>
+<body>
+<textarea id="ticket_4048"><table>
+	<tbody>
+		<tr>
+			<td>table cell</td>
+		</tr>
+	</tbody>
+</table></textarea>
+</body>
+</html>
Index: /CKEditor/branches/tests/editor/tt/4048/4048.html
===================================================================
--- /CKEditor/branches/tests/editor/tt/4048/4048.html	(revision 4093)
+++ /CKEditor/branches/tests/editor/tt/4048/4048.html	(revision 4094)
@@ -110,5 +110,7 @@
 
 							// Show context menu.
-							editor.contextMenu.show( editor._.cke_contents.getChild( 0 ).getFrameDocument().getBody().getChild( [ 0, 0, 0, 0 ] ) );
+							editor.contextMenu.show(
+								editor._.cke_contents.getChild( 0 ).getFrameDocument().getBody().getChild( [ 0, 0, 0, 0 ] )
+							);
 
 							// Wait for context menu to show.
@@ -118,5 +120,5 @@
 								submenuEval = submenuEval.split( ';' )[ 0 ];
 
-								// Show cpontext submenu.
+								// Show context submenu.
 								eval( submenuEval );
 
@@ -125,5 +127,6 @@
 								{
 									// Get submenu background color.
-									var backgroundBefore = editor.contextMenu._.menu._.subMenu._.element.getChild( [ 0, 0, 0, 0 ] ).getComputedStyle( 'background-color' );
+									var backgroundBefore = editor.contextMenu._.menu._.subMenu._.element.getChild( [ 0, 0, 0, 0 ] )
+										.getComputedStyle( 'background-color' );
 
 									// Change UI color and give it some time to propagate.
@@ -134,7 +137,12 @@
 										{
 											// Get submenu background color (the new one).
-											var backgroundAfter = editor.contextMenu._.menu._.subMenu._.element.getChild( [ 0, 0, 0, 0 ] ).getComputedStyle( 'background-color' );
-											assert.areSame( 'rgb(255,255,255)', backgroundBefore.toLowerCase().replace( / /g, '' ), 'Before UI color change' );
-											assert.areSame( 'rgb(0,0,0)', backgroundAfter.toLowerCase().replace( / /g, '' ), 'After UI color change' );
+											var backgroundAfter = editor.contextMenu._.menu._.subMenu._.element.getChild( [ 0, 0, 0, 0 ] )
+												.getComputedStyle( 'background-color' );
+											
+											assert.areSame( 'rgb(255,255,255)', backgroundBefore.toLowerCase().replace( / /g, '' ),
+												'Before UI color change' );
+
+											assert.areSame( 'rgb(0,0,0)', backgroundAfter.toLowerCase().replace( / /g, '' ),
+												'After UI color change' );
 										});
 									}, 200);
@@ -145,9 +153,4 @@
 					assert.isTrue( false, "Timed out." );
 				}, 8000);
-			},
-
-			test_alwaysTrue : function()
-			{
-				assert.isTrue( true );
 			},
 
Index: /CKEditor/branches/tests/editor/tt/4219/4219.html
===================================================================
--- /CKEditor/branches/tests/editor/tt/4219/4219.html	(revision 4094)
+++ /CKEditor/branches/tests/editor/tt/4219/4219.html	(revision 4094)
@@ -0,0 +1,104 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Ticket: #4219</title>
+	<script type="text/javascript" src="../../../cktester/cell.js"></script>
+	<script type="text/javascript">
+	//<![CDATA[
+/**
+ * Load the editor and wait for fully interactable.
+ * @param {Object} elementId
+ * @parma {Object} mode
+ * @param {Object} config
+ * @param {Object} callback Continuation with {@param editor}.
+ * @param {Object} context
+ */
+function prepareEditor( elementId, mode, config, callback, context )
+{
+	CKEDITOR.on( 'instanceReady',
+		function( evt )
+		{
+			var isMe = mode == CKEDITOR.ELEMENT_MODE_REPLACE ?
+				evt.editor.name == elementId
+				: evt.editor.element.$ ==
+					document.getElementById( elementId );
+			if ( isMe )
+			{
+				var editor = evt.editor;
+				// Force result data unformatted.
+				editor.dataProcessor.writer._.rules = {};
+				callback.call( context, editor );
+			}
+		}, this );
+
+	mode = mode || CKEDITOR.ELEMENT_MODE_REPLACE;
+	switch( mode )
+	{
+		case CKEDITOR.ELEMENT_MODE_REPLACE :
+			CKEDITOR.replace( elementId, config );
+			break;
+		case CKEDITOR.ELEMENT_MODE_APPENDTO :
+			CKEDITOR.appendTo( elementId, config );
+			break;
+	}
+}
+
+/**
+ * IE always returning CRLF for line-feed, so remove it when retrieving
+ * pre-formated text from text area.
+ */
+function getTextAreaValue( id )
+{
+	return CKEDITOR.document.getById( id ).getValue().replace( /\r/gi, '' );
+}
+
+CKEDITOR.test.addTestCase( ( function()
+	{
+
+		// Local references.
+		var assert = CKEDITOR.test.assert,
+			doc = CKEDITOR.document,
+			action = YAHOO.util.UserAction,
+			selector = YAHOO.util.Selector;
+
+		return	{
+
+			test_ticket_4219_1 : function()
+			{
+				prepareEditor( 'ticket_4219_1', null,
+					{ language : 'en-ie' },
+					function( editor )
+					{
+						this.resume( function()
+						{
+							assert.areSame( 'en', editor.langCode );
+						} );
+					}, this );
+				this.wait();
+			},
+
+			test_ticket_4219_2 : function()
+			{
+				prepareEditor( 'ticket_4219_2', null,
+					{ language : 'unsupported' },
+					function( editor )
+					{
+						this.resume( function()
+						{
+							assert.areSame( editor.config.defaultLanguage, editor.langCode );
+						} );
+					}, this );
+				this.wait();
+			},
+
+			name :document.title
+		};
+	} )() );
+	//]]>
+	</script>
+</head>
+<body>
+<textarea id="ticket_4219_1"></textarea>
+<textarea id="ticket_4219_2"></textarea>
+</body>
+</html>
Index: /CKEditor/branches/tests/profile.js
===================================================================
--- /CKEditor/branches/tests/profile.js	(revision 4093)
+++ /CKEditor/branches/tests/profile.js	(revision 4094)
@@ -30,5 +30,8 @@
 			[ '../editor/plugins/styles/styles', [  'unit', 'stable' ] ],
 			[ '../editor/plugins/selection/selection', [  'unit', 'stable' ] ],
- 			[ '../editor/tt/4048/4048', [  'unit', 'all', 'kama' ] ]
+ 			[ '../editor/plugins/jquery/jquery', [  'unit', 'stable', 'jquery', 'jquery-form' ] ],
+ 			[ '../editor/tt/4048/4048', [  'unit', 'all', 'kama' ] ],
+ 			[ '../editor/tt/4219/4219', [  'unit', 'all' ] ],
+ 			[ '../editor/tt/3978/3978', [  'unit', 'all', 'core-dom-element' ] ]
 		],
 
@@ -54,4 +57,10 @@
 				if ( tags.indexOf( 'unit' ) != -1  )
 					env.push( '${CKEDITOR_ROOT}/_source/core/test.js' );
+
+				if ( tags.indexOf( 'jquery' ) != -1  )
+					env.push( 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js' );
+
+				if ( tags.indexOf( 'jquery-form' ) != -1  )
+					env.push( 'http://malsup.com/jquery/form/jquery.form.js' );
 			}
 		]
