Crestron Components Lib - Showcase App

ch5-select: template processing

Emulator Scenario (click to expand)
{
  "cues": [
    {
      "type": "b",
      "event": "multiselect_1_clicked_1",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_1_selected_1",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_1_clicked_2",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_1_selected_2",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_1_clicked_3",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_1_selected_3",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_1_clicked_4",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_1_selected_4",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_2_clicked_1",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_2_selected_1",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_2_clicked_2",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_2_selected_2",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_2_clicked_3",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_2_selected_3",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_2_clicked_4",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_2_selected_4",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_3_clicked_1",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_3_selected_1",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_3_clicked_2",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_3_selected_2",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_3_clicked_3",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_3_selected_3",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_3_clicked_4",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_3_selected_4",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "boolean",
      "event": "select_item_1_on_click",
      "trigger": true,
      "actions": [
        {
          "state": "item_selected_after_click",
          "type": "number",
          "logic": "set",
          "value": 1
        }
      ]
    },
    {
      "type": "boolean",
      "event": "select_item_2_on_click",
      "trigger": true,
      "actions": [
        {
          "state": "item_selected_after_click",
          "type": "number",
          "logic": "set",
          "value": 2
        }
      ]
    },
    {
      "type": "boolean",
      "event": "select_item_3_on_click",
      "trigger": true,
      "actions": [
        {
          "state": "item_selected_after_click",
          "type": "number",
          "logic": "set",
          "value": 3
        }
      ]
    },
    {
      "type": "boolean",
      "event": "select_item_4_on_click",
      "trigger": true,
      "actions": [
        {
          "state": "item_selected_after_click",
          "type": "number",
          "logic": "set",
          "value": 4
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_4_clicked_1",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_4_selected_1",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_4_clicked_2",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_4_selected_2",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_4_clicked_3",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_4_selected_3",
          "type": "b",
          "logic": "toggle"
        }
      ]
    },
    {
      "type": "b",
      "event": "multiselect_4_clicked_4",
      "trigger": true,
      "actions": [
        {
          "state": "multiselect_4_selected_4",
          "type": "b",
          "logic": "toggle"
        }
      ]
    }
  ],
  "onStart": [
    {
      "type": "string",
      "state": "label_signal_1",
      "logic": "set",
      "value": "Option 1"
    },
    {
      "type": "string",
      "state": "label_signal_2",
      "logic": "set",
      "value": "Option 2"
    },
    {
      "type": "string",
      "state": "label_signal_3",
      "logic": "set",
      "value": "Option 3"
    },
    {
      "type": "string",
      "state": "label_signal_4",
      "logic": "set",
      "value": "Option 4"
    },
    {
      "type": "string",
      "state": "label_signal_5",
      "logic": "set",
      "value": "Option 5"
    },
    {
      "state": "receive_html_script_label_1",
      "type": "string",
      "logic": "set",
      "value": "<span style='color:green'>Option toggle</span> <span style='color:red'>label 1</span>"
    },
    {
      "state": "receive_html_script_label_2",
      "type": "string",
      "logic": "set",
      "value": "<span style='color:green'>Option toggle</span> <span style='color:red'>label 2</span>"
    },
    {
      "state": "receive_html_script_label_3",
      "type": "string",
      "logic": "set",
      "value": "<span style='color:green'>Option toggle</span> <span style='color:red'>label 3</span>"
    },
    {
      "state": "receive_html_script_label_4",
      "type": "string",
      "logic": "set",
      "value": "<span style='color:green'>Option toggle</span> <span style='color:red'>label 4</span>"
    },
    {
      "state": "receive_image_url_1",
      "type": "string",
      "logic": "set",
      "value": "https://imgplaceholder.com/40x40/transparent/757575/glyphicon-star"
    },
    {
      "state": "receive_image_url_2",
      "type": "string",
      "logic": "set",
      "value": "https://imgplaceholder.com/40x40/transparent/757575/glyphicon-picture"
    },
    {
      "state": "receive_image_url_3",
      "type": "string",
      "logic": "set",
      "value": "https://imgplaceholder.com/40x40/transparent/757575/glyphicon-random"
    },
    {
      "state": "receive_image_url_4",
      "type": "string",
      "logic": "set",
      "value": "https://imgplaceholder.com/40x40/transparent/757575/glyphicon-king"
    }
  ]
}

Press the Load button to load the scenario.

Press the Run button to run the scenario. You only need to do this if the scenario (the json) has an onStart key.

