SemButtons: My First WordPress PlugIn

I have written a WordPress plugin to rearrange the buttons in the post editor (the regular one, not the fancy WYSIWYG one) in a way more to my liking. It changes the names of some buttons, removes others I rarely use, and adds a few more I do use.

The code involves some really awful hacks and is a confusing mix of CSS, JavaScript, and PHP. I use CSS to hide the buttons I don’t like, and JavaScript to change the names of existing buttons and add new ones. PHP integrates this whole mess into WordPress. WordPress wasn’t really designed to support this level of customization. That’s why I have to use JavaScript to change the buttons after the page is loaded.

There are several features yet to be added:

  • Abbr and acronym need pop-ups requesting the title, like the link button has for href.
  • The span button needs a pop-up requesting the class.
  • I need to reorder the buttons. In particualr I want the more button at the end.
  • It needs a user-accessible, non-code-level API for adjusting behavior.
  • I need to figure out how not to load these scripts on pages that do not have the edit box? Currently these generate JavaScript errors.

It may well only work in FireFox. I haven’t tested it in Internet Explorer or Opera, and it uses heavy CSS and DOM so there are likely cross-browser issues. In Safari, I can change the button names and add new buttons. However you can’t use CSS to style the buttons I’m removing. (Update: that was due to a bug in the CSS. It’s fixed now and this works in Safari too.) ) I may have to change that to use JavaScript too.

And I need to put this all in source code control, and use a decent IDE. Does Eclipse have a PHP plugin? Looks like there are several. Which one should I use?

Anyway here’s iteration 0.1 of the plug-in:

<?php

/*
Plugin Name: SemButtons
Version: 0.1
Plugin URI: http://www.elharo.com/SemButtons.html
Description: This plugin makes the WordPress editor button bar more semantic.
Author: Elliotte Rusty Harold
Author URI: http://www.elharo.com/
Update:
*/

// SCRIPT INFO ///////////////////////////////////////////////////////////////////////////

/*
    SemButtons for WordPress
    © 2007 Elliotte Rusty Harold - GNU General Public License

    This has only been tested with Firefox. The JavaScript may not work on other browsers. 

    This WordPress plugin is released under the GNU General Public License.

    This WordPress plugin is released "as is". Without any warranty.


    ToDo list:

    Abbr and acronym need pop-ups requesting the title.
    span needs a popup requesting the class.
    Make buttons reorderable.
    Provide a user-accessible, non-code-level API for adjusting behavior.
    Add a Tidy button to make posts well-formed.
    Can we avoid hooking in on pages that do not have the edit box?
    Put this all in source code control, and use a decent IDE. 

*/

add_action('admin_head', 'remove_buttons');
add_action('admin_footer', 'change_names');
add_action('admin_footer', 'add_buttons');

function remove_buttons(){
    ?>
      <style type="text/css">
         #ed_lookup, #ed_spell, #ed_del, #ed_ins, #ed_close { display:none;
      </style>
    <?php 
}

function change_names() {
  ?>
    <script type='text/javascript'>
        // Probably should separate ID and name into two separate arguments
        change_button('ed_em', 'em');
        change_button('ed_strong', 'strong');
        function change_button(id, name) {
            var button = document.getElementById(id)
            button.setAttribute('value', name)
        }
    </script>        
  <?php 
}

function add_buttons(){
  ?>
   <script type="text/javascript">
    make_button('span', 3);
    make_button('cite', 2);
    make_button('abbr', 1);
    make_button('acronym', 0);

    // The i variable is an unbelievably ugly hack, perhaps
    // worthy of a daily WTF. The problem is one must pass 
    // the distance from the end of the array because JavaScript 
    // can't figure that out. PHP can't get the value from JavaScript.
    // There must be a better way to do this. Possibly it will
    // all fall out in the wash when I allow the position of individual 
    // buttons to be specified.
    function make_button(name, i) {

        var toolbar = document.getElementById('ed_toolbar');
        
        edButtons[edButtons.length] = 
        new edButton('ed_' + name,
          name,
          '<' + name + '>',
          '</' + name + '>',
          's'
        );
        
        var button = document.createElement("input");
        button.setAttribute("value", name);
        button.setAttribute("id", "ed_" + name);
        button.setAttribute("class", "ed_button");
        button.setAttribute("type", "button");
        button.setAttribute("onClick", "edInsertTag(edCanvas, edButtons.length-1-" + i + ");");
        button.setAttribute("accesskey", name);
        toolbar.appendChild(button);
    }
  </script>                
 <?php 
}
 ?>

Copy and paste this or download it.

Doubtless there are ways to improve this. Neither JavaScript nor PHP is my first language. Please comment if you see a simpler way to do anything.

Thanks to everyone on wp-hackers who helped out by answering questions and catching my mistakes.

2 Responses to “SemButtons: My First WordPress PlugIn”

  1. johnbillion Says:

    Elliotte,

    Just a couple of pointers for you, from a fellow WP-hacker :) You’ve missed a closing parenthesis in the function remove_buttons() at the end of the line display:none;

    Also it’s good practise to declare a function in JavaScript (like in any other language) before you call it, so you need to move your JavaScript function change_button() up two lines so it’s declared before you call it. The same goes for the function make_button().

    I haven’t tried this plugin out but it looks good!

    Regards, johnbillion

  2. Elliotte Rusty Harold Says:

    Is it really necessary to declare a function before you call it? If so, why? It’s certainly not necessary in Java. It is necessary in C, but C is a very old language designed to fit in systems with 32K of memory where the entire program couldn’t be stuffed into memory first.

    I’ll fix the closing parenthesis. I’m surprised that worked at all. That makes this work with Safari now too.

Leave a Reply