interestfor 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -6
- package/package.json +1 -1
- package/src/interestfor.js +18 -18
- package/src/interestfor.min.js +1 -1
- package/test/basic_test.html +5 -1
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# `interestfor` Polyfill
|
|
2
2
|
|
|
3
|
-
A polyfill for the `interestfor` attribute. This is
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
A polyfill for the `interestfor` attribute. This is a new API for "interest
|
|
4
|
+
interactions" that is in the process of being implemented in browsers. It will
|
|
5
|
+
[likely ship soon in
|
|
6
|
+
Chrome](https://groups.google.com/a/chromium.org/g/blink-dev/c/bX1G_yDt6W4?e=48417069).
|
|
7
|
+
See the explainer for all of the details for the "real" feature:
|
|
6
8
|
|
|
7
9
|
https://open-ui.org/components/interest-invokers.explainer/
|
|
8
10
|
|
|
@@ -83,9 +85,7 @@ native feature:
|
|
|
83
85
|
--interest-delay: 400ms 200ms;
|
|
84
86
|
}
|
|
85
87
|
/* The keyword `normal` can also be used to specify the default delay: */
|
|
86
|
-
[interestfor]
|
|
87
|
-
interest-delay-start: 0s;
|
|
88
|
-
--interest-delay-start: 0s;
|
|
88
|
+
[interestfor] {
|
|
89
89
|
interest-delay-end: normal;
|
|
90
90
|
--interest-delay-end: normal;
|
|
91
91
|
}
|
|
@@ -119,6 +119,11 @@ polyfill (optionally minified) or the native feature. You can run tests directly
|
|
|
119
119
|
from this repo,
|
|
120
120
|
[here](https://mfreed7.github.io/interestfor/test/test.html).
|
|
121
121
|
|
|
122
|
+
## Browser Compatibility
|
|
123
|
+
|
|
124
|
+
This polyfill uses all standard APIs, and is therefore compatible with all
|
|
125
|
+
modern browsers, including Safari and Firefox.
|
|
126
|
+
|
|
122
127
|
## Improvements / Bugs
|
|
123
128
|
|
|
124
129
|
If you find issues with the polyfill, feel free to file them [here](https://github.com/mfreed7/interestfor/issues).
|
package/package.json
CHANGED
package/src/interestfor.js
CHANGED
|
@@ -227,12 +227,15 @@
|
|
|
227
227
|
if (!isPlainHint(target)) {
|
|
228
228
|
invoker.setAttribute("aria-expanded", "true");
|
|
229
229
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
230
|
+
if (getComputedStyle(invoker).anchorName === 'none' &&
|
|
231
|
+
getComputedStyle(target).positionAnchor === 'auto') {
|
|
232
|
+
const anchorName = `--interest-anchor-${Math.random()
|
|
233
|
+
.toString(36)
|
|
234
|
+
.substring(2)}`;
|
|
235
|
+
invoker.style.anchorName = anchorName;
|
|
236
|
+
target.style.positionAnchor = anchorName;
|
|
237
|
+
data.anchorName = anchorName;
|
|
238
|
+
}
|
|
236
239
|
break;
|
|
237
240
|
default:
|
|
238
241
|
throw new Error("Invalid state");
|
|
@@ -396,18 +399,15 @@
|
|
|
396
399
|
|
|
397
400
|
// Attach listeners
|
|
398
401
|
function addEventHandlers() {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
);
|
|
405
|
-
document.body.addEventListener("
|
|
406
|
-
|
|
407
|
-
);
|
|
408
|
-
document.body.addEventListener("focusout", (e) =>
|
|
409
|
-
HandleInterestHoverOrFocus(e.target, Source.Blur)
|
|
410
|
-
);
|
|
402
|
+
const handler = (e, source) => {
|
|
403
|
+
for (let el = e.target; el; el = el.parentElement) {
|
|
404
|
+
HandleInterestHoverOrFocus(el, source);
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
document.body.addEventListener("mouseover", (e) => handler(e, Source.Hover));
|
|
408
|
+
document.body.addEventListener("mouseout", (e) => handler(e, Source.DeHover));
|
|
409
|
+
document.body.addEventListener("focusin", (e) => handler(e, Source.Focus));
|
|
410
|
+
document.body.addEventListener("focusout", (e) => handler(e, Source.Blur));
|
|
411
411
|
document.body.addEventListener("keydown", (e) => {
|
|
412
412
|
if (e.key === "Escape") {
|
|
413
413
|
invokersWithInterest.forEach((invoker) => {
|
package/src/interestfor.min.js
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
// LICENSE file in the root directory of this source tree.
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
!function(){const e="interest",t="loseinterest",n="--interest-delay-start",r="--interest-delay-end",o="--interest-delay",i="__interestForData",s="__interestForTargetData",a=new Set;let l=!1;if(window.interestForPolyfillInstalled)return;window.interestForPolyfillInstalled=!0;const c=HTMLButtonElement.prototype.hasOwnProperty("interestForElement");if(c&&!window.interestForUsePolyfillAlways)return;if(c){const n=e=>{e.isTrusted&&(e.preventDefault(),e.stopImmediatePropagation())};document.body.addEventListener(e,n,{capture:!0}),document.body.addEventListener(t,n,{capture:!0})}const d="none",u="full",m="hover",f="dehover",h="focus",g="blur";function y(t,n,r){if(!t||!n)return!1;if(!t.isConnected||b(t)!==n||r===d&&v(n)!==t)return!1;if(r!==d){const o=v(n);if(o){if(o===t)return o[i].clearLostTask(),!1;if(!y(o,n,d))return!1;if(!t.isConnected||b(t)!==n)return!1}return function(t,n){const r=t[i],o=b(t);if(n!==u)throw new Error("Invalid state");{if(r.state!==d)throw new Error("Invalid state");o.dispatchEvent(new Event(e));try{o.showPopover({source:t})}catch{}r.state=u,o[s]||(o[s]={}),o[s].invoker=t,o.hasAttribute("popover")&&(o[s].toggleListener=T,o.addEventListener("toggle",T)),a.add(t),t.classList.add("interest-source"),o.classList.add("interest-target"),P(o)||t.setAttribute("aria-expanded","true");const n=`--interest-anchor-${Math.random().toString(36).substring(2)}`;t.style.anchorName=n,o.style.positionAnchor=n,r.anchorName=n}return!0}(t,r)}return
|
|
8
|
+
!function(){const e="interest",t="loseinterest",n="--interest-delay-start",r="--interest-delay-end",o="--interest-delay",i="__interestForData",s="__interestForTargetData",a=new Set;let l=!1;if(window.interestForPolyfillInstalled)return;window.interestForPolyfillInstalled=!0;const c=HTMLButtonElement.prototype.hasOwnProperty("interestForElement");if(c&&!window.interestForUsePolyfillAlways)return;if(c){const n=e=>{e.isTrusted&&(e.preventDefault(),e.stopImmediatePropagation())};document.body.addEventListener(e,n,{capture:!0}),document.body.addEventListener(t,n,{capture:!0})}const d="none",u="full",m="hover",f="dehover",h="focus",g="blur";function y(t,n,r){if(!t||!n)return!1;if(!t.isConnected||b(t)!==n||r===d&&v(n)!==t)return!1;if(r!==d){const o=v(n);if(o){if(o===t)return o[i].clearLostTask(),!1;if(!y(o,n,d))return!1;if(!t.isConnected||b(t)!==n)return!1}return function(t,n){const r=t[i],o=b(t);if(n!==u)throw new Error("Invalid state");{if(r.state!==d)throw new Error("Invalid state");o.dispatchEvent(new Event(e));try{o.showPopover({source:t})}catch{}r.state=u,o[s]||(o[s]={}),o[s].invoker=t,o.hasAttribute("popover")&&(o[s].toggleListener=T,o.addEventListener("toggle",T)),a.add(t),t.classList.add("interest-source"),o.classList.add("interest-target"),P(o)||t.setAttribute("aria-expanded","true");const n=`--interest-anchor-${Math.random().toString(36).substring(2)}`;t.style.anchorName=n,o.style.positionAnchor=n,r.anchorName=n}return!0}(t,r)}return w(t),!0}function p(e){const t=1e3*E(e,r);!isFinite(t)||t<0||(e[i].clearLostTask(),e[i].lostTimer=setTimeout(()=>{y(e,b(e),d)},t))}function v(e){const t=e[s]?.invoker||null;return t&&t[i]?.state!==d?t:null}function b(e){const t=e.getAttribute("interestfor");return document.getElementById(t)}function T(e){const t=e.target;if("closed"===e.newState){const e=t[s]?.invoker;e&&y(e,t,d)}}function L(e){const t=String(e).trim(),n=t.match(/^([\d.]+)s$/);if(n)return parseFloat(n[1]);const r=t.match(/^([\d.]+)ms$/);return r?parseFloat(r[1])/1e3:parseFloat(t)||0}function E(e,t){const r=getComputedStyle(e),i=r.getPropertyValue(t).trim();if("normal"!==i.toLowerCase())return L(i);const s=r.getPropertyValue(o).trim();if(s&&"normal"!==s.toLowerCase()){const e=s.split(/\s+/).filter(e=>e.length>0);if(e.length>0){const r=e[0],o=e.length>1?e[1]:r;let i;if(i=t===n?r:o,"normal"!==i.toLowerCase())return L(i)}}return t===n?.5:.25}function w(e){const n=e[i];if(clearTimeout(n.gainedTimer),clearTimeout(n.lostTimer),n.state!==d){const r=b(e);r.dispatchEvent(new Event(t));try{r.hidePopover()}catch{}r[s]?.toggleListener&&r.removeEventListener("toggle",r[s].toggleListener),r[s]=null,a.delete(e),e.classList.remove("interest-source"),r.classList.remove("interest-target"),P(r)||e.setAttribute("aria-expanded","false"),n.anchorName&&(e.style.anchorName="",r.style.positionAnchor="",n.anchorName=null),n.state=d}}const k=["a[href]","area[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])","button:not([disabled])","iframe","object","embed","[contenteditable]",'[tabindex]:not([tabindex="-1"])'].join(",");function P(e){if("hint"!==e.getAttribute("popover")?.toLowerCase())return!1;if(e.querySelector(k))return!1;if(e.querySelector("h1,h2,h3,h4,h5,h6,ul,ol,li,table,nav,header,footer,main,aside,article,section,form,blockquote,details,summary,dialog"))return!1;const t=e.querySelectorAll("[role]");for(const e of t){const t=e.getAttribute("role").toLowerCase();if(!["presentation","none","generic","image"].includes(t))return!1}return!0}function A(e){if(e[i])return;e[i]={state:d,gainedTimer:null,lostTimer:null,longPressTimer:null,clearGainedTask(){clearTimeout(this.gainedTimer)},clearLostTask(){clearTimeout(this.lostTimer)}};const t=b(e);t&&function(e,t){P(t)?e.setAttribute("aria-describedby",t.id):(e.setAttribute("aria-details",t.id),e.setAttribute("aria-expanded","false"),t.hasAttribute("role")||t.setAttribute("role","tooltip"))}(e,t)}function C(e,t){if(l)return;if(!e.isConnected)return;if(!b(e)){const n=e.closest(".interest-target");if(n){const r=v(n);r&&(t===m||t===h?r[i].clearLostTask():t!==g&&e.matches(":hover")||p(r))}return}A(e);const r=e[i],o=v(e);t===m||t===h?(r.clearLostTask&&r.clearLostTask(),o&&o[i].clearLostTask(),function(e,t){const r=1e3*E(e,n);!isFinite(r)||r<0||(e[i].clearGainedTask(),e[i].gainedTimer=setTimeout(()=>{y(e,b(e),t)},r))}(e,u)):(r.clearGainedTask&&r.clearGainedTask(),r.state!==d&&p(e),o&&(o[i].clearGainedTask(),t!==g&&e.matches(":hover")||p(o)))}function F(){!function(){const e=document.createElement("style");e.textContent=`@property ${n} {syntax: "normal | <time>"; inherits: false; initial-value: normal;}\n @property ${r} {syntax: "normal | <time>"; inherits: false; initial-value: normal;}\n @property ${o} {syntax: "[ normal | <time> ]{1,2}"; inherits: false; initial-value: normal;}`,document.head.appendChild(e),document[i]={globalPropsStyle:e}}(),function(){const e=(e,t)=>{for(let n=e.target;n;n=n.parentElement)C(n,t)};document.body.addEventListener("mouseover",t=>e(t,m)),document.body.addEventListener("mouseout",t=>e(t,f)),document.body.addEventListener("focusin",t=>e(t,h)),document.body.addEventListener("focusout",t=>e(t,g)),document.body.addEventListener("keydown",e=>{"Escape"===e.key&&a.forEach(e=>{w(e)})}),document.body.addEventListener("touchstart",e=>{l=!0;const t=e.target.closest("button[interestfor]");t&&(A(t),t[i].longPressTimer=setTimeout(()=>{y(t,b(t),u),t[i].longPressTimer=null},500))});const t=e=>{const t=e.target.closest("button[interestfor]");t&&t[i]?.longPressTimer&&(clearTimeout(t[i].longPressTimer),t[i].longPressTimer=null)};document.body.addEventListener("touchend",e=>{t(e),l=!1}),document.body.addEventListener("touchmove",t)}(),console.log(`interestfor polyfill installed (native: ${c}).`)}"complete"===document.readyState?F():window.addEventListener("load",F)}();
|
package/test/basic_test.html
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
<script src="../src/interestfor.js" async></script>
|
|
4
4
|
|
|
5
5
|
<a interestfor=foo href=bar>Link - hover me, don't click me</a>
|
|
6
|
-
<button interestfor=foo>
|
|
6
|
+
<button interestfor=foo>
|
|
7
|
+
<span style="margin:10px;">Button - hover me, don't click me</span></a>
|
|
7
8
|
<div popover id=foo>Popover</div>
|
|
8
9
|
|
|
9
10
|
<style>
|
|
@@ -19,4 +20,7 @@
|
|
|
19
20
|
[popover].interest-target {
|
|
20
21
|
background-color: lightblue;
|
|
21
22
|
}
|
|
23
|
+
[popover] {
|
|
24
|
+
position-area: right center;
|
|
25
|
+
}
|
|
22
26
|
</style>
|