Page 1 of 1

FCK Plugin to read template and url data via ajax

PostPosted: 11:56am, Mon 12 Aug, 2013
by Jochen
Overview

This plugin demonstrates how to insert template and remote data directly into the FCK message field without using the place holders [CONTENT] or [URL]. The implementation is based on Ajax. Both alternatives are closer to the WYSIWYG approach because a user can view and modify an email altogether.

Image

Implementation

(1) Add your FCK plugin

Create a new folder called "layout" in "/admin/FCKeditor/editor/plugins/".
Create the file fckplugin.js in this folder with the following code:

Code: Select all
function initAjax() {
   var ajax = false;
   try {
      ajax = new ActiveXObject("Msxml2.XMLHTTP");
   } catch (e) {
      try {
         ajax = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {
         ajax = false;
      }
   }
   if (!ajax && typeof XMLHttpRequest != 'undefined') {
      try{
         ajax = new XMLHttpRequest();
      } catch (e) {
         ajax = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
      }
   }
   
   return ajax;
}

function doGetContent(url, code) {
   var ajax = initAjax();
   
   ajax.open("GET", url, true);
   ajax.onreadystatechange = function() {
      if (ajax.readyState == 4 && ajax.status == 200) {
         if (code == 0)
            FCK.SetHTML(ajax.responseText, true);
         else if (code == 1)
            FCK.InsertHtml(ajax.responseText);
      }
   }
   ajax.send(null);
}


//__________________
//
// GET CONTENT COMBO
//
//__________________

// Initialize the Combo
var getContentCombo = function(name) {
   this.Name = name;
}

// Execute the Command
getContentCombo.prototype.Execute = function(itemText, itemLabel) {
   var url='http://' + window.location.host + '/admin/ajax.php?url=' + itemText;
   doGetContent(url, 1);
}

// Manage the plugin behavior
getContentCombo.prototype.GetState = function() {
   return FCK_TRISTATE_OFF; // FCK_TRISTATE_OFF or FCK_TRISTATE_ON
}

// Register the command.
FCKCommands.RegisterCommand('getContentCombo', new getContentCombo('getContentCombo'));

// Create the toolbar button.
var getContentComboToolbar = function(tooltip, style) {
   this.Command = FCKCommands.GetCommand('getContentCombo');
   this.CommandName = 'getContentCombo';
   this.Label = this.GetLabel();
   this.Tooltip = tooltip ? tooltip : this.Label;
   this.Style = style; //FCK_TOOLBARITEM_ICONTEXT OR FCK_TOOLBARITEM_ONLYTEXT
}

// Set the toolbar prototype.
getContentComboToolbar.prototype = new FCKToolbarSpecialCombo;

// Label to appear in the FCK toolbar
getContentComboToolbar.prototype.GetLabel = function() {
   return "Get Content";
}

// Add the items to the combo list
getContentComboToolbar.prototype.CreateItems = function() {
   var tempObject = eval('(' + layout_urls + ')');
   
   // id, html, label, bgColor
   for (var i=0; i<tempObject.length; i++) {
      this._Combo.AddItem(tempObject[i].value, '<b>' + tempObject[i].name + '</b>', tempObject[i].name);
   }
}

// Register the combo with the
FCKToolbarItems.RegisterItem('getcontentcombo', new getContentComboToolbar('Get Content', FCK_TOOLBARITEM_ICONTEXT));


//__________________
//
// GET Template COMBO
//
//__________________

var getTemplateCombo = function(name) {
   this.Name = name;
}

getTemplateCombo.prototype.Execute = function(itemText, itemLabel) {
   var url='http://' + window.location.host + '/admin/ajax.php?template=' + itemText;
   doGetContent(url, 0);
}

getTemplateCombo.prototype.GetState = function() {
   return FCK_TRISTATE_OFF;
}

FCKCommands.RegisterCommand('getTemplateCombo', new getTemplateCombo('getTemplateCombo'));

var getTemplateComboToolbar = function(tooltip, style) {
   this.Command = FCKCommands.GetCommand('getTemplateCombo');
   this.CommandName = 'getTemplateCombo';
   this.Label = this.GetLabel();
   this.Tooltip = tooltip ? tooltip : this.Label;
   this.Style = style;
}

getTemplateComboToolbar.prototype = new FCKToolbarSpecialCombo;

getTemplateComboToolbar.prototype.GetLabel = function() {
   return "Templates";
}

getTemplateComboToolbar.prototype.CreateItems = function() {
   var tempObject = eval('(' + layout_templates + ')');
      
   for (var i=0; i<tempObject.length; i++) {
      this._Combo.AddItem(tempObject[i].value, '<b>' + tempObject[i].name + '</b>', tempObject[i].name);
   }
}

FCKToolbarItems.RegisterItem('gettemplatecombo', new getTemplateComboToolbar('Templates', FCK_TOOLBARITEM_ICONTEXT));


(2) Register your FCK plugin

Folder admin
File: fckphplist.php

Line 820 (add plugin):

FCKConfig.Plugins.Add( 'layout' );

Line 870 (add combo boxes):

FCKConfig.ToolbarSets["Default"] = [
['Source','DocProps','-','NewPage','Preview'],
['Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat','Link','Unlink','Anchor'],
['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'],
['OrderedList','UnorderedList','-','Outdent','Indent'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
['Image','Table','Rule','SpecialChar','TextColor','BGColor'],
'/',
['Style','FontFormat','FontName','FontSize'],
['getcontentcombo','gettemplatecombo']
] ;

At the end of this file add global javascript vars for templates and urls.

Code: Select all
<?php
   $FCK_templates = array();
   $FCK_urls = array();
   $i = 0;

   $sql = "SELECT id, title FROM " . $table_prefix . "template ORDER BY title";

   $result = mysql_query($sql, $database_connection);
   while ($row = mysql_fetch_array($result)) {
      $FCK_templates[$i]['name'] = $row['title'];
      $FCK_templates[$i++]['value'] = $row['id'];
   }
   
   $FCK_urls[0]['name'] = "phplist";
   $FCK_urls[0]['value'] = "1";
   ?>
   var layout_templates = '<?php echo json_encode($FCK_templates);?>';
   var layout_urls = '<?php echo json_encode($FCK_urls);?>';
   <?php
  exit;

} elseif ($_GET["action"]) {
  print "Sorry, not implemented";
}

?>


(3) add the file ajax.php to the admin folder

Code: Select all
<?php
   require_once "HTTP/Request.php";
   require_once("../config/config.php");

   if ( isset($_GET['template']) ) {
      global $database_connection;
      global $database_host;
      global $database_user;
      global $database_password;
      global $database_name;
      global $table_prefix;
      $rc = array();
         
      // connect to database   
      $database_connection = mysql_connect($database_host, $database_user, $database_password);
      $errno = mysql_errno();
      if (!$errno) {
         $res = mysql_select_db($database_name, $database_connection);
         $errno = mysql_errno();
      }
      if ($errno) {
         echo mysql_error();
         return;
      }

      $sql = "SELECT template FROM " . $table_prefix . "template where id = " . $_GET['template'];
      $result = mysql_query($sql, $database_connection);
      if ($row = mysql_fetch_array($result)) {
         echo str_replace('\"','"',$row['template']);
      }
      else {
         echo "No template found!";
      }
   }
   
   elseif ( isset($_GET['url']) ) {
      if ($_GET['url'] == "1") {
         $req =& new HTTP_Request('http://www.phplist.com/details');
         if (!PEAR::isError($req->sendRequest())) {
            $pattern = "/<div id=\"pageContent\">(.*)<\/div><!--pageContent-->/Usim";
            $html = array();
            preg_match($pattern, $req->getResponseBody(), $html);
                     
            $html[1] = str_replace("<ul>", "\n<ul style=\"list-style: none outside none;\">", $html[1]);
            
            $style = "font-family: Verdana; background: url('http://www.phplist.com/images/phplist-icon2.png') ";
            $style .= "no-repeat scroll 4px 0 transparent; font-size: 11px; line-height: 12px; padding-bottom: 15px; padding-left: 30px;";
            
            $html[1] = str_replace("<li>", "\n<li style=\"" . $style . "\">", $html[1]);
            
            echo $html[1];
         }
      }
   }
?>


(4) add ajax.php to .htaccess

<FilesMatch "(index.php|connector.php|upload.php|ajax.php)$">

Any feedback is very much appreciated.

Thank you.

Re: FCK Plugin to read template and url data via ajax

PostPosted: 1:07pm, Mon 12 Aug, 2013
by Dragonrider
What version are you running this on please? Adding the changes and extra files to my 2.10.19 install removes the message box on Send a Message page?

Re: FCK Plugin to read template and url data via ajax

PostPosted: 6:35pm, Mon 12 Aug, 2013
by Jochen
It is running on version 2.10.19. The error you are describing looks like a JavaScript error.

I will check the files carefully again. It's my first contribution and I can't exclude a copy & paste error. Sorry and thanks for your reply.

Re: FCK Plugin to read template and url data via ajax

PostPosted: 8:02pm, Mon 12 Aug, 2013
by Dragonrider
I've created the layout directory, added the JS file as instructed there, made the changes to the admin/fckphplist.php file as well as creating and uploading the admin/ajax.php file as well as the filematch details.

Replacing the admin/fckphplist.php file the previous unaltered copy restores my message area.

Hope this helps trace any missing details??

Re: FCK Plugin to read template and url data via ajax

PostPosted: 6:58am, Tue 13 Aug, 2013
by Jochen
I went through the instructions again without finding any error.

Some more details which might help to solve the problem:

The links between the FCK plugin and phplist are the two Javascript variables layout_templates and layout_urls at the end of the file fckphplist.php. The template values are read from the database, the example url is hard-coded.

Both variables are used in the FCK plugin to fill the combo boxes. Line 83 var tempObject = eval('(' + layout_urls + ')'); and Line 131 var tempObject = eval('(' + layout_templates + ')');.

By adding Javascript alerts you can easily debug if the program reaches this points.

fckplugin.js:

Code: Select all
getTemplateComboToolbar.prototype.CreateItems = function() {
   var tempObject = eval('(' + layout_templates + ')');
      
   alert(layout_templates);

   for (var i=0; i<tempObject.length; i++) {

      alert(tempObject[i].name);

      this._Combo.AddItem(tempObject[i].value, '<b>' + tempObject[i].name + '</b>', tempObject[i].name);
   }
}


fckphplist.php:

Code: Select all
<?php
   $FCK_templates = array();
   $FCK_urls = array();
   $i = 0;
 
   $sql = "SELECT id, title FROM " . $table_prefix . "template ORDER BY title";
   $result = mysql_query($sql, $database_connection);
   while ($row = mysql_fetch_array($result)) {
      $FCK_templates[$i]['name'] = $row['title'];
      $FCK_templates[$i++]['value'] = $row['id'];
   }
   
   $FCK_urls[0]['name'] = "phplist";
   $FCK_urls[0]['value'] = "1";
   ?>
   var layout_templates = '<?php echo json_encode($FCK_templates);?>';
   var layout_urls = '<?php echo json_encode($FCK_urls);?>';

   alert(layout_templates);

   <?php
  exit;

} elseif ($_GET["action"]) {
  print "Sorry, not implemented";
}


