TL;DR, code is at the bottom.
OK, this should work for you, but it is a beta. It works for me, but I haven't done any kind of rigorous testing. One thing, it doesn't output four consecutive
entities; it does a stuttered
[space]
[space]
, but at least it keeps them as-is when switching back-and-forth between Visual & Text modes. It only works in Visual mode, I haven't taken the time to figure out how to make it work in Text mode.
It comes in two files, name as you see fit. I used the highly imaginative name: 4Spaces. :) The TinyMCE button is on the top-row, far-right, of the editor. It'll show whatever your flavor of browser shows for non-existent images. That's easily changed in 4spaces.js, line 8:
image : url + '/' + 'YOUR_IMAGE_HERE.png'
Change `YOUR_IMAGE_HERE.png' to your image file, relative to the two files, or use an absolute URI like so:
image : '/path/to/image/YOUR_IMAGE_HERE.png'
or
image : 'http://example.com/path/to/image/YOUR_IMAGE_HERE.png'
I've commented and/or left some existing comments throughout the PHP, the JavaScript comments are sparse. You'll see in the PHP header section where the PHP code came from and kind of where the JavaScript originated.
Two notable credits, both listed in the PHP header: this WordPress.SE Answer that provided the code that stops TinyMCE (or WordPress, not sure which) from stripping out the spaces, and the link provided in the prior answer by @Alexey, which, while not critical, helped me stumble onto the JS solution.
I couldn't make the code in that link work, but eventually came back to it and found the nugget that brought it all together (with some tweaking, to be sure).
I think that about sums everything up. Here's the code:
4spaces.php
<?php
/* Plugin Name: 4Spaces
* Version: 0.1.0
* Author: AK Ted
* Author URI: http://akted.com
* License: GPLv2 or later
*
*
* PHP code adapted & refined from the following two sources:
* WordPress Codex - http://codex.wordpress.org/TinyMCE_Custom_Buttons#Loading_a_TinyMCE__Plugin
*
* WordPress Answers (Stack Exchange) - https://wordpress.stackexchange.com/questions/54398/how-can-i-stop-tinymce-from-converting-my-html-entities-to-characters#answer-54480
*
*
* The JavaScript arose from a lot of trial-and-error, with code [beat into submission...er, I mean] inspired by both of the following sources:
* tinymce wiki - http://www.tinymce.com/wiki.php/Creating_a_plugin
* &
* brett terpstra - http://brettterpstra.com/2010/04/17/adding-a-tinymce-button/
*
*/
new akt_4spaces();
class akt_4spaces {
function __construct() {
add_action('admin_init', array($this, 'init'));
} // function __construct
// callback for init
// sets all the hooks only if user has capability & rich_editing is true
function init() {
// Don't bother doing this stuff if the current user lacks permissions
if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') ) {
return;
}
// Add only in Rich Editor mode
if ( get_user_option('rich_editing') == 'true') {
add_filter('mce_buttons', array($this, 'add_button'));
add_filter('mce_external_plugins', array($this, 'add_tinymce_plugin'));
add_filter('tiny_mce_before_init', array($this, 'preserve_entities'));
}
} // function init
// callback for mce_buttons filter
// adds button to TinyMCE
function add_button($buttons) {
array_push($buttons, 'separator', 'four_spaces');
return $buttons;
} // function add_button
// callback for mce_external_plugins filter
// attaches the JavaScript file to TinyMCE
function add_tinymce_plugin($plugin_array) {
$plugin_array['four_spaces'] = plugins_url('/', __FILE__) . '4spaces.js';
return $plugin_array;
} // function add_tinymce_plugin
// callback for tiny_mce_before_init
// stops TinyMCE (WordPress?) from automatically converting entities
function preserve_entities( $initArray ) {
// The odd entries are the entity *number*, the even entries are the entity *name*. If the entity has no name,
// use the number, prefixed with a hash (for example, the service mark is "8480,#8480").
$initArray['entities'] = '160,nbsp,' . $initArray['entities'];
return $initArray;
} // function preserve_entities
} // class akt_4spaces
4spaces.js
(function() {
tinymce.create('tinymce.plugins.four_spaces', {
init : function(ed, url) {
// Register four_spaces button
ed.addButton('four_spaces', {
title : '4Spaces',
image : url + '/' + 'YOUR_IMAGE_HERE.png',
onclick : function() {
ed.execCommand(
"mceInsertContent",
false,
" "
);
}
});
}
});
// Register plugin
tinymce.PluginManager.add('four_spaces', tinymce.plugins.four_spaces);
})();
Edit: I forgot to mention, for those who don't know, put both of those files into a directory under /wp-content/plugins/
(default path). It should look something like
/wp-content/plugins/4spaces/
or whatever name you decide to call it, then activate it in Admin.
P.S. - I'm relatively new to OOP, so welcome any and all criticisms, advice, etc., from anyone viewing this answer.