Intro
Ceritanya lagi gak sreg dengan style input number yang ada dihalaman PassGen karena menampilkan tombol panah atas bawah yang kurang catchy banget dan agak menyusahkan dan juga tidak sedap dipandangnya, hehehe. Tombol panah atas bawah pada input number ini berfungsi untuk menambah dan mengurangi jumlah yang ada.

Nah, gak asik kan ngeliat style input numbernya? hehehe.
Kesulitan
Ternyata ada beberapa kesulitan dan pertimbangan yang didapat ketika lagi cari-cari ide.
Styling Input dengan Menghilangkan Panah Atas Bawah
Panah atas bawah di input number ini disebutnya spinners yang merupakan sudah menjadi baku untuk shadow dom. Tapi bisa dihilangkan sih, yaitu dengan cara:
/* Mozilla Firefox */
input[type=number] {
-moz-appearance: textfield;
appearance: textfield;
margin: 0;
}
/* Chrome */
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
Tapi! Ini bukanlah jawaban yang sedang saya cari, karena masih kurang sreg dan gak catchy solusinya.
Nah… cari-cari dan terus mencari ternyata ketemu ide yaitu dengan menambah tombol plus dan minus di input number. Dan ternyata, dengan keyword ini banyak sih di dapat tapi kebanyakan kode yang bertebaran adalah lebih kepada counter. Mmmm… input number yang saya pakai untuk Password Generator di halaman PassGen menggunakan attribut min dan max. Jadinya, kalau menggunakan script counter button input number min dan max nya tidak akan berfungsi.
Nah… ada lagi cara yang lebih mudah, yaitu menggunakan bootstrap, seperti yang ditampilkan dibawah ini.

Dengan source codenya seperti berikut:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Styling Input Number With Add Button Plus Minus</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Darto KLoning">
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">
<style>/* https://bootsnipp.com/snippets/dGWP */
.center{
width: 150px;
margin: 40px auto;
}</style>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.slim.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="center">
<p>
</p><div class="input-group">
<span class="input-group-btn">
<button type="button" class="btn btn-default btn-number" disabled="disabled" data-type="minus" data-field="quant[1]">
<span class="glyphicon glyphicon-minus"></span>
</button>
</span>
<input type="text" name="quant[1]" class="form-control input-number" value="8" min="8" max="30">
<span class="input-group-btn">
<button type="button" class="btn btn-default btn-number" data-type="plus" data-field="quant[1]">
<span class="glyphicon glyphicon-plus"></span>
</button>
</span>
</div>
<p></p>
<p>
</p><div class="input-group">
<span class="input-group-btn">
<button type="button" class="btn btn-danger btn-number" data-type="minus" data-field="quant[2]">
<span class="glyphicon glyphicon-minus"></span>
</button>
</span>
<input type="text" name="quant[2]" class="form-control input-number" value="10" min="1" max="100">
<span class="input-group-btn">
<button type="button" class="btn btn-success btn-number" data-type="plus" data-field="quant[2]">
<span class="glyphicon glyphicon-plus"></span>
</button>
</span>
</div>
<p></p>
</div>
<script>$('.btn-number').click(function(e){
e.preventDefault();
fieldName = $(this).attr('data-field');
type = $(this).attr('data-type');
var input = $("input[name='"+fieldName+"']");
var currentVal = parseInt(input.val());
if (!isNaN(currentVal)) {
if(type == 'minus') {
if(currentVal > input.attr('min')) {
input.val(currentVal - 1).change();
}
if(parseInt(input.val()) == input.attr('min')) {
$(this).attr('disabled', true);
}
} else if(type == 'plus') {
if(currentVal < input.attr('max')) {
input.val(currentVal + 1).change();
}
if(parseInt(input.val()) == input.attr('max')) {
$(this).attr('disabled', true);
}
}
} else {
input.val(0);
}
});
$('.input-number').focusin(function(){
$(this).data('oldValue', $(this).val());
});
$('.input-number').change(function() {
minValue = parseInt($(this).attr('min'));
maxValue = parseInt($(this).attr('max'));
valueCurrent = parseInt($(this).val());
name = $(this).attr('name');
if(valueCurrent >= minValue) {
$(".btn-number[data-type='minus'][data-field='"+name+"']").removeAttr('disabled')
} else {
alert('Sorry, the minimum value was reached');
$(this).val($(this).data('oldValue'));
}
if(valueCurrent <= maxValue) {
$(".btn-number[data-type='plus'][data-field='"+name+"']").removeAttr('disabled')
} else {
alert('Sorry, the maximum value was reached');
$(this).val($(this).data('oldValue'));
}
});
$(".input-number").keydown(function (e) {
// Allow: backspace, delete, tab, escape, enter and .
if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 190]) !== -1 ||
// Allow: Ctrl+A
(e.keyCode == 65 && e.ctrlKey === true) ||
// Allow: home, end, left, right
(e.keyCode >= 35 && e.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
// Ensure that it is a number and stop the keypress
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
});</script>
</body>
</html>
Tapi ini ya malah jadi nambah banyak resource, tapi nanti deh kalau lagi ingin berdandan ria, jadinya solusi menggunakan framework bootstrap ya tidak digunakan.
Solusi
Nah, solusi disini yang dimaksud adalah tanpa menggunakan resource ataupun framework css, kalau menggunakan jQuery ya so pastinya yah, karena sepertinya untuk menghilangkan spinners dan dirubah atau dengan menambah tombol plus minus maka ya dibutuhkan javascript.
Cari-cari dan terus mencari dan mungkin banyak metode untuk customize input number ini tapi akhirnya saya berhenti pada 2 metode saja, yaitu:
Metode Pertama
Untuk solusi dari metode pertama ini tampilannya adalah sebagai berikut:

