ChatGPT解决这个技术问题 Extra ChatGPT

Disable hover effects on mobile browsers

I'm writing a Web site that's meant to be used from both desktops and tablets. When it's being visited from a desktop, I want the clickable areas of the screen to light up with :hover effects (different background color, etc.) With a tablet, there's no mouse, so I don't want any hover effects.

The problem is, when I tap something on the tablet, the browser evidently has some kind of "invisible mouse cursor" that it moves to the location I tapped, and then leaves it there -- so the thing I just tapped lights up with a hover effect until I tap something else.

How can I get the hover effects when I'm using the mouse, but suppress them when I'm using the touchscreen?

In case someone was thinking of suggesting it, I don't want to use user-agent sniffing. The same device could have both a touchscreen and a mouse (maybe not so common today, but much more so in the future). I'm not interested in the device, I'm interested in how it's currently being used: mouse or touchscreen.

I already tried hooking the touchstart, touchmove, and touchend events and calling preventDefault() on all of them, which does suppress the "invisible mouse cursor" some of the time; but if I tap rapidly back and forth between two different elements, after a few taps it will start moving the "mouse cursor" and lighting up the hover effects anyway -- it's like my preventDefault isn't always honored. I won't bore you with the details unless necessary -- I'm not even sure that's the right approach to take; if anyone has a simpler fix, I'm all ears.

Edit: This can be reproduced with bog-standard CSS :hover, but here's a quick repro for reference.

<style>
  .box { border: 1px solid black; width: 150px; height: 150px; }
  .box:hover { background: blue; }
</style>
<div class="box"></div>
<div class="box"></div>

If you mouse over either of the boxes, it will get a blue background, which I want. But if you tap on either of the boxes, it will also get a blue background, which is the thing I'm trying to prevent.

I've also posted a sample here that does the above and also hooks jQuery's mouse events. You can use it to see that tap events will also fire mouseenter, mousemove and mouseleave.

@Blender, did you read the question? I already explained why user-agent sniffing is a bad choice.
Hey Joe, did you find any solution for this?
I was searching for this kind of question, glad I found it !
See also this question, which deals with disabling hover on any touch-enabled devices, not just mobile: stackoverflow.com/questions/23885255/…

C
Cœur

I take it from your question that your hover effect changes the content of your page. In that case, my advice is to:

Add hover effects on touchstart and mouseenter.

Remove hover effects on mouseleave, touchmove and click.

Alternatively, you can edit your page that there is no content change.

Background

In order to simulate a mouse, browsers such as Webkit mobile fire the following events if a user touches and releases a finger on touch screen (like iPad) (source: Touch And Mouse on html5rocks.com):

touchstart touchmove touchend 300ms delay, where the browser makes sure this is a single tap, not a double tap mouseover mouseenter Note: If a mouseover, mouseenter or mousemove event changes the page content, the following events are never fired. mousemove mousedown mouseup click

It does not seem possible to simply tell the webbrowser to skip the mouse events.

What's worse, if a mouseover event changes the page content, the click event is never fired, as explained on Safari Web Content Guide - Handling Events, in particular figure 6.4 in One-Finger Events. What exactly a "content change" is, will depend on browser and version. I've found that for iOS 7.0, a change in background color is not (or no longer?) a content change.

Solution Explained

To recap:

Add hover effects on touchstart and mouseenter.

Remove hover effects on mouseleave, touchmove and click.

Note that there is no action on touchend!

This clearly works for mouse events: mouseenter and mouseleave (slightly improved versions of mouseover and mouseout) are fired, and add and remove the hover.

If the user actually clicks a link, the hover effect is also removed. This ensure that it is removed if the user presses the back button in the web browser.

This also works for touch events: on touchstart the hover effect is added. It is '''not''' removed on touchend. It is added again on mouseenter, and since this causes no content changes (it was already added), the click event is also fired, and the link is followed without the need for the user to click again!

The 300ms delay that a browser has between a touchstart event and click is actually put in good use because the hover effect will be shown during this short time.

If the user decides to cancel the click, a move of the finger will do so just as normal. Normally, this is a problem since no mouseleave event is fired, and the hover effect remains in place. Thankfully, this can easily be fixed by removing the hover effect on touchmove.

