CFQuery for a Tri-Dependent Select

I am trying to use the <CF_ThreeSelectsRelated> tag.

I am having trouble getting it to work:

QUERY:
<!--- Query - Country/County/State --->
<cfquery name="rsTriSelect" datasource="#mm_datasource_dsn#">
      SELECT tbl_countries.CountryID, tbl_countries.Country, tbl_postalCode.CountryID, tbl_postalCode.County, tbl_postalCode.State, tbl_postalCode.StateID
      FROM tbl_postalCode, tbl_countries
      INNER JOIN tbl_countries.CountryID ON tbl_postalCode.CountryID
</cfquery>

CODE:
<cfinclude template="qry_CountyStateCity.cfm">
<form action="" method="post">
<CF_ThreeSelectsRelated
QUERY="rsTriSelect"
HTMLAFTER2="<BR>"
NAME1="Country"
NAME2="State"
NAME3="County"
VALUE1="tbl_countries.CountryID"
VALUE2="tbl_postalCode.StateCode"
VALUE3="tbl_postalCode.County"
DISPLAY1="tbl_countries.Country"
DISPLAY2="tbl_postalCode.State"
DISPLAY3="tbl_postalCode.County"
DEFAULT1="254"
SIZE1="1"
SIZE2="1"
SIZE3="1"
WIDTH1="150"
WIDTH2="150"
WIDTH3="300"
FORCEWIDTH1="40"
FORCEWIDTH2="40"
FORCEWIDTH3="90"
AUTOSELECTFIRST="yes"
MULTIPLE3="no">
</form>


How difficult is it to make this a Quad Select (Country, State, County and City)?
jollymon6672Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mrichmonCommented:
Well it is not difficult to write a 4 related selects, but there is no pre-made tag that I know of.

Here is hand code for how to write a two selects related, that can be easily extended to a 4 selects related
http://www.experts-exchange.com/Web/WebDevSoftware/ColdFusion/Q_20973970.html


Simply write a fill function i.e. fillBuyers for each sub select and attach the event like this:

<select name="DepartmentID" onChange="fillState()" style="width: 200px;">
     <option value=""></option>
     <option value="1">Unites States</option>
     <option value="2">Canada</option>
     <option value="3">Spain</option>
etc.. // or have thsi from a query too.
</select>

<select name="State" onChange="fillCounty()" style="width: 200px;"></select>
<select name="County" onChange="fillCity()" style="width: 200px;"></select>
<select name="City" style="width: 200px;"></select>
0
jollymon6672Author Commented:
Any idea why my current code is not working?
0
jollymon6672Author Commented:
Ideally I would like to extend the tri-select tag to be a quad-select tag. I am trying use a postal data table and narrow down the slection choices:

Country:
State/Region:
County:
City:
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

mrichmonCommented:
You cannot modify the tag if you do not have the source code for it
0
jollymon6672Author Commented:
<!--- REMOVE THIS AND FIRST LINE IF NOT USING CF3.1 OR LATER --->
<CFSETTING ENABLECFOUTPUTONLY="YES">

