Topics

Rich-text elements


In This Guide

Brightspot’s rich-text editor accommodates custom rich-text elements, such as embedded videos, image galleries, or pull quotes. For example, the following illustration is an example of a rich-text element rendered as a pull quote. The element contains typeface, alignment, and a left border.

Rich-text element.png


Deploying a rich-text element

The following steps outline how to design rich-text elements and attach them to the rich-text editor’s toolbar. Although the steps are specific to pull quotes, you can apply them to any custom rich-text element.

Step 1: Extend a rich-text element

All custom rich-text elements extend from RichTextElement.

import com.psddev.cms.db.RichTextElement;
import com.psddev.dari.db.Recordable;
import com.psddev.dari.util.StringUtils;

@Recordable.DisplayName("Pull Quote") 1
    @RichTextElement.Tag( 2
    value = "quote",
    preview = true,
    block = false,
    root = true,
    menu = "Enhancement")
public class PullQuoteRichTextElement extends RichTextElement {

    @Required
    private String quote;

    public String getQuote() {
        return quote;
    }

    public void setQuote(String quote) {
        this.quote = quote;
    }

    @Override 3
    public Map<String, String> toAttributes() {
        return null;
    }

    @Override
    public void fromAttributes(Map<String, String> attributes) {
    }

    @Override
    public void fromBody(String body) {
        setQuote(StringUtils.unescapeHtml(body));
    }

    @Override
    public String toBody() {
        return getQuote();
    }

}
  • Specifies the rich-text element displays as a pull quote in the rich-text toolbar.
  • Specifies the presentation aspects of the rich-text element:
    • The theme's data files use the value element for creating the view. In this snippet, the data files must provision the rich-text element using the identifier quote.
    • In the toolbar, the rich-text element appears under the menu item Enhancement.
    For information about the @RichTextElement.Tag annotation see @RichTextElement.Tag.
  • Overrides the methods toAttributes, fromAttributes, fromBody, and toBody. These methods provide the interface between the rich-text element and the associated editing widget. For details see Editing lifecycle of rich-text elements.

Step 2: Attach rich-text element to toolbar

import com.psddev.cms.rte.RichTextToolbar;
import com.psddev.cms.rte.RichTextToolbarItem;
import com.psddev.cms.rte.RichTextToolbarStyle;

public class CustomRichTextToolbar implements RichTextToolbar {

    @Override
    public List<RichTextToolbarItem> getItems() { 1
        return Arrays.asList(
            RichTextToolbarStyle.BOLD,
            RichTextToolbarStyle.ITALIC,
            RichTextToolbarStyle.UNDERLINE
            RichTextToolbarStyle.ELEMENTS);
    }

}
  • Attaches all custom rich-text elements to the toolbar.

Step 3: Create theme files

Under your project’s styleguide/ directory, create files for each field appearing in the rich-text element. For example, if a field body is typed as a rich-text field, then the theme’s files must provide the template, data file, and styling for the field body. As a best practice, ensure each file’s path and base name correspond to the rich-text element’s class. The following example provides an illustration for theme files corresponding to the class PullQuoteRichTextElement developed in Step 1.

./ 

└── <root> 

            ├── src |

                       └── main |

                                  └── java |

                                            └── brightspot |

                                                       └── content |

                                                                  └── article |

                                                                             └── PullQuoteRichTextElement.java 

             └── styleguide 

                        └── content  

                                   └── article 

                                              ├── PullQuoteRichTextElement.hbs 

                                              ├── PullQuoteRichTextElement.json 

                                              └── PullQuoteRichTextElement.less

For information about creating theming files, see Theme guide.

See also:


Editing lifecycle of rich-text elements

Subclasses of RichTextElement can implement the callbacks required for editing rich-text elements.

  • Inside the rich-text editor, clicking Edit fires two callbacks:

    • RichTextElement#fromBody to populate the editing widget’s Link Text field and the Main tab of the Link field.
    • RichTextElement#fromAttributes to populate the editing widget’s Attributes field in the Advanced tab.
  • Inside the editing widget, clicking Save & Close fires two callbacks to create a traditional HTML link of the form <a href="value" otherattribute="othervalue">link text</a>:

    • RichTextElement#toBody to retrieve the link text from the editing widget’s Link Text field.
    • RichTextElement#toAttributes to retrieve the link’s attributes from the editing widget’s Attributes field in the Advanced tab.
    Rich-text element lifecycle.svg
    Rich-text element lifecycle

The following snippet describes the interaction between the rich-text element and the editing widget.

import com.psddev.cms.db.RichTextElement;
import com.psddev.dari.util.CompactMap;
import com.psddev.dari.util.StringUtils;

public class AnotherLinkRichTextElement extends RichTextElement {

    @Required
    private Link link; 

    private String linkText; 

    public String getLinkText() {
        return linkText;
    }

    public void setLinkText(String linkText) {
        this.linkText = linkText;
    }

    @Override
    public void fromBody(String body) { 
        setLinkText(StringUtils.unescapeHtml(body));
    }

    @Override
    public String toBody() { 
        return getLinkText();
    }

    @Override
    public void fromAttributes(Map<String, String> attributes) { 
        List<Attribute> createdAttributes = attributes.keySet()
                .stream()
                .map(key -> {
                    Attribute attribute = new Attribute();
                    attribute.setName(key);
                    attribute.setValue(attributes.get(key));

                    return attribute;

                })
                .collect(Collectors.toList());

        link.setAttributes(createdAttributes);
    }

    @Override
    public Map<String, String> toAttributes() { 
        Map<String, String> htmlAttributes = new CompactMap<>(); 
        link.getAttributes()
                .forEach(attribute -> htmlAttributes.put(attribute.getName(), attribute.getValue()));
        return htmlAttributes; 
    }
}
  • Declares a Link field that contains the attributes in an HTML <a> element.
  • Declares a field, getter, and setter for the link text (the text inside an HTML <a> element.
  • Populates the field Link Text in the editing widget, unescaping any escaped HTML entities that may have been received from the rich-text element.
  • Retrieves the value in the field Link Text, and uses it as the link text when constructing an HTML <a> element.
  • Reads the attribute map passed from the rich-text element and populates the Attributes list in the editing widget's Advanced tab.
  • Reads the Attributes list in the editing widget's Advanced tab, and uses it to construct the attributes in an HTML <a> element.


Storage of rich-text elements

Brightspot stores rich-text elements in XML format, similar to the following:

{
  "caption": "Here is a link <a href=\"http://www.brightspot.com/\" target=\"_blank\" cursor=\"wait\" type=\"text/html\" >Brightspot</a>."
}

The element and attribute names you can use in a custom rich-text element are arbitrary, so you can design rich-text elements to fit your publishing needs. You then implement runtime parsers in view models that extract the elements and attributes from the database and populate the view.