Welcome to mirror list, hosted at ThFree Co, Russian Federation.

mq4-hover-shim.js « browser « src - github.com/twbs/mq4-hover-shim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 91c5525ff58603c7d2c855030f5d06b3f54f9b68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*eslint-env browser */
/*eslint no-var:2*/
/* jshint browser: true, esnext: true */
/* jshint -W080 */
/**
* @module mq4HoverShim
* @requires jquery
*/
let $ = (function () {
    try {
        import * as jQuery from 'jquery';
        return jQuery;
    }
    catch (importErr) {
        const globaljQuery = window.$ || window.jQuery || window.Zepto;
        if (!globaljQuery) {
            throw new Error('mq4HoverShim needs jQuery (or similar)');
        }
        return globaljQuery;
    }
})();

/** @type {boolean|undefined} */
let canTrulyHover = undefined;

/**
* @private
* @fires mq4HoverShim#mq4hsChange
*/
function triggerEvent() {
    $(document).trigger($.Event('mq4hsChange', {bubbles: false, trueHover: canTrulyHover}));
}

// IIFE so we can use `return`s to avoid deeply-nested if-s
(function () {
    if (!window.matchMedia) {
        // Opera Mini, IE<=9, Android<=2.3, ancient, or obscure; per http://caniuse.com/#feat=matchmedia

        // Opera Mini, Android, and IE Mobile don't support true hovering, so they're what we'll check for.
        // Other browsers are either:
        // (a) obscure
        // (b) touch-based but old enough not to attempt to emulate hovering
        // (c) old desktop browsers that do support true hovering

        // Explanation of this UA regex:
        // IE Mobile <9 seems to always have "Windows CE", "Windows Phone", or "IEMobile" in its UA string.
        // IE Mobile 9 in desktop view doesn't include "IEMobile" or "Windows Phone" in the UA string,
        // but it instead includes "XBLWP7" and/or "ZuneWP7".
        canTrulyHover = !/Opera Mini|Android|IEMobile|Windows (Phone|CE)|(XBL|Zune)WP7/.test(navigator.userAgent);

        // Since there won't be any event handlers to fire our events, do the one-and-only firing of it here and now.
        triggerEvent();
        return;
    }

    // CSSWG Media Queries Level 4 draft
    //     http://drafts.csswg.org/mediaqueries/#hover
    const HOVER_NONE = '(hover: none),(-moz-hover: none),(-ms-hover: none),(-webkit-hover: none)';
    const HOVER_ON_DEMAND = '(hover: on-demand),(-moz-hover: on-demand),(-ms-hover: on-demand),(-webkit-hover: on-demand)';
    const HOVER_HOVER = '(hover: hover),(-moz-hover: hover),(-ms-hover: hover),(-webkit-hover: hover)';
    if (window.matchMedia(`${HOVER_NONE},${HOVER_ON_DEMAND},${HOVER_HOVER}`).matches) {
        // Browser understands the `hover` media feature
        const hoverCallback = function (mql) {
            const doesMatch = mql.matches;
            if (doesMatch !== canTrulyHover) {
                canTrulyHover = doesMatch;
                triggerEvent();
            }
        };
        const atHoverQuery = window.matchMedia(HOVER_HOVER);
        atHoverQuery.addListener(hoverCallback);
        hoverCallback(atHoverQuery);
        return;
    }

    // Check for touch support instead.
    // Touch generally implies that hovering is merely emulated,
    // which doesn't count as true hovering support for our purposes
    // due to the quirkiness of the emulation (e.g. :hover being sticky).

    // W3C Pointer Events PR, 16 December 2014
    //     http://www.w3.org/TR/2014/PR-pointerevents-20141216/
    // Prefixed in IE10, per http://caniuse.com/#feat=pointer
    if (window.PointerEvent || window.MSPointerEvent) {
        // Browser supports Pointer Events

        // Browser supports touch if it has touch points
        /* jshint -W018 */
        canTrulyHover = !((window.navigator.maxTouchPoints || window.navigator.msMaxTouchPoints) > 0);
        /* jshint +W018 */
        triggerEvent();
        return;
    }

    // Mozilla's -moz-touch-enabled
    //     https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries#-moz-touch-enabled
    const touchEnabledQuery = window.matchMedia('(touch-enabled),(-moz-touch-enabled),(-ms-touch-enabled),(-webkit-touch-enabled)');
    if (touchEnabledQuery.matches) {
        canTrulyHover = false;
        triggerEvent();
        return;
    }

    // W3C Touch Events REC, 10 October 2013
    //     http://www.w3.org/TR/2013/REC-touch-events-20131010/
    if ('ontouchstart' in window) {
        canTrulyHover = false;
        triggerEvent();
        return;
    }

    // UA's pointer is non-touch and thus likely either supports true hovering or at least does not try to emulate it.
    canTrulyHover = true;
    triggerEvent();
})();


/**
* Does this UA's primary pointer support true hovering
* OR does the UA at least not try to quirkily emulate hovering,
* such that :hover CSS styles are appropriate?
* Essentially tries to shim the `@media (hover: hover)` CSS media query feature.
* @public
* @returns {boolean}
* @since 0.0.1
*/
export function supportsTrueHover() {
    return canTrulyHover;
}