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: pressing tab or other special buttons have no effect

See original GitHub issue

Describe the bug

When using a spinner component and click inside it, it’s impossible to tab to next element or click other special button combinations like ctrl+s or ctrl+p etc. (tested on 10.0.6 and 10.0.13)

Reproducer

  1. create spinner component<p:spinner id="somId" />
  2. Click inside spinner component
  3. Click tab or ctrl+s
  4. still focus inside spinner, no error visible

Expected behavior

It sould be possible to tab out the spinner and also to do all sorts of button combinations, open developer console in browser etc.

PrimeFaces edition

Elite

PrimeFaces version

10.0.6 / 10.0.13

Theme

No response

JSF implementation

MyFaces

JSF version

2.2

Browser(s)

No response

Issue Analytics

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

github_iconTop GitHub Comments

2reactions
mellowarecommented, Jul 11, 2022

Here is a MonkeyPatch you should just add to your application JS file which will override the spinner behavior.

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 = event.key === '-';
                if ($this.cfg.min >= 0 && isNegative) {
                    e.preventDefault();
                    return;
                }

                /* GitHub #5579 do not allow decimal separator for integers */
                var isDecimalSeparator = event.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(event.key);
                var isThousandsSeparator = event.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;
                }
            });
    }
};
1reaction
raphisutercommented, Jul 11, 2022

tested it and works, thank you

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spinner from shinycssloaders package loads before pressing ...
I followed the solution that it was given to the post, but as I my app is different (it has tabPanel s, it...
Read more >
Spinner buttons should not be focusable · Issue #7789 - GitHub
Spinner buttons grab focus when pressing TAB repeatedly. When focused, pressing Spacebar or Enter has no effect so they just slow down the...
Read more >
Add a scroll bar or spin button to a worksheet - Microsoft Support
Add a scroll bar or spin button to an Excel worksheet. The controls let you quickly enter or change a range of values....
Read more >
Buttons on Web Pages - SiteSpinner Pro Tutorials
Buttons This tutorial will take you through simple buttons to more complicated buttons that involve mouse over effects -- also called rollovers.
Read more >
Spinner - Android Developers
android:accessibilityHeading, Whether or not this view is a heading for ... whether a view should have sound effects enabled for events such as...
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