question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Spinner: Unable to enter values after ajax update

See original GitHub issue

Describe the bug

We are currently encountering a problem, where it is not possible to enter new values into a p:spinner input after it was refreshed by an Ajax update. The spinner definition looks like this:

<p:spinner value="#{bean.value}" min="1" max="99999" size="10" />

I’ve done some debugging and it seems like the problem is related to the keydown event handler defined in spinner.js. It uses event.key for some checks, where event references the global window.event variable. In some cases in Chrome, event points to a different event than the keydown event, or is even undefined. Then these checks will fail and the value will not get updated.

According to MDN, the window.event property is deprecated, so it maybe is no longer supported in Chrome or other browsers.

The solution would be quiet simple, by replacing the window.event reference with the event passed as parameter to the event listener.
I can provide a PR for this if desired.

Reproducer

Unfortunately the problem seems to depend heavily on external conditions, like events and other ajax requests happening on the page, so I cannot provide a reproducer.

Expected behavior

It should be possible to enter values after an ajax update.

PrimeFaces edition

Community

PrimeFaces version

10.0.0

Theme

No response

JSF implementation

MyFaces

JSF version

2.3.9

Browser(s)

Chrome 103

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
mellowarecommented, Jul 21, 2022

I see what you mean. I just submitted a PR and letting the Integration Tests run.

MonkeyPatch:

if (PrimeFaces.widget.Spinner) {
    PrimeFaces.widget.Spinner.prototype.bindEvents = function() {
        var $this = this;

        this.jq.children('.ui-spinner-button')
            .on('mouseover.spinner', function() {
                $(this).addClass('ui-state-hover');
            })
            .on('mouseout.spinner', function() {
                $(this).removeClass('ui-state-hover ui-state-active');

                if ($this.timer) {
                    clearInterval($this.timer);
                }
            })
            .on('mouseup.spinner', function() {
                clearInterval($this.timer);
                $(this).removeClass('ui-state-active').addClass('ui-state-hover');
                $this.input.trigger('change');
            })
            .on('mousedown.spinner', function(e) {
                // only act on left click
                if (e.which !== 1) {
                    return;
                }
                var element = $(this),
                    dir = element.hasClass('ui-spinner-up') ? 1 : -1;

                element.removeClass('ui-state-hover').addClass('ui-state-active');

                if ($this.input.is(':not(:focus)')) {
                    $this.input.trigger('focus');
                }

                $this.repeat(null, dir);

                //keep focused
                e.preventDefault();
            });

        this.input.on('keydown.spinner', function(e) {
                var keyCode = $.ui.keyCode;

                switch (e.which) {
                    case keyCode.UP:
                        $this.spin(1);
                        break;

                    case keyCode.DOWN:
                        $this.spin(-1);
                        break;

                    case keyCode.ENTER:
                        $this.updateValue();
                        $this.format();
                        break;

                    default:
                        //do nothing
                        break;
                }

                // #8958 allow TAB, F1, F12 etc
                var isPrintableKey = e.key.length === 1 || e.key === 'Unidentified';
                if (!isPrintableKey) {
                    return;
                }

                /* Github #1964 do not allow minus */
                var isNegative = e.key === '-';
                if ($this.cfg.min >= 0 && isNegative) {
                    e.preventDefault();
                    return;
                }

                /* GitHub #5579 do not allow decimal separator for integers */
                var isDecimalSeparator = e.key === $this.cfg.decimalSeparator;
                if (isDecimalSeparator && $this.cfg.precision === 0) {
                    e.preventDefault();
                    return;
                }

                /* GitHub #5579 prevent non numeric characters and duplicate separators */
                var value = $(this).val();
                var isNumber = isFinite(e.key);
                var isThousandsSeparator = e.key === $this.cfg.thousandSeparator;
                if ((isNegative && value.indexOf('-') != -1) ||
                    (isDecimalSeparator && value.indexOf($this.cfg.decimalSeparator) != -1) ||
                    (isThousandsSeparator && value.indexOf($this.cfg.thousandSeparator) != -1)) {
                    e.preventDefault();
                    return;
                }

                if (!isNumber && !(isNegative || isDecimalSeparator || isThousandsSeparator)) {
                    e.preventDefault();
                    return;
                }
            })
            .on('keyup.spinner', function(e) {
                $this.updateValue();

                var keyCode = $.ui.keyCode;

                /* Github #2636 */
                var checkForIE = (PrimeFaces.env.isIE(11) || PrimeFaces.env.isLtIE(11)) && (e.which === keyCode.ENTER);

                if (e.which === keyCode.UP || e.which === keyCode.DOWN || checkForIE) {
                    $this.input.trigger('change');
                    $this.format();
                }
            })
            .on('blur.spinner', function(e) {
                $this.format();
            })
            .on('mousewheel.spinner', function(event, delta) {
                if ($this.cfg.modifyValueOnWheel && $this.input.is(':focus')) {
                    if (delta > 0)
                        $this.spin(1);
                    else
                        $this.spin(-1);

                    $this.input.trigger('change');

                    return false;
                }
            });
    }
};
0reactions
cnsgithubcommented, Jul 21, 2022

Great, thanks for the quick fix!

Read more comments on GitHub >

github_iconTop Results From Across the Web

ajax - <p:spinner> max value won't change anymore into other ...
So, I solved this problem by reference of @Kukeltje. Based on this, How can I populate a text field using PrimeFaces AJAX after...
Read more >
Spinner Doesn't Work While AJAX Does Its Job - jQuery Forum
I'm trying to get a spinner to show up while my form does submitting data. So far, my AJAX works absolutely fine and...
Read more >
spinner combined with f:ajax fails - Prime Community Forum
It appears though that the spinner still remembers/tracks the number value, as spinning still shows the values quickly changing before throwing ...
Read more >
ASP.NET Core Load Partial View using Ajax with Spinner
Hi,. I can load my Partial View Using Ajax. But I failed to show the Spinner to User. Need help on Spinner. Here...
Read more >
AJAX error handling - JSNLog
Your JavaScript program receives an error response instead of data; · Your program has to wait too long for the response. You can't...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found