Jump to content

Signup Forms State Dropdown rather than Text Box


Matt

Recommended Posts

  • WHMCS CEO

We've had a number of users ask if and how they can change the state field in WHMCS signup forms to be a dropdown of options rather than simply a text field. The problem was simply changing it to a dropdown renders it unusuable for anything but a default country but the solution below will show a different dropdown of values based on the country selection and fallback to the standard text entry field if no states are specified for a particular country.

 

Installation Steps

 

These can be performed in any template with a state field.

 

1. Find:

 

{$clientcountriesdropdown}

 

and replace with:

 

{$clientcountriesdropdown|replace:'<select':'<select id="country"'}

 

2. Find the state field, usually something like :

 

<input type="text" name="state" size="25" value="{$clientstate}" />

 

and replace with:

 

<input type="text" name="state" size="25" value="{$clientstate}" id="state" /><div id="statedropdown"></div>

 

3. Add below the table of input fields these 2 JavaScript includes:

 

<script type="text/javascript" src="includes/jscript/jquerylq.js"></script>
<script type="text/javascript" src="includes/jscript/statedropdown.js"></script>

 

4. Finally, create the file statedropdown.js in the /includes/jscript/ directory and into it, insert the following code:

 

var ar = new Array();
ar['GB'] = "<option>Avon</option><option>Bedfordshire</option><option>Berkshire</option>";
ar['US'] = "<option>Alabama</option><option>Alaska</option><option>Arizona</option><option>Arkansas</option><option>California</option>";

$(document).ready(function(){
   $("#country").change(function() {
       var country = $(this).val();
       if (ar[country]) {
           $("#state").hide();
           $("#statedropdown").html('<select id="statedd">'+ar[country]+'</select>');
           $("#state").val($("#statedd").val());
       } else {
           $("#state").show();
           $("#statedropdown").html('');
       }
   });
   $("#statedd").livequery("change", function(event) {
       $("#state").val($(this).val());
   });
   var country = $("#country").val();
   if (ar[country]) {
       $("#state").hide();
       $("#statedropdown").html('<select id="statedd">'+ar[country]+'</select>');
       $("#state").val($("#statedd").val());
   } else {
       $("#state").show();
       $("#statedropdown").html('');
   }
});

 

In the code above, you simply need to enter all the various country & state combinations you want to offer following the format of the first lines. Just the first few states for the UK & US are included by default but hopefully in due course we can get users contributing the states for their own countries in this thread to build up a complete standard list.

 

Matt

Link to comment
Share on other sites

For the US states (2 minutes and a regex replace):

<option>Alabama</option><option>Alaska</option><option>Arizona</option><option>Arkansas</option><option>California</option><option>Colorado</option><option>Connecticut</option><option>Delaware</option><option>Florida</option><option>Georgia</option><option>Hawaii</option><option>Idaho</option><option>Illinois</option><option>Indiana</option><option>Iowa</option><option>Kansas</option><option>Kentucky</option><option>Louisiana</option><option>Maine</option><option>Maryland</option><option>Massachusetts</option><option>Michigan</option><option>Minnesota</option><option>Mississippi</option><option>Missouri</option><option>Montana</option><option>Nebraska</option><option>Nevada</option><option>New Hampshire</option><option>New Jersey</option><option>New Mexico</option><option>New York</option><option>North Carolina</option><option>North Dakota</option><option>Ohio</option><option>Oklahoma</option><option>Oregon</option><option>Pennsylvania</option><option>Rhode Island</option><option>South Carolina</option><option>South Dakota</option><option>Tennessee</option><option>Texas</option><option>Utah</option><option>Vermont</option><option>Virginia</option><option>Washington</option><option>West Virginia</option><option>Wisconsin</option><option>Wyoming</option>

Link to comment
Share on other sites

Added most of the states/regions and slimmed down the repetitive option tags with a sligntly updated jquery function... (All of the data was too large to post here, refer to the attached zip file)

 