That's it!

Note that it is possible to remove the 300ms delay, for example using the FastClick library, but this is out of scope for this question.

Alternative Solutions

I've found the following problems with the following alternatives:

browser detection: Extremely prone to errors. Assumes that a device has either mouse or touch, while a combination of both will become more and more common when touch displays prolifirate.

CSS media detection: The only CSS-only solution I'm aware of. Still prone to errors, and still assumes that a device has either mouse or touch, while both are possible.

Emulate the click event in touchend: This will incorrectly follow the link, even if the user only wanted to scroll or zoom, without the intention of actually clicking the link.

Use a variable to suppress mouse events: This set a variable in touchend that is used as a if-condition in subsequent mouse events to prevents state changes at that point in time. The variable is reset in the click event. See Walter Roman's answer on this page. This is a decent solution if you really don't want a hover effect on touch interfaces. Unfortunately, this does not work if a touchend is fired for another reason and no click event is fired (e.g. the user scrolled or zoomed), and is subsequently trying to following the link with a mouse (i.e on a device with both mouse and touch interface).

Further Reading

http://jsfiddle.net/macfreek/24Z5M/. Test the above solution for yourself in this sandbox.

http://www.macfreek.nl/memory/Touch_and_mouse_with_hover_effects_in_a_web_browser. This same answer, with a bit more background.

https://www.html5rocks.com/en/mobile/touchandmouse/. Great background article on html5rocks.com about touch and mouse in general.

https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html. Safari Web Content Guide - Handling Events. See in particular figure 6.4, which explains that no further events are fired after a content change during a mouseover or mousemove event.


Nice answer. I used your fiddle to start to create my own solution. The touchend is needed sometimes however. (when a touchmove doesn't run -- ie when the user moves off the document itself...)
Great answer but in most cases I'd suggest using touchend instead of touchstart in most cases to avoid triggering actions immediately when the user is trying to swipe-scroll up or down a page. Will still happen but is less likely to distract or confuse (assuming it's something harmless like displaying a label, not something the user needs to know happened)
n
nnnnnn

How can I get the hover effects when I'm using the mouse, but suppress them when I'm using the touchscreen?

Maybe don't think of it so much as suppressing hover effects for touchscreens, but as adding hover effects for mouse events?

If you want to keep the :hover effects in your CSS you could specify different styles for different media:

@media screen { /* hover styles here */ } 

@media handheld { /* non-hover styles here */ }

Except that unfortunately there are plenty of mobile devices that ignore this and just use the screen rules. Fortunately a lot of newer mobile/tablet browsers do support some fancier media queries:

@media screen and (max-width:800px) { /* non-hover styles here */ }

So even if the "screen" or "handheld" part is ignored the "max-width" will do the trick for you. You could just assume that anything with a screen smaller than 800 pixels must be a tablet or phone, and not use hover effects. For the rare users who are using a mouse on a low resolution device they wouldn't see the hover effects but your site would be fine otherwise.

Further reading on media queries? There are plenty of articles about this online - here is one: http://www.alistapart.com/articles/return-of-the-mobile-stylesheet

If you shift the hover effects out of your CSS and apply them with JavaScript then you could bind specifically to mouse events, and/or again you could just make some assumptions just based on screen size with the worst-case "problem" being that some user who is using a mouse misses out on the hover effects.


I'd love to add hover effects for mouse events only. But touch events emulate mouse events. If I hook the touch events and call preventDefault(), that sometimes suppresses the mouse events, but as I said in my question, it's not reliable.
As for media queries, what happens when Windows 8 comes out and PCs have both touch screens and mice? If the user hovers with the mouse, they'll see the mouse cursor, and I want the hover effects; if they tap with the touchscreen, I don't want the hover effects. But I haven't found a reliable way to detect the difference between touch and mouse.
Well perhaps the browser developers will be more motivated to make detection more consistent once they have larger numbers of users on devices with touch and mouse. But for now? I'd be making guesses based on screen size, but there is other advice in the other answers. Sorry I can't help further.
W
Walter Roman

