livebook/assets/js/events.js

158 lines
4.6 KiB
JavaScript
Raw Permalink Normal View History

import topbar from "topbar";
2023-12-01 03:45:33 +08:00
import scrollIntoView from "scroll-into-view-if-needed";
import { waitUntilVisible } from "./lib/utils";
export function registerTopbar() {
topbar.config({
barColors: { 0: "#b2c1ff" },
shadowColor: "rgba(0, 0, 0, .3)",
});
window.addEventListener("phx:page-loading-start", () => {
topbar.show(500);
});
window.addEventListener("phx:page-loading-stop", () => {
topbar.hide();
});
}
export function registerGlobalEventHandlers() {
window.addEventListener("lb:focus", (event) => {
// The element may be about to show up via JS.show, which wraps the
// change in requestAnimationFrame, so we do the same to make sure
// the focus is applied only after we change the element visibility
requestAnimationFrame(() => {
event.target.focus();
});
});
window.addEventListener("lb:set_value", (event) => {
event.target.value = event.detail.value;
});
window.addEventListener("lb:check", (event) => {
event.target.checked = true;
});
window.addEventListener("lb:uncheck", (event) => {
event.target.checked = false;
});
window.addEventListener("lb:set_text", (event) => {
event.target.textContent = event.detail.value;
});
window.addEventListener("lb:clipcopy", (event) => {
if ("clipboard" in navigator) {
if (event.detail.content) {
navigator.clipboard.writeText(event.detail.content);
} else if (event.target.tagName === "INPUT") {
navigator.clipboard.writeText(event.target.value);
} else {
2023-05-30 17:15:31 +08:00
navigator.clipboard.writeText(event.target.textContent);
}
} else {
alert(
"Sorry, your browser does not support clipboard copy.\nThis generally requires a secure origin — either HTTPS or localhost.",
);
}
});
2023-12-01 03:45:33 +08:00
window.addEventListener("lb:scroll_into_view", (event) => {
2024-07-15 12:19:04 +08:00
const options = event.detail || {};
2023-12-01 03:45:33 +08:00
// If the element is going to be shown, we want to wait for that
waitUntilVisible(event.target).then(() => {
scrollIntoView(event.target, {
scrollMode: "if-needed",
behavior: "smooth",
block: "nearest",
inline: "nearest",
2024-07-15 12:19:04 +08:00
...options,
2023-12-01 03:45:33 +08:00
});
});
});
2023-07-04 06:53:04 +08:00
window.addEventListener("phx:lb:exec_js", (event) => {
const selector = event.detail.to || "body";
document.querySelectorAll(selector).forEach((element) => {
window.liveSocket.execJS(element, event.detail.js);
});
});
window.addEventListener("lb:session_list:on_selection_change", () => {
const anySessionSelected = !!document.querySelector(
"[name='session_ids[]']:checked",
);
const disconnect = document.querySelector(
"#edit-sessions [name='disconnect']",
);
const closeAll = document.querySelector(
"#edit-sessions [name='close_all']",
);
2023-07-04 06:53:04 +08:00
disconnect.parentElement.classList.toggle(
"pointer-events-none",
!anySessionSelected,
2023-07-04 06:53:04 +08:00
);
disconnect.parentElement.classList.toggle(
"opacity-50",
!anySessionSelected,
2023-07-04 06:53:04 +08:00
);
closeAll.parentElement.classList.toggle(
"pointer-events-none",
!anySessionSelected,
2023-07-04 06:53:04 +08:00
);
closeAll.parentElement.classList.toggle("opacity-50", !anySessionSelected);
});
window.addEventListener("contextmenu", (event) => {
const target = event.target.closest("[data-contextmenu-trigger-click]");
if (target) {
event.preventDefault();
// LV dispatches phx-click to the target of the preceding mousedown event
target.dispatchEvent(new Event("mousedown", { bubbles: true }));
target.dispatchEvent(new Event("click", { bubbles: true }));
}
});
2023-03-18 00:12:03 +08:00
// Ignore submit events on elements with phx-nosubmit
window.addEventListener(
"submit",
(event) => {
if (event.target.hasAttribute("phx-nosubmit")) {
event.preventDefault();
event.stopPropagation();
}
},
{ capture: true },
2023-03-18 00:12:03 +08:00
);
}
/**
* Disables the auto-zoom behavior when focusing an input on a touch device.
*
* It is important that this should not prevent users from manually
* zooming if they wish. There isn't a portable solution to this
* problem, so this hook is a no-op if the detected device is not
* known to behave well.
*
* See: https://stackoverflow.com/questions/2989263/disable-auto-zoom-in-input-text-tag-safari-on-iphone
*/
export function disableZoomOnInputFocus() {
const isWebKit = /AppleWebKit/.test(navigator.userAgent);
const isTouchScreen =
"ontouchstart" in window || navigator.maxTouchPoints > 0;
if (isWebKit && isTouchScreen) {
const viewportTag = document.querySelector("meta[name='viewport']");
if (viewportTag) {
viewportTag.content += ", maximum-scale=1.0";
}
}
}