var ar = new Array();
ar['US']="Alabama|Alaska|Arizona|Arkansas|California|Colorado|Connecticut|Delaware|District of Columbia|Florida|Georgia|Hawaii|Idaho|Illinois|Indiana|Iowa|Kansas|Kentucky|Louisiana|Maine|Maryland|Massachusetts|Michigan|Minnesota|Mississippi|Missouri|Montana|Nebraska|Nevada|New Hampshire|New Jersey|New Mexico|New York|North Carolina|North Dakota|Ohio|Oklahoma|Oregon|Pennsylvania|Rhode Island|South Carolina|South Dakota|Tennessee|Texas|Utah|Vermont|Virginia|Washington|West Virginia|Wisconsin|Wyoming";
$(document).ready(function(){
$("#country").change(function() {
	var country = $(this).val();
	if (ar[country]) {
		$("#state").hide();
		$("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
		$("#state").val($("#statedd").val());
	} else {
		$("#state").show();
		$("#statedropdown").html('');
	}
});
$("#statedd").livequery("change", function(event) {
	$("#state").val($(this).val());
});
var country = $("#country").val();
if (ar[country]) {
	$("#state").hide();
	$("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
	$("#state").val($("#statedd").val());
} else {
	$("#state").show();
	$("#statedropdown").html('');
}
});

Note: The GB array needs verification since the data I had seperated out both Wales and Scotland...

statedropdown.zip

Link to comment
Share on other sites

Good effort Rob... thanks

found a bug if the state array does not exist the last value was being shown.

Highlighted the fix and used jQuery tag in case someone is using the noConflict tag

<<SNIP>> arrays at top removed to shorten the post... add them from robs zip file.

jQuery(document).ready(function(){
   jQuery("#country").change(function() {
       var country = jQuery(this).val();
       if (ar[country]) {
           jQuery("#state").hide();
           jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
           jQuery("#state").val(jQuery("#statedd").val());
       } else {
          [b] jQuery("#state").val('');[/b]
           jQuery("#state").show();
           jQuery("#statedropdown").html('');
       }
   });

   jQuery("#statedd").livequery("change", function(event) {
           jQuery("#state").val(jQuery(this).val());
   });

   var country = jQuery("#country").val();
   if (ar[country]) {
       jQuery("#state").hide();
       jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
       jQuery("#state").val(jQuery("#statedd").val());
   } else {
      [b] jQuery("#state").val('');[/b]
       jQuery("#state").show();
       jQuery("#statedropdown").html('');
   }
});

Edited by sparky
Link to comment
Share on other sites

Right now , we only have the script on the clientregister.php page for that reason...

 

But after playing a bit, I've modified the function to not touch the state if its already populated (like in the clientdetails.php page)... But if the user does changes the country, then the state will change...

 

jQuery(document).ready(function(){
jQuery("#country").change(function() {
	var country = jQuery(this).val();
	if (ar[country]) {
		jQuery("#state").hide();
		jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
		jQuery("#state").val(jQuery("#statedd").val());
	} else {
		jQuery("#state").val('');
		jQuery("#state").show();
		jQuery("#statedropdown").html('');
	}
});

jQuery("#statedd").livequery("change", function(event) {
		jQuery("#state").val(jQuery(this).val());
});

var country = jQuery("#country").val();
if (jQuery("#state").val() == '') {
	if (ar[country]) {
		jQuery("#state").hide();
		jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
		jQuery("#state").val(jQuery("#statedd").val());
	} else {
		jQuery("#state").val('');
		jQuery("#state").show();
		jQuery("#statedropdown").html('');
	}
}
});

An interesting observation is the the country list (of both two letter abbreviation value and full name) is hard coded internally and the smarty code of {$clientcountriesdropdown} pulls that list and selects the default county based on the DefaultCountry from the settings... Perhaps someone (who has multi-country clients) would write a jquery based geo-location lookup to set the default country for the clients during registration... I thought about doing that for the state code (here in the US) but that may appear to be a bit "big brother" for some visitors...

 

Now, I have a new dilema, we use the two letter codes and not the full name of the states... So I'm looking into doing a option value/name pair for the state lookups...

Link to comment
Share on other sites

Ok... here again is a revised function to allow the use of states codes in the state fields formatted as ST=State Name and each state Name/Value pair is delimited with pipes... Obviously you will need to update the appropriate arrays with these codes like this:

 

I did Australia for Sparky as an example ;) and verified the state codes with Australia Post:

ar['AU']="ACT=Australian Capital Territory|JBT=Jervis Bay Territory|NSW=New South Wales|NT=Northern Territory|QLD=Queensland|SA=South Australia|TAS=Tasmania|VIC=Victoria|WA=Western Australia";

 

NOTE: If you have the full state names in your database, switching to abbreviations may create an issue and you may need to do some manual updates or write a few update queries to align all your data.

 

Here is the updated main code:

jQuery(document).ready(function(){
jQuery("#country").change(function() {
	var country = jQuery(this).val();
	if (ar[country]) {
		jQuery("#state").hide();
		if (ar[country].indexOf('=')==-1) {
			jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
		}else{
			jQuery("#statedropdown").html('<select id="statedd"><option value="'+ar[country].replace(/\075/g, '">').replace(/\174/g,'</option><option value="')+'</option></select>');
		}
		jQuery("#state").val(jQuery("#statedd").val());
	} else {
		jQuery("#state").val('');
		jQuery("#state").show();
		jQuery("#statedropdown").html('');
	}
});

jQuery("#statedd").livequery("change", function(event) {
		jQuery("#state").val(jQuery(this).val());
});

var country = jQuery("#country").val();
var state = jQuery("#state").val();
if (ar[country]) {
	jQuery("#state").hide();
	if (ar[country].indexOf('=')==-1) {
		jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
	}else{
		if (state=='') {
			jQuery("#statedropdown").html('<select id="statedd"><option value="'+ar[country].replace(/\075/g, '">').replace(/\174/g,'</option><option value="')+'</option></select>');
		}else{
			states = '<option value="'+ar[country].replace(/\075/g, '">').replace(/\174/g,'</option><option value="')+'</option>';
			jQuery("#statedropdown").html('<select id="statedd">'+states.replace(state+'"', state+'" selected="selected"')+'</select>');
		}
	}
	jQuery("#state").val(jQuery("#statedd").val());
} else {
	jQuery("#state").show();
	jQuery("#statedropdown").html('');
}
});

 

I will update the zip file after I finish implementing and testing for other issues that I may find...

Link to comment
Share on other sites

  • 1 month later...

The below code does almost everything that I am looking for however, is it possible to display the drop down even if a state exists, but change the option to selected in the drop down? This way no matter if the client is a new sign up or changing their existing details it would always fall in the tax rules.

 

As it stands now, if the client logs in to change their info, they can manually enter a new state and avoid the tax rules.

 

jQuery(document).ready(function(){
   jQuery("#country").change(function() {
       var country = jQuery(this).val();
       if (ar[country]) {
           jQuery("#state").hide();
           jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
           jQuery("#state").val(jQuery("#statedd").val());
       } else {
           jQuery("#state").val('');
           jQuery("#state").show();
           jQuery("#statedropdown").html('');
       }
   });

   jQuery("#statedd").livequery("change", function(event) {
           jQuery("#state").val(jQuery(this).val());
   });

   var country = jQuery("#country").val();
   if (ar[country]) {
       jQuery("#state").hide();
       jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
       jQuery("#state").val(jQuery("#statedd").val());
   } else {
       jQuery("#state").val('');
       jQuery("#state").show();
       jQuery("#statedropdown").html('');
   }
});

Link to comment
Share on other sites

hmmm, i love that i have a drop down of the countries, but it never gives me an option of the states. I have followed Matt's instructions and then have added on the new statedropdown by EhsanCH for all of the states. Any Ideas? I want to state that i have edited clientregister.tpl for this.

 

My Country Line:

<tr><td class="fieldarea">{$LANG.clientareacountry}</td><td>{$clientcountriesdropdown|replace:'<select':'<select id="country"'}</td></tr>

My State Line:

<tr><td class="fieldarea">{$LANG.clientareastate}</td><td><input type="text" name="state" size="25" value="{$clientstate}" id="state" /><div id="statedropdown"></div></td></tr>

 

and i have both of the scripts added in.

 

Thanks for any help!

 

Jeremiah Shinkle

Edited by bullfrog3459
forgot to add details.
Link to comment
Share on other sites

Below is my clientregister.tpl that works, maybe it will help you out.

 

<script type="text/javascript" src="includes/jscript/jquerylq.js"></script>
<script type="text/javascript" src="includes/jscript/statedropdown.js"></script>

{if $noregistration}
Not Allowed
{else}
<script type="text/javascript" src="includes/jscript/pwstrength.js"></script>
<p>{$LANG.clientregisterheadertext}</p>
{if $errormessage}
<div class="errorbox">{$errormessage}</div>
<br />
{/if}
<form method="post" action="{$smarty.server.PHP_SELF}">
 <input type="hidden" name="register" value="true" />
 <table width="100%" cellspacing="0" cellpadding="0" class="frame">
   <tr>
     <td><table width="100%" border="0" cellpadding="10" cellspacing="0">
         <tr>
           <td width="150" class="fieldarea">{$LANG.clientareafirstname}</td>
           <td><input type="text" name="firstname" size="30" value="{$clientfirstname}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientarealastname}</td>
           <td><input type="text" name="lastname" size="30" value="{$clientlastname}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareacompanyname}</td>
           <td><input type="text" name="companyname" size="30" value="{$clientcompanyname}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareaemail}</td>
           <td><input type="text" name="email" size="50" value="{$clientemail}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareaaddress1}</td>
           <td><input type="text" name="address1" size="40" value="{$clientaddress1}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareaaddress2}</td>
           <td><input type="text" name="address2" size="30" value="{$clientaddress2}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareacity}</td>
           <td><input type="text" name="city" size="30" value="{$clientcity}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareastate}</td>
           <td><input type="text" name="state" size="25" value="{$clientstate}" id="state" /><div id="statedropdown"></div></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareapostcode}</td>
           <td><input type="text" name="postcode" size="10" value="{$clientpostcode}" /></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareacountry}</td>
           <td>{$clientcountriesdropdown|replace:'<select':'<select id="country"'}</td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareaphonenumber}</td>
           <td><input type="text" name="phonenumber" size="20" value="{$clientphonenumber}" /></td>
         </tr>
     </table></td>
   </tr>
 </table>

 {if $customfields || $securityquestions}
 <br />
 <table width="100%" cellspacing="0" cellpadding="0" class="frame">
   <tr>
     <td><table width="100%" border="0" cellpadding="10" cellspacing="0">
         {if $securityquestions}
         <tr>
           <td class="fieldarea">{$LANG.clientareasecurityquestion}</td>
           <td><select name="securityqid">