By the way it is important to clear the browser cache after you have modified fckplugin.js. This might be also the reason for your error.

I am using several FCK plugins and I have made the experience to clear all cache after adding a plugin like FCKConfig.Plugins.Add( 'layout' );.

The Ajax functionality can also be tested separate:

http://yourdomain/admin/ajax.php?template=1

or

http://yourdomain/admin/ajax.php?url=1

Hope that helps.

Re: FCK Plugin to read template and url data via ajax

PostPosted: 7:24am, Tue 13 Aug, 2013
by Dragonrider
Testing ajax.php?template=1 brings up an error message, no template found.

Testing ajax.php?url=1 brings up a page full of phpList Features??

Re: FCK Plugin to read template and url data via ajax

PostPosted: 8:18am, Tue 13 Aug, 2013
by Jochen
(1) Means that you don't have a template with the id equals 1. Have a look to your template list and take a valid id as parameter.

(2) I have taken the feature list as an example. If you want to make use of the "Get Content" combo box you have to customize the list of values (layout_urls) and ajax.php anyway.

If you just want to use the template feature you are free to remove the "getcontentcombo" from the FCK toolbar set.

Is the plugin working now?

Re: FCK Plugin to read template and url data via ajax

PostPosted: 10:08am, Tue 13 Aug, 2013
by Dragonrider
Jochen wrote:If you just want to use the template feature you are free to remove the "getcontentcombo" from the FCK toolbar set.