<!--- TAG PARAMETERS --->
<CFPARAM NAME="Attributes.Query">  
<CFPARAM NAME="Attributes.Type1" DEFAULT="Select">  
<CFPARAM NAME="Attributes.HTMLAfterEachRadio1" DEFAULT="">  
<CFPARAM NAME="Attributes.Name1" DEFAULT="TwoSelectsRelated1">
<CFPARAM NAME="Attributes.Name2" DEFAULT="TwoSelectsRelated2">
<CFPARAM NAME="Attributes.Name3" DEFAULT="TwoSelectsRelated3">
<CFPARAM NAME="Attributes.Value1">
<CFPARAM NAME="Attributes.Value2">
<CFPARAM NAME="Attributes.Value3">
<CFPARAM NAME="Attributes.Display1" DEFAULT="#Attributes.Value1#">
<CFPARAM NAME="Attributes.Display2" DEFAULT="#Attributes.Value2#">
<CFPARAM NAME="Attributes.Display2" DEFAULT="#Attributes.Value3#">
<CFPARAM NAME="Attributes.Default1" DEFAULT="xxxxxxxxxxxx">
<CFPARAM NAME="Attributes.Default2" DEFAULT="xxxxxxxxxxxx">
<CFPARAM NAME="Attributes.Default3" DEFAULT="xxxxxxxxxxxx">
<CFPARAM NAME="Attributes.Multiple3" DEFAULT="No">
<CFPARAM NAME="Attributes.Size1" DEFAULT="1">
<CFPARAM NAME="Attributes.Size2" DEFAULT="1">
<CFPARAM NAME="Attributes.Size3" DEFAULT="1">
<CFPARAM NAME="Attributes.ExtraOptions2" DEFAULT="">
<CFPARAM NAME="Attributes.ExtraOptions3" DEFAULT="">
<CFPARAM NAME="Attributes.Width1" DEFAULT="">
<CFPARAM NAME="Attributes.Width2" DEFAULT="">
<CFPARAM NAME="Attributes.Width3" DEFAULT="">
<CFPARAM NAME="Attributes.ForceWidth1" DEFAULT="">
<CFPARAM NAME="Attributes.ForceWidth2" DEFAULT="">
<CFPARAM NAME="Attributes.ForceWidth4" DEFAULT="">
<CFPARAM NAME="Attributes.ForceWidthChar" DEFAULT="&nbsp;">
<CFPARAM NAME="Attributes.EmptyText1" DEFAULT="">
<CFPARAM NAME="Attributes.EmptyText2" DEFAULT="">
<CFPARAM NAME="Attributes.EmptyText3" DEFAULT="">
<CFPARAM NAME="Attributes.Message1" DEFAULT="You must choose an option for #Attributes.Name1#.">
<CFPARAM NAME="Attributes.Message2" DEFAULT="You must choose an option for #Attributes.Name2#.">
<CFPARAM NAME="Attributes.Message3" DEFAULT="You must choose an option for #Attributes.Name3#.">
<CFPARAM NAME="Attributes.FormName" DEFAULT="forms[0]">
<CFPARAM NAME="Attributes.HTMLAfter1" DEFAULT="">
<CFPARAM NAME="Attributes.HTMLAfter2" DEFAULT="">
<CFPARAM NAME="Attributes.OnChange" DEFAULT="">
<CFPARAM NAME="Attributes.AutoSelectFirst" DEFAULT="Yes">


<CFIF Attributes.Type1 is "Radio">
  <CFSET Attributes.EmptyText1 = "">
  <CFSET Attributes.ForceWidth1 = "">
</CFIF>



<CFSET FunctionName = ReplaceList(Attributes.FormName, "[,]", ",") & "ChangeMenu">
<CFSET FunctionName2 = ReplaceList(Attributes.FormName, "[,]", ",") & "ChangeMenu2">


<!--- "MAGIC" SHORTCUTS FOR THE ONCHANGE HANDLER --->
<CFIF Attributes.OnChange is "Jump!">
  <CFSET Attributes.OnChange = "document.location = this.options[selectedIndex].value;">
<CFELSEIF Attributes.OnChange is "Submit!">
  <CFSET Attributes.OnChange = "this.form.submit();">
</CFIF>



<!--- USE PASSED QUERY WITHIN THIS CODE AS "MyQuery" --->
<CFSET MyQuery = Evaluate("Caller.#Attributes.Query#")>