{foreach key=num item=question from=$securityquestions}

               <option value="{$question.id}">{$question.question}</option>

{/foreach}

             </select></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareasecurityanswer}</td>
           <td><input type="password" name="securityqans" size="30" /> *</td>
         </tr>
         {/if}
         {foreach key=num item=customfield from=$customfields}
         <tr>
           <td class="fieldarea">{$customfield.name}</td>
           <td>{$customfield.input} {$customfield.description}</td>
         </tr>
         {/foreach}
     </table></td>
   </tr>
 </table>
 {/if}

 <h2>{$LANG.orderlogininfo}</h2>
 <p>{$LANG.orderlogininfopart1} {$companyname} {$LANG.orderlogininfopart2}</p>
 <table width="100%" cellspacing="0" cellpadding="0" class="frame">
   <tr>
     <td><table width="100%" border="0" cellpadding="10" cellspacing="0">
         <tr>
           <td width="150" class="fieldarea">{$LANG.clientareapassword}</td>
           <td width="175"><input type="password" name="password" id="newpw" size="25" /></td>
           <td><script language="JavaScript" type="text/javascript">showStrengthBar();</script></td>
         </tr>
         <tr>
           <td class="fieldarea">{$LANG.clientareaconfirmpassword}</td>
           <td colspan="2"><input type="password" name="password2" size="25" /></td>
         </tr>
     </table></td>
   </tr>
 </table>

 {if $capatacha}
 <h2>{$LANG.clientregisterverify}</h2>
 <p>{$LANG.clientregisterverifydescription}</p>
 <p align="center"><img src="includes/verifyimage.php" class="absmiddle" border="0" alt="Verify Image" />
   <input type="text" name="code" size="10" maxlength="5" />
 </p>
 {/if}

 {if $accepttos}
 <p>
   <input type="checkbox" name="accepttos" id="accepttos" />
   <label for="accepttos">{$LANG.ordertosagreement} <a href="{$tosurl}" target="_blank">{$LANG.ordertos}</a></label>
   .  </p>
 <p> {/if}  </p>
 <p align="center">
   <input type="submit" value="{$LANG.ordercontinuebutton}" />
 </p>
