From c4fd44822319a9e70806334d31097e615ebcccf4 Mon Sep 17 00:00:00 2001
From: juanf <juanf>
Date: Mon, 30 Jan 2017 13:41:49 +0000
Subject: [PATCH] SSDM-4687 : Placeholders on rich text editor

SVN: 37642
---
 .../eln-lims/html/lib/ckeditor/js/config.js   |   1 +
 .../js/plugins/confighelper/docs/install.html | 124 ++++++
 .../js/plugins/confighelper/docs/styles.css   |  59 +++
 .../js/plugins/confighelper/plugin.js         | 389 ++++++++++++++++++
 4 files changed, 573 insertions(+)
 create mode 100644 openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/install.html
 create mode 100644 openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/styles.css
 create mode 100644 openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/plugin.js

diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/config.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/config.js
index cf6eb0ea1a5..073b69f0a8f 100644
--- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/config.js
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/config.js
@@ -7,6 +7,7 @@ CKEDITOR.editorConfig = function( config ) {
 	// Define changes to default configuration here. For example:
 	// config.language = 'fr';
 	// config.uiColor = '#AADC6E';
+	config.extraPlugins='confighelper';
 	config.stylesSet = false;
 	config.toolbarGroups = [
 	    					{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/install.html b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/install.html
new file mode 100644
index 00000000000..7b229535e1b
--- /dev/null
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/install.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>Configuration Helper plugin</title>
+<link href="styles.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h1>Configuration Helper Plugin for CKEditor</h1>
+
+<h2>Introduction</h2>
+<p>This plugin tries to help setup <a href="http://www.ckeditor.com">CKEditor</a> by providing additional configuration options to perform some
+kind of common tasks.</p>
+<p>Currently if offers a "removeDialogFields" that allows to remove individual fields in the dialogs (versus removing whole tabs with
+<a href="http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html#.removeDialogTabs">removeDialogTabs</a>, and "dialogFieldsDefaultValues"
+defines default values for dialog fields.</p>
+
+<h3 id="contact">Author:</h3>
+<p><a href="mailto:amla70@gmail.com">Alfonso Mart&iacute;nez de Lizarrondo</a></p>
+
+<h3>Version history: </h3>
+<ol>
+  <li>1.0: 26-February-2012. First version.</li>
+  <li>1.1: 16-February-2012. Added placeholder.</li>
+  <li>1.2: 23-April-2012. Added hideDialogFields.</li>
+  <li>1.3: 1-December-2012. Compatibility with CKEditor 4.</li>
+  <li>1.4: 28-March-2013. Compatibility of the "placeholder" attribute with the inline mode of CKEditor 4.</li>
+  <li>1.5: 16-April-2013. Version 1.4 was broken in CKEditor 3.</li>
+  <li>1.6: 16-August-2013. Handle the setData method to update the "placeholder" status</li>
+  <li>1.7: 6-October-2013. <a href="https://github.com/AlfonsoML/confighelper/pull/2">Patch by bfavors</a> to fix handling placeholder on initial load of editor</li>
+  <li>1.8: 9-March-2014. <a href="http://ckeditor.com/comment/reply/128664/130294">Check for IE11 by Russel Ward</a><br>
+		Set caret into the empty paragraph correctly on first focus, <a href="https://github.com/AlfonsoML/confighelper/pull/5">patch by glanchow</a>
+	</li>
+  <li>1.8.1: 5-April-2014. <a href="https://github.com/AlfonsoML/confighelper/issues/6">Fix IE8 & IE9 problem with "inline textarea" if it's empty on start</a>
+	</li>
+  <li>1.8.2: 12-April-2014. <a href="https://github.com/AlfonsoML/confighelper/pull/8">Protect detection of empty content</a>. Thanks to tanihito.
+	</li>
+  <li>1.8.3: 30-November-2014. Force SCAYT to use the language that it's specified as the language for the contents.<br>
+			<a href="https://github.com/AlfonsoML/confighelper/pull/13">Listen to the contentDom event to avoid problems when calling setData in WYSIWYG mode</a>. Thanks to noam-si.
+	</li>
+</ol>
+
+<h2>Installation</h2>
+<h3>1. Copying the files</h3>
+<p>Extract the contents of the zip in you plugins directory, so it ends up like
+    this<br>
+    <!--<img src="installation.png" alt="Screenshot of installation" width="311" height="346" longdesc="#install">-->
+    </p>
+<pre id="--install">
+ckeditor\
+	...
+	images\
+	lang\
+	plugins\
+		...
+		confighelper\
+			plugin.js
+			docs\
+				install.html
+		...
+	skins\
+	themes\
+</pre>
+<h3>2. Adding it to CKEditor</h3>
+<p>Now add the plugin in your <em>config.js</em> or custom js configuration
+file:
+<code>config.extraPlugins='confighelper'; </code>
+</p>
+
+<h3>3. Configuration</h3>
+<h4>config.removeDialogFields</h4>
+<p>This entry is a string, the fields are defined as dialogName + ":" + tab + ":" + field. Fields are joined with semicolons.
+In order to learn the name of the parameters you can use the "Developer Tools plugin", launch that sample and open the dialog that you want to customize.
+Now a little popup with appear showing the info about that field, for example:
+<pre><u>Element Information</u>
+Dialog window name : image
+Tab name : info
+Element ID : txtBorder
+Element type : text
+</pre>
+so in order to remove the class attribute for images the config is:
+<pre>config.removeDialogFields="image:info:txtBorder";</pre>
+removing another field
+<pre>config.removeDialogFields="image:info:txtBorder;image:info:txtHSpace";</pre>
+
+<h4>config.dialogFieldsDefaultValues</h4>
+<p>This setting uses directly a JSON object as the configuration value, first an object that has the dialog names as properties, each property is
+a new object with the name of the tabs and finally each property name maps to the field name and it's value is the default value to use for the field.</p>
+<p>An example might be much better as I might have messed up something in the description:</p>
+<pre>config.dialogFieldsDefaultValues =
+{
+	image:
+		{
+			advanced:
+				{
+					txtGenClass : 'myClass',
+					txtGenTitle : 'Image title'
+				}
+		}
+};
+</pre>
+
+<h4>config.placeholder</h4>
+<p>This a text that will be shown when the editor is empty following the HTML5 placeholder attribute. When the user focus the editor, the content is
+cleared automatically.</p>
+<p>The value can be set in the configuration or as an attribute of the replaced element</p>
+<pre>config.placeholder = 'Type here...';</pre>
+
+<h4>config.hideDialogFields</h4>
+<p>This entry uses the same sintax that the 'removeDialogFields' option. The difference is that some fields can't be removed easily as other parts of the dialog
+might not be ready and might try to always use it, generating a javascript error. In other cases the layout might be broken if the field is removed instead of hidden.<br>
+In those cases it's possible to hide the fields using this entry, and the preview in the image dialog is an example of such a field.</p>
+<pre>config.hideDialogFields="image:info:htmlPreview";</pre>
+
+<!--
+<h2>Final notes</h2>
+-->
+
+<h2>Disclaimers</h2>
+<p>CKEditor is  &copy; CKSource.com</p>
+</body>
+</html>
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/styles.css b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/styles.css
new file mode 100644
index 00000000000..58ae80a0d67
--- /dev/null
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/docs/styles.css
@@ -0,0 +1,59 @@
+body {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 90%;
+}
+h1 {
+	text-align:center;
+	font-size:180%;
+}
+h2 {
+	border-bottom:2px solid #CCC;
+	margin:1em 0 0.4em 0;
+}
+h3 {
+	margin-bottom:0.4em;
+}
+p {
+	margin:0 0 1em 1em;
+	text-align:justify;
+}
+ol {
+	margin:0 0 1.2em 1em;
+	padding:0;
+	list-style-type:none;
+}
+ol li {
+	margin:0.2em 0;
+}
+pre, code {
+	font-size:100%;
+	font-family:"Courier New", Courier, mono;
+	background-color: #CCCCCC;
+	border:1px solid #999;
+	padding:0.2em 1em;
+	margin: 0.4em 0;
+	display:block;
+	white-space: pre;
+	overflow: auto;
+}
+form {
+	margin:0 0 0 1em;
+}
+span.key {
+	color: #006600;
+}
+#install {
+	display:none
+}
+#languages ul {
+	display:inline;
+	list-style-type:none;
+	margin:0;
+	padding:0;
+}
+#languages li {
+	display:inline;
+	margin:0;
+	padding:0;
+	vertical-align:bottom;
+}
\ No newline at end of file
diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/plugin.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/plugin.js
new file mode 100644
index 00000000000..37d2d70e347
--- /dev/null
+++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/lib/ckeditor/js/plugins/confighelper/plugin.js
@@ -0,0 +1,389 @@
+/**
+ * @file Configuration helper plugin for CKEditor
+ * Copyright (C) 2012 Alfonso Martínez de Lizarrondo
+ *
+ */
+(function() {
+"use strict";
+
+// Check if the browser supports the placeholder attribute on textareas natively.
+var supportsPlaceholder = ('placeholder' in document.createElement( 'textarea' ) );
+
+// If the data is "empty" (BR, P) or the placeholder then return an empty string.
+// Otherwise return the original data
+function dataIsEmpty( data )
+{
+	if ( !data)
+		return true;
+
+	if ( data.length > 20 )
+		return false;
+
+	var value = data.replace( /[\n|\t]*/g, '' ).toLowerCase();
+	if ( !value || value == '<br>' || value == '<p>&nbsp;<br></p>' || value == '<p><br></p>' || value == '<p>&nbsp;</p>' || value == '&nbsp;' || value == ' ' || value == '&nbsp;<br>' || value == ' <br>' )
+		return true;
+
+	return false;
+}
+
+function addPlaceholder(ev) {
+	var editor = ev.editor;
+	var root = (editor.editable ? editor.editable() : (editor.mode == 'wysiwyg' ? editor.document && editor.document.getBody() : editor.textarea  ) );
+	var placeholder = ev.listenerData;
+	if (!root)
+		return;
+
+	if (editor.mode == 'wysiwyg')
+	{
+		// If the blur is due to a dialog, don't apply the placeholder
+		if ( CKEDITOR.dialog._.currentTop )
+			return;
+
+		if ( !root )
+			return;
+
+		if ( dataIsEmpty( root.getHtml() ) )
+		{
+			root.setHtml( placeholder );
+			root.addClass( 'placeholder' );
+		}
+	}
+
+	if (editor.mode == 'source')
+	{
+		if ( supportsPlaceholder )
+		{
+			if (ev.name=='mode')
+			{
+				root.setAttribute( 'placeholder', placeholder );
+			}
+			return;
+		}
+
+		if ( dataIsEmpty( root.getValue() ) )
+		{
+			root.setValue( placeholder );
+			root.addClass( 'placeholder' );
+		}
+	}
+}
+
+function removePlaceholder(ev) {
+	var editor = ev.editor;
+	var root = (editor.editable ? editor.editable() : (editor.mode == 'wysiwyg' ? editor.document && editor.document.getBody() : editor.textarea  ) );
+	if (!root)
+		return;
+
+	if (editor.mode == 'wysiwyg' )
+	{
+		if (!root.hasClass( 'placeholder' ))
+			return;
+
+		root.removeClass( 'placeholder' );
+		// fill it properly
+		if (CKEDITOR.dtd[ root.getName() ]['p'])
+		{
+			root.setHtml( '<p><br/></p>' );
+			// Set caret in position
+			var range = new CKEDITOR.dom.range(editor.document);
+			range.moveToElementEditablePosition(root.getFirst(), true);
+			editor.getSelection().selectRanges([range]);
+		}
+		else
+		{
+			root.setHtml(' ');
+		}
+	}
+
+	if (editor.mode == 'source')
+	{
+		if ( !root.hasClass( 'placeholder' ) )
+			return;
+
+		root.removeClass( 'placeholder' );
+		root.setValue( '' );
+	}
+}
+
+
+function getLang( element )
+{
+	if (!element)
+		return null;
+
+	return element.getAttribute( 'lang' ) || getLang( element.getParent() );
+}
+
+
+CKEDITOR.plugins.add( 'confighelper',
+{
+	getPlaceholderCss : function()
+    {
+        return '.placeholder{ color: #999; }';
+    },
+
+	onLoad : function()
+    {
+        // v4
+        if (CKEDITOR.addCss)
+            CKEDITOR.addCss( this.getPlaceholderCss() );
+    },
+
+	init : function( editor )
+	{
+
+		// correct focus status after switch mode
+		editor.on( 'mode', function( ev ) {
+			// Let's update to match reality
+			ev.editor.focusManager.hasFocus = false;
+			// Now focus it:
+		});
+
+		// Placeholder - Start
+		// Get the placeholder from the replaced element or from the configuration
+		var placeholder = editor.element.getAttribute( 'placeholder' ) || editor.config.placeholder;
+
+		if (placeholder)
+		{
+			// CSS for WYSIWYG mode
+			// v3
+			if (editor.addCss)
+				editor.addCss(this.getPlaceholderCss());
+
+			// CSS for textarea mode
+			var node = CKEDITOR.document.getHead().append( 'style' );
+			node.setAttribute( 'type', 'text/css' );
+			var content = 'textarea.placeholder { color: #999; font-style: italic; }';
+
+			if ( CKEDITOR.env.ie && CKEDITOR.env.version<11)
+				node.$.styleSheet.cssText = content;
+			else
+				node.$.innerHTML = content;
+
+			// Watch for the calls to getData to remove the placeholder
+			editor.on( 'getData', function( ev ) {
+				var element = (editor.editable ? editor.editable() : (editor.mode == 'wysiwyg' ? editor.document && editor.document.getBody() : editor.textarea  ) );
+
+				if ( element && element.hasClass( 'placeholder' ) )
+					ev.data.dataValue = '';
+			});
+
+			// Watch for setData to remove placeholder class
+			editor.on('setData', function(ev) {
+				if ( CKEDITOR.dialog._.currentTop )
+					return;
+
+				if ( editor.mode =='source' && supportsPlaceholder )
+					return;
+
+				var root = (editor.editable ? editor.editable() : (editor.mode == 'wysiwyg' ? editor.document && editor.document.getBody() : editor.textarea  ) );
+
+				if ( !root )
+					return;
+
+				if ( !dataIsEmpty( ev.data.dataValue ) )
+				{
+					// Remove the class if new data is not empty
+					if ( root.hasClass( 'placeholder' ) )
+						root.removeClass( 'placeholder' );
+				}
+				else
+				{
+					// if data is empty, set it to the placeholder
+					addPlaceholder(ev);
+				}
+			});
+
+			editor.on('blur', addPlaceholder, null, placeholder);
+			editor.on('mode', addPlaceholder, null, placeholder);
+			editor.on('contentDom', addPlaceholder, null, placeholder);
+
+			editor.on('focus', removePlaceholder);
+			editor.on('beforeModeUnload', removePlaceholder);
+		} // Placeholder - End
+
+
+		// SCAYT lang from element lang:
+		var lang = editor.config.contentsLanguage || getLang( editor.element );
+		if ( lang && ! editor.config.scayt_sLang )
+		{
+			// Remove the stored language
+			if (localStorage)
+				localStorage.removeItem("scayt_0_lang");
+
+			// Convert from HTML5 Lang to spellchecker.net values
+			var map = {
+				'en'   : 'en_US',
+				'en-us': 'en_US',
+				'en-gb': 'en_GB',
+				'pt-br': 'pt_BR',
+				'da'   : 'da_DK',
+				'da-dk': 'da_DK',
+				'nl-nl': 'nl_NL',
+				'en-ca': 'en_CA',
+				'fi-fi': 'fi_FI',
+				'fr'   : 'fr_FR',
+				'fr-fr': 'fr_FR',
+				'fr-ca': 'fr_CA',
+				'de'   : 'de_DE',
+				'de-de': 'de_DE',
+				'el-gr': 'el_GR',
+				'it'   : 'it_IT',
+				'it-it': 'it_IT',
+				'nb-no': 'nb_NO',
+				'pt'   : 'pt_PT',
+				'pt-pt': 'pt_PT',
+				'es'   : 'es_ES',
+				'es-es': 'es_ES',
+				'sv-se': 'sv_SE'
+			};
+			editor.config.scayt_sLang = map[ lang.toLowerCase() ];
+		}
+
+		// Parse the config to turn it into a js object
+		// format= dialogName:tabName:fieldName
+		var parseDefinitionToObject = function ( value )
+		{
+			// Allow JSON definitions
+			if (typeof value == 'object')
+				return value;
+
+			var contents = value.split( ';' ),
+				tabsToProcess = {},
+				i;
+
+			for ( i = 0; i < contents.length; i++ )
+			{
+				var parts = contents[ i ].split( ':' );
+				if ( parts.length == 3 )
+				{
+					var dialogName = parts[ 0 ],
+						tabName = parts[ 1 ],
+						fieldName = parts[ 2 ];
+
+					if ( !tabsToProcess[ dialogName ] )
+						tabsToProcess[ dialogName ] = {};
+					if ( !tabsToProcess[ dialogName ][ tabName ] )
+						tabsToProcess[ dialogName ][ tabName ] = [];
+
+					tabsToProcess[ dialogName ][ tabName ].push( fieldName );
+				}
+			}
+			return tabsToProcess;
+		};
+
+		// Customize dialogs:
+		CKEDITOR.on( 'dialogDefinition', function( ev )
+		{
+			if ( editor != ev.editor )
+				return;
+
+			var dialogName = ev.data.name,
+				dialogDefinition = ev.data.definition,
+				tabsToProcess,
+				i, name, fields, tab;
+
+			if (dialogName=='tableProperties')
+				dialogName=='table';
+
+			// Parse the config to turn it into a js object
+			if ( !( 'removeDialogFields' in editor._ ) && editor.config.removeDialogFields )
+				editor._.removeDialogFields = parseDefinitionToObject( editor.config.removeDialogFields );
+
+			// Remove fields of this dialog.
+			if ( editor._.removeDialogFields && ( tabsToProcess = editor._.removeDialogFields[ dialogName ] ) )
+			{
+				for ( name in tabsToProcess )
+				{
+					fields = tabsToProcess[ name ];
+					tab = dialogDefinition.getContents( name );
+
+					for ( i=0; i<fields.length ; i++ )
+						tab.remove( fields[ i ] );
+				}
+			}
+
+
+			if ( !( 'hideDialogFields' in editor._ ) && editor.config.hideDialogFields )
+				editor._.hideDialogFields = parseDefinitionToObject( editor.config.hideDialogFields );
+
+			// Remove fields of this dialog.
+			if ( editor._.hideDialogFields && ( tabsToProcess = editor._.hideDialogFields[ dialogName ] ) )
+			{
+				for ( name in tabsToProcess )
+				{
+					fields = tabsToProcess[ name ];
+					tab = dialogDefinition.getContents( name );
+
+					for ( i=0; i<fields.length ; i++ )
+						tab.get( fields[ i ] ).hidden = true;
+				}
+			}
+
+			// Set default values.
+			if ( editor.config.dialogFieldsDefaultValues && ( tabsToProcess = editor.config.dialogFieldsDefaultValues[ dialogName ] ) )
+			{
+				for ( name in tabsToProcess )
+				{
+					fields = tabsToProcess[ name ];
+					tab = dialogDefinition.getContents( name );
+
+					for ( var fieldName in fields )
+					{
+						var dialogField = tab.get( fieldName );
+						if ( dialogField )
+							dialogField[ 'default' ] = fields[ fieldName ];
+					}
+				}
+			}
+
+
+		});
+
+	}
+} );
+
+})();
+
+ /**
+  * Allows to define which dialog fiels must be removed
+  * @name CKEDITOR.config.removeDialogFields
+  * @type {String}
+  * @example
+  *	editor.config.removeDialogFields = "image:info:txtBorder;image:info:txtHSpace";
+  */
+
+ /**
+  * Allows to define which dialog fiels must be hidden
+  * @name CKEDITOR.config.hideDialogFields
+  * @type {String}
+  * @example
+  *	editor.config.hideDialogFields = "image:info:htmlPreview";
+  */
+
+ /**
+  * Allows to define default values for dialog fields
+  * @name CKEDITOR.config.dialogFieldsDefaultValues
+  * @type {Object}
+  * @example
+	config.dialogFieldsDefaultValues =
+	{
+		image:
+			{
+				advanced:
+					{
+						txtGenClass : 'myClass',
+						txtGenTitle : 'Image title'
+					}
+			}
+	};
+  */
+
+
+ /**
+  * Placeholder text for empty editor
+  * @name CKEDITOR.config.placeholder
+  * @type {String}
+  * @example
+  *	editor.config.placeholder = "Please, type here...";
+  */
-- 
GitLab