Robert Robert - 3 months ago 20
HTML Question

How to reverse effects of jQuery replaceWith function on HTML select tag?

I have a page containing a "Country" HTML select tag and a "Region" select tag:

<body>
<span>Country</span><br>
<select name="country" id="id_country" onchange="changeRegion()">
<option value="" selected="selected">-- Select --</option>
<option value="US">United States</option>
<option value="UK">United Kingdom</option>
<option value="CA">Canada</option>
<option value="MX">Mexico</option>
<option value="ID">Indonesia</option>
...
</select>

<span>Region</span><br>
<select name="region" id="id_region">
<option value="" selected="selected">-- Select --</option>
<option value="AL" class="US">Alabama</option>
<option value="AK" class="US">Alaska</option>
<option value="AZ" class="US">Arizona</option>
<option value="Avon" class="UK">Avon</option>
<option value="Bedfordshire" class="UK">Bedfordshire</option>
... # other UK counties
<option value="ON" class="CA">Ontario</option>
<option value="QB" class="CA">Quebec</option>
... # other CA provinces
</select><br>
</body>


I'm using the jQuery chained plugin to change the contents of the region select tag based on the country the user selects:

<script src="https://cdn.jsdelivr.net/jquery.chained/0.9.9/jquery.chained.min.js"></script>
<script type="text/javascript">
$("#id_region").chained("#id_country");
</script>


The one wrinkle is that if the user selects a country other than the United States, the UK, or Canada, I would like to replace the region select tag with a region input text tag so that the user can enter the country-specific region they live in. I think I know how to do this with the jQuery replaceWith function:

<script type="text/javascript">
$("#id_region").chained("#id_country");

function changeRegion() {
var country = document.getElementById("id_country");
if (country.value !== 'US' && country.value !== 'UK' && country.value !== 'CA') {
$('#id_region').replaceWith($('<input type="text" name="region" id="id_region_text" />'));
}
}
</script>


This seems to work fine. The problem I'm having is figuring out how to reverse the effect of the replaceWith function if the user has selected either Mexico or Indonesia and then, for whatever reason, decides to select the US, UK, or CA. In that event, I'd like to replace the text tag with the region select tag that contains the options for the country (US, UK, or CA) that they selected. I tried creating a variable and then doing another replaceWith using that variable but it doesn't work:

<script type="text/javascript">
$("#id_region").chained("#id_country");
$select_region = '<select name="region" id=...</select>' /* This didn't work */

function changeRegion() {
var country = document.getElementById("id_country");
if (country.value !== 'US' && country.value !== 'UK' && country.value !== 'CA') {
$('#id_region').replaceWith($('<input type="text" name="region" id="id_region_text" />'));
} else {
$('#id_region_select').replaceWith($select_region); /* This didn't work */
}
}
</script>


How do I reverse the effects of this replaceWith function? Also, is there a better way to do this? If the solution does entail creating a $select_region variable, it will be difficult to maintain if I later decide to add more countries and their regions. My JavaScript and jQuery knowledge is admittedly pretty weak so I'm not sure how to get this working. The code is here.

Thanks!

Answer
$('#id_region').replaceWith($('<input type="text" name="region" id="id_region_text" />'));

You changed the id from 'id_region' to 'id_region_text'. It would work the first time you replace it because there is a node with id 'id_region', but after that, $('#id_region_select') wont return anything because you replaced the id already. Use consistent id naming

Also, with each replaceWIth(), the events bound are lost, so you have to do $("#id_region").chained("#id_country") again