Additional option in select list

Hi everyone,

I have the following code in my form:


            <tr>
                <td><label for="Title">Title</label><br />
                <select name="Title" id="Title" class="cat_dropdown_smaller">
                <option value="913142">DR</option>
                <option value="913141">MISS</option>
                <option value="913138" selected="selected">MR</option>
                <option value="913139">MRS</option>
                <option value="913140">MS</option>
                </select></td>
            </tr>


I’d like to add another value that says “Other” so that when that option is chosen, an input field appears so they can type in their own title.

I just wondered if anyone could tell me if this could be done with css or whether I need to use jQuery?

Thanks in advance.

Hi,

You would need js or jquery to do this.

My Js/jquery is very basic but I guess something like this might work:


<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>

<body>
<form id="formtest">
		<select name="Title" id="Title" class="cat_dropdown_smaller">
				<option value="913142">DR</option>
				<option value="913141">MISS</option>
				<option value="913138" selected="selected">MR</option>
				<option value="913139">MRS</option>
				<option value="913140">MS</option>
				<option value="other">Other</option>
		</select>
</form>
<script>

$('#Title').click(function() {
	$('#other').remove();
  if ($(this).val() ==="other"){
		$(this).after("<span id='other'><label for='other-choice'> Other title : </label><input type='text' name='other-choice' id='other-choice'></span>")
	}	
});
$( "#formtest" ).on( "blur", "input", function(e) {
	if( $(this).val() ) {
	 var selText= $(this).val();
	 $('#Title option:selected').text(selText);
	}
	 $('#other').remove();
});	
</script>
</body>
</html>

However, I’ll move this to the js forum for a better answer as I am sure there are holes in my approach :slight_smile:

Thanks for the help.

If anyone has any alternate code that is a bit more compact, I’d be grateful.

The best way is one that doesn’t require scripting to be available. When scripting is available we can then use that to make the experience a bit nicer for the user.

Start by having an input field just below the select one, to accept any other input:

<select name="Title" id="Title" class="cat_dropdown_smaller">
    <option value="913142">DR</option>
    <option value="913141">MISS</option>
    <option value="913138" selected="selected">MR</option>
    <option value="913139">MRS</option>
    <option value="913140">MS</option>
    <option value="other">Other</option>
</select>
<input name="otherTitle">

The above code is all ready to be used now. The server-side script that accepts the form can check if the other option is selected, and if it is then it can pay attention to the input field instead.

Notice how the input field is called otherTitle. If we have another select field called Relationship, that might have an other option too with a text field called otherRelationship.
By using the same consistent pattern for naming the other input field, we can easily use the same scripting code to handle different situations.

jQuery is not mandatory for doing this sort of work either - basic JavaScript can be used to easily do what we want to achieve.

When you hide the other input field, it’s best to use CSS to do that:


.hidden {
    display: none;
}

What we want to do with the scripting is quite easy to explain. When a select element is changed, we want to check if the selected option is the “other” one. If it is, reveal the other input field - otherwise leave it hidden.

An important aspect is to place the scripting at the end of the body, which will make it easier to interact with elements on the page while it’s loading.

We can use the onchange event to trigger the work we want to get done.


document.querySelector('select[name="Title"]').onchange = function () {
    ...
};

We can now create a small function, that will be run whenever the onchange event occurs, that checks if the other field needs to be shown.


var otherFieldHandler = function() {
  var otherInput = document.querySelector('[name="other' + this.name + '"]');

  if (this.options[this.selectedIndex].value === 'other') {
    otherInput.classList.remove('hidden');
  } else {
    otherInput.classList.add('hidden');
  }
};
document.querySelector('select[name="Title"]').onchange = otherFieldHandler;

You can see the above in action at http://codepen.io/pmw57/pen/xBdeA

and lastly we can trigger that event too, which will cause the other input to initially be hidden.


var selectTitle = document.querySelector('select[name="Title"]');
selectTitle.onchange = otherFieldHandler;
selectTitle.onchange();

We can even search the page for all select fields, and attach the otherFieldHandler on to each of them.


var otherFieldHandler = function() {
  var otherInput = document.querySelector('[name="other' + this.name + '"]');

  if (this.options[this.selectedIndex].value !== 'other') {
    otherInput.classList.add('hidden');
  } else {
    otherInput.classList.remove('hidden');
  }
},
    selects = document.querySelectorAll('select'),
    i;

for (i = 0; i < selects.length; i += 1) {
  selects[i].onchange = otherFieldHandler;
  selects[i].onchange();
}

You can see the above code in action at http://codepen.io/pmw57/pen/xBdeA/

How would this be done using jQuery? Something like this would do:


var otherFieldHandler = function() {
  var $otherInput = $('[name="other' + this.name + '"]'),
      hideField = $(this).val() !== 'other';
  
  $otherInput.toggleClass('hidden', hideField);
};
$('select').each(function () {
  $(this)
    .on('change', otherFieldHandler)
    .trigger('change');
});