</form>
{/if}<br />

Link to comment
Share on other sites

On the first page of this thread, someone posted a .zip file of the statedropdown.js. Did you FTP this to the includes/javascript directory?

 

 

I find this question slightly on the unneeded side but yes. I even went through Matt's information again and tried all of what he said to a perfect "T" and still a no go, even with the missing information for the states.

 

Thanks,

 

Jeremiah Shinkle

 

this is my current statedropdown.js

 

ar['GB'] = "<option>Avon</option><option>Bedfordshire</option><option>Berkshire</option>";
ar['US'] = "<option>Alabama</option><option>Alaska</option><option>Arizona</option><option>Arkansas</option><option>California</option>";

$(document).ready(function(){
   $("#country").change(function() {
       var country = $(this).val();
       if (ar[country]) {
           $("#state").hide();
           $("#statedropdown").html('<select id="statedd">'+ar[country]+'</select>');
           $("#state").val($("#statedd").val());
       } else {
           $("#state").show();
           $("#statedropdown").html('');
       }
   });
   $("#statedd").livequery("change", function(event) {
       $("#state").val($(this).val());
   });
   var country = $("#country").val();
   if (ar[country]) {
       $("#state").hide();
       $("#statedropdown").html('<select id="statedd">'+ar[country]+'</select>');
       $("#state").val($("#statedd").val());
   } else {
       $("#state").show();
       $("#statedropdown").html('');
   }
});

 

