Sample Source Code
eBoat: emgReadStyle.cfm

About the Program

eBoat was a web-based application designed to provide all of the functionality of the entire client/server product line. These products were mainly geared towards the behavioral health care community.

About the Code

This custom tag retrieves style information from a style sheet.

Its main use is for JavaScript code that generates HTML. In some browsers (most notably Netscape 4), HTML generated in a new dynamic element does not always inherit styles from the parent document. Nor, in some very complex cases, do inline styles always work! This tag allows the extraction of style information which can then be applied through other means (usually <font> tags).

The Code

<!--- cf_emgReadStyle - extracts a style definition from a stylesheet --->

<!--- cf_emgReadStyle parameters:
      stylesheet:   name of the style sheet
      themePath:    alternate theme to use (defaults to current theme)
      selector:     name of the style selector to match (id, class, etc)
      style:        name of the style attribute to match
      default:      value to return if no match is found
      resultVar:    variable name in the caller's scope to place return value in
---->

<!--- Declare parameters --->
<cfparam name="Attributes.stylesheet" type="string" default="content">
<cfparam name="Attributes.themePath" type="string" default="">
<cfparam name="Attributes.selector" type="string">
<cfparam name="Attributes.style" type="string">
<cfparam name="Attributes.default" type="string" default="">
<cfparam name="Attributes.resultVar" type="string">

<!--- Declare local variables --->
<cf_emgDeclare name="lsPath" type="string">
<cf_emgDeclare name="lsThemePath" type="string">
<cf_emgDeclare name="lsStyles" type="string">
<cf_emgDeclare name="lsMatch" type="numeric">
<cf_emgDeclare name="lsReturn" type="string">
<cf_emgDeclare name="lsPathDelim" type="string">

<!--- Extract the base path from the System scope --->
<cf_emgGetValue scope="System" key="BaseDirectory" localVar="lsPath">

<!--- Retrieve the theme path (or use the provided one) --->
<cfif Attributes.themePath eq "">
    <cf_emgGetThemePath resultVar="lsThemePath">
<cfelse>
    <cfset lsThemePath = Attributes.themePath>
</cfif>

<!--- Correct the path based on the operating system ('/' or '\' path delimiters) --->
<cf_emgGetValue scope="System" key="PathDelim" localVar="lsPathDelim">
<cfset lsThemePath = Replace( lsThemePath, "/", lsPathDelim, "ALL" )>

<!--- Read the stylesheet into memory --->
<cftry>
    <cffile action="read" file="#lsPath##lsThemePath##lsPathDelim##Attributes.stylesheet#.css" variable="lsStyles">
<cfcatch>
    <cfthrow type="eBoat.Internal.Stylesheet.Missing.Err" message="Missing Stylesheet" detail="The stylesheet '#Attributes.stylesheet#' is missing from the theme in '#lsThemePath#'">
</cfcatch>
</cftry>

<!--- Parse out the style definition and return it --->
<cfscript>
    // construct a regexp to match the style declaration
    lsMatch = Attributes.selector & "[ ]*{[^{]*";       // [selector] {
    lsMatch = lsMatch & Attributes.style & "[ ]*:[ ]*"; // [style]:
    lsMatch = lsMatch & "([^;]*);";                     // [DATA];

    // match on the style declaration
    rMatch = REFindNoCase( lsMatch, lsStyles, 1, TRUE );

    // return the match, if any; otherwise, return the default
    lsReturn = Attributes.default;
    if ( ArrayLen( rMatch.pos ) gt 1 )
        if ( rMatch.pos[ 2 ] gt 0 )
            lsReturn = Mid( lsStyles, rMatch.pos[ 2 ], rMatch.len[ 2 ] );

    // set the return value in the caller's scope
    SetVariable( "Caller." & Attributes.resultVar, lsReturn );
</cfscript>