-1

I want to add <div> tags inside input type="input" for a number-only input field. I know it can't be done, but I was wondering if there was some way to add the + and - buttons inside an input field that isn't input type="number". For reasons that I will not get into (it took me a good two days to solve an issue), I am unable to use input type="number".

How can I make custom spin buttons for an input that doesn't come with spin buttons? Most of the other questions on SO are asking about styling/hiding the spin buttons in a number input.

enter image description here

patrickhuang94
  • 2,085
  • 5
  • 36
  • 58
  • 1
    Did you try https://codepen.io/komarovdesign/pen/PPRbgb/? – Shreyash S Sarnayak Feb 15 '17 at 18:20
  • This is modifying an input type="number". I'm not trying to modify it because I don't have the spin buttons. – patrickhuang94 Feb 15 '17 at 18:21
  • Rather than reinvent the wheel by creating this custom element, why not ask the question "Why can't I use `type="number"` in my implementation?" That seems like the bigger problem here. – J. Titus Feb 15 '17 at 18:26
  • 1
    All I'm asking is if this is possible. If it isn't, then I'll find another solution. I really don't need more people telling me to use `type="number"` when I've already stated that I cannot use it. – patrickhuang94 Feb 15 '17 at 18:27
  • 1
    If you really want to know - I can't call `setSelectionRange` on `input="number"`: http://stackoverflow.com/questions/21177489/selectionstart-selectionend-on-input-type-number-no-longer-allowed-in-chrome – patrickhuang94 Feb 15 '17 at 18:29
  • 1
    @homerboy I tried changing it to `input type="text"` and it worked. – Shreyash S Sarnayak Feb 15 '17 at 18:31

3 Answers3

4

I suggest you to make a big div containing on a side the input number and, on the other side, make another div which contains the two buttons one on the top of the other.

enter image description here

Giorgio B
  • 193
  • 6
3

If for some reason you don't want to add divs or change input type to number, you can use this solution.

jQuery('<div class="quantity-nav"><div class="quantity-button quantity-up">+</div><div class="quantity-button quantity-down">-</div></div>').insertAfter('.quantity input');
jQuery('.quantity').each(function() {
  var spinner = jQuery(this),
    input = spinner.find('input[type="text"]'),
    btnUp = spinner.find('.quantity-up'),
    btnDown = spinner.find('.quantity-down'),
    min = input.attr('min'),
    max = input.attr('max');

  btnUp.click(function() {
    var oldValue = parseFloat(input.val());
    if (oldValue >= max) {
      var newVal = oldValue;
    } else {
      var newVal = oldValue + 1;
    }
    spinner.find("input").val(newVal);
    spinner.find("input").trigger("change");
  });

  btnDown.click(function() {
    var oldValue = parseFloat(input.val());
    if (oldValue <= min) {
      var newVal = oldValue;
    } else {
      var newVal = oldValue - 1;
    }
    spinner.find("input").val(newVal);
    spinner.find("input").trigger("change");
  });
});
.quantity {
  position: relative;
}
input[type=text]::-webkit-inner-spin-button,
input[type=text]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type=text] {
  -moz-appearance: textfield;
}
.quantity input {
  width: 45px;
  height: 42px;
  line-height: 1.65;
  float: left;
  display: block;
  padding: 0;
  margin: 0;
  padding-left: 20px;
  border: 1px solid #eee;
}
.quantity input:focus {
  outline: 0;
}
.quantity-nav {
  float: left;
  position: relative;
  height: 42px;
}
.quantity-button {
  position: relative;
  cursor: pointer;
  border-left: 1px solid #eee;
  width: 20px;
  text-align: center;
  color: #333;
  font-size: 13px;
  font-family: "Trebuchet MS", Helvetica, sans-serif !important;
  line-height: 1.7;
  -webkit-transform: translateX(-100%);
  transform: translateX(-100%);
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -o-user-select: none;
  user-select: none;
}
.quantity-button.quantity-up {
  position: absolute;
  height: 50%;
  top: 0;
  border-bottom: 1px solid #eee;
}
.quantity-button.quantity-down {
  position: absolute;
  bottom: -1px;
  height: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="quantity">
  <input type="text" value="1">
</div>

This solution seems to work on Chrome and Edge. (Not tested on other browsers).

Credits to this.

Shreyash S Sarnayak
  • 2,309
  • 19
  • 23
2

Since you can't use the type="number" for some reason, here's a small custom stepper.

var numberSteppers = document.querySelectorAll('.numberStepper input');
for(var i = 0; i < numberSteppers.length; i++){
  numberSteppers[i].oninput = function(){
    this.value = !isNaN(this.value) ? parseInt(this.value) : 0;
  }
}

var stepperButtons = document.querySelectorAll('.numberStepper button');
for(var j = 0; j < stepperButtons.length; j++){
  stepperButtons[j].onclick = function(e){
    e.preventDefault();
    var input = this.parentNode.previousElementSibling;
    input.value = input.value !== '' ? parseInt(input.value) + parseInt(this.value) : parseInt(this.value);
  }
}
.numberStepper, .numberStepper *{
  box-sizing:border-box;
}

.numberStepper{
  max-width:200px;
  position:relative;
}

.numberStepper input{
  display:block;
  width:80%;
  font-size:2em;
  min-height:3ex;
  padding:1ch;
  text-align:right;
}

.numberStepper .steppers{
  position:absolute;
  right:0;
  top:0;
  height:100%;
  width:20%;
}

.numberStepper button{
  margin:0;
  padding:0;
  border:1px solid;
  width:100%;
  cursor:pointer;
  height:50%;
}
<div class="numberStepper">
  <input type="text"/>
  <div class="steppers">
    <button value="1">+</button>
    <button value="-1">-</button>
  </div>
</div>
Donnie D'Amato
  • 3,832
  • 1
  • 15
  • 40