Saturday, September 23, 2017

How to create an editor button (editors-xtd plugin) for Joomla! (updated)

by / Sunday, 31 October 2010 / Published in Joomla! articles & tutorials

Mar 25, 2015: This article is back online, updated with the latest changes to Joomla! 3.4

Whatever you are developing - a complex application that consists of several extensions, a component or just a plugin for Joomla, you may encounter a situation when you need to add new editor button with your functionality. I faced this problem recently, and found that there's not so much information on the Web concerning this topic, at least in English. There are some fragments of necessary information, but not the complete step-by-step procedure. So I've decided to write this tutorial.

Here we are going to create new Joomla editor button from scratch, which should ask user for ID (like XXX, for instance), and then insert {sampleplugin XXX} into the editor's textarea. This is a simple task, however, this code can become a basis for your more complex things.

Joomla! Editor button itself is a plugin, of type editors-xtd. Here you can read more about extension types.

Each plugin consists of at least two files: the code itself, and a metafile describing the extension. In our case these files are xtdbutton.php and xtdbutton.xml, all located at /plugins/editors-xtd/xtdbutton/

xtdbutton is a sample name for our project, replace it with the name of your extension everywhere in the code

You can download sample code here or clone the repository from GitHub.

XML metafile

Let's begin with XML. This file contains information that is necessary for Joomla! to install the plugin. As well it's a place for storing extension's parameters (not the values of parameters, but their definitions and descriptions). This file should begin with document declaration:

<?xml version="1.0" encoding="utf-8"?>

Then goes the root tag of the file, declaring that this is a description for a plugin for Joomla! 3.4:

<extension version="3.4" type="plugin" method="upgrade" group="editors-xtd">

You can downgrade this to 2.5 to make the button compatible with older versions of Joomla!.

Then add a block of plugin parameters:

<name>Editor - XTDButton</name>
<author>Author Name</author>
<creationDate>Month 2015</creationDate>
<copyright>(c) Author Name, 2015. All rights reserved.</copyright>
<license>GPL</license>
<authorEmail>Email</authorEmail>
<authorUrl>Your URL</authorUrl>
<version>1.0.0</version>
<description>
	"This plugin adds sample button to the editor. Do not forget to publish the plugin!"
</description>

After that goes a block, defining what files to install (xml file will be installed automatically, and there's no need to name it):

<files>
	<filename plugin="xtdbutton">xtdbutton.php</filename>
</files>

Our extension is quite simple and is not going to have any parameters. So I just omit <config /> block.

Here's the full code of xtdbutton.xml:

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.4" type="plugin" method="upgrade" group="editors-xtd">
        <name>Editor - XTDButton</name>
        <author>Author Name</author>
        <creationDate>Month 2015</creationDate>
        <copyright>(c) Author Name, 2015. All rights reserved.</copyright>
        <license>GPL</license>
        <authorEmail>Email</authorEmail>
        <authorUrl>Your URL</authorUrl>
        <version>1.0.0</version>
        <description>
            "This plugin adds sample button to the editor. Do not forget to publish the plugin!"
        </description>
        <files>
            <filename plugin="xtdbutton">xtdbutton.php</filename>
        </files>
</extension>

Plugin code

And now it's time to begin writing php file, which will be the core of our editors-xtd plugin.

As usually, a file should begin with comment block and check for proper calling of the file - as an included one, to prevent direct calls (and possible security threats):

<?php
// no direct access 
defined( '_JEXEC' ) or die( 'Restricted access' );

Then we should import a helper for the plugin:

jimport( 'joomla.plugin.plugin' );

There's a certain scheme for naming the main class of the plugin: first goes plg, then type of the plugin(e.g. Button) and, finally, plugin's name (Xtdbutton). Note that all of this should be written in CamelCase. Our class should be derivated from JPlugin:

class plgButtonXtdbutton extends JPlugin {

After that we should declare a constructor for our class. Unless you have something special to initialise, it looks like   

function plgButtonXtdbutton(& $subject, $config)
{
	parent::__construct($subject, $config);
}

Almost all of button's functionality is stored inside onDisplay event. This function is called when our button is being rendered, and it should return the button object.

Unlike all other plugin types, an editors-xtd plugin must produce a client-side code, which should interact with editor script and the user itself. In more complex extensions client-side code may also include calls to server-side (for instance, getting a contents for a popup window - like in image insertion dialog with browsing server directories in Editor - Image plugin). This code is usually written in JavaScript.

Just for your knowledge

Joomla Framework provides some useful functions that allow a script to interact with editor. They allow to get content from editor, set new editor's content and make the editor to save the article. As long as these javascript methods have different names in different editors, Joomla! provides php functions returning these names to your script, so you can use them to build necessary javascript on the fly, like:

$js = " function sampleXTDButtonClick() {
          var content = ".$this->_subject->getContent($name)." alert(content); 
        }";

Then you assign this js to your button. By the way: $name is a name of current editor, it is provided as a parameter when onDisplay  is called.

So, these functions are:

      • getContent($editorname) - provides js method name for getting editor content, name ends with semicolon.
      • setContent($editorname) - provides js method name for replacing editor text, ending with semicolon
      • getInsertMethod($editorname) - provides js method name for inserting text, ending with semicolon
      • save($editorname) - provides js method name for saving content.

(Note that these are php functions. You should use them to build your code server-side).

These functions return javascript methods names for a certain editor. As usually, they receive then only one parameter (or none) - a text to insert/replace with.

Another alternative to building JavaScript for certain editor dynamically is jInsertEditorText method (javascript, client-side), which simply inserts given text to the editor. It has two parameters: the text itself, and editor name. So it acts like an interface for all descripted above, defining proper native editor functions and calling them. The only thing he needs is editor's name, which is given to our plugin's onDisplay php method (see example below).

Which one to choose is your decision. I prefer the second way.

To sum up all above, I'll write a php code with JS function which does all the work for our extension:

$js = " function sampleXTDButtonClick(editor) { jInsertEditorText('{sampleplugin}', editor); }";

We need a standalone function - main function for our button.This function will be assigned to onClick event for the button. It takes one parameter - editor name, which we pass to jInsertEditorText (as well we pass (as the first parameter ) the text to insert into the editor)

Let us slightly alter our task and add a prompt:

$js =  "function sampleXTDButtonClick(editor) {
		txt = prompt('Please enter ID','123');
		if (!txt) return;
		jInsertEditorText('{sampleplugin '+txt+'}', editor);
	}";

 - a right side of the button, like this one:

