PageSourceSearch

https://greatoceanroad-holidayrentals.com.au/media/common/2020/ven…/src/bootstrap-input-spinner.js

js greatoceanroad-holidayrentals.com.au collected 2026-10-09 21:58:20 UTC 12,285 bytes, 300 lines download raw bytes

1/**
2 * Author and copyright: Stefan Haack (https://shaack.com)
3 * Repository: https://github.com/shaack/bootstrap-input-spinner
4 * License: MIT, see file 'LICENSE'
5 */
6
7;(function ($) {
8    "use strict"
9
10    var triggerKeyPressed = false
11    var originalVal = $.fn.val
12    $.fn.val = function (value) {
13        if (arguments.length >= 1) {
14            if (this[0] && this[0]["bootstrap-input-spinner"] && this[0].setValue) {
15                var element = this[0]
16                setTimeout(function () {
17                    element.setValue(value)
18                })
19            }
20        }
21        return originalVal.apply(this, arguments)
22    }
23
24    $.fn.InputSpinner = $.fn.inputSpinner = function (options) {
25
26        var config = {
27            decrementButton: "<strong>-</strong>", // button text
28            incrementButton: "<strong>+</strong>", // ..
29            groupClass: "", // css class of the resulting input-group
30            buttonsClass: "btn-outline-secondary",
31            // buttonsWidth: "2.5rem",
32            buttonsWidth: "50px",
33            textAlign: "center",
34            autoDelay: 500, // ms holding before auto value change
35            autoInterval: 100, // speed of auto value change
36            boostThreshold: 10, // boost after these steps
37            boostMultiplier: "auto" // you can also set a constant number as multiplier
38        }
39        for (var option in options) {
40            config[option] = options[option]
41        }
42
43        var html = '<div class="input-group ' + config.groupClass + '">' +
44            '<div class="input-group-prepend">' +
45            '<button style="min-width: ' + config.buttonsWidth + '" class="btn btn-decrement ' + config.buttonsClass + '" type="button">' + config.decrementButton + '</button>' +
46            '</div>' +
47            '<input type="text" inputmode="decimal" style="background-color:white;min-width:35px;text-align: ' + config.textAlign + '" class="form-control"/>' +
48            '<div class="input-group-append">' +
49            '<button style="min-width: ' + config.buttonsWidth + '" class="btn btn-increment ' + config.buttonsClass + '" type="button">' + config.incrementButton + '</button>' +
50            '</div>' +
51            '</div>'
52
53        var locale = navigator.language || "en-US"
54
55        this.each(function () {
56
57            var $original = $(this)
58            $original[0]["bootstrap-input-spinner"] = true
59            $original.hide()
60
61            var autoDelayHandler = null
62            var autoIntervalHandler = null
63            var autoMultiplier = config.boostMultiplier === "auto"
64            var boostMultiplier = autoMultiplier ? 1 : config.boostMultiplier
65
66            var $inputGroup = $(html)
67            var $buttonDecrement = $inputGroup.find(".btn-decrement")
68            var $buttonIncrement = $inputGroup.find(".btn-increment")
69            var $input = $inputGroup.find("input")
70
71            var min = null
72            var max = null
73            var step = null
74            var stepMax = null
75            var decimals = null
76            var digitGrouping = null
77            var numberFormat = null
78
79            updateAttributes()
80
81            var value = parseFloat($original[0].value)
82            var boostStepsCount = 0
83
84            var prefix = $original.attr("data-prefix") || ""
85            var suffix = $original.attr("data-suffix") || ""
86
87            if (prefix) {
88                var prefixElement = $('<span class="input-group-text">' + prefix + '</span>')
89                $inputGroup.find(".input-group-prepend").append(prefixElement)
90            }
91            if (suffix) {
92                var suffixElement = $('<span class="input-group-text">' + suffix + '</span>')
93                $inputGroup.find(".input-group-append").prepend(suffixElement)
94            }
95
96            $original[0].setValue = function (newValue) {
97                setValue(newValue)
98            }
99
100            var observer = new MutationObserver(function () {
101                updateAttributes()
102                setValue(value, true)
103            })
104            observer.observe($original[0], {attributes: true})
105
106            $original.after($inputGroup)
107
108            setValue(value)
109
110            $input.on("paste input change focusout", function (event) {
111                var newValue = $input[0].value
112                var focusOut = event.type === "focusout"
113                newValue = parseLocaleNumber(newValue)
114                setValue(newValue, focusOut)
115                dispatchEvent($original, event.type)
116            })
117
118            onPointerDown($buttonDecrement[0], function () {
119                stepHandling(-step)
120            })
121            onPointerDown($buttonIncrement[0], function () {
122                stepHandling(step)
123            })
124            onPointerUp(document.body, function () {
125                resetTimer()
126            })
127
128            function setValue(newValue, updateInput) {
129                if (updateInput === undefined) {
130                    updateInput = true
131                }
132                if (isNaN(newValue) || newValue === "") {
133                    $original[0].value = ""
134                    if (updateInput) {
135                        $input[0].value = ""
136                    }
137                    value = NaN
138                } else {
139                    newValue = parseFloat(newValue)
140                    newValue = Math.min(Math.max(newValue, min), max)
141                    newValue = Math.round(newValue * Math.pow(10, decimals)) / Math.pow(10, decimals)
142                    $original[0].value = newValue
143                    if (updateInput) {
144                        $input[0].value = numberFormat.format(newValue)
145                    }
146                    value = newValue
147                }
148            }
149
150            function dispatchEvent($element, type) {
151                if (type) {
152                    setTimeout(function () {
153                        var event
154                        if (typeof (Event) === 'function') {
155                            event = new Event(type, {bubbles: true})
156                        } else { // IE
157                            event = document.createEvent('Event')
158                            event.initEvent(type, true, true)
159                        }
160                        $element[0].dispatchEvent(event)
161                    })
162                }
163            }
164
165            function stepHandling(step) {
166                if (!$input[0].disabled && !$input[0].readOnly) {
167                    calcStep(step)
168                    resetTimer()
169                    autoDelayHandler = setTimeout(function () {
170                        autoIntervalHandler = setInterval(function () {
171                            if (boostStepsCount > config.boostThreshold) {
172                                if (autoMultiplier) {
173                                    calcStep(step * parseInt(boostMultiplier, 10))
174                                    if (boostMultiplier < 100000000) {
175                                        boostMultiplier = boostMultiplier * 1.1
176                                    }
177                                    if (stepMax) {
178                                        boostMultiplier = Math.min(stepMax, boostMultiplier)
179                                    }
180                                } else {
181                                    calcStep(step * boostMultiplier)
182                                }
183                            } else {
184                                calcStep(step)
185                            }
186                            boostStepsCount++
187                        }, config.autoInterval)
188                    }, config.autoDelay)
189                }
190            }
191
192            function calcStep(step) {
193                if (isNaN(value)) {
194                    value = 0
195                }
196                setValue(Math.round(value / step) * step + step)
197                dispatchEvent($original, "input")
198                dispatchEvent($original, "change")
199            }
200
201            function resetTimer() {
202                boostStepsCount = 0
203                boostMultiplier = boostMultiplier = autoMultiplier ? 1 : config.boostMultiplier
204                clearTimeout(autoDelayHandler)
205                clearTimeout(autoIntervalHandler)
206            }
207
208            function updateAttributes() {
209                // copy properties from original to the new input
210                $input.prop("required", $original.prop("required"))
211                $input.prop("placeholder", $original.prop("placeholder"))
212                $input.attr("inputmode", $original.attr("inputmode") || "decimal")
213                var disabled = $original.prop("disabled")
214                var readonly = $original.prop("readonly")
215                $input.prop("disabled", disabled)
216                $input.prop("readonly", readonly)
217                $buttonIncrement.prop("disabled", disabled || readonly)
218                $buttonDecrement.prop("disabled", disabled || readonly)
219                if (disabled || readonly) {
220                    resetTimer()
221                }
222                var originalClass = $original.prop("class")
223                var groupClass = ""
224                // sizing
225                if (/form-control-sm/g.test(originalClass)) {
226                    groupClass = "input-group-sm"
227                } else if (/form-control-lg/g.test(originalClass)) {
228                    groupClass = "input-group-lg"
229                }
230                var inputClass = originalClass.replace(/form-control(-(sm|lg))?/g, "")
231                $inputGroup.prop("class", "input-group " + groupClass + " " + config.groupClass)
232                $input.prop("class", "form-control " + inputClass)
233
234                // update the main attributes
235                min = parseFloat($original.prop("min")) || 0
236                max = isNaN($original.prop("max")) || $original.prop("max") === "" ? Infinity : parseFloat($original.prop("max"))
237                step = parseFloat($original.prop("step")) || 1
238                stepMax = parseInt($original.attr("data-step-max")) || 0
239                var newDecimals = parseInt($original.attr("data-decimals")) || 0
240                var newDigitGrouping = !($original.attr("data-digit-grouping") === "fal
240se")
241                if (decimals !== newDecimals || digitGrouping !== newDigitGrouping) {
242                    decimals = newDecimals
243                    digitGrouping = newDigitGrouping
244                    numberFormat = new Intl.NumberFormat(locale, {
245                        minimumFractionDigits: decimals,
246                        maximumFractionDigits: decimals,
247                        useGrouping: digitGrouping
248                    })
249                }
250            }
251
252            function parseLocaleNumber(stringNumber) {
253                var numberFormat = new Intl.NumberFormat(locale)
254                var thousandSeparator = numberFormat.format(1111).replace(/1/g, '')
255                var decimalSeparator = numberFormat.format(1.1).replace(/1/g, '')
256                return parseFloat(stringNumber
257                    .replace(new RegExp('\\' + thousandSeparator, 'g'), '')
258                    .replace(new RegExp('\\' + decimalSeparator), '.')
259                )
260            }
261        })
262
263        return this
264    }
265
266    function onPointerUp(element, callback) {
267        element.addEventListener("mouseup", function (e) {
268            callback(e)
269        })
270        element.addEventListener("touchend", function (e) {
271            callback(e)
272        })
273        element.addEventListener("keyup", function (e) {
274            if ((e.keyCode === 32 || e.keyCode === 13)) {
275                triggerKeyPressed = false
276                callback(e)
277            }
278        })
279    }
280
281    function onPointerDown(element, callback) {
282        element.addEventListener("mousedown", function (e) {
283            e.preventDefault()
284            callback(e)
285        })
286        element.addEventListener("touchstart", function (e) {
287            if (e.cancelable) {
288                e.preventDefault()
289            }
290            callback(e)
291        })
292        element.addEventListener("keydown", function (e) {
293            if ((e.keyCode === 32 || e.keyCode === 13) && !triggerKeyPressed) {
294                triggerKeyPressed = true
295                callback(e)
296            }
297        })
298    }
299
300}(jQuery))

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.