The Emulator Scenario JSON contains an array of cues and an optional array onStart A cue is defined by: type:string, signal:string, trigger:boolean|string|number, actions:array. An action is defined by: type:string, signal:string, logic:string ... plus other fields ( depending on type)

type for cue or for action can be the string:

  • b or boolean - for a boolean signal
  • n or number or numeric - for a number signal
  • s or string - for a string signal
  • o or object - for an object signal

signal for cue or for action is a string representing the name of the signal:

trigger can be either a fixed value of the same type as the signal, or the string "&change". If it is a fixed value then, when the emulator detects that the signal has changed to the value given in trigger then it also executes the actions for that signal. If the value is the string "&change", regardless of signal type, then the actions are executed on any change in the value of the signal.

logic can be:

  • link - passes the value received on the incoming join through to the outgoing join. Using this between incompatible join types will attempt to cast the value. In the event of a cast failure the value will be set to false, 0 or "" (empty string)
  • set - assigns a specific value to the join. This requires a 5th key of 'value' and the specific value to assign. ie. {"signal":"light_level", "type":"n", "logic": "set","value":5}. If the 5th key is omitted, the default value will be sent (false, 0, "" or {})
  • toggle - (boolean Only) reads the current state and changes it to the opposite state
  • pulse - (boolean Only) value goes high and then low.
  • increment - (Numeric Only) reads the current value of the analog and adds an offset. This logic accepts an optional 5th key of 'offset which determines how many to incrementby. ie. {"signal":"volume_level","type":"n", "logic":"increment","offset":5}. If this 5th key is omitted, the default offset of 1 will be applied.
  • decrement - (Numeric Only) reads the current value of the analog and subtracts an offset. This logic accepts an optional 5th key of 'offset which determines how many to decrement by. ie. {"signal":"volume_level","type":"n", "logic":"decrement","offset":5}. If this 5th key is omitted, the default offset of 1 will be applied.

RCB logic can be accomplished by defining an action containing an object signal of RCB type:
{ "rcb":{ "value": numeric_value, "time": duration_in_ms } }
Scenario example:


    {
      "cues": [
        {
          "type": "boolean",
          "signal": "trigger",
          "trigger": true,
          "actions": [
            {
              "signal": "action1",
              "type": "boolean",
              "logic": "toggle"
            },
            {
                "signal": "rcb_signal",
                "type": "object",
                "logic": "set",
                "value": {
                    "rcb":{
                        "value": 101,
                        "time": 1500
                    }
                }
            }
          ]
        }
      ],
      "onStart": [
      ]
    }
    

Component Configuration (click to expand)
{
  "templatevariables": {
    "id": {
      "direction_select": [
          {"description": "North", "fa-icon": "up"},
          {"description": "South", "fa-icon": "down"},
          {"description": "East", "fa-icon": "right"},
          {"description": "West", "fa-icon": "left"}
        ]
    }
  }
}

Press the Load button to load the configuration.

Ch5 components can be preconfigured with default values for attributes and for templatevariables. The configuration can be done using Ch5Config and its methods:

  • loadConfig(config:TCh5Config) loads a new configuration and overrides the existing one.
  • setAttributeForId(elementId:string, attributeName:string, attributeValue:string) sets an attributeValue for an attributeName of the specified HTML elementId
  • setAttributeForComponent(componentName:string, attributeName:string, attributeValue:string) sets an attributeValue for an attributeName of the specified ch5 component (componentName)
  • setTemplateVarsForId(elementId:string, tempVarsItems:any[]) sets the template variables for the ch5 component having the specified elementId
  • getConfig() returns the current configuration object
  • getAttributesForId(elementId:string):TCh5ConfigAttributes returns the configrued attributes for the component having the specified elementId
  • getAttributesForComponent(componentName:string):TCh5ConfigAttributes returns all configured attributes for the component specified in componentName ( for example 'ch5-button')
  • getTemplateVarsForElementById(elementId:string):TCh5ConfigTemplateVars[] returns the configured template variables for the component having the specified elementId
  • getAttributesForElement(cr:Ch5Common):TCh5ConfigAttributes returns all configured attributes for a ch5 component
  • getTemplateVarsForElement(cr:Ch5Common):TCh5ConfigTemplateVars[] returns all configured templatevariables for a ch5 component


type TCh5ConfigAttributes={
    [attrName:string]: string
}
type TCh5ConfigTemplateVars={
    [varName:string]: string
}
type TCh5Config={
    "attributes": {
        "id": {
            [id:string]:TCh5ConfigAttributes
        },
        "component": {
            [component:string]:TCh5ConfigAttributes
        }
    },
    "templatevariables": {
        "id": {
            [id:string]:TCh5ConfigTemplateVars[]
        }
    }
}

