Rich-text elements
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 that the rich-text element appears as Pull Quote in the rich-text toolbar. | |
Specifies presentation aspects of the rich-text element:
For information about the | |
Overrides the methods |
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. See the illustration Quote element under enhancement toolbar menu. |
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.
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.
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; 1 private String linkText; 2 public String getLinkText() { return linkText; } public void setLinkText(String linkText) { this.linkText = linkText; } @Override public void fromBody(String body) { 3 setLinkText(StringUtils.unescapeHtml(body)); } @Override public String toBody() { 4 return getLinkText(); } @Override public void fromAttributes(Map<String, String> attributes) { 5 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() { 6 Map<String, String> htmlAttributes = new CompactMap<>(); link.getAttributes() .forEach(attribute -> htmlAttributes.put(attribute.getName(), attribute.getValue())); return htmlAttributes; } }
Declares a | |
Declares a field, getter, and setter for the link text (the text inside an HTML | |
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 use it as the link text when constructing an HTML | |
Reads the attribute map passed from the rich-text element and populate the Attributes list in the editing widget's Advanced tab. | |
Reads the Attributes list in the editing widget's Advanced tab, and use it to construct the attributes in an HTML |
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.