Reputation: 619
I am looking to change the input type of a number selector to a dropdown if the value is less than 10. For values greater than 9 (10+) the input type should change back to a number selector.
Amazon and Sears.com are doing this style of quantity selectors in their shopping carts for some desktop users (subject to AB testing).
My issue is that it will change input type once, but not back again.
Additionally what is the best practice to retain the value between input types? I've considered either using a variable or copying to a hidden input which is the actual field submitted.
HTML:
<label class="mylabel">Quantity:</label>
<input style="display: inline;" maxlength="3" min="1" pattern="\d+" autocomplete="off" name="quantityBox" class="qty-input" aria-label="Quantity" type="number">
<input type="submit" name="btnAddToCart" value="Add To Cart" id="btnAddToCart" class="">
jQuery:
$(".qty-input").change(function(){
if (parseInt(this.value) < 10){
$(".qty-input").replaceWith(
'<select id="txtQuantity" name="txtQuantity" class="qty-input">' +
'<option value="1">1</option>' +
'<option value="2">2</option>' +
'<option value="3">3</option>' +
'<option value="4">4</option>' +
'<option value="5">5</option>' +
'<option value="6">6</option>' +
'<option value="7">7</option>' +
'<option value="8">8</option>' +
'<option value="9">9</option>' +
'<option value="10">10+</option>' +
'</select>'
);
}
if (parseInt(this.value) > 9){
$(".qty-input").replaceWith(
'<input style="display: inline;" maxlength="3" min="1" pattern="\d+" autocomplete="off" name="quantityBox" class="qty-input" aria-label="Quantity" type="number">'
);
}
});
Upvotes: 1
Views: 1648
Reputation: 168
check this out what I am telling Fiddle Demo
$(".select").on('click',function(){
if(isNaN($(this).val())){
$(this).addClass("hide");
$(".more").removeClass("hide");
$(this).removeAttr("name","quantity");
$(".more").attr("name","quantity");
} });
You may refine code to your purpose.
Upvotes: 0
Reputation: 1832
This will work. Your example doesn't work since when you replace the DOM node/element, it no longer has the change event handled so function is bonded nor executed.
$(".qty-input").change(updateControl);
function updateControl(evt) {
var template;
if (parseInt(this.value) < 10 && this.tagName.toLowerCase() === "input") {
template =
'<select id="txtQuantity" name="txtQuantity" class="qty-input">' +
'<option value="1">1</option>' +
'<option value="2">2</option>' +
'<option value="3">3</option>' +
'<option value="4">4</option>' +
'<option value="5">5</option>' +
'<option value="6">6</option>' +
'<option value="7">7</option>' +
'<option value="8">8</option>' +
'<option value="9">9</option>' +
'<option value="10">10+</option>' +
'</select>';
} else if (parseInt(this.value) > 9 && this.tagName.toLowerCase() === "select") {
template =
'<input style="display: inline;" maxlength="3" min="1" pattern="\d+" autocomplete="off" name="quantityBox" class="qty-input" aria-label="Quantity" type="number" value="'+this.value+'">';
}
if (template) {
$(this).replaceWith(template);
$('.qty-input option[value='+this.value+']').attr('selected', true);
$('.qty-input').change(updateControl);
}
}
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<select id="txtQuantity" name="txtQuantity" class="qty-input">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10+</option>
</select>
Upvotes: 0
Reputation: 2604
The problem is this...
once you remove the object from the DOM you are also removing the event handler if you still want to take the replace approach you would have to re-bind the event handler something like
$(document).ready(function() {
function test(){
if (parseInt(this.value) < 10) {
$(".container ").html(
'<select id="txtQuantity" name="txtQuantity" class="qty-input">' +
'<option value="1">1</option>' +
'<option value="2">2</option>' +
'<option value="3">3</option>' +
'<option value="4">4</option>' +
'<option value="5">5</option>' +
'<option value="6">6</option>' +
'<option value="7">7</option>' +
'<option value="8">8</option>' +
'<option value="9">9</option>' +
'<option value="10">10+</option>' +
'</select>'
);
} else {
$(".container").html(
'<input style="display: inline;" maxlength="3" min="1" pattern="\d+" autocomplete="off" name="quantityBox" class="qty-input" aria-label="Quantity" type="number">'
);
}
$(".qty-input").on('change', test);
}
$(".qty-input").on('change', test);
});
https://jsfiddle.net/happymacarts/pn1qeyg9/1/
Upvotes: 0
Reputation: 1899
Although there are better ways of doing this I'm posting this to answer why your version is not working. Basically you're binding to an element that doesn't exist yet i.e. dynamic content.
Jquery handles this using the on
method.
You can get it to work by adding a static ancestor and binding to that instead. For a better understanding of how event bubbling and delegation works check out this link. http://api.jquery.com/on/
Something like this
HTML
<label class="mylabel">Quantity:</label>
<div id="staticAncestor">
<input style="display: inline;" maxlength="3" min="1" pattern="\d+" autocomplete="off" name="quantityBox" class="qty-input" aria-label="Quantity" type="number">
</div>
JS
$("#staticAncestor").on("change",'.qty-input',function(){
if (parseInt(this.value) < 10 && !$( "#txtQuantity" ).length){
$(".qty-input").replaceWith(
'<select id="txtQuantity" name="txtQuantity" class="qty-input">' +
'<option value="1">1</option>' +
'<option value="2">2</option>' +
'<option value="3">3</option>' +
'<option value="4">4</option>' +
'<option value="5">5</option>' +
'<option value="6">6</option>' +
'<option value="7">7</option>' +
'<option value="8">8</option>' +
'<option value="9">9</option>' +
'<option value="10">10+</option>' +
'</select>'
);
}
if (parseInt(this.value) > 9){
$(".qty-input").replaceWith(
'<input style="display: inline;" maxlength="3" min="1" pattern="\d+" autocomplete="off" name="quantityBox" class="qty-input" aria-label="Quantity" type="number">'
);
}
});
Here is the pen http://codepen.io/anon/pen/jAQogj
Cheers and happy coding!
Upvotes: 0
Reputation: 42520
There is no need to render and re-render the fields each time they should switch. It is easier to simply hide them.
A very basic solution, error handling and styling is up to you:
var high = $('#high')
var low = $('#low')
function onChange() {
if (low.is(':visible')) {
var value = low.val();
high.val(value);
if (parseInt(value) > 9) toggleInputs();
} else {
var value = high.val();
low.val(value);
if (parseInt(value) <= 9) toggleInputs();
}
}
function toggleInputs() {
$('#low').toggle();
$('#high').toggle();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Quantity:</label>
<input onchange='onChange()' id='high' style='display: none' />
<select onchange='onChange()' id='low'>
<option value='0'>0</option>
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
<option value='4'>4</option>
<option value='5'>5</option>
<option value='6'>6</option>
<option value='7'>7</option>
<option value='8'>8</option>
<option value='9'>9</option>
<option value='10'>10+</option>
</select>
Upvotes: 1
Reputation: 168
You can do it with two particular different selectors one for dropdown other for text to take getter than ten.selecting 10+ will change the select control name and it will be point to your textbox name or if want to switch back then restore the old name of select box and remove text box name.
Using jquery toggle method and prop attribute you can handle or modify name prop of the controls you are using.I think you got it.
Your server side code can catch the post data easily with this logic.
If not getting, can ask for sample code i can show you.
Upvotes: 0