I have a button in my truck that no longer works. I have the full knowledge of how to use it, have done so often, but really have no clue what really goes on under the hood when I click it.

That goes for interface buttons too. And that’s design, no matter how complex things are, I as a button clicker don’t need to know.

As a button maker, I do.

What’s all this button talk? I recently made a big leap (towards simpler) with the TRU Writer SPLOT theme.

In it’s near five year run (born December 5, 2014), it’s relied on a cheap trick to let people upload media to something they are writing, editing from outside the WordPress interface what is done inside. To access the media uploader (and a few other things), this SPLOT (and others) did this trick of invisible logging in a visitor as a hidden user.

This new version did away with the secret logins, and simplified the checking of access codes to save a bunch of round robin web redirects. I was able to create a dropzone/click to media for the featured image (this is done via PHP when the form is submitted to check content) but had lost the ability to upload/insert in the middle of writing (this is done the old way via some ajax into the WordPress media library; this is impossible when not logged in).

This bothered me.

The front end editor used in this SPLOTs is something called tinyMCE, it’s more or less the old Classic Editor Which People Love to Death. It’s integrated into WordPress and I can invoke it in my form template pages via the wp_editor() command.

There’s a lot of web pages in the tinyMCE documentation but it’s not too directly applicable to WordPress, where it is set up somewhere inside the big blue engine.

I was able to get a simple image button activated in the editor:

arrow pointing to the Insert Image button icon in the editor

This presents a dialog box, but you have to have a full URL for where an image exists. This is entered as Source:

Insert/edit image dialog box

It does work, and images inserted this way can be aligned, resized, add captions, etc. But it’s not nearly as useful as an uploader; how many people can ferret the full URL for an image they want to use? And what if it’s an image on their own computer?

By the way, for the code readers, this is done in WordPress by adding a filter for mce_buttons

add_filter('mce_buttons','truwriter_tinymce_buttons');

The function I have had some code to remove the button for the “more” thing in WordPress (it’s not needed in the parent theme), I just had to add one line to get the image button in the mix. I forgot where I even found this trick.

function truwriter_tinymce_buttons($buttons) {
	//Remove the more button
	$remove = 'wp_more';

	// Find the array key and then unset
	if ( ( $key = array_search($remove,$buttons) ) !== false )
		unset($buttons[$key]);
	// now add the image button in
	$buttons[] = 'image';

	return $buttons;
 }

I chase around all kinds of coding rabbit holes trying to find out how to implement an upload button. I got hints that it was built in via the tinyMCE documentation, but their method of doing it via JavaScript got me nowhere. This codepen did what i wanted, but it’s method does not work in any way could see via WordPress. This question got me thinking in another direction.

i finally figured out/guessed that the tiny_mce_before_init filter was a way to add the settings I saw others doing in plain Javascript. And that got me going on what we have now… the insert image button now has an Upload tab:

Insert image dialog button with Upload tab.

And the interface all comes with what tinyMCE provides- a button click to get a file selector or a dropzone.

Insert image upload tab with button "Browse for an image" and an area marked DROP AN IMAGE HERE

The thing I had to write was a JavaScript function that would upload via ajax and a WordPress side function to process a callback from that script.

But it works, you can see it in action at http://splot.ca/writer/write – the screen shots above were all created in the Writer when using the form to write http://splot.ca/writer/2019/706.

As an interface sidenote, when I DM-ed it to Tom Woodward to test, he responded that he could not get it to work (he was expecting the old Add media button or drag and drop in the writing area that you can do in WordPress). He actually just missed the tiny icon, which I can understand. So I kludged in the present interface where this a text button next to it labeled “Insert Image”! It’s hokey because all this button does when clicked is send a click event to the button with the image icon.

And now… code! Yay! Or RUN AWAY.

Here is what I have in WordPress for adding the initialization for the upload sequence. It’s largely lifted from the tinyMCE docs on rolling your own image uploader, it’s adding an images_upload_handler callback

add_filter( 'tiny_mce_before_init', 'truwriter_tinymce_settings' );