I wrote the following JS for a recent project, which was a desktop/mobile/tablet site that has hover effects that shouldn't appear on-touch.

The mobileNoHoverState module below has a variable preventMouseover (initially declared as false), that is set to true when a user fires the touchstart event on an element, $target.

preventMouseover is then being set back to false whenever the mouseover event is fired, which allows the site to work as intended if a user is using both their touchscreen and mouse.

We know that mouseover is being triggered after touchstart because of the order that they are being declared within init.

var mobileNoHoverState = function() {

    var hoverClass = 'hover',
        $target = $(".foo"), 
        preventMouseover = false;

    function forTouchstart() {
        preventMouseover = true;
    }

    function forMouseover() {
        if (preventMouseover === false) {
            $(this).addClass(hoverClass);
        } else {
            preventMouseover = false;
        }
    }

    function forMouseout() {
        $(this).removeClass(hoverClass);
    }

    function init() {
        $target.on({
            touchstart  : forTouchstart,
            mouseover   : forMouseover,
            mouseout    : forMouseout
        });                
    }

    return {
        init: init
    };
}();

The module is then instantiated further down the line:

mobileNoHoverState.init();

"preventMouseover is then being set back to true whenever the mouseover event is fired, which allows the site to work as intended if a user is using both their touchscreen and mouse." - Your code is not doing that. Am I missing something?
@Redtopia Thanks for the heads up! I've updated the answer with the bit of code that got left out.
You don't need semicolons after function declaration
@nacholibre Proper semi-colon usage has been put in place
f
flintinatux

I really wanted a pure css solution to this myself, since sprinkling a weighty javascript solution around all of my views seemed like an unpleasant option. Finally found the @media.hover query, which can detect "whether the primary input mechanism allows the user to hover over elements." This avoids touch devices where "hovering" is more of an emulated action than a direct capability of the input device.

So for example, if I have a link:

<a href="/" class="link">Home</a>

Then I can safely style it to only :hover when the device easily supports it with this css:

@media (hover: hover) {
  .link:hover { /* hover styles */ }
}

While most modern browsers support interaction media feature queries, some popular browsers such as IE and Firefox do not. In my case this works fine, since I only intended to support Chrome on desktop and Chrome and Safari on mobile.


Nice solution that seems to work when you emulate devices in Chrome devtools. But it still doesn't work for Chrome Android :-(
I think this is the most convenient and correct solution. Hope it will be added to W3C standards soon.
B
Bnaya

My solution is to add hover-active css class to the HTML tag, and use it on the beginning of all the CSS selectors with :hover and remove that class on the first touchstart event.

http://codepen.io/Bnaya/pen/EoJlb

JS:

(function () {
    'use strict';

    if (!('addEventListener' in window)) {
        return;
    }

    var htmlElement = document.querySelector('html');

    function touchStart () {
        document.querySelector('html').classList.remove('hover-active');

        htmlElement.removeEventListener('touchstart', touchStart);
    }

    htmlElement.addEventListener('touchstart', touchStart);
}());

HTML:

<html class="hover-active">

CSS:

.hover-active .mybutton:hover {
    box-shadow: 1px 1px 1px #000;
}

Instead of listening to a touch event, you can test for 'ontouchstart' in window. e.g. if ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
@YuvalA. The reason i'm waiting for the touch event it that there are devices with pointer and touch support, and of the user is using the pointer i don't want to remove the hover. Its possible that the user will use touch and then pointer but i don't have much to do about that
C
Community

What I've done to solve the same problem is to have a feature detection (I use something like this code), seeing if onTouchMove is defined, and if so I add the css class "touchMode" to the body, else i add "desktopMode".

Then every time some style effect only applies to a touch device, or only to a desktop the css rule is prepended with the appropriate class:

.desktopMode .someClass:hover{ color: red }
.touchMode .mainDiv { width: 100%; margin: 0; /*etc.*/ }

Edit: This strategy of course adds a few extra characters to your css, so If you're concerned about css size, you could search for the touchMode and desktopMode definitons and put them into different files, so you can serve optimized css for each device type; or you could change the class names to something much shorter before going to prod.


D
Daft