Dan kodenya sebagai berikut:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Styling Input Number With Add Button Plus Minus</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Darto KLoning">
<style>.center{
width: 150px;
margin: 40px auto;
}
.quantity {
position: relative;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button
{
-webkit-appearance: none;
margin: 0;
}
input[type=number]
{
-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%;
}</style>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.slim.min.js"></script>
</head>
<body>
<div class="center quantity">
<input type="number" min="1" max="9" step="1" value="1" />
</div>
<script>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="number"]'),
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");
});
});</script>
</body>
</html>
source: @komarovdesign
Metode Kedua
Untuk solusi metode kedua, tampilannya sebagai berikut:

Dan untuk kodenya sebagai berikut:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Styling Input Number With Add Button Plus Minus</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Darto KLoning">
<style>.center{
width: 150px;
margin: 40px auto;
}
/* -- quantity box -- */
.quantity {
display: inline-block; }
.quantity .input-text.qty {
width: 35px;
height: 39px;
padding: 0 5px;
text-align: center;
background-color: transparent;
border: 1px solid #efefef;
}
.quantity.buttons_added {
text-align: left;
position: relative;
white-space: nowrap;
vertical-align: top; }
.quantity.buttons_added input {
display: inline-block;
margin: 0;
vertical-align: top;
box-shadow: none;
}
.quantity.buttons_added .minus,
.quantity.buttons_added .plus {
padding: 7px 10px 8px;
height: 41px;
background-color: #ffffff;
border: 1px solid #efefef;
cursor:pointer;}
.quantity.buttons_added .minus {
border-right: 0; }
.quantity.buttons_added .plus {
border-left: 0; }
.quantity.buttons_added .minus:hover,
.quantity.buttons_added .plus:hover {
background: #eeeeee; }
.quantity input::-webkit-outer-spin-button,
.quantity input::-webkit-inner-spin-button {
-webkit-appearance: none;
-moz-appearance: none;
margin: 0; }
.quantity.buttons_added .minus:focus,
.quantity.buttons_added .plus:focus {
outline: none; }
</style>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.slim.min.js"></script>
</head>
<body>
<div class="center">
<div class="quantity buttons_added">
<input type="button" value="-" class="minus"><input type="number" step="1" min="1" max="" name="quantity" value="1" title="Qty" class="input-text qty text" size="4" pattern="" inputmode=""><input type="button" value="+" class="plus">
</div>
</div>
<script>function wcqib_refresh_quantity_increments() {
jQuery("div.quantity:not(.buttons_added), td.quantity:not(.buttons_added)").each(function(a, b) {
var c = jQuery(b);
c.addClass("buttons_added"), c.children().first().before('<input type="button" value="-" class="minus" />'), c.children().last().after('<input type="button" value="+" class="plus" />')
})
}
String.prototype.getDecimals || (String.prototype.getDecimals = function() {
var a = this,
b = ("" + a).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
return b ? Math.max(0, (b[1] ? b[1].length : 0) - (b[2] ? +b[2] : 0)) : 0
}), jQuery(document).ready(function() {
wcqib_refresh_quantity_increments()
}), jQuery(document).on("updated_wc_div", function() {
wcqib_refresh_quantity_increments()
}), jQuery(document).on("click", ".plus, .minus", function() {
var a = jQuery(this).closest(".quantity").find(".qty"),
b = parseFloat(a.val()),
c = parseFloat(a.attr("max")),
d = parseFloat(a.attr("min")),
e = a.attr("step");
b && "" !== b && "NaN" !== b || (b = 0), "" !== c && "NaN" !== c || (c = ""), "" !== d && "NaN" !== d || (d = 0), "any" !== e && "" !== e && void 0 !== e && "NaN" !== parseFloat(e) || (e = 1), jQuery(this).is(".plus") ? c && b >= c ? a.val(c) : a.val((b + parseFloat(e)).toFixed(e.getDecimals())) : d && b <= d ? a.val(d) : b > 0 && a.val((b - parseFloat(e)).toFixed(e.getDecimals())), a.trigger("change")
});</script>
</body>
</html>
source: @TNLakhalani
Dan akhirnya saya memilih untuk menampilkan input number dengan metode kedua, karena tombol plus minusnya agak besar.