Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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