<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://greggsmith.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Prohacx</id>
		<title>SDU - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://greggsmith.net/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Prohacx"/>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Special:Contributions/Prohacx"/>
		<updated>2026-09-23T07:55:37Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.26.1</generator>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Yellow_Pages:TechTeam_Global&amp;diff=4275</id>
		<title>Yellow Pages:TechTeam Global</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Yellow_Pages:TechTeam_Global&amp;diff=4275"/>
				<updated>2011-01-03T11:01:30Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* '''GET THE RIGHT TOOLS FOR THE JOB''' */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:TechTeam_logo.jpeg|TechTeam Global]]&lt;br /&gt;
&lt;br /&gt;
== '''GET THE RIGHT TOOLS FOR THE JOB''' ==&lt;br /&gt;
&lt;br /&gt;
Delivering global service management requires the right tools. TechTeam has developed significant expertise using CA’s Service Desk Manager, IT Client Manager, IT Asset Manager, CA Spectrum and CA eHealth Network Performance Manager.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
CA’s tools enable the automation of TechTeam’s ITIL-based best practices in our IT outsourcing company. We deliver a world-class customer service experience and improve availability, while reducing costs for our outsourcing customers by increasing first call resolution and moving from reactive help to proactive support. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We can help you gain the benefit of CA tools even when IT infrastructure outsourcing is not in the picture. Whether you want to deploy the CA suite at your site, or obtain access through our hosted managed service to leverage a Software as a Service (SaaS) approach, TechTeam consultants can help you use this powerful solution to automate service support and integrate IT Service Management with all aspects of the business.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''TechTeam’s expertise and capabilities include:'''&lt;br /&gt;
*Request, incident, problem, and knowledge management &lt;br /&gt;
*Change and configuration management &lt;br /&gt;
*Availability management, including server and network management &lt;br /&gt;
*IT client management &lt;br /&gt;
*IT asset management &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''TechTeam Offers CA Service Management Solutions as:'''&lt;br /&gt;
*An enabling technology for our portfolio of IT outsourcing solutions &lt;br /&gt;
*A hosted and managed solution -- a SaaS model &lt;br /&gt;
*An onsite solution, deployed, implemented and maintained by TechTeam professional consultants&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Gary Cotshott, TechTeam Chairman and CEO, and Mark Morgan, CA Practice Manager, explain how we use CA's Enterprise IT Management to improve and expand IT outsourcing services to customers.'''   [http://www.ca.com/us/products/collateral.aspx?cid=203423   CA Channel Partner Video]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://www.techteam.com/images/pdfs/services/customer%20success%20story.pdf  Read our CA Customer Success Story]&lt;br /&gt;
&lt;br /&gt;
Learn more about TechTeam:  [http://www.techteam.com www.techteam.com]&lt;br /&gt;
&lt;br /&gt;
'''Contact Mark Morgan at 248.263.5243 or by email at [mailto:mmorgan1@techteam.com mmorgan1@techteam.com]'''&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3810</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3810"/>
				<updated>2009-03-24T20:57:56Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* All together now */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code uses a pdm_list tag to get all rootcauses from the server and populate the allRootCauses javascript array.&lt;br /&gt;
&lt;br /&gt;
After all code is parsed by the server, it should look like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
allRootCauses[0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;;&lt;br /&gt;
allRootCauses[1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;;&lt;br /&gt;
allRootCauses[2] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;;&lt;br /&gt;
allRootCauses[3] = &amp;quot;40004|Hardware.Network.Router&amp;quot;;&lt;br /&gt;
allRootCauses[4] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;;&lt;br /&gt;
allRootCauses[5] = &amp;quot;40006|Software.Browser.Settings&amp;quot;;&lt;br /&gt;
allRootCauses[6] = &amp;quot;40007|Software.Browser.Version&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the code loops through these root causes and converts them into an array of arrays much like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
thevalues[0][0][0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;&lt;br /&gt;
thevalues[0][0][1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;&lt;br /&gt;
thevalues[0][1][0] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;&lt;br /&gt;
thevalues[0][1][1] = &amp;quot;40004|Hardware.Network.Router&amp;quot;&lt;br /&gt;
thevalues[0][1][2] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;&lt;br /&gt;
thevalues[1][0][0] = &amp;quot;40006|Software.Browser.Settings&amp;quot;&lt;br /&gt;
thevalues[1][0][1] = &amp;quot;40007|Software.Browser.Version&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will be easier to parse later on.&lt;br /&gt;
&lt;br /&gt;
The '''readrootcause''' function fills 3 variables: thelevel1, thelevel2 and thelevel3, these are the text values that will be displayed in the read only version of the fields.&lt;br /&gt;
&lt;br /&gt;
The '''fillDependantDropdown''' function is capable of filling the dropdown of list1, list2 or list3. While doing so, it takes a variable (indicator) to indicate the list you want to populate. It will take into account the selection made in a previous dropdown, as well as the values from thelevel1, thelevel2 and thelevel3, making sure that when you go to edit mode the value set from a previous save is displayed as the selected one in each dropdown.&lt;br /&gt;
&lt;br /&gt;
The '''setrootcause''' function will trigger when you make a selection on the list3 dropdown. It will then set the hidden field (SET.rootcause) to the id of your selected rootcause (remember that the allRootCauses looks like id|level1;level2.level3, so this function will set that id into the SET.rootcause field so that it is saved into the back-end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section adds the 3 dropdown fields to your form and makes sure that the saved rootcause values are set (by calling the readrootcause).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will populate the dropdowns when in edit mode and make sure that the previously saved values are selected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3809</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3809"/>
				<updated>2009-03-24T13:12:55Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code uses a pdm_list tag to get all rootcauses from the server and populate the allRootCauses javascript array.&lt;br /&gt;
&lt;br /&gt;
After all code is parsed by the server, it should look like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
	allRootCauses[0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;;&lt;br /&gt;
	allRootCauses[1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;;&lt;br /&gt;
	allRootCauses[2] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;;&lt;br /&gt;
	allRootCauses[3] = &amp;quot;40004|Hardware.Network.Router&amp;quot;;&lt;br /&gt;
	allRootCauses[4] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;;&lt;br /&gt;
	allRootCauses[5] = &amp;quot;40006|Software.Browser.Settings&amp;quot;;&lt;br /&gt;
	allRootCauses[6] = &amp;quot;40007|Software.Browser.Version&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the code loops through these root causes and converts them into an array of arrays much like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
thevalues[0][0][0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;&lt;br /&gt;
thevalues[0][0][1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;&lt;br /&gt;
thevalues[0][1][0] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;&lt;br /&gt;
thevalues[0][1][1] = &amp;quot;40004|Hardware.Network.Router&amp;quot;&lt;br /&gt;
thevalues[0][1][2] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;&lt;br /&gt;
thevalues[1][0][0] = &amp;quot;40006|Software.Browser.Settings&amp;quot;&lt;br /&gt;
thevalues[1][0][1] = &amp;quot;40007|Software.Browser.Version&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will be easier to parse later on.&lt;br /&gt;
&lt;br /&gt;
The '''readrootcause''' function fills 3 variables: thelevel1, thelevel2 and thelevel3, these are the text values that will be displayed in the read only version of the fields.&lt;br /&gt;
&lt;br /&gt;
The '''fillDependantDropdown''' function is capable of filling the dropdown of list1, list2 or list3. While doing so, it takes a variable (indicator) to indicate the list you want to populate. It will take into account the selection made in a previous dropdown, as well as the values from thelevel1, thelevel2 and thelevel3, making sure that when you go to edit mode the value set from a previous save is displayed as the selected one in each dropdown.&lt;br /&gt;
&lt;br /&gt;
The '''setrootcause''' function will trigger when you make a selection on the list3 dropdown. It will then set the hidden field (SET.rootcause) to the id of your selected rootcause (remember that the allRootCauses looks like id|level1;level2.level3, so this function will set that id into the SET.rootcause field so that it is saved into the back-end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section adds the 3 dropdown fields to your form and makes sure that the saved rootcause values are set (by calling the readrootcause).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will populate the dropdowns when in edit mode and make sure that the previously saved values are selected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3808</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3808"/>
				<updated>2009-03-24T13:12:25Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Client side */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code uses a pdm_list tag to get all rootcauses from the server and populate the allRootCauses javascript array.&lt;br /&gt;
&lt;br /&gt;
After all code is parsed by the server, it should look like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
	allRootCauses[0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;;&lt;br /&gt;
	allRootCauses[1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;;&lt;br /&gt;
	allRootCauses[2] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;;&lt;br /&gt;
	allRootCauses[3] = &amp;quot;40004|Hardware.Network.Router&amp;quot;;&lt;br /&gt;
	allRootCauses[4] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;;&lt;br /&gt;
	allRootCauses[5] = &amp;quot;40006|Software.Browser.Settings&amp;quot;;&lt;br /&gt;
	allRootCauses[6] = &amp;quot;40007|Software.Browser.Version&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the code loops through these root causes and converts them into an array of arrays much like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
thevalues[0][0][0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;&lt;br /&gt;
thevalues[0][0][1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;&lt;br /&gt;
thevalues[0][1][0] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;&lt;br /&gt;
thevalues[0][1][1] = &amp;quot;40004|Hardware.Network.Router&amp;quot;&lt;br /&gt;
thevalues[0][1][2] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;&lt;br /&gt;
thevalues[1][0][0] = &amp;quot;40006|Software.Browser.Settings&amp;quot;&lt;br /&gt;
thevalues[1][0][1] = &amp;quot;40007|Software.Browser.Version&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will be easier to parse later on.&lt;br /&gt;
&lt;br /&gt;
The '''readrootcause''' function fills 3 variables: thelevel1, thelevel2 and thelevel3, these are the text values that will be displayed in the read only version of the fields.&lt;br /&gt;
&lt;br /&gt;
The '''fillDependantDropdown''' function is capable of filling the dropdown of list1, list2 or list3. While doing so, it takes a variable (indicator) to indicate the list you want to populate. It will take into account the selection made in a previous dropdown, as well as the values from thelevel1, thelevel2 and thelevel3, making sure that when you go to edit mode the value set from a previous save is displayed as the selected one in each dropdown.&lt;br /&gt;
&lt;br /&gt;
The '''setrootcause''' function will trigger when you make a selection on the list3 dropdown. It will then set the hidden field (SET.rootcause) to the id of your selected rootcause (remember that the allRootCauses looks like id|level1;level2.level3, so this function will set that id into the SET.rootcause field so that it is saved into the back-end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section adds the 3 dropdown fields to your form and makes sure that the saved rootcause values are set (by calling the readrootcause).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will populate the dropdowns when in edit mode and make sure that the previously saved values are selected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3807</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3807"/>
				<updated>2009-03-24T13:11:52Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code uses a pdm_list tag to get all rootcauses from the server and populate the allRootCauses javascript array.&lt;br /&gt;
&lt;br /&gt;
After all code is parsed by the server, it should look like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
	allRootCauses[0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;;&lt;br /&gt;
	allRootCauses[1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;;&lt;br /&gt;
	allRootCauses[2] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;;&lt;br /&gt;
	allRootCauses[3] = &amp;quot;40004|Hardware.Network.Router&amp;quot;;&lt;br /&gt;
	allRootCauses[4] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;;&lt;br /&gt;
	allRootCauses[5] = &amp;quot;40006|Software.Browser.Settings&amp;quot;;&lt;br /&gt;
	allRootCauses[6] = &amp;quot;40007|Software.Browser.Version&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the code loops through these root causes and converts them into an array of arrays much like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
thevalues[0][0][0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;&lt;br /&gt;
thevalues[0][0][1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;&lt;br /&gt;
thevalues[0][1][0] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;&lt;br /&gt;
thevalues[0][1][1] = &amp;quot;40004|Hardware.Network.Router&amp;quot;&lt;br /&gt;
thevalues[0][1][2] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;&lt;br /&gt;
thevalues[1][0][0] = &amp;quot;40006|Software.Browser.Settings&amp;quot;&lt;br /&gt;
thevalues[1][0][1] = &amp;quot;40007|Software.Browser.Version&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will be easier to parse later on.&lt;br /&gt;
&lt;br /&gt;
The '''readrootcause''' function fills 3 variables: thelevel1, thelevel2 and thelevel3, these are the text values that will be displayed in the read only version of the fields.&lt;br /&gt;
&lt;br /&gt;
The '''fillDependantDropdown''' function is capable of filling the dropdown of list1, list2 or list3. While doing so, it takes a variable (indicator) to indicate the list you want to populate. It will take into account the selection made in a previous dropdown, as well as the values from thelevel1, thelevel2 and thelevel3, making sure that when you go to edit mode the value set from a previous save is displayed as the selected one in each dropdown.&lt;br /&gt;
&lt;br /&gt;
The '''setrootcause''' function will trigger when you make a selection on the list3 dropdown. It will then set the hidden field (SET.rootcause) to the id of your selected rootcause (remember that the allRootCauses looks like id|level1;level2.level3, so this function will set that id into the SET.rootcause field so that it is saved into the back-end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section adds the 3 dropdown fields to your form and makes sure that the saved rootcause values are set (by calling the readrootcause).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will populate the dropdowns when in edit mode and make sure that the previously saved values are selected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3806</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3806"/>
				<updated>2009-03-24T13:11:22Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code uses a pdm_list tag to get all rootcauses from the server and populate the allRootCauses javascript array.&lt;br /&gt;
&lt;br /&gt;
After all code is parsed by the server, it should look like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
	allRootCauses[0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;;&lt;br /&gt;
	allRootCauses[1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;;&lt;br /&gt;
	allRootCauses[2] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;;&lt;br /&gt;
	allRootCauses[3] = &amp;quot;40004|Hardware.Network.Router&amp;quot;;&lt;br /&gt;
	allRootCauses[4] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;;&lt;br /&gt;
	allRootCauses[5] = &amp;quot;40006|Software.Browser.Settings&amp;quot;;&lt;br /&gt;
	allRootCauses[6] = &amp;quot;40007|Software.Browser.Version&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the code loops through these root causes and converts them into an array of arrays much like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
thevalues[0][0][0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;&lt;br /&gt;
thevalues[0][0][1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;&lt;br /&gt;
thevalues[0][1][0] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;&lt;br /&gt;
thevalues[0][1][1] = &amp;quot;40004|Hardware.Network.Router&amp;quot;&lt;br /&gt;
thevalues[0][1][2] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;&lt;br /&gt;
thevalues[1][0][0] = &amp;quot;40006|Software.Browser.Settings&amp;quot;&lt;br /&gt;
thevalues[1][0][1] = &amp;quot;40007|Software.Browser.Version&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will be easier to parse later on.&lt;br /&gt;
&lt;br /&gt;
The '''readrootcause''' function fills 3 variables: thelevel1, thelevel2 and thelevel3, these are the text values that will be displayed in the read only version of the fields.&lt;br /&gt;
&lt;br /&gt;
The '''fillDependantDropdown''' function is capable of filling the dropdown of list1, list2 or list3. While doing so, it takes a variable (indicator) to indicate the list you want to populate. It will take into account the selection made in a previous dropdown, as well as the values from thelevel1, thelevel2 and thelevel3, making sure that when you go to edit mode the value set from a previous save is displayed as the selected one in each dropdown.&lt;br /&gt;
&lt;br /&gt;
The '''setrootcause''' function will trigger when you make a selection on the list3 dropdown. It will then set the hidden field (SET.rootcause) to the id of your selected rootcause (remember that the allRootCauses looks like id|level1;level2.level3, so this function will set that id into the SET.rootcause field so that it is saved into the back-end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section adds the 3 dropdown fields to your form and makes sure that the saved rootcause values are set (by calling the readrootcause).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will populate the dropdowns when in edit mode and make sure that the previously saved values are selected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3805</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3805"/>
				<updated>2009-03-24T13:10:51Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* All together now */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code uses a pdm_list tag to get all rootcauses from the server and populate the allRootCauses javascript array.&lt;br /&gt;
&lt;br /&gt;
After all code is parsed by the server, it should look like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
	allRootCauses[0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;;&lt;br /&gt;
	allRootCauses[1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;;&lt;br /&gt;
	allRootCauses[2] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;;&lt;br /&gt;
	allRootCauses[3] = &amp;quot;40004|Hardware.Network.Router&amp;quot;;&lt;br /&gt;
	allRootCauses[4] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;;&lt;br /&gt;
	allRootCauses[5] = &amp;quot;40006|Software.Browser.Settings&amp;quot;;&lt;br /&gt;
	allRootCauses[6] = &amp;quot;40007|Software.Browser.Version&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the code loops through these root causes and converts them into an array of arrays much like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
thevalues[0][0][0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;&lt;br /&gt;
thevalues[0][0][1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;&lt;br /&gt;
thevalues[0][1][0] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;&lt;br /&gt;
thevalues[0][1][1] = &amp;quot;40004|Hardware.Network.Router&amp;quot;&lt;br /&gt;
thevalues[0][1][2] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;&lt;br /&gt;
thevalues[1][0][0] = &amp;quot;40006|Software.Browser.Settings&amp;quot;&lt;br /&gt;
thevalues[1][0][1] = &amp;quot;40007|Software.Browser.Version&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will be easier to parse later on.&lt;br /&gt;
&lt;br /&gt;
The '''readrootcause''' function fills 3 variables: thelevel1, thelevel2 and thelevel3, these are the text values that will be displayed in the read only version of the fields.&lt;br /&gt;
&lt;br /&gt;
The '''fillDependantDropdown''' function is capable of filling the dropdown of list1, list2 or list3. While doing so, it takes a variable (indicator) to indicate the list you want to populate. It will take into account the selection made in a previous dropdown, as well as the values from thelevel1, thelevel2 and thelevel3, making sure that when you go to edit mode the value set from a previous save is displayed as the selected one in each dropdown.&lt;br /&gt;
&lt;br /&gt;
The '''setrootcause''' function will trigger when you make a selection on the list3 dropdown. It will then set the hidden field (SET.rootcause) to the id of your selected rootcause (remember that the allRootCauses looks like id|level1;level2.level3, so this function will set that id into the SET.rootcause field so that it is saved into the back-end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section adds the 3 dropdown fields to your form and makes sure that the saved rootcause values are set (by calling the readrootcause).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will populate the dropdowns when in edit mode and make sure that the previously saved values are selected.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3804</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3804"/>
				<updated>2009-03-24T13:07:16Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* All together now */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code uses a pdm_list tag to get all rootcauses from the server and populate the allRootCauses javascript array.&lt;br /&gt;
&lt;br /&gt;
After all code is parsed by the server, it should look like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
	allRootCauses[0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;;&lt;br /&gt;
	allRootCauses[1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;;&lt;br /&gt;
	allRootCauses[2] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;;&lt;br /&gt;
	allRootCauses[3] = &amp;quot;40004|Hardware.Network.Router&amp;quot;;&lt;br /&gt;
	allRootCauses[4] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;;&lt;br /&gt;
	allRootCauses[5] = &amp;quot;40006|Software.Browser.Settings&amp;quot;;&lt;br /&gt;
	allRootCauses[6] = &amp;quot;40007|Software.Browser.Version&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, the code loops through these root causes and converts them into an array of arrays much like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
thevalues[0][0][0] = &amp;quot;40001|Hardware.Server.Error&amp;quot;&lt;br /&gt;
thevalues[0][0][1] = &amp;quot;40002|Hardware.Server.Component Failure&amp;quot;&lt;br /&gt;
thevalues[0][1][0] = &amp;quot;40003|Hardware.Network.Firewall&amp;quot;&lt;br /&gt;
thevalues[0][1][1] = &amp;quot;40004|Hardware.Network.Router&amp;quot;&lt;br /&gt;
thevalues[0][1][2] = &amp;quot;40005|Hardware.Network.Cable&amp;quot;&lt;br /&gt;
thevalues[1][0][0] = &amp;quot;40006|Software.Browser.Settings&amp;quot;&lt;br /&gt;
thevalues[1][0][1] = &amp;quot;40007|Software.Browser.Version&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will be easier to parse later on.&lt;br /&gt;
&lt;br /&gt;
The '''readrootcause''' function fills 3 variables: thelevel1, thelevel2 and thelevel3, these are the text values that will be displayed in the read only version of the fields.&lt;br /&gt;
&lt;br /&gt;
The '''fillDependantDropdown''' function is capable of filling the dropdown of list1, list2 or list3. While doing so, it takes a variable (indicator) to indicate the list you want to populate. It will take into account the selection made in a previous dropdown, as well as the values from thelevel1, thelevel2 and thelevel3, making sure that when you go to edit mode the value set from a previous save is displayed as the selected one in each dropdown.&lt;br /&gt;
&lt;br /&gt;
The '''setrootcause''' function will trigger when you make a selection on the list3 dropdown. It will then set the hidden field (SET.rootcause) to the id of your selected rootcause (remember that the allRootCauses looks like id|level1;level2.level3, so this function will set that id into the SET.rootcause field so that it is saved into the back-end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3803</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3803"/>
				<updated>2009-03-24T12:45:12Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Client side */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3802</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3802"/>
				<updated>2009-03-24T12:44:51Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Client side */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode &lt;br /&gt;
[[Image:DropdownsEDIT.jpg|edit mode]]&lt;br /&gt;
&lt;br /&gt;
and plain text when in viewing mode.&lt;br /&gt;
[[Image:DropdownsVIEW.jpg|view mode]]&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=File:DropdownsEDIT.jpg&amp;diff=3801</id>
		<title>File:DropdownsEDIT.jpg</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=File:DropdownsEDIT.jpg&amp;diff=3801"/>
				<updated>2009-03-24T12:42:46Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=File:DropdownsVIEW.jpg&amp;diff=3800</id>
		<title>File:DropdownsVIEW.jpg</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=File:DropdownsVIEW.jpg&amp;diff=3800"/>
				<updated>2009-03-24T12:41:45Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3799</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3799"/>
				<updated>2009-03-24T12:31:17Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Server side */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like dependent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3798</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3798"/>
				<updated>2009-03-24T10:27:57Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like denpendent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL, before the dtlEndTable tag, add this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* on the BODY tag, make sure you add the setting of your dropdowns (for edit mode):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;BODY class=detailro onLoad=&amp;quot;loadActions();fillDependantDropdown(1);fillDependantDropdown(2);fillDependantDropdown(3)&amp;quot; onUnload=&amp;quot;unloadActions()&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* also add the SET.rootcause field to you form (after &amp;lt;PDM_IF &amp;quot;$prop.form_name_3&amp;quot; == &amp;quot;edit&amp;quot;&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;input type=hidden NAME=SET.rootcause value=&amp;quot;$args.rootcause&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3797</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3797"/>
				<updated>2009-03-24T10:21:03Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like denpendent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
* At the top of your page, right after all the javascript include files, create your own javascript tag containing this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* In your HTMPL &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;PDM_MACRO NAME=dtlStartRow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	readrootcause();&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 1&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText;&lt;br /&gt;
		htmlText = &amp;quot;&amp;lt;select id=list1 name=list1 onchange=\&amp;quot;fillDependantDropdown(2)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel1);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 2&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText2;&lt;br /&gt;
		htmlText2 = &amp;quot;&amp;lt;select id=list2 name=list2 onchange=\&amp;quot;fillDependantDropdown(3)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText2);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	detailRowHdr(&amp;quot;LIST 3&amp;quot;, 1, 0);&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
		var htmlText3;&lt;br /&gt;
		htmlText3 = &amp;quot;&amp;lt;select id=list3 name=list3 onchange=\&amp;quot;setrootcause(this.options[this.options.selectedIndex].value)\&amp;quot;&amp;gt;&amp;lt;option&amp;gt;-- select --&amp;lt;/option&amp;gt;&amp;lt;/select&amp;gt;&amp;quot;;&lt;br /&gt;
		detailSetRowData(htmlText3);&lt;br /&gt;
	} else {&lt;br /&gt;
		detailSetRowData(&amp;quot;&amp;quot;+thelevel3);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3796</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3796"/>
				<updated>2009-03-24T10:16:27Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like denpendent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3795</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3795"/>
				<updated>2009-03-24T10:16:03Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like denpendent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get these values from the back end and pass them onto our front end (javascript) we will use a PDM_LIST tag.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;br /&gt;
&lt;br /&gt;
This solution will display 3 dependent dropdowns on the detail_cr.htmpl form and allow you to view, select and store values into the rootcause field using these dropdowns.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lange=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var allRootCauses = new Array();&lt;br /&gt;
var thevalues = new Array();&lt;br /&gt;
&lt;br /&gt;
var somevalue;&lt;br /&gt;
&amp;lt;PDM_LIST PREFIX=rootcauses WHERE=&amp;quot;delete_flag = 0&amp;quot; FACTORY=rc&amp;gt;&lt;br /&gt;
somevalue = &amp;quot;$rootcauses.id&amp;quot; + &amp;quot;|&amp;quot; + &amp;quot;$rootcauses.sym&amp;quot;;&lt;br /&gt;
allRootCauses[allRootCauses.length] = somevalue;&lt;br /&gt;
&amp;lt;/PDM_LIST&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var tempArray;&lt;br /&gt;
var somecounter;&lt;br /&gt;
var temp;&lt;br /&gt;
var tempArr1;&lt;br /&gt;
var tempArr2;&lt;br /&gt;
var prevlevel1;&lt;br /&gt;
prevlevel1 = &amp;quot;&amp;quot;;&lt;br /&gt;
var prevlevel2;&lt;br /&gt;
prevlevel2 = &amp;quot;&amp;quot;;&lt;br /&gt;
var len1;&lt;br /&gt;
var len2;&lt;br /&gt;
var len3;&lt;br /&gt;
len1 = -1;&lt;br /&gt;
len2 = -1;&lt;br /&gt;
len3 = -1;&lt;br /&gt;
&lt;br /&gt;
for (somecounter=0; somecounter &amp;lt; allRootCauses.length; somecounter++) {&lt;br /&gt;
&lt;br /&gt;
	tempArr1 = new Array();&lt;br /&gt;
	tempArr1 = allRootCauses[somecounter].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	tempArr2 = new Array();&lt;br /&gt;
	tempArr2 = tempArr1[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[0] != prevlevel1) {&lt;br /&gt;
		len1+= 1;&lt;br /&gt;
		thevalues[len1] = new Array();&lt;br /&gt;
		prevlevel1 = tempArr2[0];&lt;br /&gt;
		len2 = -1;&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	if (tempArr2[1] != prevlevel2) {&lt;br /&gt;
		len2 += 1;&lt;br /&gt;
		thevalues[len1][len2] = new Array();&lt;br /&gt;
		prevlevel2 = tempArr2[1];&lt;br /&gt;
		len3 = -1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	len3 += 1;&lt;br /&gt;
	thevalues[len1][len2][len3] =  allRootCauses[somecounter];&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var thelevel1;&lt;br /&gt;
var thelevel2;&lt;br /&gt;
var thelevel3;&lt;br /&gt;
function readrootcause() {&lt;br /&gt;
	var readcounter;&lt;br /&gt;
	var readid;&lt;br /&gt;
	var tempsplit;&lt;br /&gt;
	for (readcounter=0; readcounter &amp;lt; allRootCauses.length; readcounter++) {&lt;br /&gt;
		readid = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[0];&lt;br /&gt;
&lt;br /&gt;
		if (readid == &amp;quot;$args.rootcause&amp;quot;) {&lt;br /&gt;
			tempsplit = allRootCauses[readcounter].split(&amp;quot;|&amp;quot;)[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
			thelevel1 = tempsplit[0];&lt;br /&gt;
			thelevel2 = tempsplit[1];&lt;br /&gt;
			thelevel3 = tempsplit[2];&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fillDependantDropdown(indicator) {&lt;br /&gt;
&lt;br /&gt;
	if (_dtl.edit) {&lt;br /&gt;
&lt;br /&gt;
		var list1index;&lt;br /&gt;
		var list2index;&lt;br /&gt;
&lt;br /&gt;
		list1index = document.main_form.list1.selectedIndex-1;&lt;br /&gt;
		list2index = document.main_form.list2.selectedIndex-1;&lt;br /&gt;
&lt;br /&gt;
		var i;&lt;br /&gt;
		var somevalue;&lt;br /&gt;
		var sometext;&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 1) {&lt;br /&gt;
			for (i=document.main_form.list1.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list1.options[i] = null;&lt;br /&gt;
			}		&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list1.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues.length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[i][0][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list1.options[i+1] = new Option(sometext[0], somevalue[0]);&lt;br /&gt;
				if (sometext[0] == thelevel1) {&lt;br /&gt;
					document.main_form.list1.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (indicator == 2) {&lt;br /&gt;
			for (i=document.main_form.list2.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list2.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list2.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][i][0].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list2.options[i+1] = new Option(sometext[1], somevalue[0]);&lt;br /&gt;
				if (sometext[1] == thelevel2) {&lt;br /&gt;
					document.main_form.list2.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		if (indicator == 3) {&lt;br /&gt;
			for (i=document.main_form.list3.options.length; i&amp;gt;0; i--) {&lt;br /&gt;
				document.main_form.list3.options[i] = null;&lt;br /&gt;
			}&lt;br /&gt;
			document.main_form.list3.options[0] = new Option(&amp;quot;-- select --&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
			for (i=0; i&amp;lt;thevalues[list1index][list2index].length; i++) {&lt;br /&gt;
				somevalue = new Array();&lt;br /&gt;
				somevalue = thevalues[list1index][list2index][i].split(&amp;quot;|&amp;quot;);&lt;br /&gt;
				sometext = new Array();&lt;br /&gt;
				sometext = somevalue[1].split(&amp;quot;.&amp;quot;);&lt;br /&gt;
				document.main_form.list3.options[i+1] = new Option(sometext[2], somevalue[0]);&lt;br /&gt;
				if (sometext[2] == thelevel3) {&lt;br /&gt;
					document.main_form.list3.options[i+1].selected = true;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setrootcause(thenewvalue) {&lt;br /&gt;
	document.main_form.elements[&amp;quot;SET.rootcause&amp;quot;].value = thenewvalue;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3794</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3794"/>
				<updated>2009-03-24T10:12:13Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like denpendent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
As you can see in the previous section, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above. These fields will be added to the detail_cr.htmpl form. These fields will be dropdowns when in edit mode and plain text when in viewing mode.&lt;br /&gt;
&lt;br /&gt;
An additional field (SET.rootcause) will be necessary to make sure that any selection made in the dropdowns is stored into the database when you save the form.&lt;br /&gt;
&lt;br /&gt;
Next to the fields, we will need (javascript) logic to do 4 things:&lt;br /&gt;
* build the relationships&lt;br /&gt;
* populate a dropwdown based on values from a previous one (fillDependantDropdown)&lt;br /&gt;
* save the values to the database once a selection is made in the last dropdown (setrootcause)&lt;br /&gt;
* display values back from the database when the form is initially loaded (readrootcause)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3793</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3793"/>
				<updated>2009-03-24T10:05:36Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like denpendent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this example, we will (re)use the rootcause field and the structure it provides (using . as a separator), but you could of course create your own table for this.&lt;br /&gt;
&lt;br /&gt;
The values in my rootcause table are:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Hardware.Server.Error&lt;br /&gt;
Hardware.Server.Component Failure&lt;br /&gt;
Hardware.Network.Firewall&lt;br /&gt;
Hardware.Network.Router&lt;br /&gt;
Hardware.Network.Cable&lt;br /&gt;
Software.Browser.Settings&lt;br /&gt;
Software.Browser.Version&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;This code comes as is, and has been tested for these values only. Further finetuning may be necessary when deviating from a 3 level deep structure.&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we will be using 3 dropdown fields (list1, list2 and list3), each containing a level of the tree shown above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3792</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3792"/>
				<updated>2009-03-24T09:58:44Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
To start, you will want to have a place in the database where you store the values of the drowndowns and their dependencies.&lt;br /&gt;
This can be done in many different ways (having 3 custom tables, then using 2 more to store the LREL between them), but let's keep it simple for now: as you may know, the request area structure is much like denpendent dropdowns: once you select a node in the tree, you get access to the underlying nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;As a sidenote, you could simply use one field similar to the request area to implement this functionality instead of using all dropdown fields. But in case you still want to go ahead with the dropdowns, read on...&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3791</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3791"/>
				<updated>2009-03-24T09:52:41Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
;dependent dropdowns&lt;br /&gt;
: values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
* use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
* an AJAX implementation&lt;br /&gt;
* find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
* pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
When a web server gets a request to serve a page it will first parse all server side code (HTMPL) and replace that code with valid HTML code before passing that HTML back to the requester of the page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3790</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3790"/>
				<updated>2009-03-24T09:48:36Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
With dependent dropdowns, we mean values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
+ use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
+ an AJAX implementation&lt;br /&gt;
+ find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
+ pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
Let's take a look at an implementation that pre-loads all data.&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3789</id>
		<title>Dependent dropdowns</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Dependent_dropdowns&amp;diff=3789"/>
				<updated>2009-03-24T09:47:21Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: A possible implementation of dropdowns based on values in other dropdowns&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
On a regular basis, people ask on the forums for a solution implementing dependent dropdowns.&lt;br /&gt;
&lt;br /&gt;
With dependent dropdowns, we mean values in a dropdown are depending on a selection made in an earlier dropdown field.&lt;br /&gt;
&lt;br /&gt;
Since selecting a value in a dropdown is done client-side, at least some part of the solution will include (client-side) javascript coding.&lt;br /&gt;
&lt;br /&gt;
Possible solutions may exist out of these:&lt;br /&gt;
+ use hidden frames to call a custom made HTMPL file containing the values for the next dropdown, then use this data to populate the dropdown in the main window&lt;br /&gt;
+ an AJAX implementation&lt;br /&gt;
+ find a way to call the CA Service Desk web services using javascript, get the necessary values from the server and populate the dropdown&lt;br /&gt;
+ pre-load all data when your form gets loaded, then use javascript to display values when making selections in the dropdowns&lt;br /&gt;
&lt;br /&gt;
All these solutions will have advantages and disadvantages (e.g. calling webservices, using AJAX and even the 'hidden frame solution' may work a little slower compared to pre-loading all data. On the other hand, pre-loading data may take a long time if you have hundreds of values)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== All together now ==&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=QREL&amp;diff=3538</id>
		<title>QREL</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=QREL&amp;diff=3538"/>
				<updated>2008-11-18T16:10:06Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: QREL&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A QREL attribute is a &amp;quot;Query RELation&amp;quot;. A QREL attribute is also a list of objects defined by a where clause.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
QREL Syntax&lt;br /&gt;
children QREL chg DYNAMIC {&lt;br /&gt;
WHERE &amp;quot;parent = ? &amp;quot; ;&lt;br /&gt;
PARAM_NAMES { id } ;&lt;br /&gt;
DOMSET chg_list ;&lt;br /&gt;
} ;&lt;br /&gt;
&lt;br /&gt;
Used to access a list of objects related to the current object using where clause&lt;br /&gt;
Many to One Relationship&lt;br /&gt;
Example: The relationship of many Child Requests to Parent Request&lt;br /&gt;
&lt;br /&gt;
Indicates a virtual column representing a set of objects selected by the&lt;br /&gt;
where clause on the Advanced tab. It exists only in the Object Engine&lt;br /&gt;
and is not physically stored in the database.&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Variables_and_Types&amp;diff=1877</id>
		<title>Variables and Types</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Variables_and_Types&amp;diff=1877"/>
				<updated>2008-04-18T13:59:11Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Spel Reference Guide|&amp;lt;&amp;lt; back]]&lt;br /&gt;
&lt;br /&gt;
== Declaring variables ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
int theInt;&lt;br /&gt;
long theLong;&lt;br /&gt;
string theString;&lt;br /&gt;
object theObject;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Assignment of variables ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
int theInt, anotherInt;&lt;br /&gt;
theInt = 0;&lt;br /&gt;
anotherInt = 10;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Casting ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
string theString;&lt;br /&gt;
theString = &amp;quot;5&amp;quot;;&lt;br /&gt;
int theInt;&lt;br /&gt;
theInt = (int)theString;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== NULL ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
object theObject;&lt;br /&gt;
theObject = NULL;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Operators&amp;diff=1876</id>
		<title>Operators</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Operators&amp;diff=1876"/>
				<updated>2008-04-18T13:58:13Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Spel Reference Guide|&amp;lt;&amp;lt; back]]&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
+&lt;br /&gt;
-&lt;br /&gt;
*&lt;br /&gt;
/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Comparison Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
==&lt;br /&gt;
!=&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Concatenation Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
+&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logical Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
&amp;amp;&amp;amp;&lt;br /&gt;
!&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Operators&amp;diff=1875</id>
		<title>Operators</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Operators&amp;diff=1875"/>
				<updated>2008-04-18T13:57:30Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Spel Reference Guide]]&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
+&lt;br /&gt;
-&lt;br /&gt;
*&lt;br /&gt;
/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Comparison Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
==&lt;br /&gt;
!=&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Concatenation Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
+&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logical Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
&amp;amp;&amp;amp;&lt;br /&gt;
!&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Operators&amp;diff=1874</id>
		<title>Operators</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Operators&amp;diff=1874"/>
				<updated>2008-04-18T13:55:59Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: New page:  == Arithmetic Operators ==  &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt; + - * / &amp;lt;/source&amp;gt;  == Comparison Operators ==  &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt; == != &amp;lt;/source&amp;gt;  == Concatenation Operators ==  &amp;lt;source la...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Arithmetic Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
+&lt;br /&gt;
-&lt;br /&gt;
*&lt;br /&gt;
/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Comparison Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
==&lt;br /&gt;
!=&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Concatenation Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
+&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logical Operators ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
&amp;amp;&amp;amp;&lt;br /&gt;
!&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Spel_Reference_Guide&amp;diff=1873</id>
		<title>Spel Reference Guide</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Spel_Reference_Guide&amp;diff=1873"/>
				<updated>2008-04-18T13:53:54Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Reference Sections */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Customization]]&lt;br /&gt;
=What Is Spel=&lt;br /&gt;
&lt;br /&gt;
[[Category:Customization]]&lt;br /&gt;
=Reference Sections=&lt;br /&gt;
*Errors&lt;br /&gt;
*[[Functions]]&lt;br /&gt;
*[[Operators]]&lt;br /&gt;
**Arithmetic Operators&lt;br /&gt;
**Comparison Operators&lt;br /&gt;
**Concatenation Operators&lt;br /&gt;
**Logical Operators&lt;br /&gt;
*Statements&lt;br /&gt;
**[[If]]&lt;br /&gt;
**[[For]]&lt;br /&gt;
**[[Sindex]]&lt;br /&gt;
*[[Variables and Types]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;div align='center'&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;To make corrections or additions to this article, select the ''edit'' tab above.&amp;lt;br&amp;gt;&lt;br /&gt;
To discuss or ask questions about this article, select the ''discussion'' tab above.&amp;lt;/font&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Variables_and_Types&amp;diff=1872</id>
		<title>Variables and Types</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Variables_and_Types&amp;diff=1872"/>
				<updated>2008-04-18T13:49:27Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Declaring variables ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
int theInt;&lt;br /&gt;
long theLong;&lt;br /&gt;
string theString;&lt;br /&gt;
object theObject;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Assignment of variables ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
int theInt, anotherInt;&lt;br /&gt;
theInt = 0;&lt;br /&gt;
anotherInt = 10;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Casting ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
string theString;&lt;br /&gt;
theString = &amp;quot;5&amp;quot;;&lt;br /&gt;
int theInt;&lt;br /&gt;
theInt = (int)theString;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== NULL ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
object theObject;&lt;br /&gt;
theObject = NULL;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Variables_and_Types&amp;diff=1871</id>
		<title>Variables and Types</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Variables_and_Types&amp;diff=1871"/>
				<updated>2008-04-18T13:45:42Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: New page: Declaring variables  int theInt; long theLong; string theString; object theObject;  Assignment of variables  int theInt, anotherInt; theInt = 0; anotherInt = 10;  Casting  string theString...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Declaring variables&lt;br /&gt;
&lt;br /&gt;
int theInt;&lt;br /&gt;
long theLong;&lt;br /&gt;
string theString;&lt;br /&gt;
object theObject;&lt;br /&gt;
&lt;br /&gt;
Assignment of variables&lt;br /&gt;
&lt;br /&gt;
int theInt, anotherInt;&lt;br /&gt;
theInt = 0;&lt;br /&gt;
anotherInt = 10;&lt;br /&gt;
&lt;br /&gt;
Casting&lt;br /&gt;
&lt;br /&gt;
string theString;&lt;br /&gt;
theString = &amp;quot;5&amp;quot;;&lt;br /&gt;
int theInt;&lt;br /&gt;
theInt = (int)theString;&lt;br /&gt;
&lt;br /&gt;
NULL&lt;br /&gt;
&lt;br /&gt;
object theObject;&lt;br /&gt;
theObject = NULL;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	<entry>
		<id>http://greggsmith.net/wiki/index.php?title=Spel_Reference_Guide&amp;diff=1870</id>
		<title>Spel Reference Guide</title>
		<link rel="alternate" type="text/html" href="http://greggsmith.net/wiki/index.php?title=Spel_Reference_Guide&amp;diff=1870"/>
				<updated>2008-04-18T13:43:21Z</updated>
		
		<summary type="html">&lt;p&gt;Prohacx: /* Reference Sections */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Customization]]&lt;br /&gt;
=What Is Spel=&lt;br /&gt;
&lt;br /&gt;
[[Category:Customization]]&lt;br /&gt;
=Reference Sections=&lt;br /&gt;
*Errors&lt;br /&gt;
*[[Functions]]&lt;br /&gt;
*Operators&lt;br /&gt;
**Arithmetic Operators&lt;br /&gt;
**Comparison Operators&lt;br /&gt;
**Concatenation Operators&lt;br /&gt;
**Logical Operators&lt;br /&gt;
*Statements&lt;br /&gt;
**[[If]]&lt;br /&gt;
**[[For]]&lt;br /&gt;
**[[Sindex]]&lt;br /&gt;
*[[Variables and Types]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;div align='center'&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;To make corrections or additions to this article, select the ''edit'' tab above.&amp;lt;br&amp;gt;&lt;br /&gt;
To discuss or ask questions about this article, select the ''discussion'' tab above.&amp;lt;/font&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Prohacx</name></author>	</entry>

	</feed>