Controlling URLs For Image Uploads

EditLive! includes the ability to automatically upload local images and when it does, the URL is changed to point to the new version on the server. The simplest way to control the resulting URL is to adjust the base attribute of the httpUpload element in your configuration file. When EditLive! uploads an image it simply appends the image name to the base you provide. So if the base is http://example.com/images/ and the image name is bob.jpg the resulting URL is http://example.com/images/bob.jpg

Sometimes though you need to change the directory or image name to avoid file conflicts or to better organize the image library (eg a folder for each page or each user). In those cases the image upload script can take control of generating the URL itself and simply pass it back to EditLive! All that's required is for the upload script to return only the URL to use on a single line. The URL can be absolute or relative - it will be used exactly as is by EditLive! so it needs to be correctly URL encoded. EditLive! will then ignore the base attribute and use the URL exactly as it was returned by the upload script.

Ephox Quarterly Product Update

To help keep our clients and partners up to date with the latest developments at Ephox, we'll be holding quarterly product update webinars to give you an overview of what's new and what's coming soon. The first of these will be held Wednesday 5th March and will be presented by Damien Fitzpatrick our Product Manager and myself (Adrian Sutton, CTO). We'll run the webinar twice to help avoid timezone issues:

US Timezone

11am PST, 5 March 2008. Register for this session

European Timezone

10am GMT, 5 March 2008. Register for this session

We'll also be providing a recorded version online afterwards for those who can't make it. We'll let you know here when that's available.

Upgrading EditLive! in RedDot version 7.5

In March last year RedDot released RedDot CMS version 7.5 and as part of that release they shipped a trial version of EditLive!.  It's not something that made it onto the press release, but if you dig through the release notes you'll find it there, along with instructions on how to use it.  Unfortunately though, the version of EditLive! that ships with RedDot CMS 7.5 is EditLive! 5.0.8, and if you've looked at the Ephox release blog any time recently, you'll know that that's a very old version of EditLive!.  

The good news is that here at Ephox we recently received a copy of RedDot CMS 7.5.  We can now provide support and instructions for those of you seeking to upgrade to the latest version of EditLive! in order to take advantage of functionality like track changes, improved styling capabilities and all those other features and bug fixes we've added in the last year or so.

If you're a RedDot user and would like to upgrade your EditLive! install all you need to do is follow these steps:

  1. Download a copy of the latest release of EditLive! from http://www.ephox.com/products/editlive/download.html and extract it.
  2. On your RedDot server go to the REDDOT_HOME/CMS/ASP/ephox/java directory where REDDOT_HOME is the location of your RedDot installation.
  3. From the EditLive! distribution copy the contents webfolder/redistributables/editlivejava directory into the RedDot "java" directory opened in step 2.  Overwrite any files when prompted.

…and that's it, you're done.  Any users now editing rich text content in RedDot CMS will be automatically updated to the latest version of EditLive! you've just installed.

EditLive! Configuration File for RedDot

As an important aside the configuration file for EditLive! in the RedDot integration is the Configuration.xml file located in the REDDOT_HOME/CMS/ASP/ephox directory.  This is where you'll need to add any license key you receive from Ephox or make customizations to EditLive! (e.g. changes to the menu or toolbar configuration).

Want to Know What's New Since EditLive! 5.0.8?

If you're a RedDot user who has evaluated the packaged integration and want to know what's in EditLive! 6.3 and what's shortly to be released in EditLive! 6.4 please get in touch with us via the web site.  We'll be running a series of webinars throughout March and April with myself (Damien Fitzpatrick, Product Manager) and Adrian Sutton, Ephox CTO, that will talk through the features added throughout the EditLive! 6.x releases.  We'll also be previewing what's coming throughout this year and most importantly, taking your feedback and suggestions.

Tutorial: Custom Components for Hyperlink Dialog

EditLive!’s “Hyperlink” dialog consists of a set of panels, used to insert hyperlinks from different sources. EditLive! allows you to customize this dialog, by adding your own custom panels. This can be done using the EditLive! Swing SDK, or as an Advanced API plugin.