Is the plugin working now?


I've removed the line with both getcontent and gettemplate and I've still no message area.

So, that's a no, it doesn't work for me, and I'm going to call it a day on this for now.

Re: FCK Plugin to read template and url data via ajax

PostPosted: 10:29am, Tue 13 Aug, 2013
by Jochen
It's a pity that it is not working on your site.
Have you cleared your browser cache?
Have you tried to debug with the javascript alerts?

It is strange, because the whole thing consists just of a simple FCK plugin using two variables filled in php to retrieve data via Ajax. I have tested it successfully on Firefox and MS Explorer.

Re: FCK Plugin to read template and url data via ajax

PostPosted: 12:12pm, Tue 13 Aug, 2013
by Dragonrider
Jochen wrote:It's a pity that it is not working on your site.
Have you cleared your browser cache?
Have you tried to debug with the javascript alerts?


Cleared cache, yes, where would I put the extra code, or is it a case of replacing the existing files whist running the test? That's not clear.

Re: FCK Plugin to read template and url data via ajax

PostPosted: 12:43pm, Tue 13 Aug, 2013
by Jochen
"alert(layout_templates);" is added at the end of fckphplist.php.

If you can see this alert which displays a json array containing your templates the fckphplist.php file is fine.

You could also add "alert('PHP-Debug' + layout_templates);" to make it clearer and to distinguish it from the other alerts.

