├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── es5-deprecated
├── index.html
├── src
│ ├── bootstrap-input-spinner.js
│ └── custom-editors.js
└── test
│ ├── Test.js
│ ├── index.html
│ └── test-pages
│ ├── native-number-input.html
│ ├── test-bug-98.html
│ └── test.css
├── favicon.ico
├── index.html
├── package-lock.json
├── package.json
└── src
├── InputSpinner.js
└── custom-editors.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | src/bootstrap-input-spinner.js linguist-vendored=false
2 | index.html linguist-documentation
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /.idea
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Stefan Haack - http://shaack.com
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bootstrap-input-spinner
2 |
3 | A Bootstrap extension to create input spinner elements for number input.
4 |
5 | > Note: bootstrap-input-spinner is now a ES6 module. You find the old ES5 version in the folder `es5-deprecated`. The ES5 version is not maintained anymore and will be removed in the future.
6 |
7 | 
8 | *Examples with floating-point and german localization*
9 |
10 | ## References
11 |
12 | - [Demo page with usage examples](http://shaack.com/projekte/bootstrap-input-spinner/)
13 | - [GitHub repository](https://github.com/shaack/bootstrap-input-spinner/)
14 | - [npm package](https://www.npmjs.com/package/bootstrap-input-spinner)
15 |
16 | ### Older version, Bootstrap 4 compatible
17 |
18 | > The current is compatible with **Bootstrap 5**, but we remain a Bootstrap 4 compatible version with the branch
19 | > bootstrap4-compatible.
20 | > npm package versions 3.x are Bootstrap 5 compatible, versions 2.x Bootstrap 4 compatible.
21 |
22 | - [Bootstrap 4 compatible npm package](https://www.npmjs.com/package/bootstrap-input-spinner/v/2.1.2)
23 |
24 | ## Features
25 |
26 | The Bootstrap InputSpinner
27 |
28 | - is **mobile friendly** and **responsive**,
29 | - automatically changes the value when **holding a button**,
30 | - has **internationalized** number formatting,
31 | - allows setting a **prefix** or a **suffix** text in the input,
32 | - handles **`val()`** like the native element,
33 | - **dynamically handles** changing **attribute values** like `disabled` or `class`,
34 | - supports **templates** and **custom editors**, (*new!*)
35 | - dispatches **`change`** and **`input`** **events on value change** like the native element and
36 | - works **without extra css**, only Bootstrap 5 is needed.
37 |
38 | ## Quickstart
39 |
40 | ### Installation
41 |
42 | Current version, Bootstrap 5 compatible
43 | ```bash
44 | npm install bootstrap-input-spinner
45 | ```
46 | Bootstrap 4 compatible version
47 | ```bash
48 | npm install bootstrap-input-spinner@2.2.0
49 | ```
50 |
51 |
52 | Or just download the GitHub repository and include `src/bootstrap-input-spinner.js`.
53 |
54 | ### HTML
55 |
56 | Create the element in HTML. The attributes are compatible to the native `input[type="number"]` element.
57 |
58 | ```html
59 |
60 | ```
61 |
62 | ### Script
63 |
64 | ```html
65 |
73 | ```
74 |
75 | That's it. **No extra css needed**, just Bootstrap 5 and jQuery. (Note: jQuery will be removed in the future)
76 |
77 | ## API Reference
78 |
79 | ### HTML Attributes
80 |
81 | ```html
82 |
83 | ```
84 |
85 | Use these attributes to configure the behaviour
86 |
87 | - `value` // starting value on element creation
88 | - `min` // minimum value when stepping
89 | - `max` // maximum value when stepping
90 | - `step` // step size
91 | - `inputmode` // the "inputmode" of the input, defaults to "decimal" (shows decimal keyboard on touch devices)
92 | - `data-decimals` // shown decimal places
93 | - `data-digit-grouping` // "false" to disable grouping (thousands separator), default is "true"
94 | - `data-prefix` // show a prefix text in the input element
95 | - `data-suffix` // show a suffix text in the input element
96 |
97 | The InputSpinner also handles the standard input attributes `required`, `disabled`, `readonly` and `placeholder`.
98 |
99 | ### Create an instance in JavaScript
100 |
101 | Use JavaScript to create the instance as a jQuery plugin. You may provide additional configuration in an object as a
102 | config parameter.
103 |
104 | ```js
105 | $(element).inputSpinner(config);
106 | ```
107 |
108 | #### Configuration (props)
109 |
110 | The default configuration is
111 |
112 | ```javascript
113 | var props = {
114 | decrementButton: "−", // button text
115 | incrementButton: "+", // ..
116 | groupClass: "", // css class of the resulting input-group
117 | buttonsClass: "btn-outline-secondary",
118 | buttonsWidth: "2.5rem",
119 | textAlign: "center", // alignment of the entered number
120 | autoDelay: 500, // ms threshold before auto value change
121 | autoInterval: 50, // speed of auto value change, set to `undefined` to disable auto-change
122 | buttonsOnly: false, // set this `true` to disable the possibility to enter or paste the number via keyboard
123 | keyboardStepping: true, // set this to `false` to disallow the use of the up and down arrow keys to step
124 | locale: navigator.language, // the locale, per default detected automatically from the browser
125 | editor: I18nEditor, // the editor (parsing and rendering of the input)
126 | template: // the template of the input
127 | '
' +
128 | '' +
129 | '' +
130 | '' +
131 | '
'
132 | }
133 | ```
134 |
135 | ##### decrementButton, incrementButton
136 |
137 | HTML of the texts inside the buttons.
138 |
139 | ##### groupClass
140 |
141 | Additional css class for the `input-group` of the rendered Bootstrap input.
142 |
143 | ##### buttonsClass
144 |
145 | The css class of the buttons. Use it to style the increment and decrement buttons as
146 | described [here](https://getbootstrap.com/docs/4.0/components/buttons/). Maybe `buttonsClass: btn-primary`
147 | or `btn-success` or whatever type of buttons you want.
148 |
149 | ##### buttonsWidth
150 |
151 | The width of the increment and decrement buttons.
152 |
153 | ##### textAlign
154 |
155 | The text alignment inside the ``.
156 |
157 | ##### autoDelay
158 |
159 | The delay in ms after which the input automatically changes the value, when holding the increment or decrement button.
160 |
161 | ##### autoInterval
162 |
163 | Speed of the value change when holding the button in ms. A lower value makes it faster.
164 |
165 | ##### buttonsOnly
166 |
167 | In `buttonsOnly` mode (set `true`) no direct text input is allowed, the text-input gets the attribute `readonly`, but
168 | the plus and minus buttons still allow to change the value.
169 |
170 | ##### keyboardStepping
171 |
172 | In `keyboardStepping` mode (set `true`) allows the use of the up/down arrow keys to increase/decrease the number by the
173 | step.
174 |
175 | ##### locale
176 |
177 | Used to format the number in the UI. Detected automatically from the user's browser, can be set to "de", "en",… or "
178 | de_DE", "en_GB",….
179 |
180 | ##### editor (*new!*)
181 |
182 | An Editor defines, how the input is parsed and rendered. The default editor of the spinner is the `I18nEditor`, which
183 | renders and parses an internationalized number value. There are custom editors in `/src/custom-editors.js`. An Editor
184 | must implement the two functions `parse(customValue)`, to parse the input to a number and `render(number)` to render the
185 | number to the spinner input.
186 |
187 | The simplest custom Editor is the `RawEditor`, it renders just the value und parses just the value, without any changes,
188 | like a native number input. It looks like this:
189 |
190 | ```javascript
191 | var RawEditor = function (props, element) {
192 | this.parse = function (customFormat) {
193 | // parse nothing
194 | return customFormat
195 | }
196 | this.render = function (number) {
197 | // render raw
198 | return number
199 | }
200 | }
201 | ```
202 |
203 | `props` is the configuration of the spinner and `element` is the original HTML element. You can use these values for the
204 | configuration of the Editor, like in `I18nEditor`, which uses `props` for the language and `element` for the attributes.
205 |
206 | The `TimeEditor` renders and parses the number to time in hours and minutes, separated by a colon.
207 |
208 | 
209 | *Supports custom editors to parse and render everything*
210 |
211 | ##### template
212 |
213 | To modify the look completely, you can use the template parameter. There is an example about this on the
214 | [Demo Page](http://shaack.com/projekte/bootstrap-input-spinner/).
215 |
216 | ### Programmatic change and read of value
217 |
218 | To change or read the value just use the jQuery `val()` function on the input, like this
219 |
220 | ```javascript
221 | var currentValue = $(element).val() // read
222 | $(element).val(newValue) // write
223 | ```
224 |
225 | > **Hint:** Reading the value in vanilla JS with `element.value` will also work, but to set the value you have to use `element.setValue(newValue)` or `$(element).val(newValue)`
226 |
227 | ### Handling attributes
228 |
229 | The attributes
230 | `min`, `max`, `step`, `decimals`, `placeholder`, `required`, `disabled`, `readonly` and `class`
231 | are handled dynamically. The `class` attribute value is dynamically copied to the input element.
232 |
233 | #### Sizing
234 |
235 | If the original elements class is set to `form-control-sm` of `form-control-lg` the class of the resulting input-group
236 | is dynamically set to `input-group-sm` or `input-group-lg`.
237 |
238 | ### Events
239 |
240 | The InputSpinner handles `input` and `change` events like the native element.
241 |
242 | #### Event handling with vanilla JavaScript
243 |
244 | ```javascript
245 | element.addEventListener("change", function (event) {
246 | newValue = this.value
247 | })
248 | ```
249 |
250 | #### Event handling with jQuery syntax
251 |
252 | ```javascript
253 | $(element).on("change", function (event) {
254 | newValue = $(this).val()
255 | })
256 | ```
257 |
258 | ### Methods
259 |
260 | Methods are passed as string values instead of the options object.
261 |
262 | #### destroy
263 |
264 | Removes the InputSpinner and shows the original input element.
265 |
266 | ```javascript
267 | $(element).inputSpinner("destroy")
268 | ```
269 |
270 | ## Minified version
271 |
272 | I don't provide a minified version because I think it should be up to the using programmer to create minified versions,
273 | with all the used script sources concatenated to one file.
274 |
275 | But, if you want it, it is easy to create your minified version with uglify: https://www.npmjs.com/package/uglify-js
276 |
277 | Just install uglify
278 |
279 | ```bash
280 | npm install uglify-js -g
281 | ```
282 |
283 | and then in the src-folder
284 |
285 | ```bash
286 | uglifyjs bootstrap-input-spinner.js --compress --mangle > bootstrap-input-spinner.min.js
287 | ```
288 |
289 | Violà! :)
290 |
291 | ## Browser support
292 |
293 | The spinner works in all modern browsers and Internet Explorer. Not tested with IE < 11.
294 |
295 | For older browsers (IE 9 or so), that doesn't support `Intl`, when you get an error message like
296 | **"Intl is not defined"** (See [issue #34](https://github.com/shaack/bootstrap-input-spinner/issues/34)), just use a
297 | shim or polyfill like [Intl.js](https://github.com/andyearnshaw/Intl.js), and it works.
298 |
299 | ---
300 |
301 | Find more high quality modules from [shaack.com](https://shaack.com)
302 | on [our projects page](https://shaack.com/works).
303 |
--------------------------------------------------------------------------------
/es5-deprecated/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | bootstrap-input-spinner
7 |
8 |
9 |
10 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
bootstrap-input-spinner
34 |
35 | A Bootstrap / jQuery plugin to create input spinner elements for number input, by
36 | shaack.com engineering. For now it needs jQuery, but I am working on it.
37 |
38 |
This version is compatible with Bootstrap 5, but we remain a Bootstrap 4 compatible version with the branch
39 | bootstrap4-compatible. npm versions 3.x are Bootstrap 5 compatible, versions 2.x Bootstrap 4 compatible.
Handle change and input events and
110 | read the value from JavaScript
111 | with val()
112 |
113 | Type in a number to see the difference between change and input events.
114 |
115 |
116 |
117 |
118 |
119 | Value on input:
120 | Value on change:
121 |
122 |
137 |
var $changedInput = $("#changedInput")
138 | var $valueOnInput = $("#valueOnInput")
139 | var $valueOnChange = $("#valueOnChange")
140 | $changedInput.on("input", function (event) {
141 | $valueOnInput.html($(event.target).val())
142 | // or $valueOnInput.html(event.target.value) // in vanilla js
143 | // or $valueOnInput.html($changedInput.val())
144 | })
145 | $changedInput.on("change", function (event) {
146 | $valueOnChange.html($(event.target).val())
147 | })
148 |
Programmatic changing the value with val()
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
168 |
$inputNet.on("input", function (event) {
169 | $inputGross.val($(event.target).val() * 1.19)
170 | // or $inputGross[0].setValue(event.target.value * 1.19) // in vanilla js
171 | // or $inputGross.val($inputNet.val() * 1.19)
172 | // do all the same
173 | })
174 | $inputGross.on("input", function (event) {
175 | $inputNet.val($(event.target).val() / 1.19)
176 | })
177 |
Attributes placeholder and required
178 |
186 |
187 |
Attribute disabled, dynamically changing
188 |
Attributes are handled dynamically.
189 |
217 |
218 |
buttonsOnly mode and disabled autoInterval
219 |
220 | In buttonsOnly mode no direct text input is allowed, the text-input
221 | gets the attribute readonly. But the plus and minus buttons still allow to change the value.
222 | autoInterval: undefined additionally disables the auto increase/decrease, when you hold the button.
223 |
Sizing works out of the box. Just set the original inputs class to form-control-sm or
258 | form-control-lg, and
259 | the resulting group gets the class input-group-sm or input-group-lg.
"Loop" the value between 0 and 360 with the change event in JavaScript.
375 |
var $inputLoop = $("#inputLoop")
376 | $inputLoop.on("input", function(event) {
377 | var value = $inputLoop.val()
378 | value = (value < 0) ? 360 + parseInt(value, 10) : value % 360
379 | $inputLoop.val(value)
380 | })
381 |
382 |
Custom Editors
383 |
384 |
An Editor defines, how the input is parsed and rendered. The inputSpinner is shipped with some custom Editors in
385 | /src/custom-editors.js.
386 |
387 |
RawEditor
388 |
389 |
The simplest custom Editor is the RawEditor, it renders just the value und parses just the value,
390 | without any
391 | changes, like a native number input. No internationalization, no digit grouping.
36 | A Bootstrap / jQuery plugin to create input spinner elements for number input, by
37 | shaack.com engineering. For now it needs jQuery, but I am working on it.
38 |
39 |
This version is compatible with Bootstrap 5, but we remain a Bootstrap 4 compatible version with the branch
40 | bootstrap4-compatible.
41 | npm versions 3.x are Bootstrap 5 compatible, versions 2.x Bootstrap 4 compatible.
Handle change and input events and
112 | read the value from JavaScript
113 | with val()
114 |
115 | Type in a number to see the difference between change and input events.
116 |
117 |
118 |
119 |
120 |
121 | Value on input:
122 | Value on change:
123 |
124 |
139 |
var $changedInput = $("#changedInput")
140 | var $valueOnInput = $("#valueOnInput")
141 | var $valueOnChange = $("#valueOnChange")
142 | $changedInput.on("input", function (event) {
143 | $valueOnInput.html($(event.target).val())
144 | // or $valueOnInput.html(event.target.value) // in vanilla js
145 | // or $valueOnInput.html($changedInput.val())
146 | })
147 | $changedInput.on("change", function (event) {
148 | $valueOnChange.html($(event.target).val())
149 | })
150 |
Programmatic changing the value with val()
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
170 |
$inputNet.on("input", function (event) {
171 | $inputGross.val($(event.target).val() * 1.19)
172 | // or $inputGross[0].setValue(event.target.value * 1.19) // in vanilla js
173 | // or $inputGross.val($inputNet.val() * 1.19)
174 | // do all the same
175 | })
176 | $inputGross.on("input", function (event) {
177 | $inputNet.val($(event.target).val() / 1.19)
178 | })
179 |
Attributes placeholder and required
180 |
188 |
189 |
Attribute disabled, dynamically changing
190 |
Attributes are handled dynamically.
191 |
219 |
220 |
buttonsOnly mode and disabled autoInterval
221 |
222 | In buttonsOnly mode no direct text input is allowed, the text-input
223 | gets the attribute readonly. But the plus and minus buttons still allow to change the value.
224 | autoInterval: undefined additionally disables the auto increase/decrease, when you hold the
225 | button.
226 |
Sizing works out of the box. Just set the original inputs class to form-control-sm or
267 | form-control-lg, and
268 | the resulting group gets the class input-group-sm or input-group-lg.
"Loop" the value between 0 and 360 with the change event in JavaScript.
387 |
var $inputLoop = $("#inputLoop")
388 | $inputLoop.on("input", function(event) {
389 | var value = $inputLoop.val()
390 | value = (value < 0) ? 360 + parseInt(value, 10) : value % 360
391 | $inputLoop.val(value)
392 | })
393 |
394 |
Custom Editors
395 |
396 |
An Editor defines, how the input is parsed and rendered. The inputSpinner is shipped with some custom Editors in
397 | /src/custom-editors.js.
398 |
399 |
RawEditor
400 |
401 |
The simplest custom Editor is the RawEditor, it renders just the value und parses just the value,
402 | without any
403 | changes, like a native number input. No internationalization, no digit grouping.