Index: CKEditor/branches/versions/3.5.x/CHANGES.html
===================================================================
--- CKEditor/branches/versions/3.5.x/CHANGES.html	(revision 6050)
+++ CKEditor/branches/versions/3.5.x/CHANGES.html	(revision 6051)
@@ -43,4 +43,5 @@
 		<li><a href="http://dev.ckeditor.com/ticket/4648">#4648</a> : Added the new Iframe plugin.</li>
 		<li><a href="http://dev.ckeditor.com/ticket/6010">#6010</a> : The "automatic" option of the font/background color panel now represents the real color.</li>
+		<li><a href="http://dev.ckeditor.com/ticket/5654">#5654</a> : Added the new placeholder plugin.</li>
 	</ul>
 	<p>
Index: CKEditor/branches/versions/3.5.x/_samples/index.html
===================================================================
--- CKEditor/branches/versions/3.5.x/_samples/index.html	(revision 6050)
+++ CKEditor/branches/versions/3.5.x/_samples/index.html	(revision 6051)
@@ -44,4 +44,5 @@
 		<li><a href="output_for_flash.html">Output for Flash</a></li>
 		<li><a href="autogrow.html">AutoGrow plugin</a></li>
+		<li><a href="placeholder.html">Placeholder plugin</a></li>
 	</ul>
 	<div id="footer">
