1

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).

If 10+ is selected, you can type a number.

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">'
        );
     }
});
5
  • Sorry, and your question is? Commented Aug 9, 2016 at 19:07
  • And the question is ? Commented Aug 9, 2016 at 19:08
  • 1
    Added question to body. Commented Aug 9, 2016 at 19:09
  • Well, when you remove .qty-input with replaceWith ... it's no longer there, and the event handler stops working ? Commented Aug 9, 2016 at 19:12
  • 1
    It looks like a binding issue. You might need to delegate your change event by using on since you're adding dynamic content into the mix Commented Aug 9, 2016 at 19:19

6 Answers 6

1

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>

Sign up to request clarification or add additional context in comments.

Comments

0

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.

2 Comments

Thanks for the advice. I'm half following, but I am confused what you mean by "select control name". Would you mind providing a sample?
I don't mind but i am on half sleep, your problem logic is not so hard what you have written,i will share you a sample what i am trying to teach.you ask "select control name" means select tag name property can be changed through toggle method and set that name to your text box and for the reverse as same so please keep following your post..
0

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!

Comments

0

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/

Comments

0

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>

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.