Ticket #30 (new New Feature)

Opened 2 years ago

Last modified 10 months ago

Passing arrays to configuration without custom js file

Reported by: alfonsoml Owned by:
Priority: Normal Milestone: CKEditor 3.0
Component: General Version:
Keywords: Confirmed Cc:

Description

I plan to study this set of patches: https://sourceforge.net/tracker/index.php?func=detail&aid=1605345&group_id=75348&atid=543655
https://sourceforge.net/tracker/index.php?func=detail&aid=1504513&group_id=75348&atid=543655
https://sourceforge.net/tracker/index.php?func=detail&aid=1026583&group_id=75348&atid=543655
https://sourceforge.net/tracker/index.php?func=detail&aid=1026582&group_id=75348&atid=543655

so it's possible and documented how to define a custom toolbar without using a customconfig.js file but instead just specifying its contents at the moment the editor is created. This should allow also other kind of customizations in the future.

I'll work in a new branch were I'll apply other patches, I'll try to open tickets for each one .

This might be a fix to this bug: https://sourceforge.net/tracker/index.php?func=detail&aid=1613963&group_id=75348&atid=543653

Change History

follow-up: ↓ 2   Changed 2 years ago by FredCK

A similar feature is something I've been thinking about for a long time. I was planning to have this one done "until" the 3.0.

I've thought about creating a string which can simply be evaluated (eval()) in the browser. Similar to JSON (http://www.json.org/), but without defining a single object, and making it possible to call functions.

For compatibility, we could also "mark" the new model, making it start with "#". And to make it more compact, we could (optionally) replace all entries of "FCKConfig." with "$.".

So, for example, the following custom settings:

FCKConfig.DefaultLanguage = 'fr' ;
FCKConfig.ContextMenu = ['Generic','Link','Anchor'] ;
FCKConfig.Plugins.Add( 'autogrow' ) ;
FCKConfig.AutoGrowMax = 400 ;
FCKConfig.FullPage = true ;

Could be sent from the user in the hidden config field as:

#$.DefaultLanguage='fr';$.ContextMenu=['Generic','Link','Anchor'];$.Plugins.Add('autogrow');$.AutoGrowMax=400;$.FullPage=true;

So, in the editor we simply execute the following and the job is done:

eval( hiddenValue.replace( /$\./g, 'FCKConfig.' ) ) ;

Actually the server side implementation would be able to do any kind of job using it, not only set FCKConfig entries. In this way, it will be up to the server implementation to make it more or less flexible to the end user to define the configurations.

in reply to: ↑ 1   Changed 2 years ago by alfonsoml

Replying to FredCK:

I've thought about creating a string which can simply be evaluated (eval()) in the browser. Similar to JSON (http://www.json.org/), but without defining a single object, and making it possible to call functions.

That's what I was thinking about, but I forgot about functions, although it's very interesting to also have the ability to load a plugin this way (I don't see right now other functions that could be called).

I think that that would require to create a special object to set the configuration so it has a fake .Plugins.Add() function that instead of executing the code it does add some code that will be later serializad to the same call.

Actually the server side implementation would be able to do any kind of job using it, not only set FCKConfig entries. In this way, it will be up to the server implementation to make it more or less flexible to the end user to define the configurations.

The problem is how to set up the server code so it does generate the proper string that later will be evaluated. Due to that I don't think that the server will have full control about what it can do, but it will be limited to just the set of elements that have been predefined that can be converted to a js string (maybe add also another way to directly pass js code as a string?)

I need to study all the code related to the config as I almost haven't touched it so far and I'm not sure about all the details, when I study it and check the proposed changes in those patches I'll have a better overview about what can be done.

  Changed 2 years ago by FredCK

During the last weeks, I've been thinking about many aspects of the project. One of them was the current config system. I strongly believe we can improve it.

Do we want to work on a radical change of it for version 2.5? Are you interested on being the maintainer of it Alfonso?

If we decide to make this move, we can create a component in the components page called "Core: Config" and trace the specifications of it. I would trace a draft for the first specifications and then we could discuss over it.

Does it sound reasonable?

  Changed 2 years ago by FredCK

Just a tip for the wiki formatting...

You don't need to do a [[BR]] at the end of each paragraph. Just place a blank line between then and you will have it in different <p>s.

Use [[BR]] only if you want to place text attached to a paragraph, right after it. It is useful when making references to URLs, like this sample:
http://tools.assembla.com/fckeditor/wiki/WikiFormatting

Actually, just use the method you fell more comfortable with ;)

  Changed 2 years ago by alfonsoml

