Uploading images using TinyMCE’s Browse Button

It is a bit surprising that the current version of TinyMCE does not support the uploading of images. While there are a handful of plugins that will manage this for you, I felt that most of them were too heavy for the small part TinyMCE has to play in the app I am working on. For those who may be in the same boat, here’s how you can minimally integrate TinyMCE image uploads.

Note: This post assumes that you have included JQuery and TinyMCE on your page.

Browsers are very finnicky when it comes to file uploads, and rightfully so, since file uploads need to access the user’s hard drive. Therefore, we need to create a hidden file upload form somewhere on our page

<form style="display:none" id="fileUploadForm" method="post">
    <input id="fileUploader" type="file" name="fileUpload"  />
</form>

Next, lets setup our barebones TinyMCEInstance. (Make sure you wrap this in a $(document).ready)

 

tinymce.init({
		selector: '#editor',
		plugins: "image",
		toolbar: "image",		
		file_picker_callback: function(callback, value, meta) {
			if (meta.filetype == 'image') {
				$("#fileUploader").unbind( "change" );
				$("#fileUploader").change(function(event) { onFileChosen(event,callback);});
				$("#fileUploader").click();
			}
		},
		convert_urls: false,
});

The file_picker_callback option provides a callback function when the user clicks the browse button in the images dialog. Consequently, the browse button does not show up unless this option is specified.
tinmce

This callback function is called whenever a media browse button is clicked in TinyMCE. In this example, we only want to handle when the user clicks the browse button in the images dialog, so we wrap our function body in

if (meta.filetype == 'image') {
}

The next two lines bind to the change function of our hidden file upload form.

$("#fileUploader").unbind( "change" );
$("#fileUploader").change(function(event) { onFileChosen(event,callback);});

You may be asking youself why we have to bind to the change event every time. This is because our change function has to pass the callback variable to the onFileChosen function. You could technically get away with a global variable and only binding when the document is ready, but I found this method to be cleaner.

Lastly, we trigger the input click event to open the user’s file browser

$("#fileUploader").click();

Now the handler function is a little long, but its not too horrible

function onFileChosen(event,callback)
{
  //Detach any current submit handlers
  $("#fileUploadForm").unbind("submit");
  $("#fileUploadForm").submit(function(e) {

    e.stopPropagation(); // Stop stuff happening
    e.preventDefault(); // Totally stop stuff happening
		
    //Prepare file in form for transmission via ajax call
    var formData = new FormData();
    $.each(event.target.files, function(i, file) {
        formData.append('file-'+i, file);
    });

    //The url that will handle the file upload
    var url = "http://yourdomain.com/tinymce_upload"

    //Do ajax call
    $.ajax({
      type: "POST",
      url: url,
      data: formData,
      cache: false,
      contentType: false,
      processData: false,
      success: function(data)
      {	
        //You can process the response however you want, but I chose to return a json string
        var response = JSON.parse(data)[0];
				
        if(response.succeeded == true)
        {
          //This is the important part. This callback will tell TinyMCE the path of the uploaded image
          callback(response.newPath);
        }
        else{
          alert("The image upload was not successful. Reason:" + response.status);
        }
      },
    });

  });
  $("#fileUploadForm").submit();
}

Now you should be able to upload a file and when the function returns, TinyMCE’s image dialog will have the new file url in the source box.

2 thoughts on “Uploading images using TinyMCE’s Browse Button

  1. The post refers to a “callback” function. Is that function defined somewhere? If not, could you give an example of it?

    1. There are two callback functions in the article. The file_picker_callback specified inside of init is a function that you give to tinyMCE which it will call when the user clicks on the upload button.

      When tinyMCE calls your file_picker_callback function, it passes it’s own callback function as the first parameter. The only way to let tinyMCE know what the uploaded image’s url is to send it back via the provided callback function, i.e. callback(“http://example.com/urltoimage.png”)

      We give tinyMCE’s callback to the onFileChosen method by rebinding the “change” event of the #fileUploader input with tinyMCE’s callback as part of the closure:

      $(“#fileUploader”).change(function(event) { onFileChosen(event,callback);});

Leave a Reply

Your email address will not be published. Required fields are marked *