Compare the end of your fckphplist.php file with this code:

Code: Select all
FCKConfig.PreventSubmitHandler = false ;

<?php
   $FCK_templates = array();
   $FCK_urls = array();
   $i = 0;
 
   $sql = "SELECT id, title FROM " . $table_prefix . "template ORDER BY title";
   $result = mysql_query($sql, $database_connection);
   while ($row = mysql_fetch_array($result)) {
      $FCK_templates[$i]['name'] = $row['title'];
      $FCK_templates[$i++]['value'] = $row['id'];
   }
   
   $FCK_urls[0]['name'] = "phplist";
   $FCK_urls[0]['value'] = "1";
   ?>
   var layout_templates = '<?php echo json_encode($FCK_templates);?>';
   var layout_urls = '<?php echo json_encode($FCK_urls);?>';

   alert(layout_templates);

   <?php
  exit;

} elseif ($_GET["action"]) {
  print "Sorry, not implemented";
}


The other alerts are added to the fckplugin.js in the folder /admin/FCKeditor/editor/plugins/layout

Here is a complete listing of the file including alerts:

Code: Select all
function initAjax() {
   var ajax = false;
   try {
      ajax = new ActiveXObject("Msxml2.XMLHTTP");
   } catch (e) {
      try {
         ajax = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {
         ajax = false;
      }
   }
   if (!ajax && typeof XMLHttpRequest != 'undefined') {
      try{
         ajax = new XMLHttpRequest();
      } catch (e) {
         ajax = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
      }
   }
   
   return ajax;
}

function doGetContent(url, code) {
   var ajax = initAjax();
   
   ajax.open("GET", url, true);
   ajax.onreadystatechange = function() {
      if (ajax.readyState == 4 && ajax.status == 200) {
         if (code == 0)
            FCK.SetHTML(ajax.responseText, true);
         else if (code == 1)
            FCK.InsertHtml(ajax.responseText);
      }
   }
   ajax.send(null);
}


//__________________
//
// GET CONTENT COMBO
//
//__________________

// Initialize the Combo
var getContentCombo = function(name) {
   this.Name = name;
}

// Execute the Command
getContentCombo.prototype.Execute = function(itemText, itemLabel) {
   var url='http://' + window.location.host + '/admin/ajax.php?url=' + itemText;
   doGetContent(url, 1);
}

// Manage the plugin behavior
getContentCombo.prototype.GetState = function() {
   return FCK_TRISTATE_OFF; // FCK_TRISTATE_OFF or FCK_TRISTATE_ON
}

// Register the command.
FCKCommands.RegisterCommand('getContentCombo', new getContentCombo('getContentCombo'));

// Create the toolbar button.
var getContentComboToolbar = function(tooltip, style) {
   this.Command = FCKCommands.GetCommand('getContentCombo');
   this.CommandName = 'getContentCombo';
   this.Label = this.GetLabel();
   this.Tooltip = tooltip ? tooltip : this.Label;
   this.Style = style; //FCK_TOOLBARITEM_ICONTEXT OR FCK_TOOLBARITEM_ONLYTEXT
}

// Set the toolbar prototype.
getContentComboToolbar.prototype = new FCKToolbarSpecialCombo;

// Label to appear in the FCK toolbar
getContentComboToolbar.prototype.GetLabel = function() {
   return "Get Content";
}

// Add the items to the combo list
getContentComboToolbar.prototype.CreateItems = function() {
   alert(layout_urls);
   
   var tempObject = eval('(' + layout_urls + ')');
   
   // id, html, label, bgColor
   for (var i=0; i<tempObject.length; i++) {
      this._Combo.AddItem(tempObject[i].value, '<b>' + tempObject[i].name + '</b>', tempObject[i].name);
   }
}

// Register the combo with the
FCKToolbarItems.RegisterItem('getcontentcombo', new getContentComboToolbar('Get Content', FCK_TOOLBARITEM_ICONTEXT));


//__________________
//
// GET Template COMBO
//
//__________________

var getTemplateCombo = function(name) {
   this.Name = name;
}

getTemplateCombo.prototype.Execute = function(itemText, itemLabel) {
   var url='http://' + window.location.host + '/admin/ajax.php?template=' + itemText;
   doGetContent(url, 0);
}

getTemplateCombo.prototype.GetState = function() {
   return FCK_TRISTATE_OFF;
}

FCKCommands.RegisterCommand('getTemplateCombo', new getTemplateCombo('getTemplateCombo'));

var getTemplateComboToolbar = function(tooltip, style) {
   this.Command = FCKCommands.GetCommand('getTemplateCombo');
   this.CommandName = 'getTemplateCombo';
   this.Label = this.GetLabel();
   this.Tooltip = tooltip ? tooltip : this.Label;
   this.Style = style;
}

getTemplateComboToolbar.prototype = new FCKToolbarSpecialCombo;

getTemplateComboToolbar.prototype.GetLabel = function() {
   return "Templates";
}

getTemplateComboToolbar.prototype.CreateItems = function() {
   alert(layout_templates);
   
   var tempObject = eval('(' + layout_templates + ')');
      
   for (var i=0; i<tempObject.length; i++) {
      alert(tempObject[i].name);
      this._Combo.AddItem(tempObject[i].value, '<b>' + tempObject[i].name + '</b>', tempObject[i].name);
   }
}

FCKToolbarItems.RegisterItem('gettemplatecombo', new getTemplateComboToolbar('Templates', FCK_TOOLBARITEM_ICONTEXT));


These alerts are called when the plugin is built.