If the current system needs to be redone then I think that instead of working on improving this one we can start drafting the requirements and specifications about how it should work, and then if the changes are really that importat setup its own specific branch for it, and merge it when it's done and not sooner.

  Changed 22 months ago by fredck

  • keywords Config added
  • summary changed from passing arrays to configuration without custom js file to Passing arrays to configuration without custom js file
  • milestone set to FCKeditor 3.0

Ok... I've finally completed the first draft of the specifications:

wiki:Components/Configuration

Improvements are welcome.

  Changed 21 months ago by alfonsoml

#305 has been marked as dup of this bug.

  Changed 21 months ago by tallyce

I am really glad this is being looked at, as configuration and upgrades will be much easier when the js config file need not be touched when instantiating via PHP.

Can I *strongly* request that the wiki:Components/Configuration makes quite explicit in the specification that *all* settings should be possible to set via server-side calling, so that the js config need not be touched?

follow-up: ↓ 11   Changed 21 months ago by tallyce

Is there any scope for getting the connector config also set outside the FCKeditor tree as part of these changes? At present, one must drive through about 5 directories deep and make a change to a config file there, rather than setting via any server-side call.

I realise the connectors are effectively separate, but perhaps some way of adding a routing mechanism that passes things off to the connector, but with the requests going via the central point, might be one way to handle this perhaps?

in reply to: ↑ 10   Changed 21 months ago by alfonsoml

Replying to tallyce:

Is there any scope for getting the connector config also set outside the FCKeditor tree as part of these changes? At present, one must drive through about 5 directories deep and make a change to a config file there, rather than setting via any server-side call.

If I do the changes I'll focus just on the configuration of the editor, not the filebrowser as that is a different element.

  Changed 19 months ago by fredck

  • keywords Config removed

Check #304 when implementing it.

  Changed 18 months ago by alfonsoml

The code from https://sourceforge.net/tracker/index.php?func=detail&aid=1026581&group_id=75348&atid=543655

// On line 18 of your 'fck_startup.js' file, replace the second half of that line with the code below starting from the term "FCKConfig.LoadHiddenField = function()" to the end.

FCKConfig.LoadHiddenField = function()
{ 
	var oConfigField = window.parent.document.getElementById( FCK.Name + '___Config' ) ;
	if ( ! oConfigField ) return ; 

	var aCouples = oConfigField.value.split('&') ; 
	var gToolbar = ""; 
	var gToolrow = ""; 
	for ( var i = 0 ; i < aCouples.length ; i++ )
	{
		var aConfig = aCouples[i].split('=') ;
		var sConfigName = aConfig[0] ;
		var sConfigValue = aConfig[1] ;
		var gConfig = sConfigName.split('[') ;
		var gConfigName = gConfig[0] ;
		if ( gConfigName == "ToolbarSets" )
		{ 
		var gConfigTool = gConfig [1].substring( 0, ( gConfig [1].length - 1 ) ) ;
		var gConfigVal1 = gConfig [2].substring( 0, ( gConfig [2].length - 1 ) ) ;
		var gConfigVal2 = gConfig [3].substring( 0, ( gConfig [3].length - 1 ) ) ;
		if ( gToolbar == "" )
			gToolbar = "FCKConfig.ToolbarSets[\"" + gConfigTool + "\"] = ["; if ( gToolrow == "" )gToolbar += "[";
		else
			if ( gToolrow != gConfigVal1 )
				gToolbar += "],[";

		if ( gConfigVal2 == '0' )
			gToolbar += "'" + sConfigValue + "'";
		else 
			gToolbar += ",'" + sConfigValue + "'";

		gToolrow = gConfigVal1;
		}
		else 
			if ( sConfigValue == "true" )
				FCKConfig[sConfigName] = true ; 
			else 
				if ( sConfigValue == "false" )
					FCKConfig[sConfigName] = false ; 
				else 
					if ( ! isNaN(sConfigValue) )
						FCKConfig[sConfigName] = parseInt( sConfigValue ) ; 
					else 
						FCKConfig[sConfigName] = sConfigValue ;
	}
	if ( gToolbar != "" )
	{ 
		gToolbar += "]];"; 
		eval( gToolbar );
	}
}

fckeditor.php

<?php