ch5-select: template processing

Options creation is depending on the following attributes: size, indexId, receiveStateTemplateVars and "templatevariables" from global config data.


By default, when we have a template defined, the option is created using "templatevariables" data and can be updated by receiveStateTemplateVars signal data. When an option is selected the top line will display the entire option html (singleselection case) or a list of comma separated labels/"N items selected" (multiselect case). Note: For multiselect make sure receiveStateLabel is used to provide option label. If this signal attribute is not used, multiselect top line will display empty values as label.

Example 1: ch5-select in mode plain. Each option description is set from global config "templatevariables" (in this case).

Example 2: ch5-select, multiselect=false, default template, iconPosition=first

Example 3: ch5-select, multiselect=false, default template, iconPosition=last

Example 4: ch5-select, multiselect=true, default template and iconPosition=first

Note: for all multiselect examples option labels are set using the same receiveStateLabel signals set. Also, receiveStateUrl signals are providing default template image URL.

Since ch5-toggle has no receiveStateSelected attribute, ch5-select-option.receiveStateSelected is also used to set ch5-toggle.receiveStateValue.

For multiselect with default template ch5-select-option.sendEventOnClick is not sent by option element, it is assigned to ch5-toggle.

Example 5: ch5-select, multiselect=true, default template and iconPosition=last

Example 6: ch5-select, multiselect=true, default template and receiveStateScriptLabelHTML

- receiveStateScriptLabelHTML signal is used to set ch5-toggle label

Example 7: ch5-select, multiselect=false, feedbackMode=submit and default template.

Dirty:

Example 8: ch5-select, multiselect=true, feedbackMode=submit and default template.

Dirty:

Issues using default template for multiselect:
  • using receiveStateScriptLabelHTML, UI looks bad with 2 labels (option label provided by receiveStateLabel) and ch5-toggle label (provided by receiveStateScriptLabelHTML)
  • No way to set on/off ch5-toggle labels, unless we add 2 more new attributes on ch5-select-option
<div class="row">
    <p><strong>Example 1:</strong> ch5-select in mode plain. Each option description is set from global config
    "templatevariables" (in this case).</p>
    
    <ch5-select id="direction_select" size="4" indexId="Index" noneSelectedPrompt="Select">
        <template>
            <ch5-select-option>
                <div>
                    <i class="fas fa-arrow-{{fa-icon}}"></i>
                    <span>item_{{Index}} {{description}}</span>
                </div>
            </ch5-select-option>
        </template>
    </ch5-select>
    
</div>

<div class="row">
    <p><strong>Example 2:</strong> ch5-select, multiselect=false, default template, iconPosition=first</p>
    
    <ch5-select id="singleselect-icon-first" size="4" indexId="Index" noneSelectedPrompt="Select">
        <template>
            <ch5-select-option sendEventOnClick="user_select_clicked_{{Index}}" useDefaultTmpl
                                receiveStateLabel="label_signal_{{Index}}"
                                receiveStateUrl="receive_image_url_{{Index}}">
            </ch5-select-option>
        </template>
    </ch5-select>
    
</div>

<div class="row">
    <p><strong>Example 3:</strong> ch5-select, multiselect=false, default template, iconPosition=last</p>
    
    <ch5-select id="singleselect-icon-last" size="4" indexId="Index" noneSelectedPrompt="Select"
        mode="panel">
        <template>
            <ch5-select-option sendEventOnClick="user_select_clicked_{{Index}}"
                                useDefaultTmpl iconPosition="last"
                                receiveStateLabel="label_signal_{{Index}}"
                                receiveStateUrl="receive_image_url_{{Index}}">
            </ch5-select-option>
        </template>
    </ch5-select>
    
</div>

<div class="row">
    <p><strong>Example 4:</strong> ch5-select, multiselect=true, default template and iconPosition=first</p>
    <p>
        <strong>Note: </strong> for all multiselect examples option labels are set using the same receiveStateLabel
        signals set. Also, receiveStateUrl signals are providing default template image URL.<br><br>
        Since ch5-toggle has no receiveStateSelected attribute, ch5-select-option.receiveStateSelected is also used
        to set ch5-toggle.receiveStateValue.<br><br>
        For multiselect with default template ch5-select-option.sendEventOnClick
        is not sent by option element, it is assigned to ch5-toggle.
    </p>
    
    <ch5-select id="multiselect_1" size="4" indexId="Index" noneSelectedPrompt="Select"
        mode="panel" multiselect>
        <template>
            <ch5-select-option sendEventOnClick="multiselect_1_clicked_{{Index}}"
                                receiveStateSelected="multiselect_1_selected_{{Index}}"
                                useDefaultTmpl
                                receiveStateLabel="label_signal_{{Index}}"
                                receiveStateUrl="receive_image_url_{{Index}}">
            </ch5-select-option>
        </template>
    </ch5-select>
    
