Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Do not specify supported browsers and their versions in code comments or prose,

- The "insert-adjacent" directory contains basic demos for [insertAdjacentElement](https://mdn.github.io/dom-examples/insert-adjacent/insertAdjacentElement.html) and [insertAdjacentText](https://mdn.github.io/dom-examples/insert-adjacent/insertAdjacentText.html).

- The "interest-invokers" directory is for [interest invoker](https://developer.mozilla.org/docs/Web/API/Popover_API/Interest_invokers) examples. Go to the [Interest invoker examples index](https://mdn.github.io/dom-examples/interest-invokers/) to see what's available.

- The "launch-handler" directory contains a demo for the [Launch Handler API](https://developer.mozilla.org/en-US/docs/Web/API/Launch_Handler_API). [View the demo live](https://mdn.github.io/dom-examples/launch-handler/). This example was originally published on Glitch by [Thomas Steiner](https://front-end.social/@tomayac@toot.cafe).

- The "local-font-access" directory contains a demo for the [Local Font Access API](https://developer.mozilla.org/en-US/docs/Web/API/Local_Font_Access_API). [View the demo live](https://mdn.github.io/dom-examples/local-font-access/).
Expand Down Expand Up @@ -123,7 +125,6 @@ Do not specify supported browsers and their versions in code comments or prose,
- Another example of view transitions in a [simple multiple-page app](https://mdn.github.io/dom-examples/view-transitions/mpa-homepage/)
- [The `match-element` value](https://mdn.github.io/dom-examples/view-transitions/match-element/) for the `view-transition-name` property


- The "web-share" directory contains a basic demo to show usage of the [Web Share API](https://developer.mozilla.org/docs/Web/API/Navigator/share). [View the demo live](https://mdn.github.io/dom-examples/web-share/).

- The "web-workers" directory contains several demos that show how [Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) operate. For example, view the live [simple web worker demo](https://mdn.github.io/dom-examples/web-workers/simple-web-worker/).
Expand Down
41 changes: 41 additions & 0 deletions interest-invokers/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Interest invoker examples</title>
</head>
<body>
<h1>MDN interest invoker examples</h1>

<p>
This set of examples demonstrates usage of
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/Popover_API/Interest_invokers"
>Interest invokers</a
>.
</p>

<ul>
<li>
<a href="popover-examples/">Popover examples</a>: Demonstrates a couple
of examples of displaying popovers via interest invokers, including a
typical link preview popover.
</li>
<li>
<a href="style-preview/">Style preview</a>: Demonstrates non-popover
usage of interest invokers. In this example, several buttons can be
pressed to apply different style themes to a style preview pane.
Interest invokers have been used to progressively enhance the demo,
making it so that hovering/focusing the buttons previews the styles on
the pane without having to click to apply each one.
</li>
<li>
<a href="stock-moving/">Stock tracking example</a>: A more complex
example that shows a greengrocer's stock represented by buttons in
different columns. You can hover/focus a stock button to start
incrementing a number of items to move, and then click the butotn to
move them over to the other column.
</li>
</ul>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions interest-invokers/popover-examples/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>interestfor example</title>

<link href="styles.css" rel="stylesheet" />
<script defer src="index.js"></script>
</head>
<body>
<p>
I think
<a href="https://github.com/chrisdavidmills/" interestfor="user-info"
>@chrisdavidmills</a
>
should know about this.
</p>

<div id="user-info" popover="hint">
<div class="wrapper">
<img src="chris-mills.jpg" alt="chris mills" />
<section>
<p><strong>Chris Mills</strong></p>
<p>
Independent tech writer and web technology tinkerer, working on MDN
on behalf of Google and Mozilla. A11y and open standards advocate.
Heavy metal drummer.
</p>
<p>🌍 Greenfield, UK</p>
</section>
</div>
</div>

<p><button interestfor="button-tooltip">Press me</button></p>

<div id="button-tooltip" popover="auto">
<p>This button does absolutely nothing.</p>
</div>
</body>
</html>
35 changes: 35 additions & 0 deletions interest-invokers/popover-examples/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const interestLink = document.querySelector("[interestfor='user-info']");
const interestButton = document.querySelector("[interestfor='button-tooltip']");
const userInfo = document.getElementById("user-info");
const buttonTooltip = document.getElementById("button-tooltip");

// Feature detection

const supported =
HTMLButtonElement.prototype.hasOwnProperty("interestForElement");
if (!supported) {
document.querySelector("html").classList.add("no-interest-invokers");
}

// interestForElement example

console.log(interestLink.interestForElement);
console.log(interestButton.interestForElement);

// Event examples

userInfo.addEventListener("interest", reportInterest);
buttonTooltip.addEventListener("interest", reportInterest);
userInfo.addEventListener("loseinterest", reportInterest);
buttonTooltip.addEventListener("loseinterest", reportInterest);

function reportInterest(e) {
let action;
if (e.type === "interest") {
action = "Interest gained";
} else {
action = "Interest lost";
}

console.log(`${action} on ${e.source.tagName}`);
}
96 changes: 96 additions & 0 deletions interest-invokers/popover-examples/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
html {
font-family: sans-serif;
}

* {
box-sizing: border-box;
}

/* Browser support banner */

.no-interest-invokers body::before {
content: "Your browser doesn't support interest invokers.";
background-color: wheat;
display: block;
padding: 10px 0;
width: 100%;
text-align: center;
}

/* Link interestfor styles */

a[interestfor] {
interest-delay: 1s 2s;
}

/* Shared styles across popovers */

#user-info,
#button-tooltip {
border: 1px solid lightgray;
border-radius: 5px;
padding: 0 10px;
margin: 5px;
background-color: white;
font-size: 0.8rem;
}

#user-info {
position-area: bottom right;
}

#user-info .wrapper {
display: flex;
align-items: center;
gap: 20px;
width: 480px;
font-size: 0.8rem;
}

#user-info img {
margin: 10px 0;
border: 1px solid lightgray;
border-radius: 5px;
}

/* button interestfor styles */

button[interestfor="button-tooltip"] {
border: 1px solid transparent;
padding: 5px 10px;
border-radius: 5px;
color: white;
background-color: rgb(200 0 0);
}

/* Applies styles to the interest invoker, but only when the user is showing interest */
button:interest-source {
background-color: rgb(255 0 0);
}

button[interestfor="button-tooltip"]:active {
color: rgb(255 0 0);
border: 1px solid rgb(255 0 0);
background-color: white;
}

#button-tooltip {
position-area: right;
}

/* animation for interest targets */

[popover]:interest-target {
opacity: 1;
}

[popover] {
opacity: 0;
transition: all 0.7s allow-discrete;
}

@starting-style {
[popover]:interest-target {
opacity: 0;
}
}
60 changes: 60 additions & 0 deletions interest-invokers/stock-moving/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>interestfor stock moving example</title>

<link href="styles.css" rel="stylesheet" />
<script defer src="index.js"></script>
</head>
<body>
<h1>interestfor stock moving example</h1>
<div class="wrapper">
<p id="button-tooltip" popover="auto"></p>
<section>
<h2>Stock to keep</h2>
<div class="keep">
<button
data-stock="9"
data-product="🥕 Carrots"
interestfor="button-tooltip"
>
🥕 Carrots (9)
</button>
<button
data-stock="50"
data-product="🫛 Peas"
interestfor="button-tooltip"
>
🫛 Peas (50)
</button>
<button
data-stock="20"
data-product="🥔 Potatoes"
interestfor="button-tooltip"
>
🥔 Potatoes (20)
</button>
<button
data-stock="12"
data-product="🌶️ Peppers"
interestfor="button-tooltip"
>
🌶️ Peppers (12)
</button>
<button
data-stock="15"
data-product="🍅 Tomatoes"
interestfor="button-tooltip"
>
🍅 Tomatoes (15)
</button>
</div>
</section>
<section>
<h2>Stock to sell</h2>
<div class="sell"></div>
</section>
</div>
</body>
</html>
102 changes: 102 additions & 0 deletions interest-invokers/stock-moving/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Feature detection

const supported =
HTMLButtonElement.prototype.hasOwnProperty("interestForElement");
if (!supported) {
document.querySelector("html").classList.add("no-interest-invokers");
}

// Variable and handler definition

const interestBtns = document.querySelectorAll("button");
const btnTooltip = document.getElementById("button-tooltip");
const keepList = document.querySelector(".keep");
const sellList = document.querySelector(".sell");

let interval;
let stockToMove = 0;

btnTooltip.addEventListener("interest", incrementStock);
btnTooltip.addEventListener("loseinterest", resetStock);
interestBtns.forEach((btn) => btn.addEventListener("click", moveStock));

// Increment the amount of stock to move when interest is shown
function incrementStock(e) {
const sourceElem = e.source;
stockToMove = 0;

function updateStockCount() {
// Only increment stockToMove if it is smaler than the entire available stock
let stock = Number(sourceElem.getAttribute("data-stock"));
if (stockToMove < stock) {
stockToMove++;
btnTooltip.textContent = `Stock to move: ${stockToMove}`;
}
}

// Immediately increment stock to move, and then do it repeated every 250ms
updateStockCount();
interval = setInterval(updateStockCount, 250);
}

// Reset the amount of stock to move when interest is lost
function resetStock(e) {
// Clear the interval and the tooltip's text content, ready for next time
clearInterval(interval);
btnTooltip.textContent = "";
}

// Move the stock when the button is actually clicked
function moveStock(e) {
// Determine which list we are moving the stock item to
let targetList;
if (e.target.parentNode === keepList) {
targetList = sellList;
} else {
targetList = keepList;
}

// number of items and product to move
const newStock = stockToMove;
const newProduct = e.target.getAttribute("data-product");

// Determine whether a stack of that item already
// exists at the place to move the item to
const targetProductsList = Array.from(targetList.children);
const existingNewProduct = targetProductsList.find(
(element) => element.getAttribute("data-product") === newProduct
);

// If so, just add the items to the existing stack
if (existingNewProduct) {
const totalStock =
Number(existingNewProduct.getAttribute("data-stock")) + newStock;
existingNewProduct.setAttribute("data-stock", totalStock);
existingNewProduct.textContent = `${newProduct} (${totalStock})`;
} else {
// If not, create a new stack and append it to the list
const newBtn = document.createElement("button");
newBtn.setAttribute("interestFor", "button-tooltip");
newBtn.setAttribute("data-stock", newStock);
newBtn.setAttribute("data-product", newProduct);
newBtn.textContent = `${newProduct} (${newStock})`;
newBtn.addEventListener("click", moveStock);
targetList.appendChild(newBtn);
}

// Update the stack the stock was moved FROM to show the remaining items
const oldStock = Number(e.target.getAttribute("data-stock")) - stockToMove;
e.target.setAttribute("data-stock", oldStock);
e.target.textContent = `${newProduct} (${oldStock})`;

// Unfocus the button interest was being shown in. If you don't do this, you get weird behavior
// when it was focused via the keyboard — the interestfor target element starts incrementing again
// immediately, and if the stack goes to 0 and disappears (see next block), the focus shifts to the
// body and you get the interestfor target appearing at the top of the viewport!
e.target.blur();

// If the stack the stock was moved from has no remaining items, remove it from the DOM
if (e.target.getAttribute("data-stock") === "0") {
e.target.remove();
}
}
Loading