I have tried Robb's, Sparkys and the one with EhsanCH's.

Edited by bullfrog3459
Link to comment
Share on other sites

The below code does almost everything that I am looking for however, is it possible to display the drop down even if a state exists, but change the option to selected in the drop down? This way no matter if the client is a new sign up or changing their existing details it would always fall in the tax rules.

 

As it stands now, if the client logs in to change their info, they can manually enter a new state and avoid the tax rules.

 

jQuery(document).ready(function(){
   jQuery("#country").change(function() {
       var country = jQuery(this).val();
       if (ar[country]) {
           jQuery("#state").hide();
           jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
           jQuery("#state").val(jQuery("#statedd").val());
       } else {
           jQuery("#state").val('');
           jQuery("#state").show();
           jQuery("#statedropdown").html('');
       }
   });

   jQuery("#statedd").livequery("change", function(event) {
           jQuery("#state").val(jQuery(this).val());
   });

   var country = jQuery("#country").val();
   if (ar[country]) {
       jQuery("#state").hide();
       jQuery("#statedropdown").html('<select id="statedd"><option>'+ar[country].replace(/\174/g,"</option><option>")+'</option></select>');
       jQuery("#state").val(jQuery("#statedd").val());
   } else {
       jQuery("#state").val('');
       jQuery("#state").show();
       jQuery("#statedropdown").html('');
   }
});

 

To Double check, i did what you asked and then also grabbed the code you have posted. I double checked robb's and Sparkys code and still no go. Am i missing something just plain and easily? I do apologize now it has been a very long week so i likely am missing something easy.

 

Thanks for your help with this!

Link to comment
Share on other sites

Might of been a copy/paste bug, but it looks like your missing a closing }); for $(document).ready(function(){

 

Add one more }); at the end

 

Either A. I am too tired to work on this(unlikely but an option), B. I am just missing something obvious! I have tried that and still no go. Would you share your statedropdown.js file? Please and Thanks!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated