How to add custom button to TinyMCE toolbar with Bootstrap modal image library

I was building a custom application where I implemented TinyMCE editor. I also needed to provide an easy access to local media/image library, so that users can select images in media library and insert them to posts. Pretty much like with WordPress “Add Media” functionality.

There is an “add image” button in TinyMCE, which opens dialog window to input image url. User will have to type in or copy/paste image url. I think it’s not very user friendly to make users remember urls of images or to browse them in another browser tab and then copy/paste them in to dialog. There are of course some already built file managers as TinyMCE plugins, but I wanted my own solution.

For that and for the sake of learning, I decided to build my own. It’s not that difficult after all.

In this tutorial I assume you have at least basic understanding of Bootstrap framework, Javascript (jQuery) and you know how to implement (init) TinyMCE editor on your webpage. I have included example files and live demo in the end of this tutorial, but basically you need to have Bootstrap and jQuery loaded and a html page with web form textarea where you initialize TinyMCE as part of.

If you don’t know how to do it, please follow tutorial on TinyMCE website. But, like I mentioned earlier, you can download fully working example files here.

What we want to accomplish

User can click a button in TinyMCE editor to open Bootstrap modal for image browsing. They can select an image with mouse click and insert it to current post. In this tutorial we use static selection of images, but it can easily be converted to a dynamically constructed image library.

You can take a peek of what we are building. But now, let’s do it.

1. Create a custom button in TinyMCE editor

First we want to make that custom button appear on our TinyMCE editor. Like the one:
tinymce-custom-button

We achieve this with the following code:

[php]

tinymce.init({
 selector: "#mytextarea",
 menubar: false,
 height: 200,
 plugins: [
 ‘advlist autolink link lists charmap print preview hr anchor pagebreak spellchecker’,
 ‘searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking’,
 ‘save table contextmenu directionality emoticons template paste textcolor’
 ],
setup: function (editor) {
editor.addButton(‘newmedia’, {
 text: ‘Add media’,
 title: ‘Add image to article’,
 icon: ‘image’,
 onclick: function() {
$("#MediaModal").modal("show");
} });
 },
content_css: ‘https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css’,
 toolbar: "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link unlink newmedia"
});

[/php]

That is a basic initialize code for the TinyMCE editor. The magical part, which creates our custom button, is this:

[php]setup: function (editor) {
editor.addButton(‘newmedia’, {
text: ‘Add media’, // Text of button
title: ‘Add image to article’, // Tooltip text
icon: ‘image’, // This icon comes with TinyMCE
onclick: function() {
$("#MediaModal").modal("show"); // When user clicks our button, open modal
} });
}
[/php]

I have commented the code and most of it is pretty self-explanatory, but the important part is the onclick function. Code in that function is executed when the user clicks our custom button. In this case it shows our modal, ie. #MediaModal, which we will construct next.

2. Construct modal with images to select from

This piece of html markup creates our modal – #MediaModal.

[php]

<div id="MediaModal" class="modal fade" role="dialog">

<div class="modal-dialog modal-lg">

    <!– Modal content–>

<div class="modal-content">

<div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;</button>

<h4 class="modal-title">Image library</h4>

      </div>

<div class="modal-body">
<div class="row">
      

<div class="col-xs-4">
        <img class="img-responsive" src="photo1.jpg">
        </div>

<div class="col-xs-4">
        <img class="img-responsive" src="photo2.jpg">
        </div>

<div class="col-xs-4">
        <img class="img-responsive" src="photo3.jpg">
        </div>

        </div>

       
      </div>

<div class="modal-footer">
        <button type="button" class="btn btn-primary" id="InsertPhoto" data-id="" data-dismiss="modal">Insert to post</button>  <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
      </div>

    </div>

  </div>

</div>

[/php]

That’s a pretty basic Bootstrap modal with some images. Notice that id=”InsertPhoto” and data-id attributes on “Insert to post” button? We will be using them in our callback function.

Now that we have our modal set up, let’s add a bit of jQuery as our callback function which is fired when the user clicks “Insert to post” button on our modal. We will also make some styling, because we want our user to see which image is currently selected, when s/he clicks one. On our base html page we will have this style declaration:

[css]

<style>
#MediaModal img:hover {
border: #000 1px solid;
cursor: pointer;
}
.selected {
border: #000 2px solid;
}
</style>

[/css]

As you can see it makes our selected image surrounded with 2px thick black border and hovered image surrounded with 1px black border. Not very stylish, but you can improve that. At this point user has clicked our previously made custom button “Add media” and opened a modal dialog with the following view.

bsmodal

Now user can select an image by clicking it and then clicking “Insert to post”. For the selected image to actually appear in editor, we need to pass data of selected image back to TinyMCE editor. That’s why we will create a callback function to insert selected image to post.

3. Create a callback function to insert selected image to post

[php]

/* User clicks the "Insert to post" button */
$(‘#InsertPhoto’).click(function () {
$(‘#MediaModal’).modal("hide"); // Close the modal
var insmedia = $("#InsertPhoto").data(‘id’); // Save the data-id value of #InsertPhoto button to variable

/* If variable value is not empty we pass it to tinymce function and it inserts the image to post */
if (insmedia != "") {
tinymce.activeEditor.execCommand(‘mceInsertContent’, false, ‘<img src="’ + insmedia + ‘">’); }
});
/* When user clicks an image in the modal, we add .selected style class to that image and remove the class from the rest of the images */
$("#Mediamodal img").click(function () {
$("img").removeClass("selected");
$(this).addClass("selected");
var postimageid = $(this).attr(‘src’) //Grab the src value of selected image to variable
$("#InsertPhoto").data("id",postimageid); //Save the value to data-id attribute of #InsertPhoto button
})

$(‘#MediaModal’).on(‘show.bs.modal’, function (event) {
$("img").removeClass("selected");
$("#InsertPhoto").data("id",""); // Reset the data-id value of #InsertPhoto button
})

[/php]

By adding the code above, we now have functions to both send the data of selected image to TinyMCE editor and styling the clicked/selected image. Eventhough I have commented the code, let’s go through it a bit.

Basically the idea is that when user clicks an image, the following happens: The selected image gets added a css class .selected which paints the thick black border around it.

We also pass the src value ie. url of the image to variable and store it to data-id attribute of “Insert to post” button. When user actually decides to add the selected image to post s/he clicks the “Insert to post” button, then we grab the data-id value of it and if it’s not empty, we pass it to TinyMCE function:

[php]
if (insmedia != "") {
tinymce.activeEditor.execCommand(‘mceInsertContent’, false, ‘<img src="’ + insmedia + ‘">’); }
[/php]

And that marvellous function handles all the rest and our image appears in the article nicely!

Ok, this concludes our tutorial and now we have fully functional TinyMCE editor with our custom button to open Bootstrap modal dialog. Modal has (small) image library where user can select an image with mouse click and insert it to the post.

Thanks for reading.

Download example files Live demo