The above can be seen at http://codepen.io/pmw57/pen/hqCpL/

In fact, the above code wouldn’t be used by many people. They would instead deeply nest things, resulting in a higher level of confusion when it comes to trying to understand things.


$('select').each(function () {
  $(this).on('change', function() {
    $('[name="other' + this.name + '"]').toggleClass('hidden', $(this).val() !== 'other');
  }).trigger('change');
});

which tends to be more difficult to understand than the other code above.

Either way though, using jQuery to do this means that your page also needs to load a large amount of code for the jQuery library, weighing in at 100 kilobytes, most of which will be wasted for such a small task. Is it worth it? That’s up to you to decide.

Thanks for such a detailed response,

I just have a couple of questions if that’s ok. Your html uses the following for the other option value:

&lt;option value="other"&gt;Other&lt;/option&gt;

The problem with that is that I’m using a CMS that automatically creates the value so it would look more like the following:


<select name="Title" id="Title" class="cat_dropdown_smaller">
    <option value="913142">DR</option>
    <option value="913141">MISS</option>
    <option value="913138" selected="selected">MR</option>
    <option value="913139">MRS</option>
    <option value="913140">MS</option>
    <option value="913141">Other</option>
</select>
<input name="otherTitle">

That is, it would have a specific number for the value instead of saying “other”,

Would the code still work in this case?

Also, with regard to the jQuery, I already have the code listed at the bottom of this reply, in the head of my document and it looks like I’m loading two libraries:


<script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>

<script src="/_assets/js/jquery-1.10.2.min.js"></script>

Sorry my jQuery and JS skill is very low so this may sound like an odd question but are they both jQuery libraries that I’m loading? If yes, are they both needed and if I’m already loading a jQuery library for other code on the page then I guess it makes sense to use it for this example also.

Could you advise me on this?


<script type="text/javascript">
$(function () {
    // redirect to non-secure version of page
    $("a").each(function (idx) {
        var href = $(this).attr("href");
        if (href.indexOf("http") == -1 && href.indexOf("https") == -1) {
            href = '{module_webapps,0,i,17464 template="/_settings/site-url"}' + href;
            $(this).attr("href", href);
        }
    });
});
</script>
<script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>
<script>
var guests = 0;
function calc() {
  var numberOfGuests = 0;
  $(".guestrow").each(function() {
    numberOfGuests+= $(this).find(".cat_textbox").val()!="";
  });
  var price = $('#event-price').text();
  var participants = numberOfGuests+1;// add the organiser
  var total = participants*price;
  $("#BookingAllocation").val(participants);
  $("#booked").toggle(numberOfGuests>0); // only show booked if guests
  $("#Amount").val(total.toFixed(2));
}


$(function () {
    calc();
    $(".cat_textbox").on("keyup",function() { calc(); /* handle removal of gues*/});
    $("#catwebformbutton").on("click", function () {
        guests++;
        if (guests <= 10) {
            $(".guestrow").eq(guests-1).show();
        }
        $("#removeGuest").toggle(guests>0);
        calc();
    });
    $("#removeGuest").on("click",function(e) {
        guests--;
        $(this).toggle(guests>0);
        var $row = $(".guestrow").eq(guests);
        $row.find(".cat_textbox").val("");
        $row.hide();
        calc();
    });
    $('form[name="catwebformform81201"]').on("submit", function (e) {
        calc();
        if (checkWholeForm81201(this)) {
            // ...
        }
        else {
          e.preventDefault(); // cancel submit
        }
    });
});
</script>
<script src="/_assets/js/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
$(function() {
    $('#Title).append(
            $("<option></option>").attr("value","").text("")
    );
})
</script>
<script>
$(document).ready(function() {
$('#creditCardType , #payOffline').hide();
$('.creditCard').click(function() {
$('#creditCardType').toggle();
$('#payOffline').hide();
});
$('.payPal').click(function() {
$('#creditCardType').hide();
$('#payOffline').hide();
});
    $('.payOffline').click(function() {
$('#payOffline').toggle();
$('#creditCardType').hide();
});
});
</script>
<script type="text/javascript">
$(function(){
var pfull = $(".meter").data("pfull");
$(".meter").css("width",pfull)
});
</script>

It can still work with a minor adjustment, so that the HTML of the selected option is compared with “Other” instead.


  var hideField = ($(':selected', this).html() !== 'Other'),
      $otherInput = $('[name="other' + this.name + '"]');

That was the jQuery version.

The basic JavaScript version of the code has an even smaller change that’s needed, just changing .value to .innerHTML:


if (this.options[this.selectedIndex].innerHTML !== 'Other') {

The git version of jQuery is constantly updating with the most recent version of jQuery, which is not a good idea for production websites as future changes can be incompatible with existing techniques you’re using on the site.

Normally only one library is needed. When a second one is loaded it overwrites the previous version. You already have the one in your assets area so that’s a good one to use.

Thanks for clarifying things. I’ll see if I can get this working …