Skip to content

mxm, IT's mad science

Sections
Personal tools
You are here: Home » Papers » Extending kupu for Plone #1
Downloads
You can download mxm products here.

Due to it's technical and international nature, this section is in english.

Max M Has a blog too.

og er glad for mad

 

Extending kupu for Plone #1

I found it difficult to write code for adding a new button to Kupu, so I am retracing my steps here in the hope that it might help others.

To add the graphics

All templates that needs to be modified are in kupu/plone/kupu_plone_layer

Find "kupu_wysiwyg_support.html".

Find the toolbar div with these definitions:

    <div class="kupu-tb" id="toolbar">

Add a buttongroup and a button as html with the following pattern:

      <span class="kupu-tb-buttongroup" id="kupu-bg-alert">
        <button type="button" class="kupu-alert" id="kupu-alert-button" 
                title="alert popup" i18n:attributes="title" accesskey="d">&#160;</button>
      </span>

class="kupu-tb-buttongroup" is the default css class for kupu buttons.

id="kupu-bg-alert" is an id that is set for this particular group. It is not really necessary in this case as there is only one button.

When it comes to the button itself, the most important ting is to set the class, as it is used later by JavaScript to register an event handler against.

The look of the button is also made with class="kupu-alert". For this you need to make a css class. You can either add it to "kupustyles.css" or to your "ploneCustom.css".

Most of the css is allready set by the "kupu-tb-buttongroup" class, so it is enough just to point to set the backrgound image to a 20px*20px gif:

    kupu-alert {background-image: url("alert.gif");}

To add the code

For the button to work we need to attach an event handler to the it. We use the helper kupu specific function "addEventHandler":

    addEventHandler(element, event, method, context)
        - bind <method> to <event> on <element>, using <context> as context 
          ('this' inside the method body).

The direct way to do it is by writing code that looks a bit like this:

    function alertMe(){
      alert('Be aware. The button was pressed!');
    }
    button = getFromSelector(buttonid);
    addEventHandler(button, 'click', alertMe, this)

The "getFromSelector(selector)" function is a replacement for window.document.getElementById()

It first tries to get the button from the selector, which is a string with this pattern: "#id tag.class"

If that fails it reverses to getElementById(selector)

But Kupu has a standard way of defining buttons with event handlers in code, so we just use that method. To do so we must define a subclass of KupuTool::

First we create a simple button class called DynaButton:

      function DynaButton(buttonid){
        // A tool for making a button that shows an alert
        this.buttonid = buttonid;
        this.button = getFromSelector(this.buttonid);

        this.initialize = function(editor) {
            // The initialize method is called automaticaly by Kupu
            // This is where we add the event handler.
            this.editor = editor;
            addEventHandler(this.button, 'click', this.execCommand, this);
        };

        this.execCommand = function(){
            // This method is called on an event
            alert('Something happened!');
        };

      }

      // Make it a subclass of KupuTool
      DynaButton.prototype = new KupuTool;

We make it a subclass of the KupuTool that is defined in 'kupu/common/kupubasetools.js':

      DynaButton.prototype = new KupuTool;

We make an instance and register it with Kupu:

      // make an instance and register it with Kupu
      // id needs to be a uniqe 'selector', to allow more than 1 kupu/page
      var uniqId = prefix+'button.kupu-dyna'
      // prefix is defined in 'kupuploneinit.js'
      // example if field is called text:
      // uniqId = '#kupu-editor-text button.kupu-dyna'
      var dynabutton = new DynaButton(uniqId);
      kupu.registerTool('dynabutton', dynabutton);

Now, when we press the new button en Kupu, we get an alert box.

Summary

The complete chunk of html in "kupu_wysiwyg_support.html":

    <span class="kupu-tb-buttongroup" id="kupu-bg-alert">
      <button type="button" class="kupu-alert" id="kupu-alert-button" 
              title="alert popup" i18n:attributes="title" accesskey="d">&#160;</button>
    </span>

The css class to go with that. Remember to add the alert.gif:

    .kupu-alert {background-image: url("alert.gif");}

The complete chunk of javascript that is added to "kupuploneinit.js" is:

    function AlertButton(buttonid){
      // A tool for making a button that shows an alert
      this.buttonid = buttonid;
      this.button = getFromSelector(this.buttonid);

      this.initialize = function(editor) {
          // The initialize method is called automaticaly by Kupu
          // This is where we add the event handler.
          this.editor = editor;
          addEventHandler(this.button, 'click', this.execCommand, this);
      };

      this.execCommand = function(){
          // This method is called on an event
          alert('Something happened!');
      };
    }

    AlertButton.prototype = new KupuTool;

    // make an instance and register it with Kupu
    var uniqId = prefix+'button.kupu-alert'
    var alertbutton = new AlertButton(uniqId);
    kupu.registerTool('alertbutton', alertbutton);

Appendix

I made an example which takes the selected text and inserts a span tag around it. It also sets some attributes on the span tag. I figure someone else might need this too:

    function DynaButton(buttonid){
      // A tool for making a button that shows an dyna
      this.buttonid = buttonid;
      this.button = getFromSelector(this.buttonid);

      this.initialize = function(editor) {
          // The initialize method is called automaticaly by Kupu
          // This is where we add the event handler.
          this.editor = editor;
          addEventHandler(this.button, 'click', this.execCommand, this);
      };

      this.makeDynaSpan = function(doc, uid, view){
          // Makes a span with dynatag attributes
          // TODO: need to check first that we are not inside another dynafield tag
          var newnode = doc.createElement('span');
          // sets the class to dynafield
          newnode.setAttribute('class', 'dynafield');
          if (uid){
              newnode.setAttribute('dynafield:uid', uid);
          }
          if (view){
              newnode.setAttribute('dynafield:view', view);
          }
          return newnode;
      }

      this.getUidAndView = function(){
          // get the uid and view from Plone (just a stub)
          return ['2cb5fcda62e41430a6a6d3032f2b1a07', 'description_view']
      }

      this.execCommand = function(){
          // This method is called on an event
          kupu = this.editor
          var doc = kupu.getInnerDocument();
          var uidAndView = this.getUidAndView()
          var uid = uidAndView[0];
          var view = uidAndView[1];
          newnode = this.makeDynaSpan(doc, uid, view)
          // add put selected text inside the span
          var selection = doc.getSelection();
          var text = doc.createTextNode(selection);
          newnode.appendChild(text);
          kupu.insertNodeAtSelection(newnode, 1);
      };
    }

    DynaButton.prototype = new KupuTool;

    // make an instance and register it with Kupu
    var uniqId = prefix+'button.kupu-dyna'
    var dynabutton = NoContextMenu(new DynaButton(uniqId));
    kupu.registerTool('dynabutton', dynabutton);

This code transforms this text in kupu:

    This is an example result

To this text (minus the code folding):

    This is an <span dynafield:view="description_view" 
                dynafield:uid="2cb5fcda62e41430a6a6d3032f2b1a07" 
                class="dynafield">example</span>result

Created by maxm
Last modified 2007-09-20 12:37 PM