For this example, I’ll be creating a custom panel plugin which lets you change the “id” and “class” of a hyperlink. Note: due to the design of the hyperlink dialog, these attributes will only be saved if this panel is active when the user clicks ok.

The key parts are:

  1. Creating the plugin and registering with EditLive!.
  2. Creating the panel.
  3. Writing the new attributes on save.
  4. Reading the existing link’s attributes on load.

1. Creating the plugin and registering with EditLive!

Firstly, we need a basic Advanced API plugin class. This involves creating a class which takes an ELJBean in its constructor. To actually load the plugin, there are other steps required, which are described in the EditLive! documentation. There are also previous LiveWorks! articles to help: Using Plugins To Extend EditLive! and Initializing Background Loading Plugins.

public class CustomPanel {
        public CustomPanel(ELJBean bean) {
        }
}

Next, we need a class which implements the HyperlinkDialogComponent interface in the Advanced API.  We might as well add this to the current class, as it’s not doing much else. For the moment, just provide dummy implementations for the interface’s methods (“Override/Implement Methods” in Eclipse).

public class CustomPanel implements HyperlinkDialogComponent {
...
}

To register this component as a hyperlink dialog, call the “addHyperlinkDialogComponent” bean method. We’ll do this in the constructor. The first parameter is the class that the Hyperlink dialog instantiates to create the custom panel.  In our instance, we’re adding the current class. I’ll discuss the second parameter in a minute.

public CustomPanel(ELJBean bean) {
        bean.addHyperlinkDialogComponent(this.getClass(), new Object[] { bean });
}

Now, when the hyperlink dialog instantiates a custom component, it looks for a constructor which takes an Object[] as its only parameter. So, we will need another constructor in our CustomPanel class.

private ELJBean bean;  
public CustomPanel(Object[] params) {
        this.bean = (ELJBean)params[0];
}

The Object array allows us to pass parameters through from the plugin to the custom panel. In this case, we’re passing a reference to the bean, which we’ll use later. Note that this class is instantiated twice – once as a plugin, and once as a dialog component. In real code it would probably be better to use a separate class for each role to avoid confusion.

2. Creating the panel

Now the framework is in place, its time to implement the HyperlinkDialogComponent methods. Let’s start with the getJComponent() method, which provides the actual panel displayed in the hyperlink dialog. For this example, I’ll use a simple form which asks for the “id” and “class” of the link.

public JComponent getJComponent() {
        panel = new JPanel(new BorderLayout());
        subPanel = new JPanel(new GridLayout(2, 2));
        panel.add(subPanel, BorderLayout.NORTH);
        panel.add(Box.createGlue());  
        subPanel.add(new JLabel("id"));
        idField = new JTextField();
        subPanel.add(idField);
        subPanel.add(new JLabel("class"));
        classField = new JTextField();
        subPanel.add(classField);
        return panel;
}

If you load the plugin now, it should display the panel, but the button to activate the panel will be blank. We can specify these with the getButtonImage() and getButtonText() functions. For simplicity, I’ll just leave the icon blank.

public ImageIcon getButtonImage() {
        return null;
}
public String getButtonText() {
        return "Advanced Link";
}

3. Writing the new attributes on save.

We now need to get the data from these fields into the actual hyperlink. This is done in the getAttributeMap method. This method gets an input of the current attributes of the link, including those from fields outside the switch panels (like the href, target and title). Add to this map, then return it.

I’ve also wrapped the map additions in a method which ensures the attribute is only in the map if its not blank which avoids adding redundant attributes to the HTML.

private void addIfSpecified(Map in, String name, String value) {
        if (!value.trim().isEmpty()) {
                in.put(name, value.trim());
        } else {
                in.remove(name);
        }
}

public Map getAttributeMap(Map in) {
        addIfSpecified(in, "id", idField.getText());
        addIfSpecified(in, "class", (String)classField.getText());
        return in;
}

4. Reading the existing link’s attributes on load.

At this stage, this panel will set the properties of the hyperlink, but if you edit an existing hyperlink, the custom panel’s fields will not display the current values. This is where we need the ELJBean object.

