This tip can meet all of these needs: organized help.
Ref*Name*Needroles*Location d1*Weather Applications*a,b,c,d*../help/d1.cfm d2*Precipitation Control*a,b,c,d*../help/d2.cfm d3*Wind*a,b*../help/d3.cfm d4*Temperature Control*c,d*../help/d4.cfm d5*Direction Control*c*../help2/d5.cfm d6*Intensity Control*d*../help2/d6.cfm
Here's the other half, with Ref repeated for clarity. (You can parse these with Excel to get them into your database.)
Ref*FromList*ToList*Description d1**d2,d3*Do something about the weather d2*d1*d4*Changes the level of moisture d3*d1*d5,d6*Modifies the airflow d4*d1,d5**Makes it colder or warmer d5*d3*d4,d6*Changes wind direction d6*d3**Change wind intensity
The data is nonsense, but its structure is not; consider each column of the first half of the row in turn. Ref is a short reference used as a link parameter and table key. It can certainly be closer to the meaning of the screen than the example shown here, as long as it doesn't have spaces or odd punctuation. Name will be displayed as a title and in selection lists. Needroles contains a comma-delimited LIST of roles, any of which are allowed to access the screen. Location tells how to find the page.
Consider second half of the row. Fromlist is a LIST of Refs for screens that can reach this one; screens at the top of the food chain have none. Tolist is a LIST of Refs for screens that this one can reach; screens at the bottom of the food chain have no children. Description is handy to avoid confusion during maintenance and to introduce a help page.
Set defaults for the form's submit button and list of checkboxes, then test. If the submit button was used, replace the list in the cookie with the list of roles for which boxes were checked.
<cfparam name="form.Set" default=""> <cfparam name="form.Rolelist" default=""> <cfif len(trim(form.Set))> <cfcookie name="Helpdemo" value="#form.Rolelist#"> </cfif>
The form is straightforward and will be posted. Because the help facility to be created will use cflocation to shift from one page to another, we won't set the cookie and move to the first help in the same motion. We'll take two steps: set and see the checkboxes, and select the link to begin the help demo. This means we need to test the submitted value of each checkbox and supply it to cause the boxes to actually be checked after submission (to avoid confusion). Checkboxes having the same name return a comma-delimited list of values; so, the contains function is a natural for this application. (If your values are more complex, use listContains instead.)
At the end of the form, supply the link for the help demo. This link doesn't go to the first page directly. It supplies the Ref value for the first page to work/help.cfm. Notice that for simplicity later on, the help function and its related pages are in a work directory of their own, one level below demo.cfm.
<form method="post"> Check your roles for the demonstration.<br> <input type="checkbox" name="Rolelist" value="a" <cfif Rolelist contains "a">checked</cfif>>a <input type="checkbox" name="Rolelist" value="b" <cfif Rolelist contains "b">checked</cfif>>b <input type="checkbox" name="Rolelist" value="c" <cfif Rolelist contains "c">checked</cfif>>c <input type="checkbox" name="Rolelist" value="d" <cfif Rolelist contains "d">checked</cfif>>d <input type="submit" name="Set" value="Set"><br> <a href="work/help.cfm?Ref=d1">Begin</a> </form>
Begin by handling the "list" case. Skip the rest of the logic if a list was requested.
<!--- Provide the "list" if requested ---> <cfparam name="url.Ref" default=""> <cfif url.Ref is "list"> <cfinclude template="list.cfm"> <cfabort> </cfif>
If the user didn't ask for a list, get information about the screen and see if the user has a role needed for access to the screen. The code loops through needed roles, stopping the search when the contains function finds that the list of the user's roles (in the cookie) contains a role that's needed.
<!--- Otherwise... get help parameters ---> <cfquery name="Helpget1" datasource="context"> select * from Screenhelp where Ref = '#Ref#' </cfquery> <!--- See if user has a needed role ---> <cfset OK=0> <cfloop list="#helpget1.Needroles#" index="Needs"> <cfif cookie.Helpdemo contains Needs> <cfset OK=1> <cfbreak> </cfif> </cfloop>
If so, present a response. Include work/fromlist.cfm to show a list of links from which the user can follow to get to this screen. Include work/tolist.cfm to show a list of links the user can go to from this screen. Provide a heading consisting of the name and the description. Include the location found in the Screenlist table. You would normally close with a link that invites the user to list available screens. However, because this is a demo, add one more link to get back to work/demo.cfm in order to change roles and start over.
If not, block the user. Tell the user to employ the back button to get back on track. (The user showed creativity to get this response.)
<!--- If so, present a response ---> <cfif OK> <cfinclude template="fromlist.cfm"> <cfinclude template="tolist.cfm"> <cfoutput> <strong>#helpget1.Name#</strong> - #helpget1.Description# </cfoutput> <hr> <cfinclude template="#helpget1.Location#"> <hr> <a href="help.cfm?Ref=list"> List all available screens</a> <hr> <a href="../demo.cfm">demo roles</a> <cfabort> </cfif> <!--- If not, block the user ---> You cannot perform this function.<br> Please press your back button to continue. <cfabort>
<!--- Loop through "from" references --->
<cfset HeadShown=0>
<cfloop list="#helpget1.FromList#" index="Ref">
<!--- Get parameters for a "from" reference --->
<cfquery name="helpGet" datasource="context">
select * from Screenhelp
where Ref = '#Ref#'
</cfquery>
<!--- See if the user has a needed role --->
<cfset OK=0>
<cfloop list="#helpget.Needroles#" index="Needs">
<cfif cookie.Helpdemo contains Needs>
<cfset OK=1>
<cfbreak>
</cfif>
</cfloop>
<!--- If so, show:
- a header (once)
- a list of "from" screen links the user can follow
--->
<cfif OK>
<cfif not HeadShown>
<strong><cfoutput>#helpget1.Name#
</cfoutput></strong> can be reached from<br>
<cfset HeadShown=1>
</cfif>
<cfoutput>
<a href=
"help.cfm?Ref=#Helpget.Ref#"
>#Helpget.Name#</a>
</cfoutput><br>
</cfif>
<!--- Close the loop --->
</cfloop>
<!--- Loop through "to" references --->
<cfset HeadShown=0>
<cfloop list="#helpget1.ToList#" index="Ref">
<!--- Get parameters for a "to" reference --->
<cfquery name="helpGet" datasource="context">
select * from Screenhelp
where Ref = '#Ref#'
</cfquery>
<!--- See if the user has a needed role --->
<cfset OK=0>
<cfloop list="#helpget.Needroles#" index="Needs">
<cfif cookie.Helpdemo contains Needs>
<cfset OK=1>
<cfbreak>
</cfif>
</cfloop>
<!--- If so, show:
- a header (once)
- a list of "to" screen links the user can follow
--->
<cfif OK>
<cfif not HeadShown>
<strong><cfoutput>#helpget1.Name#
</cfoutput></strong> can reach<br>
<cfset HeadShown=1>
</cfif>
<cfoutput>
<a href=
"help.cfm?Ref=#Helpget.Ref#"
>#Helpget.Name#</a>
</cfoutput><br>
</cfif>
<!--- Close the loop --->
</cfloop>
<!--- Get all screens ---> <cfquery name="Screenlist" datasource="context"> select * from Screenhelp order by Name </cfquery> <!--- For each screen... ---> <cfoutput query="Screenlist"> <!--- See if user has a needed role ---> <cfset OK=0> <cfloop list="#Screenlist.Needroles#" index="Needs"> <cfif cookie.Helpdemo contains Needs> <cfset OK=1> <cfbreak> </cfif> </cfloop> <!--- If so, show the screen name in a link ---> <cfif OK> <a href="help.cfm?Ref=#Ref#">#Name#</a><br> </cfif> <!--- ...close the loop ---> </cfoutput>
Ze wtg vmttri qt kjqvm qdjbrjvqztbr, wtg vjb eqc td rivgdipw vtcw qmin fzdivqpw qt tgd ezpi ridaid. J sjqihjw ridaid czvor gc qmi ezpi kw rivgdi nijbr, jdvmzair zq, jbf cjrrir zq qt qmi hik ridaid. Qmi hik ridaid cidetdnr qmi rjni ifzqr ijvm qdjbrjvqztb htgpf divizai ze zq hidi ibqidif azj qmi kdthrid. Ze rtni te qmi qdjbrjvqztbr hidi btq vtddivq, qmi dirq jdi ctrqif qt qmi hik fjqjkjri jr ze qmiw vjni edtn qmi kdthrid.
It's actually a cryptogram with no connection to the task at hand except for use as page filler.
You lack permission to explore this area.<br> Please press your back button to continue. <cfabort>
Use the same contents in help2/Application.cfm to protect the help2 directory in the same fashion. For the purpose of this demo, help2 represents a major customer's functions that might be supported by a different team.
Each of these documents has a cfinclude tag to make the text longer and to demonstrate that the full range of ColdFusion tags is available here.
Here's help/d1.cfm. Notice the directory name.
Weather Applications can modify key weather attributes over a small area. The effect is too small to affect a region over the long term but can save a party or make an enemy VERY uncomfortable during key battles. <cfinclude template="../work/junktext.cfm">
Here's help/d2.cfm.
Precipitation Control shifts moisture from one area to another. Its indirect effects can be wider-ranging than its direct effects. For example, if used in a dry climate, it may have to suck moisture from an area hundreds of miles on a side in order to dump twelve inches of rain on an area 3 miles to a side. <cfinclude template="../work/junktext.cfm">
Here's help/d3.cfm.
Wind is the most powerful tool in the kit; because, its impact can be restricted to a small area. Other tools in a zero-sum manner must shift a weather attribute from one place to another in order to concentrate its impact, but spiral wind can be designed to have a local impact. <cfinclude template="../work/junktext.cfm">
Here's help/d4.cfm.
Temperature Control has the capacity to freeze or bake nine square miles. <cfinclude template="../work/junktext.cfm">
Here's help2/d5.cfm. Notice this directory name, simulating a place for another team to maintain pages.
Direction Control shapes spiral airflow or determines the primary direction of a non-spiral airflow. <cfinclude template="../work/junktext.cfm">
Here's help2/d6.cfm.
Intensity provides power, but it also requires power. Doubling the perceived effect requires the input power to be squared (not cubed; because, effects have a built-in height limitation). <cfinclude template="../work/junktext.cfm">
For your own application, tie this structure to yours, or include this structure in your application. For example, replace Needroles in Screenlist with ties to your existing permission structure; replace Fromlist and Tolist in Screenlist with ties to the navigation of your own application. Or, add columns to tables in your application so that a separate table won't be needed to support organized help; it will truly be integrated with your application.
Either adjustment will align your on-line help with the application in the manner shown here. Subject matter specialists from multiple teams can maintain your help screens, which can be anywhere in your application. In some cases, you may want your help pages to perform queries so their text is secondary to their purpose. Improve this organization for on-line help, and tell us how it works for you. =Marty=