<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Tuan Do</title><link href="http://world.optimizely.com" /><updated>2017-08-03T06:29:03.0000000Z</updated><id>https://world.optimizely.com/blogs/tuan-do/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Limiting items in a ContentArea</title><link href="https://world.optimizely.com/blogs/tuan-do/dates/2017/8/limiting-items-in-a-contentarea/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h2&gt;Feature&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;ContentArea&lt;/em&gt; should&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Supported to limits a number of block inside it (for individual &lt;em&gt;ContentArea&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;When total blocks is over max limited size, the action links section should be hidden.&lt;/li&gt;
&lt;li&gt;When total blocks is over max limited size, editor cannot DnD a block to that &lt;em&gt;ContentArea&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;h3&gt;The attribute&lt;/h3&gt;
&lt;p&gt;By using attribute, we can set individual limited total items for each ContentArea.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class MaxItemCountAttribute : Attribute
{
    public int Count { get; }

    public MaxItemCountAttribute(int maxItemCount)
    {
        Count = maxItemCount;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;The editor descriptor&lt;/h3&gt;
&lt;p&gt;We needed to extend both &lt;em&gt;ContentArea&lt;/em&gt; and &lt;em&gt;ContentAreaEditor&lt;/em&gt; widgets. Inside the custom editor descriptor, we read the value of attribute and then render it to client side.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Editor descriptor that extends the &amp;lt;see cref=&quot;ContentAreaEditorDescriptor&quot;/&amp;gt; for a &amp;lt;see cref=&quot;ContentArea&quot;/&amp;gt;
/// that marked with &amp;lt;see cref=&quot;MaxItemCountAttribute&quot;/&amp;gt; in order to limits total items inside it.
/// &amp;lt;/summary&amp;gt;
[EditorDescriptorRegistration(TargetType = typeof(ContentArea), UIHint = &quot;ContentAreaWithMaxItem&quot;)]
public class CustomContentAreaEditorDescriptor : ContentAreaEditorDescriptor
{
    public CustomContentAreaEditorDescriptor()
    {
        ClientEditingClass = &quot;alloy/contentediting/editors/CustomContentAreaEditor&quot;;
    }

    public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable&amp;lt;Attribute&amp;gt; attributes)
    {
        const string maxItemCount = &quot;maxItemCount&quot;;
        var maxItemCountAttribute = metadata.Attributes.OfType&amp;lt;MaxItemCountAttribute&amp;gt;().SingleOrDefault();
        if (maxItemCountAttribute != null)
        {
            metadata.EditorConfiguration[maxItemCount] = maxItemCountAttribute.Count;
            metadata.OverlayConfiguration[maxItemCount] = maxItemCountAttribute.Count;
        }

        base.ModifyMetadata(metadata, attributes);

        metadata.OverlayConfiguration[&quot;customType&quot;] = &quot;alloy/widget/overlay/CustomContentArea&quot;;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;The custom ContentAreaEditor&lt;/h3&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;define([
// dojo
    &quot;dojo/_base/declare&quot;,
    &quot;dojo/dom-style&quot;,
// epi
    &quot;epi-cms/contentediting/editors/ContentAreaEditor&quot;
], function (
// dojo
    declare,
    domStyle,
// epi
    ContentAreaEditor
) {
    return declare([ContentAreaEditor], {
        postCreate: function () {
            this.inherited(arguments);
            this._toggleDisplayActionLinks();
        },

        onChange: function (value) {
            this._toggleDisplayActionLinks();
        },

        _setValueAttr: function (value) {
            this.inherited(arguments);
            this._toggleDisplayActionLinks();
        },

        _toggleDisplayActionLinks: function () {
            var display = this._canAddItem();
            this.actionsContainer &amp;amp;&amp;amp; domStyle.set(this.actionsContainer, &quot;display&quot;, display ? &quot;&quot; : &quot;none&quot;);
            this.tree &amp;amp;&amp;amp; this.tree.set(&quot;readOnly&quot;, !display);
        },

        _canAddItem: function () {
            // tags:
            //      private

            if (this.maxItemCount == undefined) {
                return true;
            }

            return this.maxItemCount &amp;gt; this.model.get(&quot;value&quot;).length;
        }
    });
});&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;The custom ContentArea&lt;/h3&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;define([
// dojo
    &quot;dojo/_base/declare&quot;,
    &quot;dojo/dom-style&quot;,
// epi
    &quot;epi-cms/widget/overlay/ContentArea&quot;
], function (
// dojo
    declare,
    domStyle,
// epi
    ContentArea
) {
    return declare([ContentArea], {
        updatePosition: function () {
            this.inherited(arguments);
            this._toggleDisplayActionLinks();
        },

        executeAction: function (actionName) {
            this._toggleDisplayActionLinks();
            if (actionName === &quot;createnewblock&quot; &amp;amp;&amp;amp; !this._canAddItem()) {
                return;
            }

            this.inherited(arguments);
        },

        _onDrop: function (data, source, nodes, isCopy) {
            // isCopy:
            //      Flag indicating whether the drag is a copy. False indicates a move.
            // tags:
            //      protected extension

            this._toggleDisplayActionLinks();
            if (isCopy &amp;amp;&amp;amp; !this._canAddItem()) {
                return;
            }

            this.inherited(arguments);
        },

        _toggleDisplayActionLinks: function () {
            this.textWithLinks &amp;amp;&amp;amp; domStyle.set(this.textWithLinks.domNode, &quot;display&quot;, this._canAddItem() ? &quot;&quot; : &quot;none&quot;);
        },

        _canAddItem: function () {
            // tags:
            //      private

            if (this.maxItemCount == undefined) {
                return true;
            }

            return this.maxItemCount &amp;gt; this.getChildren().length;
        }
    });
});&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Start page&lt;/h3&gt;
&lt;p&gt;Add following&amp;nbsp;attributes&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[UIHint(&quot;ContentAreaWithMaxItem&quot;)]
[MaxItemCount(5)]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to &lt;em&gt;MainContentArea&lt;/em&gt; property&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[Display(
    GroupName = SystemTabNames.Content,
    Order = 320)]
[CultureSpecific]
[UIHint(&quot;ContentAreaWithMaxItem&quot;)]
[MaxItemCount(5)]
public virtual ContentArea MainContentArea { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Result&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;em&gt;On-Page Editing&lt;/em&gt; mode&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When total items inside the ContentArea is 4 (qualified with the max item count), action links section still displayed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/4e/9f/6b/4e9f6bbdc3234348f97e54484258603e.png&quot; width=&quot;1199&quot; alt=&quot;action links displayed when not over max size of limited items&quot; height=&quot;350&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The action links section in ContentArea is hidden when total items inside that ContentArea is 5.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/c2/5d/44/c25d4433a62732cb3b729c4f7a2a06fa.png&quot; width=&quot;972&quot; alt=&quot;hide action links in ContentArea on-page editing mode&quot; height=&quot;802&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;em&gt;On-Page Editing &lt;/em&gt;mode&amp;nbsp;with popup&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The action links section in ContentArea is hidden when total items inside that ContentArea are 5&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/75/79/75/757975259c60541b30043a64de922824.png&quot; width=&quot;807&quot; alt=&quot;hide action links in popup on-page editing mode&quot; height=&quot;476&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;em&gt;All Properties&lt;/em&gt; mode&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The action links section in ContentArea is hidden when total items inside that ContentArea are 5&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/44/6f/78/446f78ec77fdfd07a28c2eab3a529919.png&quot; width=&quot;793&quot; alt=&quot;hide action links in ContentArea all-properties mode&quot; height=&quot;504&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Related topics&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/link/cd88002025b544f2ade6441440e24911.aspx&quot;&gt;Show label for a ContentArea when hovering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2017-08-03T06:29:03.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Show overlay label for ContentArea when hovering in On-Page-Edit mode</title><link href="https://world.optimizely.com/blogs/tuan-do/dates/2017/7/show-overlay-label-for-contentarea-when-hovering-in-on-page-edit-mode/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;Following this forum thread - &lt;a href=&quot;/link/8cc90d703fb743e1b2805321913b5a86.aspx&quot;&gt;Show overlay label for ContentArea when hovering in On-Page-Edit mode&lt;/a&gt;, I created a custom content area to resolve it (in&amp;nbsp;Alloy MVC template).&lt;/p&gt;
&lt;p&gt;Firstly, to see how a property display its overlay label when hover, inspect its markup code&amp;nbsp;(in this case, I inspected logo on Start page). You will see it used &lt;strong&gt;infomationNode&amp;nbsp;&lt;/strong&gt;to showing:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/f6/7f/b7/f67fb7ffa6fc3a1adf52d1369da22ccc.png&quot; width=&quot;1045&quot; alt=&quot;informationNode dojo attach point&quot; height=&quot;405&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And then, looking in &lt;strong&gt;epi/shell/widget/overlay/Item&lt;/strong&gt; widget source, I found that overlay label value set by following code block:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/87/d1/3a/87d13a6b60a2a41b53bdf522f557502e.png&quot; width=&quot;1211&quot; alt=&quot;overlay label code block&quot; height=&quot;451&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Let&#39;s take a look in &lt;strong&gt;ContentArea&lt;/strong&gt; source code (see how to view source code at &lt;a href=&quot;/link/ae233441257c43f899c457011f466fdd.aspx&quot;&gt;link&lt;/a&gt;), it extended from &lt;strong&gt;epi/shell/widget/overlay/Item&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/5f/fe/a0/5ffea0ed15eb26e959e4ddbd332b60ab.png&quot; width=&quot;498&quot; alt=&quot;ContentArea source&quot; height=&quot;283&quot; /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;and also had it own template:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/83/3c/e9/833ce98cc48b9a8db5ca0a98ca1d7c50.png&quot; width=&quot;709&quot; alt=&quot;default ContentArea template&quot; height=&quot;490&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The above template missed &lt;strong&gt;informationNode&lt;/strong&gt; section, so that, nothing displayed when hover a ContentArea property in Edit mode. Well, to show overlay label for ContentArea, we just needed to add that section to ContentArea&#39;s template, like that&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/6a/1c/5e/6a1c5ecc604138f2059eb5063257d67e.png&quot; width=&quot;715&quot; alt=&quot;ContentArea with template have informationNode&quot; height=&quot;458&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;strong&gt;Let&#39;s do it step by step&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Create custom content area editor descriptor (under &quot;/Business/EditorDescriptors/&quot; folder)&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Editor descriptor that extends base editor descriptor for &amp;lt;see cref=&quot;ContentArea&quot;/&amp;gt; in order to show overlay label when hovering in On-Page-Edit mode
/// &amp;lt;/summary&amp;gt;
[EditorDescriptorRegistration(TargetType = typeof(ContentArea), UIHint = &quot;CustomContentArea&quot;)]
public class CustomContentAreaEditorDescriptor : ContentAreaEditorDescriptor
{
    public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable&amp;lt;Attribute&amp;gt; attributes)
    {
        base.ModifyMetadata(metadata, attributes);

        metadata.OverlayConfiguration[&quot;customType&quot;] = &quot;alloy/widget/overlay/CustomContentArea&quot;;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create custom content area template (under &quot;&lt;span&gt;/ClientResources/Scripts/widget/templates/&lt;/span&gt;&quot; folder), named &quot;CustomContentArea.html&quot;&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;epi-overlay-blockarea&quot;&amp;gt;
    &amp;lt;div class=&quot;epi-overlay-item-container&quot;&amp;gt;
        &amp;lt;div class=&quot;epi-overlay-bracket&quot;&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div data-dojo-attach-point=&quot;containerNode&quot; class=&quot;epi-overlay-blockarea-container&quot;&amp;gt;
        &amp;lt;span data-dojo-attach-point=&quot;informationNode&quot; class=&quot;epi-overlay-item-info&quot;&amp;gt;&amp;lt;/span&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div data-dojo-attach-point=&quot;actionsNode&quot; class=&quot;epi-overlay-blockarea-actionscontainer&quot;&amp;gt;
        &amp;lt;div data-dojo-attach-point=&quot;actionsNodeControls&quot; class=&quot;epi-overlay-blockarea-actions&quot;&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create custom content area widget (under &quot;/ClientResources/Scripts/widget/overlay/&quot; folder), named &quot;CustomContentArea.js&quot;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;define([
// dojo
    &quot;dojo/_base/declare&quot;,
// epi
    &quot;epi-cms/widget/overlay/ContentArea&quot;,
// resources
    &quot;dojo/text!../templates/CustomContentArea.html&quot;
], function (
// dojo
    declare,
// epi
    ContentArea,
// resources
    template
) {
    return declare(&quot;alloy.widget.overlay.CustomContentArea&quot;, [ContentArea], {
        templateString: template
    });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, add UIHint for MainContentArea&amp;nbsp;property of Start page&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[Display(
    GroupName = SystemTabNames.Content,
    Order = 320)]
[CultureSpecific]
[UIHint(&quot;CustomContentArea&quot;)]
public virtual ContentArea MainContentArea { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In additional, we have another way to marked all ContentArea properties to rendered with custom editor (without added [UIHint(&quot;CustomContentArea&quot;)] attribute for each)&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Editor descriptor that extends base editor descriptor for &amp;lt;see cref=&quot;ContentArea&quot;/&amp;gt; in order to show overlay label when hovering in On-Page-Edit mode
/// &amp;lt;/summary&amp;gt;
[EditorDescriptorRegistration(TargetType = typeof(ContentArea), EditorDescriptorBehavior = EditorDescriptorBehavior.OverrideDefault)]
public class CustomContentAreaEditorDescriptor : ContentAreaEditorDescriptor&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, here is the result when edit Start page&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s-media-cache-ak0.pinimg.com/originals/3e/e0/73/3ee0732ea16d0ee5ea62d9a531d5c39a.png&quot; width=&quot;637&quot; alt=&quot;custom content area show overlay label when hovering in on-page-edit mode&quot; height=&quot;447&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Related topics&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/link/216188c9af974124a6566bc65fd6b597.aspx&quot;&gt;Limiting items in a ContentArea&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2017-07-28T14:29:36.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>