building custom controls

I’m implementing a custom control - an option transfer where you can shuttle items from one multi-select element to another (see http://blog.jeremymartin.name/2008/02/easy-multi-select-transfer-with-jquery.html). So, if anyone has already created this and would be willing to share that would be appreciated :).

Aside from that, I do have a general question about building custom controls. The Technical Reference Guide talks about how, in general, to create a custom control - i.e. where to put the .xsl file, that DTD that it uses and such. However, what I don’t find is a complete picture of the interaction between the form and Percussion engine, how you get the control persist data and all the details that have gone into making the existing controls work. Can someone provide a more complete picture or point me some other documents? I have the front end working on the form where you can shuttle the values back and forth, but it’s not persisting anything and obviously I need to understand better the full chain of responsibility here.

Thanks!

Thanks,
Duane

When defining a custom control, there are 3 places you can put the code for them:

[ol]
[li]sys_resources/stylesheets/sys_Templates.xsl - Only edit this file if you absolutely must. Any time patches or updates are applied, this file will be overwritten with system defaults.[/li][li]rx_resources/stylesheets/rx_Templates.xsl - This file was the standard place to put custom controls prior to the advent of package builder.[/li][li]rx_resources/stylesheets/controls/controlName.xsl - In 6.7 and later, they recommend you place code for custom controls in files in the controls folder. I’ve not been able to implement this approach myself with complete success yet.[/li][/ol]

Within these XSL files, a control definition is made up of 2 parts:

Control Metadata

This section defines the properties that you can set for your control, the default values of the properties, and files that the edit form will need to include in order to make the control work.

Example:


<psxctl:ControlMeta name="rx_myGreatControl" dimension="single" choiceset="none">
    <psxctl:Description>Does something cool.</psxctl:Description>
    <psxctl:ParamList>
        <psxctl:Param name="greatness" datatype="String" paramtype="generic">
            <psxctl:Description>Indicates how great this control is.</psxctl:Description>
            <psxctl:DefaultValue>datadisplay</psxctl:DefaultValue>
        </psxctl:Param>
    </psxctl:ParamList>
    <psxctl:AssociatedFileList>
        <psxctl:FileDescriptor name="myGreatStyles.css" type="css" mimetype="text/css">
            <psxctl:FileLocation>../rx_resources/css/myGreatStyles.css</psxctl:FileLocation>
            <psxctl:Timestamp/>
        </psxctl:FileDescriptor>
        <psxctl:FileDescriptor name="myGreatScripts.js" type="script" mimetype="text/javascript">
            <psxctl:FileLocation>../rx_resources/js/myGreatScripts.js</psxctl:FileLocation>
            <psxctl:Timestamp/>
        </psxctl:FileDescriptor>
    </psxctl:AssociatedFileList>
    <psxctl:Dependencies>
        <psxctl:Dependency status="readyToGo" occurrence="single">
            <psxctl:Default>
                <PSXExtensionCall id="0">
                    <name>Java/global/percussion/generic/myGreatExtension</name>
                </PSXExtensionCall>
            </psxctl:Default>
        </psxctl:Dependency>
    </psxctl:Dependencies>
</psxctl:ControlMeta>

I’m not entirely certain how the dependencies section works, but I think you can trigger extension calls with it… don’t include it in your definition if you don’t need it.

Control Display and Behavior Templates

This section looks a lot more like standard XSL code. You can provide templates to render your control in a couple of different “modes” which corelate to different sections of the rendered page:

[ul]
[li]psxcontrol-body-onload - Any text rendered in this mode will be placed inside the edit form page’s body onload attribute. Keep the output short. Call functions you define in .js files or womething.[/li][li]psxcontrol - This controls the actual display of the field for your control in the edit form. Your templates can optionally match against read-only status as well (most do).[/li][/ul]

Example:


<xsl:template match="Control[@name='rx_myGreatControl' and @isReadOnly='yes']" priority="10" mode="psxcontrol">
    <xsl:value-of select="Value"/>
</xsl:template>

<xsl:template match="Control[@name='rx_myGreatControl']" mode="psxcontrol">
    <xsl:variable name="greatness">
        <xsl:choose>
            <xsl:when test="ParamList/Param[@name='greatness']">
                <xsl:value-of select="ParamList/Param[@name='greatness']"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="document('')/*/psxctl:ControlMeta[@name='rx_myGreatControl']/psxctl:ParamList/psxctl:Param[@name='greatness']/psxctl:DefaultValue"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <input name={@paramName} type="text" value="{Value}"/> greatness: <xsl:value-of select="$greatness"/>
</xsl:template>

<xsl:template match="Control[@name='rx_myGreatControl']" mode="psxcontrol-body-onload">
    <xsl:if test="not(preceding::Control[@name='rx_myGreatControl'])">
        <xsl:text>initMyGreatControls();</xsl:text>
    </xsl:if>
</xsl:template>

Persisting Your Values

The examples above don’t have any guts in them, but in reality you could have just about anything. The only critical component in your control’s rendering is that there must be an HTML form input element with a name of “{@paramName}” defined. Rhythmyx can deal with check-box groups or multi-selects if you set the “dimension” value of your control to “array.” The value or selections of this element will be saved to the back-end repository.

Now, to Answer Your Question

If you are doing anything complex, as you seem to be in your problem description, you’ll want to have a hidden control with the actual selected value(s) in it.

In the example you describe, you have 2 multi-select boxes… but in order to persist your selections with an “array” dimension, you’ll want a 3rd multi-select that’s hidden, that has all the same options as what’s in the right-hand multi-select, but where all the options in this box are set to “selected”. If you want to persist data as a “single” dimension (which lets you use it in child tables, if necessary), then you should have a hidden input whose value you create by concatenating all the option values in the right-hand multi-select.

When you do finish your control, post it in the code snippets forum. It sounds like it’d be a great addition to have in any arsenal.


I hope that clears a few things up.

Thanks for explaining this, I really appreciate it. Especially the big about having to create a 3rd hidden multi-select, that wasn’t obvious to me. I’ll certainly share this with the forum once I get everything working.