You can download this image and use it like a template for your buttons.
(rename it to test.png to follow this example)

Having everything prepared now, we may embed the script to the page. To do this, we get JDocument object, that gives us access to the necessary functions:

$doc = & JFactory::getDocument(); 
$doc->addScriptDeclaration($js);

The final step is creation of the button itself:

  1. Create a new object (by using JObject class)
  2. Set modal property to false
  3. Add our function as onClick event handler. Do not forget to pass a parameter - current editor's name, which is given to onDisplay method (see full code below)
  4. Add text to the button
  5. Set button's name, which will also stand for icon
  6. Set link for the button. We don't need this, so we use # as link target.
$button = new JObject;		
$button->modal = false;
$button->class = 'btn';
$button->link = '#';
$button->text = JText::_('Insert sampleplugin');
$button->name = 'wand';
$button->onclick = 'sampleXTDButtonClick(\''.$name.'\'); return false;';

And, finally, we return the button object to Joomla!:

return $button;

To personalize the button we need to choose an icon from IcoMoon iconset. You can view it contents here and here. You need to specify the right part of icon name (without icon- ) in $button->name field.

Here is the full code:

<?php
 // no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
jimport( 'joomla.plugin.plugin' );
class plgButtonXtdbutton extends JPlugin {
    function plgButtonXtdbutton(& $subject, $config)
    {
        parent::__construct($subject, $config);
    }
    function onDisplay($name)
    {
        $js =  "function sampleXTDButtonClick(editor) {
			txt = prompt('Please enter ID','123');
			if (!txt) return;
			jInsertEditorText('{sampleplugin '+txt+'}', editor);
		}";
        $doc = & JFactory::getDocument();
        $doc->addScriptDeclaration($js);
        $button = new JObject;		
	$button->modal = false;
	$button->class = 'btn';
	$button->link = '#';
	$button->text = JText::_('Insert sampleplugin');
	$button->name = 'wand';
	$button->onclick = 'sampleXTDButtonClick(\''.$name.'\'); return false;';
        return $button;
    }
}

Congratulations! We have successfully created an editor button - editors-xtd plugin for Joomla! Now you should pack xtdbutton.php and xtdbutton.xml into zip archive, and you can upload it to your site.

If you have any suggestion or modifications, please send them via a pull request on GitHub.

Read 2604 times Last modified on Wednesday, 25 March 2015 18:08

Do you like this? Please share!

Simon Tushev

Simon is IT professional with interests in web design, electronics, photography and astronomy. He writes about PHP, Yii, Joomla!, Arduino and several other topics.

Welcome!

Here I publish articles related to my areas of interest, my brief notes that may save some time to others, as well as some of my works.

This site is a work in progress. I will add more sections in the future, such as

  • More photos to photogallery
  • More Joomla!-related articles
  • ...

 

themeforest

New Posts

Using dynamic GeoIP module with nginx (CentOS)

nginx introduced dynamic module support in v. 1.9.11. This brief article provides step-by-step procedure...

13-04-2016 in Linux, BSD, Unix

READ MORE

Visual difference between pseudo and true random data

This is is "random" image generated using PHP rand() function: And this is an image...

20-11-2015 in Blog

READ MORE

Best EEPROM practices

(this article is a work in progress). My own advice will be added later...   Having...

12-10-2015 in Arduino

READ MORE
Scroll to top

We use cookies, just to track visits to our website, we store no personal details Privacy policy