Right, I jst had a similar problem but managed to fix it with media queries and simple CSS. I'm sure I'm breaking some rules here, but it's working for me.

I basically had to take a massive application someone made, and make it responsive. They used jQueryUI and asked me not to tamper with any of their jQuery, so I was restricted to using CSS alone.

When I pressed one of their buttons in touchscreen mode, the hover effect woudld fire for a second before the button's action took effect. Here's how I fixed it.

@media only screen and (max-width:1024px) {

       #buttonOne{
            height: 44px;
        }


        #buttonOne:hover{
            display:none;
        }
}   

S
Stanislav Berkov

In my project we solved this issue using https://www.npmjs.com/package/postcss-hover-prefix and https://modernizr.com/ First we post-process output css files with postcss-hover-prefix. It adds .no-touch for all css hover rules.

const fs = require("fs");
const postcss = require("postcss");
const hoverPrfx = require("postcss-hover-prefix");

var css = fs.readFileSync(cssFileName, "utf8").toString();
postcss()
   .use(hoverPrfx("no-touch"))
   .process(css)
   .then((result) => {
      fs.writeFileSync(cssFileName, result);
   });

css

a.text-primary:hover {
  color: #62686d;
}

becomes

.no-touch a.text-primary:hover {
  color: #62686d;
}

At runtime Modernizr automatically adds css classes to html tag like this

<html class="wpfe-full-height js flexbox flexboxlegacy canvas canvastext webgl 
  no-touch 
  geolocation postmessage websqldatabase indexeddb hashchange
  history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage
  borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients
  cssreflections csstransforms csstransforms3d csstransitions fontface
  generatedcontent video audio localstorage sessionstorage webworkers
  applicationcache svg inlinesvg smil svgclippaths websocketsbinary">

Such post-processing of css plus Modernizr disables hover for touch devices and enables for others. In fact this approach was inspired by Bootstrap 4, how they solve the same issue: https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#sticky-hoverfocus-on-mobile


S
Said Kholov

You can trigger the mouseLeave event whenever you touch an element on touchscreen. Here is a solution for all <a> tags:

function removeHover() {
    var anchors = document.getElementsByTagName('a');
    for(i=0; i<anchors.length; i++) {
        anchors[i].addEventListener('touchstart', function(e){
            $('a').mouseleave();
        }, false);
    }
}

JSHint says "don't make functions within a loop".
It's a hack. It is NOT a reusable code that can be considered as good practice. @NetOperatorWibby
Well it's not really helpful to post code that can't be considered good practice. That's like putting a Band-Aid on a knife wound.
C
Community

Iv'd found 2 solutions to the problem, which its implied that you detect touch with modernizr or something else and set a touch class on the html element.

This is good but not supported very well:

html.touch *:hover {
    all:unset!important;
}

But this has a very good support:

html.touch *:hover {
    pointer-events: none !important;
}

Works flawless for me, it makes all the hover effects be like when you have a touch on a button it will light up but not end up buggy as the initial hover effect for mouse events.

Detecting touch from no-touch devices i think modernizr has done the best job:

https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js

EDIT

I found a better and simpler solution to this issue

How to determine if the client is a touch device


b
balach

It might help to see your CSS, as it sounds like a rather weird issue. But anyway, if it is happening and all else is good, you could try shifting the hover effect to javascript (you could use jquery as well). Simply, bind to the mouseover or better still mouseenter event and light up your element when the event fires.

Checkout the last example here: http://api.jquery.com/mouseover/, you could use something similar to log when the event fires and take it from there!


Nothing special about the CSS; see my edit. And I already tried mouseenter; no dice. Tapping moves the "invisible mouse cursor", so it triggers mouseenter and mousemove (and mouseleave when you tap somewhere else).
S
Stanz

If you are happy to use JavaScript then you can use Modernizr in your page. When the page loads, a non-touch screen browser will have the class '.no-touch' added to the html tag, but for a touch screen browser, the html tag will have the class '.touch' added to the html tag.

Then it is simply a case of checking to see if the html tag has the no-touch class before deciding to add your mouseenter and mouseleave listeners.