function truwriter_tinymce_settings( $settings ) {

	$settings['images_upload_handler'] = 'function (blobInfo, success, failure) {
    var xhr, formData;

    xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open(\'POST\', \'' . admin_url('admin-ajax.php') . '\');

    xhr.onload = function() {
      var json;

      if (xhr.status != 200) {
        failure(\'HTTP Error: \' + xhr.status);
        return;
      }

      json = JSON.parse(xhr.responseText);

      if (!json || typeof json.location != \'string\') {
        failure(\'Invalid JSON: \' + xhr.responseText);
        return;
      }

      success(json.location);
    };

    formData = new FormData();
    formData.append(\'file\', blobInfo.blob(), blobInfo.filename());
    formData.append(\'action\', \'truwriter_upload_action\');
    xhr.send(formData);
  }';

The thing that makes it work in WordPress is using the URL for it’s ajax handler for the URL to open, and appending to the data a value for action to indicate the WordPress function in my code to handle the upload.

This is to show the fiddling around on one thing can payoff later. I created most of this function while doing some tests for a WordPress dropzone uploader.

We add two actions to let this request be handled via ajax, whether logged in or not.

// this is the handler used in the tiny_mce editor to manage image upload
add_action( 'wp_ajax_nopriv_truwriter_upload_action', 'truwriter_upload_action' ); //allow on front-end
add_action( 'wp_ajax_truwriter_upload_action', 'truwriter_upload_action' );

function truwriter_upload_action() {	

    $newupload = 0;

    if ( !empty($_FILES) ) {
        $files = $_FILES;
        foreach($files as $file) {
            $newfile = array (
                    'name' => $file['name'],
                    'type' => $file['type'],
                    'tmp_name' => $file['tmp_name'],
                    'error' => $file['error'],
                    'size' => $file['size']
            );

            $_FILES = array('upload'=>$newfile);
            foreach($_FILES as $file => $array) {
                $newupload = media_handle_upload( $file, 0);
            }
        }
    }
    echo json_encode( array('id'=> $newupload, 'location' => wp_get_attachment_image_src( $newupload, 'large' )[0], 'caption' => get_attachment_caption_by_id( $newupload ) ) );
    die();	
}

I can say I know about 90% of what it does 😉

Putting the extra button in was something I had done a while ago for the Timebuddy Plugin thing I made for Virtually Connecting. I first register a button, and set it to a the Javascript code that gives the button something to do.

add_filter("mce_external_plugins", "truwriter_register_buttons");

function truwriter_register_buttons( $plugin_array ) {
	$plugin_array['imgbutton'] = get_stylesheet_directory_uri() . '/js/image-button.js';
	return $plugin_array;
}

And here is what that button does- it says, “Hi! My name is Image button. If you click me I will click button number 12.” (I wish I could give these buttons IDs).

(function() {
    tinymce.PluginManager.add('imgbutton', function( editor, url ) {
        editor.addButton( 'imgbutton', {
            text: 'Insert Image',
            icon: false,
			onclick: function() {
				jQuery('#mceu_12-button').click();
			}
        });
    });
})();

It’s got all the functionality of the WordPress media uploader, maybe a bit less of its elegance, but it does the job. This is all worth it to have a SPLOT not using those shaky invisible logins, and is easier to set up (there are no longer required plugins), especially on multisite.

This has already been rolled into a new authorless version of SPLOTbox (that’s another post for another day). But also, these experiments in creating uploads is also put into play in a soon to be released venti sized update to the DS106 Assignment bank theme.

That button has legs.

If only I could program that button in my truck.


Image Credit:

If this kind of stuff has value, please support me by tossing a one time PayPal kibble or monthly on Patreon
Become a patron at Patreon!
Profile Picture for CogDog The Blog
An early 90s builder of web stuff and blogging Alan Levine barks at CogDogBlog.com on web storytelling (#ds106 #4life), photography, bending WordPress, and serendipity in the infinite internet river. He thinks it's weird to write about himself in the third person. And he is 100% into the Fediverse (or tells himself so) Tooting as @cogdog@cosocial.ca

Leave a Reply

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