Wednesday, April 15, 2009

Prevent Nested Execution of a Custom Tag

After discovering this little gem of a function "GetBaseTagList()" I was able to find an easy solution to an issue I was facing on a recent project. (Thank you once again, Ben Nadel, http://www.bennadel.com/blog/657-Determine-The-Parent-ColdFusion-Custom-Tag-Hierarchy-Using-GetBaseTagList-.htm.)

I needed to wrap each display box with a shadow, and I wanted to be able to edit it, site-wide, easily in one place.

The issue was that if a content box was included within another content box I did not want to display the nested execution of the shadow wrapper. I tried to think if various ways to count the executions to do this manually, but they were all messy and potentially buggy. Thanks to the native function "GetBaseTagList()" that is no longer an issue. It displays the nested execution hierarchy with the current one first and the initial ancestor last. So, "ListRest(GetBaseTagList())" will display any and all parents in order. But if things were complicated and there were other nested tags involved (probably not a good idea), or we just wanted to be clear, specific, on the safe side and prepare for whatever idiot might touch the project in the future, then we might want to count only instances of the current custom tag "ListFindNoCase(ListRest(GetBaseTagList()),"CF_CONTENTWRAPPER")". This worked beautifully. See the full code example below.



<!--- contentwrapper.cfm  -  <cf_contentwrapper>content</cf_contentwrapper> --->

<!--- DON'T ALLOW NESTED INSTANCES OF THIS CUSTOM TAG CONTENT WRAPPER! --->


<cfif (ListFindNoCase(ListRest(GetBaseTagList()),"CF_CONTENTWRAPPER") IS 0)>

    <cfif thisTag.executionMode EQ "start">


    <table border="1" cellspacing="0" cellpadding="0">
        <tr>
            <td class="wrapshadow_tl"></td>
            <td class="wrapshadow_tc"></td>
            <td class="wrapshadow_tr"></td>
        </tr>
        <tr>
            <td class="wrapshadow_ml"></td>
            <td class="wrapshadow_mc">
                <!--- tag body contents are displayed in here --->
   
    <cfelse>

                <!--- tag body contents are displayed in here --->   
            </td>
            <td class="wrapshadow_mr"></td>
        </tr>
        <tr>
            <td class="wrapshadow_bl"></td>
            <td class="wrapshadow_bc"></td>
            <td class="wrapshadow_br"></td>
        </tr>
    </table>

           
    </cfif>

</cfif>




Now, this will display as intented:


<!--- content1.cfm --->

<cf_contentwrapper> <!--- this custom tag will only execute when it's not included inside another instance --->
    <div style="width:400px; height:50px;">testing content 1</div>
</cf_contentwrapper>



<!--- content2.cfm --->

<cf_contentwrapper> <!--- this custom tag will only execute when it's not included inside another instance --->
    <div style="width:400px; height:50px;">testing content 2</div>
    <cfinclude template="content1.cfm"><!--- the nested custom tag in the included file will not process, but the content1 html will display --->
</cf_contentwrapper>



Isn't that just grand?