How To Create Joomla Editors-xtd Plugin Button and Open in Modal Popup

Category: Joomla
How To Create Joomla Editors-xtd Plugin Button and Open in Modal Popup

In this tutorial we are going to build plugin for Joomla’s content editor. These plugins are called editors-xtd plugins and are meant to extend Joomla’s content editor functionality.

In this tutorial we will build a plugin that will display a button right underneath of Joomla’s default TinyMCE editor just like Article, Image, Page Break and Read More buttons. On the click it will open a Modal window and will load a view from the component.

So now, with the help of the button, instead of typing {youtube_vid}SOME_ID{/youtube_vid} users will directly paste youtube video id into popup and it will directly add the code.

NOTE: The previous article Developing Joomla! 3 Content Plugin – Youtube Video For Joomla Article covered creating Joomla’s basic content type plugin and performing replacement of youtube video id by an iframe using regex.

After some research I have discovered that there are very few tutorials on creating Joomla editors-xtd plugins and they don’t show the Joomla way of creating this kind of plugin.

To start off, if you take a look at any pre-built editor plugins, for ex. Page Break, you will notice that it contains two files. An XML file that contains installation information and a php file with the code for the button.

The xml file is pretty straightforward so, here it is:

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin" group="editors-xtd" method="upgrade">
	<name>Button - Youtubevid</name>
	<author>mrGott</author>
	<creationDate>December 2015</creationDate>
	<copyright>Copyright (C) 2005 - 2015 Open Source Matters. All rights reserved.</copyright>
	<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
	<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
	<authorUrl>www.mrgott.com</authorUrl>
	<version>1.0.0</version>
	<description>Button for Youtube Video insert into article body</description>
	<files>
		<filename plugin="youtubevid">youtubevid.php</filename>
	</files>
</extension>

Now let’s get to the main code of our plugin. This is a common template for it:

<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Editors-xtd.youtubevid
 *
 * @copyright   Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Editor Pagebreak buton
 *
 * @since  1.5
 */
class PlgButtonMyCode extends JPlugin
{
	/**
	 * Load the language file on instantiation.
	 *
	 * @var    boolean
	 * @since  3.1
	 */
	protected $autoloadLanguage = true;

	/**
	 * Display the button
	 *
	 * @param   string  $name  The name of the button to add
	 *
	 * @return array A two element array of (imageName, textToInsert)
	 */
	public function onDisplay($name)
	{

	$link = 'index.php?option=com_content&amp;amp;view=article&amp;layout=mymodalcode&amp;tmpl=component&amp;e_name=' . $name;

	$button = new JObject;
	$button->modal = true;
	$button->class = 'btn';
	$button->link  = $link;
	$button->text  = JText::_('Youtube');
	$button->name  = 'youtube';
	$button->options = "{handler: 'iframe', size: {x: 600, y: 400}}";

	return $button;
	}
}

This code is very simple to understand too. It runs a function onDisplay that includes setup parameters for the button.

The variable $link contains a link to the component of Joomla for which we are adding some functionality to the editor. The rest of the code is button setup that contains css class, link, text for the title on the button, name parameter that really is a css class and displays an icon and options parameter that takes information for the sizes of the modal window.

Except the Read More button of Joomla, the rest of the buttons open in modals that contain forms and content relevant to it’s functionality. So where do these modals come from?

The modal windows, Joomla’s editors-xtd buttons, load respective views from Joomla’s components that are set in the $link variable. In case of Page Break and Article, these buttons extend Joomla-s com_content component functionality, and Image button extends com_media component functionality.

In this specific case we don’t have any component to do youtube video placement. All we want to do to let the user insert some data and let the button format it automatically and insert formatted data into the editor.

The easy way to achieve this is to call browser’s popup box, display single text type input field, let the user insert data there and insert the formatted value into the editor.

To build it we have to change the above code for setting up the button as follows:

    $js =  "function insertYouTubeVidId(editor) {
	txt = prompt('Please enter Video ID','');
	if (!txt) return;
	jInsertEditorText('{youtube_vid}'+txt+'{/youtube_vid}}', editor);
	}";

    $doc = &amp; JFactory::getDocument();
    $doc->addScriptDeclaration($js);
    
    $button = new JObject;		
    $button->modal = false;
    $button->class = 'btn';
    $button->link = '#';
    $button->text = JText::_('Youtube');
    $button->name = 'youtube';
    $button->onclick = 'insertYouTubeVidId(\''.$name.'\'); return false;';
    return $button;

If we take a closer look, instead of calling a modal box with $button->options property, what we actually do is call a function insertYouTubeVidId on the button click that will run browser’s alert with a single text input. To insert our custom JS script into Joomla’s page we get JDocument object $doc = & JFactory::getDocument() and then add $js variable $doc->addScriptDeclaration($js). The final result looks like this:

NOTE: This solution was grabbed from Simon Tushev’s blog.

As mentioned above, it’s an easy way to do it. As for me – I don’t like it as it’s very simple, looks ugly and what if I needed to have many input fields? And maybe I’d like to do some complicated data formatting? What if a user clicks prevent displaying the popup from this webpage?

The other solution found was to directly include some php file into the frame that would contain the forms and javascript code. I won’t go into much details on this solution, but you can check it out here on Stackoverflow and on Webkul, and even check out already built plugin on JED – TXTHighlightjs.

In my opinion this is a very dirty and unsecure solution though authors include Joomla framework and add “defined( '_JEXEC' ) or die;”. I’m sure you’ll agree that it a bad override. It doesn’t load Joomla’s administration css and js files either and the forms look ugly.

So the final and the only solution following Joomla’s best practices is to build your own component. You can go to Joomla Component Creator, register and build a simple component in just about 2 minutes, install it and get back to plugin development.

But as far as I’m a person who doesn’t trust any third party extensions, or any unclear solutions I did come up with another way to implement the code in Joomla manner. I added another view into com_content.

NOTE: Yes, the first question that arises is: What if after each update your file will be removed as it’s not a part of Joomla’s com_content component. Yeah, that’s right, but actually I’m fine by keeping this file, and uploading it after each system update, rather then doing plugin development in the wrong and dirty way.

If you are building this plugin for your client, you should better build a component, or maybe you already built some component and just add a new view file there for your editors-xtd plugin.

Now let’s get to how to add the view and what code it should contain.

First you need to create a file. In my case I called it youtubeid.php. The name doesn’t really matter.

As you might know, Joomla directly calls for files from the URL. If the URL is called from the administrator and the link is as follows: index.php?option=com_content&view=article&layout=youtubeid&tmpl=component, Joomla will go to administrator -> components -> com_content -> views -> article -> tmpl -> youtubevid.php and will load without the surrounding context (such as menus, header logos etc.) thank to tmpl=component parameter in the URL. To learn more about tmpl=component visit Joomla Docs.

Now, Let’s do it!

For the Youtube editors-xtd plugin I chose to put my file called youtubeid.php in administrator -> components -> com_content -> views -> article -> tmpl folder. And the URL inside my plugin code is: 

$link = 'index.php?option=com_content&amp;view=article&layout=youtubeid&tmpl=component&e_name=' . $name;

NOTE: In case if you placed your file into your own component you should change this URL accordingly.

At the end of the link you will notice e_name parameter. This is a name of the current editor. It is provided as a parameter when onDisplay is called.

Joomla’s wise developers knew that there are many editor extensions out there and if you would develop your editors-xtd plugin for ex. for TinyMCE, it wouldn’t work with the other one because the names would differ. So to make life easier Joomla kindly provides us with a name of the current editor so we can later pass it in our javascript code.

So now my onDisplay function inside editors-xtd plugin php file looks like this:

public function onDisplay($name){

	$link = 'index.php?option=com_content&amp;amp;view=article&amp;layout=youtubeid&amp;tmpl=component&amp;e_name=' . $name;

	$button = new JObject;
	$button->modal = true;
	$button->class = 'btn';
	$button->link  = $link;
	$button->text  = JText::_('Youtube');
	$button->name  = 'youtube';
	$button->options = "{handler: 'iframe', size: {x: 600, y: 400}}";
	return $button;
}

Now let’s get to the contents inside the modal window.
The file youtubeid.php will contain one single text input, and by pressing insert button we will call javascript function that will pass the contents of text input back to our editor and will close the modal window. So here it is:

<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_content
 *
 * @copyright   Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$script  = 'function insertYoutubeVid() {' . "\n\t";

// Get the pagebreak title
$script .= 'var codeInsert = document.getElementById("codeInsert").value;' . "\n\t";
$script .= 'var tag = "{youtube_vid}"+codeInsert+"{/youtube_vid}";' . "\n\t";
$script .= 'window.parent.jInsertEditorText(tag, ' . json_encode($this->eName) . ');' . "\n\t";
$script .= 'window.parent.jModalClose();' . "\n\t";
$script .= 'return false;' . "\n";
$script .= '}' . "\n";

JFactory::getDocument()->addScriptDeclaration($script);
?>
<form class="form">
  <h3>Insert ID</h3>
  <input type="text" id="codeInsert" name="codeInsert" class="form-control" placeholder="Paste Youtube Video Id"/>
  <button onclick="insertYoutubeVid();" class="btn btn-primary"><?php echo JText::_('Insert'); ?></button>
</form>

Conclusion

This is it! I hope you will find this tutorial helpful. Just in case I missed something or didn’t give enough explanations, or in case you came up with a better solution - please feel free to contact me and I will update this article.