From the bean, we can get the HTMLPane object – this is the editing pane (JTextPane object) for the “design” view. We then call getInputAttributes to get the “a” element and its attributes. We can then populate our text fields with these attribute values.

private void setFieldFromAttribute(AttributeSet attrs, Object attribute, JTextField field) {
        Object value = attrs.getAttribute(attribute);          
        if (value != null) {
                field.setText(value.toString());
        }
}
public JComponent getJComponent() {
       …
       Object aTag = bean.getHTMLPane().getInputAttributes().getAttribute(HTML.Tag.A);
       if (aTag != null) {
                setFieldFromAttribute((AttributeSet)aTag, HTML.Attribute.CLASS, classField);
                setFieldFromAttribute((AttributeSet)aTag, HTML.Attribute.ID, idField);         
       }
       return panel;
}

There are 3 remaining interface methods which we don’t need for this example. They would be useful for things such as opening/closing connections to external systems.

public void setActive(boolean active) { }      
public void setHyperlinkDialog(HyperlinkDialog parent) { }
public void cleanUp() { }

Where to from here?

The custom panel is complete. Feel free to use this plugin as-is, or as a template for creating your own components.

This example sets special attributes of the hyperlink, however hyperlink dialog components could also be used to provide an integrated way of linking to existing content in a repository.

EditLive! also offers several alternatives for providing similar functionality.

With an Advanced API plugin, you could create an entire JDialog to replace the existing hyperlink dialog. Register this plugin as an EventListener, and listen for TextEvent.HYPERLINK_ACTION. When this event is triggered, display your dialog, then call event.setHandled(true) to prevent the built-in dialog from displaying. When the dialog closes, use the DocumentModifier methods (available from ELJBean.getDocumentModifier()) to edit the content.

Finally, a custom menu item or toolbar button can trigger a Javascript method, which you could use to pop up a new browser window which displays a specific URL containing the dialog. Then, you can use the “insertHTMLAtCursor” or “insertHyperlinkAtCursor” functions from our Javascript API to edit EditLive!’s content.

Download the Custom Hyperlink Dialog Plugin 

Overcoming Keyboard Shortcut Limitations in Mac Browsers

In many ways Java has a magnificent partnership with browsers operating on Mac. However, a partnership can never be perfect and Java and Mac is no exception.

One limitation of Java applets running in Mac browsers is that certain key combinations are consumed by Mac OS X and never passed to Java. One example that can be easily seen in EditLive! is when you attempt to open either the Edit or Insert menus via their respective mnemonics (option + E and option + I).

For developers wishing to circumvent this unfortunate limitation a solution can be found by changing the name attribute for menu configuration file elements. Adding the string & before a letter in the menu name will set this letter to be the new mnemonic.

For example, here is a snippet from an EditLive! configuration file where a menu has been specified that displays the text Edit. This menu has the letter D specified as the mnemonic.

...
<menu name="E&amp;dit">
   …
</menu>

Note: changing the name attribute for a menu configuration item from it's default internationalized version to a custom string value will cause the menu item to appear the same for each user regardless of their locale.

Controlling Entity Encoding

There are two key APIs that control how special characters such as non-english characters or complex punctuation are encoded in the HTML output from EditLive!

The setOutputCharset function allows you to control which character set is used when serializing the HTML content (see also Solving Character Set Issues With Legacy Systems). Any characters that are supported by that character set are output directly as single characters without any encoding, any characters that aren't supported are encoded. The outputXHTML and outputXML attributes control whether named or numeric entities are used (see our previous article on how and why that works). The table below shows how these two settings work together when outputting special characters.

  ASCII Output Charset UTF-8 Output Charset
outputXHTML or outputXML is true Numeric entities No encoding
outputXHTML and outputXML is false Named entities No encoding

The ASCII charset is one of the simplest charset and supports very few characters - it also tends to avoid any character set problems with other systems. The UTF-8 character set on the other hand can represent nearly any character supported by HTML directly as a character so you generally don't get any encoded characters.