Pages

Friday, October 1, 2021

Popup TextArea Property Editor

Inline editing in Optimizely delivers a great editor experience due to the WYSIWYG approach for content authors. Sometimes, though, the inline editing can get cumbersome. When making a bunch of edits, or editing a complex component, it can be easier to edit out of line. When working with string properties in these scenarios, I like to use a popup editing box, and this is how I do it.

Constant inline updates can impact authoring

First, a little insight into what the issue is. Optimizely updates inline as you edit for most properties, when using the PropertyFor helper. If you are formatting string properties - adding extra styles, adding rendering logic, modifying the value in the page, etc... - the editor can sometimes differ enough that it gets in the way. It can also be difficult to tell you are in edit mode for strings in some situations. EditAttributes and DisplayTemplates give a little more control of the rendering, but you can use PreviewableText to help further.

Optimizely provides UIHint.PreviewableText for strings

PreviewableText allows you to edit string values outside of inline page formatting. This can be useful when you have titles or values that are formatted with custom styles like colors or fonts, that make them difficult to read. It adds a few more clicks to the process, but it can be very helpful. When you click inside an editable area in the page or block, a box pops up with a Change link to edit in a textbox within the popup.

Unfortunately, PreviewableText only presents a textbox, making it difficult to work with longer strings. There is a UIHint for longer strings called UIHint.TextArea, but that doesn't give the popup preview option. Additionally, PreviewableText also still updates inline as you type and if you use FullRefreshPropertiesMetaData this is especially annoying. 

To deal with these issues, I adapted PreviewableText to create PreviewableTextarea.

This approach involves a custom EditorDescriptor and a modified Dojo Dijit. The EditorDescriptor tells Optimizely which Dijit to load and adds a style to make the popup and textarea a bit wider than the out-of-box popup.

[pre class="brush:csharp;class-name:'collapse-box'" title="PreviewableTextareaDescriptor.cs"]
    [EditorDescriptorRegistration(TargetType = typeof(string), UIHint = "previewtextarea")]
    public class PreviewableTextareaDescriptor : EditorDescriptor
    {
        public PreviewableTextareaDescriptor()
        {
            base.ClientEditingClass = "shell/editors/PreviewableTextArea";
        }

        public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
        {
            base.ModifyMetadata(metadata, attributes);
            if (metadata is ContentDataMetadata)
            {
                metadata.EditorConfiguration["style"] = "width:400px;";
            }
        }
    }
[/pre]

 

The Dojo code is adapted from the PreviewableTextEditor Dijit that Optimizely includes. 

[pre class="brush:js;class-name:'collapse-box'" title="PreviewableTextArea.js"]
define("shell/editors/PreviewableTextArea", [
    "dojo/_base/array",
    "dojo/_base/declare",
    "dojo/dom-construct",

    "epi/shell/widget/ValidationTextarea",   // changed from ValidationTextBox to ValidationTextarea
    "epi-cms/contentediting/editors/_PreviewableEditor"
], function (
    array,
    declare,
    domConstruct,

    TextArea,
    _PreviewableEditor
) {
    return declare([_PreviewableEditor], {
        // tags:
        //      internal

        required: false,

        // controlParams: Array
        //      Properties to copy from this widget into the wrapped control
        controlParams: ["regExp", "required", "invalidMessage"],
                 // this function creates the TextArea to override the TextBox that would otherwise display
         buildRendering: function () {
             this.control = new TextArea(); 
            this.inherited(arguments);
        },

        _getRegExpAttr: function () {
            return this.regExp || "";
        }
    });
});
[/pre]

 

The PreviewableTextEditor Dijit references the ValidationTextBox for the editor control that gets loaded, so I changed it to the ValidationTextArea control. I also removed the "intermediateChanges" parameter to prevent the page or block from refreshing the view as I type.

This Dojo file is placed in the ClientResources/Scripts/Editors path in your solution.

Make sure module.config is set properly

If you don't have a module.config file already, create one in the root of your site. I have a basic copy of one below. The <dojo> node maps the path for the dojo files being used, referenced in the EditorDescriptor. If you use this, make sure you update the module/assemblies value to match your project.

[pre class="brush:xml;class-name:'collapse-box'" title="module.config"]
<?xml version="1.0" encoding="utf-8"?>
<module>
    <assemblies>
        <!-- This adds the template assembly to the "default module" -->
        <add assembly="EpiSandbox" />
    </assemblies>
    <clientResources>
        <add name="epi-cms.widgets.base" path="Styles/Styles.css" resourceType="Style"/>
    </clientResources>
    <dojo>
        <!-- This maps "shell" to ~/ClientResources/Scripts for the dojo loader configuration -->
        <paths>
            <add name="shell" path="Scripts" />
        </paths>
    </dojo>
</module>
[/pre]

 

The end result is a popup textarea editor

The UIHint attribute [UIHint("previewtextarea")] can be used for any string property to get the popup editor. Click an editable area and the popup box shows up. When the box is dismissed after editing, the view updates the value. If using FullRefreshPropertiesMetaData, the page will refresh when it's dismissed. 


 The full code is available here: Previewable Text Area.

No comments:

Post a Comment

Share your thoughts or ask questions...