class FCKeditor
{
################################
##  VARS
################################
	var $InstanceName   = 'defaultFCKeditor';
	var $Width          = '100%';
	var $Height         = '200';
	var $ToolbarSet     = 'Default';
	var $Value          = '' ;
	var $BasePath		= '/fckeditor/' ;
	var $CheckBrowser	= true ;
	var $Config ;
################################
##  CONSTRUCTOR
################################
	function FCKeditor ()
	{
				
	}
################################
##  METHODS
################################	
	function CreateFCKeditor( $instanceName = false, $width = false, $height = false )
	{
		echo $this->ReturnFCKeditor( $instanceName, $width, $height );
	}
	
	function ReturnFCKeditor( $instanceName = false, $width = false, $height = false )
	{
		$fck_value    = htmlspecialchars( $this->Value ) ;
		$fck_instance = ( $instanceName ) ? $instanceName : $this->InstanceName ;
		$fck_width    = ( $width ) ? $width : $this->Width ;
		$fck_height   = ( $height ) ? $height : $this->Height ;
		if ( !$this->CheckBrowser || $this->IsCompatible() )
		{
			$fck_basepath = $this->BasePath ;
			$fck_toolbar  = ( $this->ToolbarSet != '' ) ? $this->ToolbarSet : 'Default' ;
			$fck_config   = ( is_array( $this->Config ) ) ? $this->http_build_query( $this->Config ) : '' ;
			$fck_editor   = "<div class=\"fckeditor\">
	<input type=\"hidden\" id=\"$fck_instance\" name=\"$fck_instance\" value=\"$fck_value\">
	<input type=\"hidden\" id=\"{$fck_instance}___Config\" value=\"$fck_config\">
	<iframe id=\"{$fck_instance}___Frame\" src=\"{$fck_basepath}editor/fckeditor.html?InstanceName=$fck_instance&Toolbar=$fck_toolbar\" width=\"$fck_width\" height=\"$fck_height\" frameborder=\"no\" scrolling=\"no\"></iframe>
</div>\n";
		}
		else
		{
			if ( strpos( $fck_width, '%' ) != ( strlen( $fck_width ) - 1 ) )
				$fck_width = $fck_width.'px';
			if ( strpos( $fck_height, '%' ) != ( strlen( $fck_height ) - 1 ) )
				$fck_height = $fck_height.'px';
			$fck_editor   = "<div class=\"fckeditor\">
	<textarea name=\"$fck_instance\" rows=\"4\" cols=\"40\" style=\"width: $fck_width; height: $fck_height\" wrap=\"virtual\">$fck_value</textarea>
</div>\n";
		}
		
		return $fck_editor ;
	}
	
	function IsCompatible()
	{
		$sAgent = $_SERVER['HTTP_USER_AGENT'] ;
		if ( is_integer( strpos($sAgent, 'MSIE') ) && is_integer( strpos($sAgent, 'Windows') ) && !is_integer( strpos($sAgent, 'Opera') ) )
		{
			$iVersion = floatval( substr( $sAgent, strpos( $sAgent, 'MSIE' ) + 5, 3) ) ;
			return ( $iVersion >= floatval( 5.5 ) ) ;
		}
		elseif ( is_integer( strpos($sAgent, 'Gecko/') ) )
		{
			$iVersion = intval( substr( $sAgent, strpos( $sAgent, 'Gecko/' ) + 6, 8) ) ;
			return ( $iVersion >= intval( 20030210 ) ) ;
		}
		else
			return false;
	}
	
	function Config( $sent_config, $sent_value )
	{
		$this->Config[$sent_config] = $sent_value;
	}
	
	function http_build_query( &$a, $pref = '', $f = '', $idx = '')
	{//Altered code from a help article at http://us3.php.net/function.http-build-query
		$ret = '';
		foreach ( $a as $i => $j )
		{
			if ( $idx != '' )
				$i = $idx."[$i]";
			if ( is_array( $j ) )
				$ret .= $this->http_build_query( $j, '', $f, $i );
			else
			{
				$j = urlencode( $j );
				if ( is_int( $i ) )
					$ret .= "$f$pref$i=$j";
				else
					$ret .= "$f$i=$j";
			}
			$f = '&';
		}
		return $ret;
	}

}
?>

  Changed 12 months ago by tallyce

For the sake of others wondering whether this issue is resolved in the major version 2.5 release:

- Confirmed that setting of arrays in PHP is *not* fixed for 2.5

- Confirmed that setting of a tab in PHP using $instance->FormatIndentator is *not* fixed for 2.5 (see #304)

  Changed 10 months ago by alfonsoml

  • owner alfonsoml deleted

  Changed 10 months ago by w.olchawa

  • keywords Confirmed added
Note: See TracTickets for help on using tickets.