add button that updates the calendar with another source. tooltip format change, multiple color

commit frequently pls
This commit is contained in:
lda committed 2025-05-22 04:47:57 +07:00
1 parent 6800a75825
commit 3330ff1205
4 files changed
+68 -10

No files matched your search

+6 -2
View File
@@ -9,8 +9,12 @@
</head>
<body>
<input type="text" id="ics_file">
<input type="button" value="hi" id="ics_run">
<div class="flex_input">
<input type="text" id="ics_file">
<input type="button" value="new calendar" id="ics_run">
<input type="button" value="add a calendar" id="ics_add">
</div>
<div id="calendar"></div>
</body>
+9
View File
@@ -0,0 +1,9 @@
let sourceCount = 0;
/** how ass would this shit be? */
export function getNextColor() {
// Spread hues evenly around the color wheel
const hue = (sourceCount * 137) % 360; // 137 is the golden angle
sourceCount++;
return `hsl(${hue}, 70%, 50%)`;
}
+28 -8
View File
@@ -10,24 +10,30 @@ import bootstrap5Plugin from "@fullcalendar/bootstrap5";
import tippy, { followCursor } from "tippy.js";
import "tippy.js/dist/tippy.css";
import { getNextColor } from "./color_generator";
import { formatTooltip } from "./tooltip_parser";
const text_field = document.getElementById("ics_file");
const confirm_button = document.getElementById("ics_run");
const cal = document.getElementById("calendar");
const add_button = document.getElementById("ics_add");
const cal_ele = document.getElementById("calendar");
let currentTippy = null;
let calendar = null;
const new_tippy = (info) => {
if (info.el._tippy === currentTippy) {
currentTippy.show();
} // what does this even MEAN
else if (info.event.extendedProps.description) {
} // what does this even MEAN
else { // if (info.event.extendedProps.description)
// Destroy previous tippy if exists
if (currentTippy) {
currentTippy.destroy();
currentTippy = null;
}
currentTippy = tippy(info.el, {
content: info.event.extendedProps.description,
content: formatTooltip(
info.event.title,
info.event.extendedProps.description
),
allowHTML: true,
theme: "light",
interactive: true,
@@ -57,7 +63,8 @@ const tippy_die = (info) => {
confirm_button.addEventListener("click", (_e) => {
console.log("nawgh:", text_field.value);
if (text_field.value) {
const calendar = new Calendar(cal, {
if (calendar) calendar.destroy();
calendar = new Calendar(cal_ele, {
plugins: [
bootstrap5Plugin,
listPlugin,
@@ -69,23 +76,26 @@ confirm_button.addEventListener("click", (_e) => {
// multiMonthMaxColumns: 1,
navLinks: true,
dayMaxEvents: true,
eventMaxStack: 3,
dayMaxEventRows: true,
nowIndicator: true,
weekNumbers: true,
headerToolbar: {
left: "prev,next",
center: "title",
right: "today dayGridMonth,timeGridWeek,timeGridDay,listWeek", // Add the views you want
right: "today dayGridMonth,timeGridWeek,timeGridDay,listMonth", // Add the views you want
},
views: {
dayGridMonth: { buttonText: "Month" },
timeGridWeek: { buttonText: "Week" },
timeGridDay: { buttonText: "Day" },
listWeek: { buttonText: "List" },
listMonth: { buttonText: "List" },
},
events: {
url: text_field.value,
format: "ics",
color: getNextColor(),
},
// eventClick: new_tippy,
eventMouseEnter: new_tippy,
@@ -99,3 +109,13 @@ confirm_button.addEventListener("click", (_e) => {
// text_field.value = "http://127.0.0.1:8080/filtered-ics";
// confirm_button.click();
// wow
add_button.addEventListener("click", () => {
if (calendar && text_field.value) {
calendar.addEventSource({
url: text_field.value,
format: "ics",
color: getNextColor(),
});
}
});
+25
View File
@@ -0,0 +1,25 @@
// Escapes HTML special characters to prevent XSS
export function escapeHtml(text) {
const div = document.createElement("div");
div.innerText = text;
return div.innerHTML;
}
// Converts URLs in text to clickable links, after escaping
export function linkify(text) {
let safe = escapeHtml(text);
return safe.replace(
/(https?:\/\/[^\s<]+)/g,
(url) =>
`<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`
);
}
// Formats tooltip content: escapes, linkifies, and replaces newlines with <br>
export function formatTooltip(title, description) {
const safeTitle = escapeHtml(title);
const safeDesc = description
? linkify(description).replace(/\n/g, "<br>")
: "";
return `<strong>${safeTitle}</strong><br><br>${safeDesc}`;
}