<!--- BEGIN JAVASCRIPTING --->
<CFOUTPUT>
      <SCRIPT LANGUAGE="JavaScript1.1">
        // javascript code generated by the CF_TwoSelectsRelated Cold Fusion tag (Nate Weiss, 4/98)
            // portions adapted from Nick Heinle's code at http://webreference.com/javascript/960902/select_boxes.html
        var maxlength = 10;
        OneA = new Array;

            var trueLength = OneA.length;  
            var lst = OneA.length;
    var Trak = 0;

    function require_#Attributes.Name1#() {
              with (document.#Attributes.FormName#.#Attributes.Name1#) {
                    RetVal = true;
                    if (Trak == -1) RetVal = false;
                          <CFIF Attributes.Type1 is "Select">
                          else RetVal = !(options[Trak].value == '');
                              <CFELSEIF Attributes.Type1 is "Radio">
                          else { if (document.#Attributes.FormName#.#Attributes.Name1#[Trak].value == '') RetVal = false; else RetVal = true;}
                              </CFIF>
                    if (!RetVal) alert('#Attributes.Message1#');
                        return RetVal;
                  }
            }

    function require_#Attributes.Name2#() {
              with (document.#Attributes.FormName#.#Attributes.Name2#) {
                    RetVal = true;
                    if (selectedIndex == -1) RetVal = false;
                          else RetVal = !(options[selectedIndex].value == '');
                    if (!RetVal) alert('#Attributes.Message2#');
        return eval(RetVal);
                        return RetVal;
                  }
            }
            
    function require_#Attributes.Name3#() {
              with (document.#Attributes.FormName#.#Attributes.Name3#) {
                    RetVal = true;
                    if (selectedIndex == -1) RetVal = false;
                          else RetVal = !(options[selectedIndex].value == '');
                    if (!RetVal) alert('#Attributes.Message3#');
                        return RetVal
                  }
            }
            
            function require_#Attributes.Name1#And#Attributes.Name2#() {
              return ((require_#Attributes.Name1#()) && (require_#Attributes.Name2#()));
            }

            function require_#Attributes.Name2#And#Attributes.Name3#() {
              return ((require_#Attributes.Name2#()) && (require_#Attributes.Name3#()));
            }
            
            function require_#Attributes.Name1#And#Attributes.Name2#And#Attributes.Name3#() {
              return ((require_#Attributes.Name1#And#Attributes.Name2#()) && (require_#Attributes.Name3#()));
            }
                        
            function #FunctionName#(menuNum) {
               OneA.length = 0;
               if (menuNum == null) return;  
                   Trak = menuNum;
                   <!--- ignore if a blank item gets clicked --->
                   <CFIF Attributes.Type1 is "Select">
                   if (document.#Attributes.FormName#.#Attributes.Name1#.options[menuNum].value == '') return;
                   if (document.#Attributes.FormName#.#Attributes.Name1#.options[menuNum].value == null) return;
                   </CFIF>
</CFOUTPUT>


<!--- COUNTER VARIABLE WILL HOLD NUMBER OF GROUPS (OPTIONS IN FIRST SELECT) --->
<CFSET Counter = IIF(Attributes.EmptyText1 is not "", 1, 0)>

<!--- CREATE AN "IF" STATEMENT THAT COVERS EACH ITEM IN THE FIRST SELECT BOX --->
<!--- WITHIN THE "IF" STATMENT, PRE-POPULATE ARRAY WITH CORRESPONDING ITEMS FOR SECOND SELECT  --->
<CFOUTPUT QUERY="MyQuery" GROUP="#Attributes.Display1#">
      if (menuNum == #Counter#) {
        NewOpt = new Array;
            NewVal = new Array;
    <CFSET Counter2 = IIF(Attributes.EmptyText2 is not "", 1, 0)>
    <CFIF Attributes.EmptyText2 is not ""><CFOUTPUT>NewOpt[0] = new Option("#Attributes.EmptyText2#");      NewOpt[0].value = '';      </CFOUTPUT></CFIF>
            <CFOUTPUT GROUP="#Attributes.Display2#">NewOpt[#Counter2#] = new Option("#Evaluate(Attributes.Display2)#");      NewOpt[#Counter2#].value = '#Evaluate(Attributes.Value2)#'; <CFSET Counter2 = Counter2 + 1></CFOUTPUT>
      } <CFSET Counter = Counter + 1>
</CFOUTPUT>


<!--- finish up the ChangeMenu() function --->
<CFOUTPUT>
  tot = NewOpt.length;
      lst = document.#Attributes.FormName#.#Attributes.Name2#.options.length;
      for (i = lst; i > 0; i--) {
        document.#Attributes.FormName#.#Attributes.Name2#.options[i] = null;
      }
  for (i = 0; i < tot; i++) {
        document.#Attributes.FormName#.#Attributes.Name2#.options[i] = NewOpt[i];
      }
  <!--- <CFIF Attributes.AutoSelectFirst is "Yes"> --->
        document.#Attributes.FormName#.#Attributes.Name2#.options[0].selected = true;
      <!--- </CFIF> --->
      #FunctionName2#(0);
}
</CFOUTPUT>




<!--- ALLOW FOR AUTO-SIZING "SHORTCUT" OF SELECT BOXES --->
<CFIF Attributes.Size1 is "Auto">
  <!--- MAKE THE FIRST SELECT BE BIG ENOUGH FOR ALL OF ITS OPTIONS --->
  <CFSET Attributes.Size1 = Counter>
</CFIF>
<CFIF Attributes.Size2 is "Auto">
  <!--- MAKE THE SECOND SELECT BE THE SAME SIZE AS THE FIRST --->
  <CFSET Attributes.Size2 = Attributes.Size1>
</CFIF>
<CFIF Attributes.Size3 is "Auto">
  <!--- MAKE THE SECOND SELECT BE THE SAME SIZE AS THE FIRST --->
  <CFSET Attributes.Size3 = Attributes.Size1>
</CFIF>



<CFOUTPUT>
            function #FunctionName2#() {
               OneA.length = 0;
                   menuNum = Trak;
               //menuNum = document.#Attributes.FormName#.#Attributes.Name1#.selectedIndex;
               menuNum2 = document.#Attributes.FormName#.#Attributes.Name2#.selectedIndex;
               if (menuNum == -1) return;  
               if (menuNum2 == null) return;  
                   <!--- ignore if a the blank item gets clicked --->
                   if (document.#Attributes.FormName#.#Attributes.Name2#.options[menuNum2].value == '') return;
</CFOUTPUT>


<!--- COUNTER VARIABLE WILL HOLD NUMBER OF GROUPS (OPTIONS IN FIRST SELECT) --->
<CFSET Counter1 = 0>

<!--- CREATE AN "IF" STATEMENT THAT COVERS EACH ITEM IN THE FIRST SELECT BOX --->
<!--- WITHIN THE "IF" STATMENT, PRE-POPULATE ARRAY WITH CORRESPONDING ITEMS FOR SECOND SELECT  --->
<CFOUTPUT QUERY="MyQuery" GROUP="#Attributes.Display1#">
if (menuNum == #Counter1#) {
<CFSET Counter = IIF(Attributes.EmptyText2 is not "", 1, 0)>
<CFOUTPUT GROUP="#Attributes.Display2#">
      if (menuNum2 == #Counter#) {
        NewOpt = new Array;
            NewVal = new Array;
    <CFSET Counter2 = IIF(Attributes.EmptyText2 is not "", 1, 0)>
    <CFIF Attributes.EmptyText3 is not "">NewOpt[0] = new Option("#Attributes.EmptyText3#");      NewOpt[0].value = '';      </CFIF>
            <CFOUTPUT>
              NewOpt[#Counter2#] = new Option("#Evaluate(Attributes.Display3)#");
                  NewOpt[#Counter2#].value = '#Evaluate(Attributes.Value3)#';
                  <CFSET Counter2 = Counter2 + 1>
            </CFOUTPUT>
      } <CFSET Counter = Counter + 1>
</CFOUTPUT>      
}      <CFSET Counter1 = Counter1 + 1>
</CFOUTPUT>


<CFOUTPUT>
  tot = NewOpt.length;
      lst = document.#Attributes.FormName#.#Attributes.Name3#.options.length;
      
      for (i = lst; i > 0; i--) {
        document.#Attributes.FormName#.#Attributes.Name3#.options[i] = null;
      }
  for (i = 0; i < tot; i++) {
        document.#Attributes.FormName#.#Attributes.Name3#.options[i] = NewOpt[i];
      }
  <CFIF Attributes.AutoSelectFirst is "Yes">
        document.#Attributes.FormName#.#Attributes.Name3#.options[0].selected = true;
      </CFIF>
}
</SCRIPT>
</CFOUTPUT>

<!--- DONE WITH JAVASCRIPTING.  NOW WE JUST HAVE TO DISPLAY THE FORM ELEMENTS --->







<!--- OUTPUT FIRST FORM ELEMENT --->
<CFIF Attributes.Type1 is "Select">
<CFOUTPUT><SELECT NAME="#Attributes.Name1#" onChange="#FunctionName#(this.selectedIndex)" SIZE="#Attributes.Size1#" <CFIF Attributes.Width1 is not "">STYLE="width:#Attributes.Width1#"</CFIF>></CFOUTPUT>
      <!--- SPECIAL FIRST ITEM, IF REQUESTED --->
      <CFIF Attributes.EmptyText1 is not ""><CFOUTPUT><OPTION VALUE="">#Attributes.EmptyText1#</CFOUTPUT></CFIF>
      <!--- GENERATE REMAINING ITEMS FROM QUERY --->
      <CFOUTPUT QUERY="MyQuery" GROUP="#Attributes.Display1#"><OPTION VALUE="#Evaluate(Attributes.Value1)#"  <CFIF Evaluate(Attributes.Value1) is Attributes.Default1>SELECTED</CFIF>>#Evaluate(Attributes.Display1)#</CFOUTPUT>
      
  <!--- "FORCE WIDTH" OPTION AT BOTTOM, IF REQUESTED --->
      <CFIF Attributes.ForceWidth1 is not ""><CFOUTPUT><OPTION VALUE="">#RepeatString(Attributes.ForceWidthChar, Attributes.ForceWidth1)#</CFOUTPUT></CFIF>
<CFOUTPUT></SELECT></CFOUTPUT>

<CFELSE>
  <!--- RADIO BOXES --->
  <CFSET Counter = 0>
  <CFOUTPUT QUERY="MyQuery" GROUP="#Attributes.Display1#"><INPUT TYPE="Radio" NAME="#Attributes.Name1#" VALUE="#Evaluate(Attributes.Value1)#" <CFIF Evaluate(Attributes.Value1) is Attributes.Default1>CHECKED</CFIF> onClick="#FunctionName#(#Counter#)">#Evaluate(Attributes.Display1)##Attributes.HTMLAfterEachRadio1#<CFSET Counter = Counter + 1></CFOUTPUT>

</CFIF>



<!--- INSERT ANY REQUESTED HTML BETWEEN 1ST AND SECOND ITEMS --->
<CFOUTPUT>#Attributes.HTMLAfter1#</CFOUTPUT>



<!--- OUTPUT SECOND SELECT BOX --->
<CFOUTPUT><SELECT NAME="#Attributes.Name2#" SIZE="#Attributes.Size2#" onChange="#FunctionName2#(this.selectedIndex)" <CFIF Attributes.Width2 is not "">STYLE="width:#Attributes.Width2#"</CFIF>></CFOUTPUT>
      <!--- SPECIAL FIRST ITEM, IF REQUESTED --->
      <CFIF Attributes.EmptyText2 is not ""><CFOUTPUT><OPTION VALUE="">#Attributes.EmptyText2#</CFOUTPUT></CFIF>
      
      <!--- GENERATE REMAINING ITEMS FROM QUERY --->
      <!--- WE ONLY NEED TO OUTPUT THE CHOICES FOR THE FIRST GROUP --->
      <!--- <CFSET FirstGroup = Evaluate("MyQuery.#Attributes.Value1#[1]")> --->
      <CFSET FirstGroup = Attributes.Default1>
      <CFSET CurrentGroup2 = "">
      <CFIF Attributes.EmptyText1 is "">
            <CFLOOP QUERY="MyQuery">
              <CFIF Evaluate("MyQuery.#Attributes.Value1#") is Variables.FirstGroup>
                    <CFSET ThisValue = Evaluate("MyQuery.#Attributes.Value2#")>
                    <CFIF Variables.ThisValue is not Variables.CurrentGroup2>
                      <CFOUTPUT><OPTION VALUE="#Variables.ThisValue#" <CFIF Variables.ThisValue is Attributes.Default2>SELECTED</CFIF>>#Evaluate("MyQuery.#Attributes.Display2#")#</CFOUTPUT>
                        <CFSET CurrentGroup2 = Evaluate("MyQuery.#Attributes.Value2#")>
                        </CFIF>
                  <!--- <CFELSE>
                    <CFBREAK> --->
                  </CFIF>
            </CFLOOP>
      </CFIF>      

  <!--- "FORCE WIDTH" OPTION AT BOTTOM, IF REQUESTED --->
      <CFIF Attributes.ForceWidth2 is not ""><CFOUTPUT><OPTION VALUE="">#RepeatString(Attributes.ForceWidthChar, Attributes.ForceWidth2)#</CFOUTPUT></CFIF>
      <CFIF Attributes.ExtraOptions2 is not ""><CFLOOP INDEX="This" FROM="1" TO="#Attributes.ExtraOptions2#"><CFOUTPUT><OPTION VALUE=""></CFOUTPUT></CFLOOP></CFIF>
<CFOUTPUT></SELECT></CFOUTPUT>



<!--- INSERT ANY REQUESTED HTML BETWEEN 2ND AND 3RD ITEMS --->
<CFOUTPUT>#Attributes.HTMLAfter2#</CFOUTPUT>



<!--- OUTPUT THIRD SELECT BOX --->
<CFOUTPUT><SELECT NAME="#Attributes.Name3#" SIZE="#Attributes.Size3#" <CFIF Attributes.Multiple3 is "Yes">MULTIPLE </CFIF><CFIF Attributes.Width3 is not "">STYLE="width:#Attributes.Width3#"</CFIF><CFIF Attributes.OnChange is not ""> OnChange="#Attributes.OnChange#"</CFIF>></CFOUTPUT>
      <CFSET FirstGroup = Attributes.Default1>
      <CFIF Attributes.EmptyText3 is "">
            <CFLOOP QUERY="MyQuery">
              <CFIF Evaluate("MyQuery.#Attributes.Value1#") is Variables.FirstGroup>
                    <CFSET Hack = Evaluate("MyQuery.#Attributes.Value2#")>
                    <CFSET ThisValue = Evaluate("MyQuery.#Attributes.Value3#")>
                    <CFPARAM NAME="Variables.FirstGroup2" DEFAULT="#Variables.Hack#">
                    <CFIF Evaluate("MyQuery.#Attributes.Value2#") is Variables.FirstGroup2>
                          <CFOUTPUT><OPTION VALUE="#Variables.ThisValue#" <CFIF Variables.ThisValue is Attributes.Default3>SELECTED</CFIF>>#Evaluate("MyQuery.#Attributes.Display3#")#</CFOUTPUT>
                        </CFIF>      
                  </CFIF>
            </CFLOOP>
      </CFIF>      

      <CFIF Attributes.ForceWidth3 is not ""><CFOUTPUT><OPTION VALUE="">#RepeatString(Attributes.ForceWidthChar, Attributes.ForceWidth3)#</CFOUTPUT></CFIF>
      <CFIF Attributes.ExtraOptions3 is not ""><CFLOOP INDEX="This" FROM="1" TO="#Attributes.ExtraOptions3#"><CFOUTPUT><OPTION VALUE=""></CFOUTPUT></CFLOOP></CFIF>
<CFOUTPUT></SELECT></CFOUTPUT>

<!--- REMOVE THIS AND FIRST LINE IF NOT USING CF3.1 OR LATER --->
<CFSETTING ENABLECFOUTPUTONLY="NO">
0
jollymon6672Author Commented:
Above is the tag source code. In my first post is the tag implimentation and my query. Any ideas on why it is not working in it's original state and how I can extend the custom tag to be a quad select or more?

Thanks for you help.
0
mrichmonCommented:
Sorry, I did not get the notification (or it was seen as spam) that you had posted

No ideas on why it is not working.  Not worth my time to look into since it is more code than my example of writing the solution by hand.

As for how to extend the tag.  SImply copy everywhere that has a 3 and and change to a 4

For example:

function require_#Attributes.Name3#() {
            with (document.#Attributes.FormName#.#Attributes.Name3#) {
                 RetVal = true;
                 if (selectedIndex == -1) RetVal = false;
                      else RetVal = !(options[selectedIndex].value == '');
                 if (!RetVal) alert('#Attributes.Message3#');
                    return RetVal
               }
          }

So you expand by adding this:

function require_#Attributes.Name4#() {
            with (document.#Attributes.FormName#.#Attributes.Name4#) {
                 RetVal = true;
                 if (selectedIndex == -1) RetVal = false;
                      else RetVal = !(options[selectedIndex].value == '');
                 if (!RetVal) alert('#Attributes.Message4#');
                    return RetVal
               }
          }

Do this throughout hte tag to extend to 4 options.

If you see a place that has a 3 with other numbers like here:
function require_#Attributes.Name2#And#Attributes.Name3#() {
            return ((require_#Attributes.Name2#()) && (require_#Attributes.Name3#()));
          }

then change the 3 to a 4 and the 2 to a 3 in the copy like this:

function require_#Attributes.Name3#And#Attributes.Name4#() {
            return ((require_#Attributes.Name3#()) && (require_#Attributes.Name4#()));
          }
0
jollymon6672Author Commented:
OK, then based on your originial example is this the correct way to impliment?
<!--- Query - Country/County/State --->
<cfquery name="rsCountry" datasource="#mm_DATASOURCE_dsn#">
      SELECT tbl_countries.Country, tbl_postalCode.State, tbl_postalCode.StateCode, tbl_postalCode.City, tbl_postalCode.County
      FROM tbl_countries
      INNER JOIN tbl_postalCode
      ON tbl_countries.CountryID = tbl_postalCode.CountryID
      ORDER BY tbl_countries.CountryID
</cfquery>

<script type="text/javascript" language="JavaScript">
<!--
/* Dynamically populate State select box based on seleted Country */
// Create an array to hold State
var StateArray = new Array;

// Define a custom Javascript object type to represent a single State
function State(County, Country, State)
{
     this.County = County;
     this.Country = Country;
     this.State = State;
}
<!--- For each State, append a new State object to the array of State --->
<cfoutput query="GetState">
     StateArray[StateArray.length] = new State("#JSStringFormat(Username)#", "#JSStringFormat(Country)#", "#JSStringFormat(State)#");
</cfoutput>

/* Fill the State select box based on the Country */
function fillState()
{
     // Stop if there is no selected ParentID
     if (document.AddIssue.Country.selectedIndex == -1)
     {
          return;
     }
     
     var Country = document.AddIssue.Country.options[document.AddIssue.Country.selectedIndex].value;
     
     // Remove all options in the State select box
     document.AddIssue.State.options.length = 0;
     
     // For each item in the State array ...
     for (var i = 0; i < StateArray.length; i++)
     {
          // If the State's Country is the same as the currently selected Country
          if (StateArray[i].Country == Country)
          {
               // Put a new option in the State select box
               document.AddIssue.State.options[document.AddIssue.State.options.length] = new Option(StateArray[i].State, StateArray[i].County);
          }
     }
}
-->
</script>



<select name="CountryID" onChange="fillCountries()" style="width: 200px;">
  <option value="">Select Country</option>
  <cfoutput query="rsCountry">
    <option value="#rsCountry.Country#">#rsCountry.Country#</option>
  </cfoutput>
</select>

<select name="State" style="width: 200px;"></select>
0
mrichmonCommented:
Very close, but not quite.  Here is an example with the county related to the state.
You should be able to easily exoand to the county and city but I couldn't write out for you since I did not see what the CityId or CountyId fields were called.

To expand simply write another query like GetStates.  One for GetCounties and one for GetCities.  Then duplicate the javascript block changing the word state to County and Country to State.  Then duplicate again and change the word country to county and state to city.  Then you will have it.

<cfquery name="rsCountry" datasource="#mm_DATASOURCE_dsn#">
     SELECT tbl_countries.Country, tbl_postalCode.State, tbl_postalCode.StateCode, tbl_postalCode.City, tbl_postalCode.County
     FROM tbl_countries
     INNER JOIN tbl_postalCode
     ON tbl_countries.CountryID = tbl_postalCode.CountryID
     ORDER BY tbl_countries.CountryID
</cfquery>

<cfquery name="GetStates" datasource="#mm_DATASOURCE_dsn#">
     SELECT tbl_countries.CountryID, tbl_postalCode.State, tbl_postalCode.StateCode
     FROM tbl_countries
     INNER JOIN tbl_postalCode
     ON tbl_countries.CountryID = tbl_postalCode.CountryID
     ORDER BY tbl_countries.CountryID, tbl_postalCode.State
</cfquery>

<script type="text/javascript" language="JavaScript">
<!--
/* Dynamically populate States select box based on seleted Country */
// Create an array to hold States
var StateArray = new Array;

// Define a custom Javascript object type to represent a single Buyer
function State(StateCode, CountryID, State)
{
     this.StateCode= StateCode;
     this.CountryID= CountryID;
     this.State= State;
}
<!--- For each State, append a new Stateobject to the array of States --->
<cfoutput query="GetStates">
     StateArray[StateArray.length] = new State("#JSStringFormat(StateCode)#", "#JSStringFormat(CountryID)#", "#JSStringFormat(State)#");
</cfoutput>

/* Fill the State select box based on the CountryID*/
function fillStates()
{
     // Stop if there is no selected CountryID
     if (document.formName.CountryID.selectedIndex == -1)
     {
          return;
     }
     
     var CountryID= document.formName.CountryID.options[document.formName.CountryID.selectedIndex].value;
     
     // Remove all options in the State select box
     document.formName.State.options.length = 0;
     
     // For each item in the State array ...
     for (var i = 0; i < StateArray.length; i++)
     {
          // If the State's CountryIDis the same as the currently selected CountryID
          if (StateArray[i].CountryID== CountryID)
          {
               // Put a new option in the Stateselect box
               document.formName.State.options[document.formName.State.options.length] = new Option(StateArray[i].State, StateArray[i].StateCode);
          }
     }
}
-->
</script>


<select name="CountryID" onChange="fillState()" style="width: 200px;">
     <option value="">Select Country</option>
     <cfoutput query="rsCountry">
         <option value="#rsCountry.Country#">#rsCountry.Country#</option>
      </cfoutput>
</select>

<select name="State" onChange="fillCounty()" style="width: 200px;"></select>
<select name="County" onChange="fillCity()" style="width: 200px;"></select>
<select name="City" style="width: 200px;"></select>
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Servers

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.