</div>

<div class="row">
    <p><strong>Example 5:</strong> ch5-select, multiselect=true, default template and iconPosition=last</p>
    
    <ch5-select id="multiselect_2" size="4" indexId="Index" noneSelectedPrompt="Select"
        mode="panel" multiselect>
        <template>
            <ch5-select-option sendEventOnClick="multiselect_2_clicked_{{Index}}"
                                receiveStateSelected="multiselect_2_selected_{{Index}}"
                                useDefaultTmpl iconPosition="last"
                                receiveStateLabel="label_signal_{{Index}}"
                                receiveStateUrl="receive_image_url_{{Index}}">
            </ch5-select-option>
        </template>
    </ch5-select>
    
</div>

<div class="row">
    <p><strong>Example 6:</strong> ch5-select, multiselect=true, default template and receiveStateScriptLabelHTML</p>
    <p>- receiveStateScriptLabelHTML signal is used to set ch5-toggle label</p>
    
    <ch5-select id="multiselect_3" size="4" indexId="Index" noneSelectedPrompt="Select"
        mode="panel" multiselect>
        <template>
            <ch5-select-option sendEventOnClick="multiselect_3_clicked_{{Index}}"
                                receiveStateSelected="multiselect_3_selected_{{Index}}"
                                useDefaultTmpl
                                receiveStateLabel="label_signal_{{Index}}"
                                receiveStateScriptLabelHTML="receive_html_script_label_{{Index}}"
                                receiveStateUrl="receive_image_url_{{Index}}">
            </ch5-select-option>
        </template>
    </ch5-select>
    
</div>

<div class="row">
    <p><strong>Example 7:</strong> ch5-select, multiselect=false, feedbackMode=submit and default template.</p>
    
        <ch5-select id="default_tmpl_f_submit_single"
                     size="4" indexId="Idx"
                     receiveStateValue="item_selected_after_click"
                     feedbackMode="submit"
                     noneSelectedPrompt="Select"
                     mode="panel">
             <template>
                <ch5-select-option sendEventOnClick="select_item_{{Idx}}_on_click"
                                    useDefaultTmpl
                                    receiveStateLabel="label_signal_{{Idx}}"
                                    receiveStateUrl="receive_image_url_{{Idx}}">
                </ch5-select-option>
             </template>
        </ch5-select>
    
    <p style="margin-top: 24px;">
        Dirty: <span id="dirty-select-1"></span><br><br>
        <ch5-button id="submit-btn-1" label="Submit"></ch5-button>
        <ch5-button id="reset-btn-1" label="Reset"></ch5-button>
    </p>
</div>

<div class="row">
    <p><strong>Example 8:</strong> ch5-select, multiselect=true, feedbackMode=submit and default template.</p>
    
        <ch5-select id="default_tmpl_f_submit_multi"
                     size="4" indexId="Idx"
                     feedbackMode="submit"
                     noneSelectedPrompt="Select options(s)"
                     mode="panel" multiselect>
             <template>
                <ch5-select-option sendEventOnClick="multiselect_4_clicked_{{Idx}}"
                                    receiveStateSelected="multiselect_4_selected_{{Idx}}"
                                    useDefaultTmpl
                                    receiveStateLabel="label_signal_{{Idx}}"
                                    receiveStateUrl="receive_image_url_{{Idx}}">
                </ch5-select-option>
             </template>
        </ch5-select>
    
    <p style="margin-top: 24px;">
        Dirty: <span id="dirty-select-2"></span><br><br>
        <ch5-button id="submit-btn-2" label="Submit"></ch5-button>
        <ch5-button id="reset-btn-2" label="Reset"></ch5-button>
    </p>
</div>

<div class="row">
    <!-- TODO: remove this after issues are fixed -->
    <strong>Issues using default template for multiselect:</strong>
    <ul>
        <li>using receiveStateScriptLabelHTML, UI looks bad with 2 labels (option label provided by receiveStateLabel) and
        ch5-toggle label (provided by receiveStateScriptLabelHTML)</li>
        <li>No way to set on/off ch5-toggle labels, unless we add 2 more new attributes on ch5-select-option</li>
    </ul>
</div>