Index: CKEditor/branches/versions/3.5.x/_samples/placeholder.html
===================================================================
--- CKEditor/branches/versions/3.5.x/_samples/placeholder.html	(revision 6051)
+++ CKEditor/branches/versions/3.5.x/_samples/placeholder.html	(revision 6051)
@@ -0,0 +1,66 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2010, 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>Placeholder Plugin - CKEditor Sample</title>
+	<meta content="text/html; charset=utf-8" http-equiv="content-type" />
+	<!-- CKReleaser %REMOVE_LINE%
+	<script type="text/javascript" src="../ckeditor.js"></script>
+	CKReleaser %REMOVE_START% -->
+	<script type="text/javascript" src="../ckeditor_source.js"></script>
+	<!-- CKReleaser %REMOVE_END% -->
+	<script src="sample.js" type="text/javascript"></script>
+	<link href="sample.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+	<h1>
+		CKEditor Sample
+	</h1>
+	<!-- This <div> holds alert messages to be display in the sample page. -->
+	<div id="alerts">
+		<noscript>
+			<p>
+				<strong>CKEditor requires JavaScript to run</strong>. In a browser with no JavaScript
+				support, like yours, you should still see the contents (HTML data) and you should
+				be able to edit it normally, without a rich editor interface.
+			</p>
+		</noscript>
+	</div>
+	<form action="sample_posteddata.php" method="post">
+		<p>
+			In this sample the Placeholder plugin is available.<br />
+			It replaces text in the format of <code>[[text]]</code> to uneditable sections, and lets the user edit them and create new ones using a dialog.</p>
+		<p>
+			<label for="editor1">
+				With default configuration:</label><br />
+			<textarea cols="80" id="editor1" name="editor1" rows="10">&lt;p&gt;This is a [[sample placeholder]]. You are using &lt;a href="http://ckeditor.com/"&gt;CKEditor&lt;/a&gt;. &lt;/p&gt;</textarea>
+			<script type="text/javascript">
+			//<![CDATA[
+
+				CKEDITOR.replace( 'editor1', {
+					extraPlugins : 'placeholder',
+					toolbar : [ [ 'Source', 'CreatePlaceholder' ] ]
+				});
+
+			//]]>
+			</script>
+		</p>
+		<p>
+			<input type="submit" value="Submit" />
+		</p>
+	</form>
+	<div id="footer">
+		<hr />
+		<p>
+			CKEditor - The text editor for Internet - <a href="http://ckeditor.com/">http://ckeditor.com</a>
+		</p>
+		<p id="copy">
+			Copyright &copy; 2003-2010, <a href="http://cksource.com/">CKSource</a> - Frederico
+			Knabben. All rights reserved.
+		</p>
+	</div>
+</body>
+</html>
Index: CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/dialogs/placeholder.js
===================================================================
--- CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/dialogs/placeholder.js	(revision 6051)
+++ CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/dialogs/placeholder.js	(revision 6051)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.html or http://ckeditor.com/license
+ */
+
+(function()
+{
+	function placeholderDialog( editor, isEdit )
+	{
+
+		var lang = editor.lang.placeholder,
+			generalLabel = editor.lang.common.generalTab;
+		return {
+			title : lang.title,
+			minWidth : 300,
+			minHeight : 80,
+			contents :
+			[
+				{
+					id : 'info',
+					label : generalLabel,
+					title : generalLabel,
+					elements :
+					[
+						{
+							id : 'text',
+							type : 'text',
+							style : 'width: 100%;',
+							label : lang.text,
+							'default' : '',
+							required : true,
+							validate : CKEDITOR.dialog.validate.notEmpty( lang.textMissing ),
+							setup : function( element )
+							{
+								if ( isEdit )
+									this.setValue( element.getText().slice( 2, -2 ) );
+							},
+							commit : function( element )
+							{
+								var text = '[[' + this.getValue() + ']]';
+								// The placeholder must be recreated.
+								CKEDITOR.plugins.placeholder.createPlaceholder( editor, element, text );
+							}
+						}
+					]
+				}
+			],
+			onShow : function()
+			{
+				if ( isEdit )
+				{
+					var range = editor.getSelection().getRanges()[0];
+					range.shrink( CKEDITOR.SHRINK_TEXT );
+					var node = range.startContainer;
+					while( node && !( node.type == CKEDITOR.NODE_ELEMENT && node.hasAttributes( '_cke_placeholder' ) ) )
+						node = node.getParent();
+					this._element = node;
+				}
+
+				this.setupContent( this._element );
+			},
+			onOk : function()
+			{
+				this.commitContent( this._element );
+				delete this._element;
+			}
+		};
+	}
+
+	CKEDITOR.dialog.add( 'createplaceholder', function( editor )
+		{
+			return placeholderDialog( editor );
+		});
+	CKEDITOR.dialog.add( 'editplaceholder', function( editor )
+		{
+			return placeholderDialog( editor, 1 );
+		});
+} )();
Index: CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/lang/en.js
===================================================================
--- CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/lang/en.js	(revision 6051)
+++ CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/lang/en.js	(revision 6051)
@@ -0,0 +1,16 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+CKEDITOR.plugins.setLang( 'placeholder', 'en',
+{
+	placeholder :
+	{
+		title		: 'Placeholder Properties',
+		toolbar		: 'Create Placeholder',
+		text		: 'Placeholder Text',
+		edit		: 'Edit Placeholder',
+		textMissing	: 'The placeholder must contain text.'
+	}
+});
Index: CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/plugin.js
===================================================================
--- CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/plugin.js	(revision 6051)
+++ CKEditor/branches/versions/3.5.x/_source/plugins/placeholder/plugin.js	(revision 6051)
@@ -0,0 +1,160 @@
+/*
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @fileOverview The "placeholder" plugin.
+ *
+ */
+
+(function()
+{
+	var placeholderReplaceRegex = /\[\[[^\]]+\]\]/g;
+	CKEDITOR.plugins.add( 'placeholder',
+	{
+		requires : [ 'dialog' ],
+		lang : [ 'en' ],
+		init : function( editor )
+		{
+			var lang = editor.lang.placeholder;
+
+			editor.addCommand( 'createplaceholder', new CKEDITOR.dialogCommand( 'createplaceholder' ) );
+			editor.addCommand( 'editplaceholder', new CKEDITOR.dialogCommand( 'editplaceholder' ) );
+
+			editor.ui.addButton( 'CreatePlaceholder',
+			{
+				label : lang.toolbar,
+				command :'createplaceholder',
+				icon : this.path + 'placeholder.gif'
+			});
+
+			if ( editor.addMenuItems )
+			{
+				editor.addMenuGroup( 'placeholder', 20 );
+				editor.addMenuItems(
+					{
+						editplaceholder :
+						{
+							label : lang.edit,
+							command : 'editplaceholder',
+							group : 'placeholder',
+							order : 1,
+							icon : this.path + 'placeholder.gif'
+						}
+					} );
+
+				if ( editor.contextMenu )
+				{
+					editor.contextMenu.addListener( function( element, selection )
+						{
+							if ( !element || !element.hasAttribute( '_cke_placeholder' ) )
+								return null;
+
+							return { editplaceholder : CKEDITOR.TRISTATE_OFF };
+						} );
+				}
+			}
+
+			editor.on( 'doubleclick', function( evt )
+				{
+					var element = evt.data.element;
+					if ( element.hasAttribute( '_cke_placeholder' ) )
+						evt.data.dialog = 'editplaceholder';
+				});
+
+			editor.addCss(
+				'.cke_placeholder' + 
+				'{' + 
+					'background-color: #ffff00;' + 
+					( CKEDITOR.env.gecko ? 'cursor: default;' : '' ) +
+				'}'
+			);
+
+			editor.on( 'contentDom', function()
+				{
+					editor.document.getBody().on( 'resizestart', function( evt )
+						{
+							if ( editor.getSelection().getSelectedElement().hasAttribute( '_cke_placeholder' ) )
+								evt.data.preventDefault();
+						});
+				});
+
+			CKEDITOR.dialog.add( 'createplaceholder', this.path + 'dialogs/placeholder.js' );
+			CKEDITOR.dialog.add( 'editplaceholder', this.path + 'dialogs/placeholder.js' );
+		},
+		afterInit : function( editor )
+		{
+			var dataProcessor = editor.dataProcessor,
+				dataFilter = dataProcessor && dataProcessor.dataFilter;
+				htmlFilter = dataProcessor && dataProcessor.htmlFilter;
+
+			if ( dataFilter )
+			{
+				dataFilter.addRules(
+				{
+					text : function( text )
+					{
+						return text.replace( placeholderReplaceRegex, function( match )
+							{
+								return CKEDITOR.plugins.placeholder.createPlaceholder( editor, null, match, 1 );
+							});
+					}
+				});
+			}
+
+			if ( htmlFilter )
+			{
+				htmlFilter.addRules(
+				{
+					elements :
+					{
+						'span' : function( element )
+						{
+							if ( element.attributes && element.attributes._cke_placeholder )
+								delete element.name;
+						}
+					}
+				});
+			}
+		}
+	});
+})();
+
+CKEDITOR.plugins.placeholder = 
+{
+	createPlaceholder : function( editor, oldElement, text, isGet )
+	{
+		var element = new CKEDITOR.dom.element( 'span', editor.document );
+		element.setAttributes(
+			{
+				contentEditable	: 'false',
+				_cke_placeholder	: 1,
+				'class'		: 'cke_placeholder'
+			}
+		);
+
+		text && element.setText( text );
+
+		if ( isGet )
+			return element.getOuterHtml();
+
+		if ( oldElement )
+		{
+			if ( CKEDITOR.env.ie )
+			{
+				element.insertAfter( oldElement );
+				// Some time is required for IE before the element is removed.
+				setTimeout( function()
+					{
+						oldElement.remove();
+						element.focus();
+					}, 10 );
+			}
+			else
+				element.replace( oldElement );
+		}
+		else
+			editor.insertElement( element );
+	}
+};
