1

I am having a bit of trouble creating a custom input[type=number].

Starting from the top, I have manipulated an input[type=number] to have custom increment buttons.

These buttons when clicked I wish to figure out the current value of the input and either plus or minus one to that value without refreshing the page.

To my knowledge buttons on click shouldn't refresh a page, which is not the case with my code.

I also am having trouble using 'this' as a variable to make the script reusable.

Please can someone help me link my buttons to my script, stop the reload issue, and to actually increment the input up and down depending on user engagement?

function InputStepUp() {
 var input = this.parentNode.querySelector('input[type=number]').val();
 console.log(input);
 var inputStepUp = input + 1;
 console.log(inputStepUp);
 input.val(inputStepUp);
 console.log(input);
}
function InputStepDown() {
 var input = this.parentNode.querySelector('input[type=number]').val();
 console.log(input);
 var inputStepDown = input - 1;
 console.log(inputStepDown);
 input.val(inputStepDown);
 console.log(input);
}
input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
.number-input {
border: 1px solid #585CD3;
display: inline-flex;
}
.number-input button {
outline:none;
-webkit-appearance: none;
background-color: transparent;
border: none;
align-items: center;
justify-content: center;
width: 20px;
cursor: pointer;
margin: 0;
position: relative;
}
.number-input button:before,
.number-input button:after {
display: inline-block;
position: absolute;
content: '';
width: 10px;
height: 2px;
background-color: #585CD3;
transform: translate(-50%, -50%);
}
.number-input button.plus:after {
transform: translate(-50%, -50%) rotate(90deg);
}
.number-input input[type=number] {
text-align: center;
}
<div class="number-input">
 <button onclick="InputStepDown()"></button>
 <input class="cart-product-price-multiplier" type="number" name="updates[]" id="updates_{{ item.key }}" value="5" min="0">
 <button onclick="InputStepUp()" class="plus"></button>
</div>

Here is a stripped down version of my code, hopefully if we can fix this I can fix my more complicated version.

I've exhausted my brain and would really appreciate any advice people could give around using the 'this' variable within a function in this man

Jason Is My Name
  • 929
  • 2
  • 14
  • 38

1 Answers1

1

In your particular case this is context, from where your function was called, it has global scope - window. You tagged your question jQuery so if you can use it, things come much easier. I've tried to add comments to my code.

I'd like to recommend you a good article about this keyword and it's understanding.

// I've added common class 'btn' to both buttons and I'm handling their clicks
$('.btn').on('click', function() {
  const $input = $('.cart-product-price-multiplier'); //your current input
  const currentVal = Number($input.val()); // current input's value cated to number
  
  // we gonna identify which btn was clicked using class minus/plus
  // or you can set value to each btn and handle it instead
  const newVal = $(this).hasClass('minus') ? currentVal - 1 : currentVal + 1;
  
  $input.val(newVal); //finally we are setting new value to your input
});
input[type="number"] {
  -webkit-appearance: textfield;
  -moz-appearance: textfield;
  appearance: textfield;
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
  -webkit-appearance: none;
}

.number-input {
  border: 1px solid #585CD3;
  display: inline-flex;
}

.number-input button {
  outline: none;
  -webkit-appearance: none;
  background-color: transparent;
  border: none;
  align-items: center;
  justify-content: center;
  width: 20px;
  cursor: pointer;
  margin: 0;
  position: relative;
}

.number-input button:before,
.number-input button:after {
  display: inline-block;
  position: absolute;
  content: '';
  width: 10px;
  height: 2px;
  background-color: #585CD3;
  transform: translate(-50%, -50%);
}

.number-input button.plus:after {
  transform: translate(-50%, -50%) rotate(90deg);
}

.number-input input[type=number] {
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="number-input">
  <button class='btn minus'></button>
  <input class="cart-product-price-multiplier" type="number" name="updates[]" id="updates_{{ item.key }}" value="5" min="0">
  <button class="btn plus"></button>
</div>
dganenco
  • 1,596
  • 1
  • 5
  • 16
  • Your code works an absolute charm my friend! Love the link to the documentation too, I will work my way through that tree of links from that article and hopefully I will be less daft. One final point that's a real hang-up. It refreshes my page on the click of the buttons. I can't figure out why for the life of me. – Jason Is My Name Sep 11 '19 at 15:00
  • This piece of code can't refresh page. You should try to find another click handlers on your page – dganenco Sep 11 '19 at 15:07
  • Yeah that was my thoughts, If I am on the page using this, right click on the button and inspect, it takes me to that button. I don't think there is anything else I am accidentally clicking on. – Jason Is My Name Sep 11 '19 at 15:08
  • It is because I am using a button within a form... Do you know how to prevent the default action of these buttons only within the form? – Jason Is My Name Sep 11 '19 at 15:12
  • I found out that within forms it presumes a button is the submit button, therefore by applying type="button" you change the buttons state from submit to a standard button. Now I have a working shopping cart! – Jason Is My Name Sep 11 '19 at 15:21
  • Please upvote if you enjoyed answering my question! – Jason Is My Name Sep 11 '19 at 15:37
  • Bro, I have found a bug, it updates all of the items in my cart at the same time. As they all have the same class... – Jason Is My Name Sep 11 '19 at 15:45
  • changed my const $ input to be: const $input = $(this).closest('.number-input').children('.cart-product-price-multiplier'); works a charm c: – Jason Is My Name Sep 11 '19 at 15:53