This is how my custom tag for building forms TerraForm does it. There
are a couple of gotchas. 1) the order of the items in the stack trace is
reversed between CF5 and CFMX. 2) CFMX6.1 (and 7 I think) has a few
entries in the stack trace where the template is just the drive letter,
so you just skip these ones. This code looks rather fragile and I dread
the day it stops working....
Here's the TF code:
<!--- calculate path back to calling template. This will be used for
intelligently processing paths supplied by the developer. We have one
report of this not working on a CF5 platform. It seems as if there is
nothing returned in the cfcatch.tagcontext array. If this is the case,
relative paths will not work. --->
<cfset SUB = Chr(26)>
<cfset parentTemplate = "">
<cftry>
<cfthrow message="No error. Just examining tag context.">
<cfcatch type="Any">
<!--- the cfcatch.tagcontext array is in reverse order
on the CFMX server --->
<cfif listfirst(server.coldfusion.productversion) eq 5>
<!--- CF5 server --->
<cfloop index="i"
from="#arraylen(cfcatch.tagcontext)#" to="1" step="-1">
<cfif cfcatch.tagcontext[i].template neq
getcurrenttemplatepath()>
<cfset parentTemplate =
cfcatch.tagcontext[i].template>
<cfbreak>
</cfif>
</cfloop>
<cfelse>
<!--- CFMX server --->
<cfloop index="i" from="1"
to="#arraylen(cfcatch.tagcontext)#">
<cfif cfcatch.tagcontext[i].template neq
getcurrenttemplatepath() and len(cfcatch.tagcontext[i].template) gt 1>
<!--- bugfix for 6.1: 6.1 spits out "template paths" of just one letter
(apparently the drive letter) sometimes. Skip these. --->
<cfset parentTemplate =
cfcatch.tagcontext[i].template>
<cfbreak>
</cfif>
</cfloop>
</cfif>
</cfcatch>
</cftry>
<cfset currenttemplatefolder =
getdirectoryfrompath(getcurrenttemplatepath())>
<cfif len(parentTemplate)> <!--- if the code above did not fail... --->
<cfset parentTemplateFolder =
getdirectoryfrompath(parentTemplate)>
<cfloop index="i" from="1"
to="#min(listlen(parentTemplateFolder, "/\"),
listlen(currenttemplatefolder, "/\"))#">
<cfif listGetAt(parentTemplateFolder, i, "/\") eq
listGetAt(currenttemplatefolder, i, "/\")>
<cfset currenttemplatefolder =
listSetAt(currenttemplatefolder, i, SUB, "/\")>
<cfset parentTemplateFolder =
listSetAt(parentTemplateFolder, i, SUB, "/\")>
<cfelse>
<cfbreak>
</cfif>
</cfloop>
<cfset relativePathToParentTemplateFolder = "">
<cfloop index="i" from="#listLen(currenttemplatefolder, "/\")#"
to="1" step="-1">
<cfset folder = listGetAt(currenttemplatefolder, i,
"/\")>
<cfif folder eq SUB>
<cfbreak>
</cfif>
<cfset relativePathToParentTemplateFolder =
listPrepend(relativePathToParentTemplateFolder, "..", "\")>
</cfloop>
<cfloop index="i" from="1" to="#listLen(parentTemplateFolder,
"/\")#">
<cfset folder = listGetAt(parentTemplateFolder, i,
"/\")>
<cfif folder neq SUB>
<cfset relativePathToParentTemplateFolder =
listAppend(relativePathToParentTemplateFolder, folder, "\")>
</cfif>
</cfloop>
<cfif len(relativePathToParentTemplateFolder)>
<cfset relativePathToParentTemplateFolder =
relativePathToParentTemplateFolder & "\">
</cfif>
</cfif>
-----Original Message-----
From: Barney Boisvert [mailto:[EMAIL PROTECTED]
Sent: Sunday, 4 September 2005 4:46 a.m.
To: CF-Talk
Subject: Re: getCallingTemplatePath()
I've always handled this by throwing an exception, catching the error,
and examining the stack trace. Hardly elegant, but suits the need.
Just wrap the functionality up in another custom tag that simply
returns the full call stack, and then the code that calls the custom
tag can figure out what piece it needs (the one directly 'above'
getCurrentTemplatePath(), in this case).
cheers,
barneyb
On 9/2/05, S. Isaac Dealey <[EMAIL PROTECTED]> wrote:
> I could be going crazy, but I could swear I remembered reading that
> someone had broken the black-magic code that would allow you to get
> the value of getCurrentTemplatePath() from the calling template within
> a custom tag...
>
> This just became important at my day job actually ... we (or my boss
> rather) implemented a custom tag for handling client customizations
> which swaps out sections of the calling code with customized code for
> the client (it's not how I prefer to handle this problem personally,
> but I have to admit it's more elegant than most of the solutions I've
> seen)... but for this to work it needs to know what the path of the
> calling template is... Right now we're using
>
> <cfparam name="attributes.path" type="string"
> default="#getBaseTemplatePath()#">
>
> Which works, but the base template isn't always the template being
> customized, so in the event that we have an included file or another
> custom tag, we then have to explicitly declare <cf_customcode
> path="#getCurrentTemplatePath()#"> -- even tho that attribute will
> _never_ contain any value other than that function call, and it's
> really annoying since presumably, the CF server _must_ know what the
> path to that template was in order to function (because it maps those
> paths to the generated java classes).
>
> Anybody have any insight into this?
>
> s. isaac dealey 954.522.6080
> new epoch : isn't it time for a change?
>
> add features without fixtures with
> the onTap open source framework
>
--
Barney Boisvert
[EMAIL PROTECTED]
360.319.6145
http://www.barneyb.com/
Got Gmail? I have 100 invites.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
Logware (www.logware.us): a new and convenient web-based time tracking
application. Start tracking and documenting hours spent on a project or with a
client with Logware today. Try it for free with a 15 day trial account.
http://www.houseoffusion.com/banners/view.cfm?bannerid=67
Message: http://www.houseoffusion.com/lists.cfm/link=i:4:217332
Archives: http://www.houseoffusion.com/cf_lists/threads.cfm/4
Subscription: http://www.houseoffusion.com/lists.cfm/link=s:4
Unsubscribe: http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4
Donations & Support: http://www.houseoffusion.com/tiny.cfm/54