nekrochan/static/js/hover.js
2024-03-03 15:12:35 +01:00

139 řádky
3.7 KiB
JavaScript

$.fn.isInViewport = function () {
let element_top = $(this).offset().top;
let element_bottom = element_top + $(this).outerHeight();
let viewport_top = $(window).scrollTop();
let viewport_bottom = viewport_top + $(window).height();
return element_bottom > viewport_top && element_top < viewport_bottom;
};
$(function () {
let cache = {};
let hovering = false;
let preview_w = 0;
let preview_h = 0;
$(window).on("setup_post_events", function (event) {
setup_events($(`#${event.id}`).find(".quote"));
});
setup_events($(".quote"));
function setup_events(elements) {
elements.on("mouseover", function (event) {
toggle_hover($(this), event);
});
elements.on("mouseout", function (event) {
toggle_hover($(this), event);
});
elements.on("click", function (event) {
toggle_hover($(this), event);
});
elements.on("mousemove", move_preview);
}
function toggle_hover(quote, event) {
hovering = event.type === "mouseover";
if ($("#preview").length !== 0 && !hovering) {
remove_preview();
return;
}
let path_segments = quote.prop("pathname").split("/");
let board = path_segments[2];
let thread = path_segments[3];
let id = quote.prop("hash").slice(1);
let post = $(`#${id}[data-board="${board}"]`);
if (post.length !== 0 && post.isInViewport()) {
post.toggleClass("highlighted", hovering);
return;
}
if (post.length !== 0 && hovering) {
create_preview(post.clone(), event.clientX, event.clientY);
return;
}
let html;
let cached_thread = cache[`${board}/${thread}`];
if (cached_thread) {
html = cached_thread[id];
post = $($.parseHTML(html));
create_preview(post, event.clientX, event.clientY);
return;
}
quote.css("cursor", "wait");
try {
$.get(`/thread-json/${board}/${thread}`, function (data) {
quote.css("cursor", "");
cache[`${board}/${thread}`] = data;
html = data[id];
post = $($.parseHTML(html));
create_preview(post, event.clientX, event.clientY);
});
} catch (e) {
quote.css("cursor", "");
console.error(e);
}
}
function move_preview(event) {
position_preview($("#preview"), event.clientX, event.clientY);
}
function create_preview(preview, x, y) {
if (!hovering) {
return;
}
preview.attr("id", "preview");
preview.addClass("box");
preview.removeClass("highlighted");
preview.css("position", "fixed");
let existing = $("#preview");
if (existing.length !== 0) {
existing.replaceWith(preview);
} else {
preview.appendTo("body");
}
preview_w = preview.outerWidth();
preview_h = preview.outerHeight();
position_preview(preview, x, y);
$(window).trigger({ type: "setup_post_events", id: "preview" });
}
function remove_preview() {
$("#preview").remove();
}
function position_preview(preview, x, y) {
let ww = $(window).width();
let wh = $(window).height();
preview.css("left", `${Math.min(x + 4, ww - preview_w)}px`);
if (preview_h + y < wh) {
preview.css("top", `${y + 4}px`);
preview.css("bottom", "");
} else {
preview.css("bottom", `${wh - y + 4}px`);
preview.css("top", "");
}
}
});