if($('html').hasClass('no-touch')){
    $('.box').on("mouseenter", function(event){
            $(this).css('background-color','#0000ff')
    });
    $('.box').on("mouseleave", function(event){
            $(this).css('background-color','')
    });
}

For a touchscreen device the events will have no listeners so you will get no hover effect when you tap.


When it can be done with css dont use javascript(jquery) its a waste of computer power
Simpler yet, in your CSS, you could define separate rules for .touch and .no-touch. To rewrite your answer in CSS together with Modernizer, html.no-touch .box:hover {background-color: "#0000ff"} and not defining anything for html.touch .box:hover should do the trick, since the OP is only trying to avoid mobile :hovers.
t
toon81

In a project I did recently, I solved this problem with jQuery's delegated events feature. It looks for certain elements using a jQuery selector, and adds/removes a CSS class to those elements when the mouse is over the element. It seems to work well as far as I've been able to test it, which includes IE10 on a touch-capable notebook running Windows 8.

$(document).ready(
    function()
    {
        // insert your own selector here: maybe '.hoverable'?
        var selector = 'button, .hotspot';

        $('body')
            .on('mouseover', selector, function(){ $(this).addClass('mouseover');    })
            .on('mouseout',  selector, function(){ $(this).removeClass('mouseover'); })
            .on('click',     selector, function(){ $(this).removeClass('mouseover'); });
    }
);

edit: this solution does, of course, require that you alter your CSS to remove the ":hover" selectors, and contemplate in advance on which elements you want to be "hoverable".

If you have very many elements on your page (like several thousand) it may get a bit slow, though, because this solution catches events of three types on all elements in the page, and then does its thing if the selector matches. I named the CSS class "mouseover" instead of "hover", because I didn't want any CSS readers to read ":hover" where I wrote ".hover".


A
Agamemnus

Here is my solution: http://jsfiddle.net/agamemnus/g56aw709/-- code below.

All one needs to do is to convert their ":hover" to ".hover"... that's it! The big difference between this and the rest is that this will also work on non-singular element selectors such as .my_class > *:hover {.

handle_css_hover_effects ()

function handle_css_hover_effects (init) {
 var init = init || {}
 var handle_touch_events = init.handle_touch_events || true
 var handle_mouse_events = init.handle_mouse_events || true
 var hover_class         = init.hover_class         || "hover"
 var delay_preferences   = init.delay_preferences   || {touch: {add: 500, remove: 500}}
 function default_handler (curobj, input_type, op) {
  var hovered_element_selector = "*" + ((op == "add") ? ":" : ("." + hover_class))
  var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll(hovered_element_selector))
  var modified_list = []
  while (true) {
   if ((curobj == null) || (curobj == document.documentElement)) break
   if (hovered_elements.indexOf(curobj) != -1) modified_list.push (curobj)
   curobj = curobj.parentNode
  }
  function do_hover_change () {modified_list.forEach (function (curobj) {curobj.classList[op](hover_class)})}
  if ((!delay_preferences[input_type]) || (!delay_preferences[input_type][op])) {
   do_hover_change ()
  } else {
   setTimeout (do_hover_change, delay_preferences[input_type][op])
  }
 }

 if (handle_mouse_events) {
  document.body.addEventListener ('mouseover' , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "add")})
  document.body.addEventListener ('mouseout'  , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
  document.body.addEventListener ('click'     , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
 }

 if (handle_touch_events) {
  document.body.addEventListener ('touchstart', function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "add")})
  document.body.addEventListener ('touchend'  , function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "remove")})
  document.body.addEventListener ('touchmove',  function (evt) {
   var curobj = evt.target
   var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll("*:hover"))
   var lastobj = null
   evt = evt.changedTouches[0]
   var elements_at_point = get_elements_at_point (evt.pageX, evt.pageY)
   // Get the last element that isn't at the current point but is still hovered over, and remove only its hover attribute.
   while (true) {
    if ((curobj == null) || (curobj == document.documentElement)) break
    if ((hovered_elements.indexOf(curobj) != -1) && (elements_at_point.indexOf(curobj) == -1)) lastobj = curobj
    curobj = curobj.parentNode
   }
   if (lastobj == null) return
   if ((!delay_preferences.touch) || (!delay_preferences.touch.remove)) {
    lastobj.classList.remove(hover_class)
   } else {
    setTimeout (function () {lastobj.classList.remove(hover_class)}, delay_preferences.touch.remove)
   }

   function get_elements_at_point (x, y) {
    var el_list = [], pe_list = []
    while (true) {
     var curobj = document.elementFromPoint(x, y)
     if ((curobj == null) || (curobj == document.documentElement)) break
     el_list.push (curobj); pe_list.push (curobj.style.pointerEvents)
     curobj.style.pointerEvents = "none"
    }
    el_list.forEach (function (current_element, i) {current_element.style.pointerEvents = pe_list[i]})
    return el_list
   }
  })
 }
}

J
Jonathan Potter

Include Modernizr on your page and set your hover states like this instead:

html.no-touchevents .box:hover {
    background: blue;
}

o
olanod

Hello person from the future, you probably want to use the pointer and/or hover media query. The handheld media query was deprecated.

/* device is using a mouse or similar */
@media (pointer: fine) {
  a:hover {
    background: red;
  }
}

S
Sasha Jovanovic

.services-list .fa { transition: 0.5s; -webkit-transform: rotate(0deg); transform: rotate(0deg); color: blue; } /* For me, @media query is the easiest way for disabling hover on mobile devices */ @media only screen and (min-width: 981px) { .services-list .fa:hover { color: #faa152; transition: 0.5s; -webkit-transform: rotate(360deg); transform: rotate(360deg); } } /* You can actiate hover on mobile with :active */ .services-list .fa:active { color: #faa152; transition: 0.5s; -webkit-transform: rotate(360deg); transform: rotate(360deg); } .services-list .fa-car { font-size:20px; margin-right:15px; } .services-list .fa-user { font-size:48px; margin-right:15px; } .services-list .fa-mobile { font-size:60px; } Hover effects on mobile browsers

For example: https://jsfiddle.net/lesac4/jg9f4c5r/8/


A
Avinav Chalise

You can use js. It should work as expected.

function myFunction(){ var x = document.getElementById("DIV"); x.style.backgroundColor="red"; x.style.cursor="pointer"; x.style.color="white" } function my2Function(){ var x = document.getElementById("DIV"); x.style.backgroundColor="white"; x.style.color="red" } .mydiv { background-color: white; color: red; }

hi


A
Akshay Pal

Here my issue has been fixed(mouseenter & touch related issue in React js) by using

onMouseEnter={() => addHeaderClassName()} onMouseLeave={() => removeHeaderClassName()} onFocus={() => addHeaderClassName()} onBlur={() => removeHeaderClassName()}

the above mentioned "onMouseEnter & onMouseLeave" works for large device like as desktop where mouse event can be detected, on the otherhand "onFocus & onBlur" works on small device like as tablet & mobile where touch can be detected.


j
j__carlson

Here my issue has been fixed(mouseenter & touch related issue in React js) by using

onMouseEnter={() => addHeaderClassName()} onMouseLeave={() => removeHeaderClassName()} onFocus={() => addHeaderClassName()} onBlur={() => removeHeaderClassName()}

the above mentioned "onMouseEnter & onMouseLeave" works for large device like as desktop where mouse event can be detected, on the otherhand "onFocus & onBlur" works on small device like as tablet & mobile where touch can be detected.


p
pissall

Try this easy 2019 jquery solution, although its been around a while;

add this plugin to head: src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js" add this to js: $("*").on("touchend", function(e) { $(this).focus(); }); //applies to all elements some suggested variations to this are: $(":input, :checkbox,").on("touchend", function(e) {(this).focus);}); //specify elements $("*").on("click, touchend", function(e) { $(this).focus(); }); //include click event` css: body { cursor: pointer; } //touch anywhere to end a focus`

Notes

place plugin before bootstrap.js, if applicable, to avoid affecting tooltips

only tested on iphone XR ios 12.1.12, and ipad 3 ios 9.3.5, using Safari or Chrome.

References:

https://code.jquery.com/ui/

https://api.jquery.com/category/selectors/jquery-selector-extensions/