form: hide sidebar by default; icons: swap like/comment sprites
Form sidebar is hidden for saved docs by default; user's explicit toggle persists via localStorage (jey-form-sidebar). Swap Frappe's hard-coded sprite refs on render: #icon-heart -> #icon-star (like action) #es-line-chat-alt -> #jey-icon-comment (local sprite, 2-line bubble) Injected sprite + MutationObserver keep swaps applied as nodes stream in. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
373ffd73b8
commit
f0cc94d96f
|
|
@ -817,6 +817,49 @@
|
||||||
observer.observe(document.body, { childList: true, subtree: true });
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Form sidebar: hidden by default
|
||||||
|
Frappe shows the form sidebar for saved docs; we hide it by default and
|
||||||
|
remember the user's explicit toggle via localStorage.
|
||||||
|
========================================================================== */
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var STORAGE_KEY = "jey-form-sidebar"; // "hidden" | "visible"
|
||||||
|
|
||||||
|
function getPreference() {
|
||||||
|
return localStorage.getItem(STORAGE_KEY) === "visible" ? "visible" : "hidden";
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyPreference(frm) {
|
||||||
|
if (!frm || !frm.sidebar || !frm.sidebar.sidebar) return;
|
||||||
|
if (frm.doc && frm.doc.__islocal) return; // Frappe already hides new docs
|
||||||
|
var wrap = frm.sidebar.sidebar.parent();
|
||||||
|
if (!wrap || !wrap.length) return;
|
||||||
|
var page_sidebar = frm.sidebar.page && frm.sidebar.page.sidebar;
|
||||||
|
if (getPreference() === "hidden") {
|
||||||
|
wrap.hide();
|
||||||
|
if (page_sidebar) page_sidebar.addClass("hide-sidebar");
|
||||||
|
} else {
|
||||||
|
wrap.show();
|
||||||
|
if (page_sidebar) page_sidebar.removeClass("hide-sidebar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on("form-refresh", function (e, frm) {
|
||||||
|
applyPreference(frm);
|
||||||
|
});
|
||||||
|
|
||||||
|
// When user clicks "Toggle Sidebar", persist the new state
|
||||||
|
$(document.body).on("toggleSidebar", function () {
|
||||||
|
var frm = window.cur_frm;
|
||||||
|
if (!frm || !frm.sidebar || !frm.sidebar.sidebar) return;
|
||||||
|
var wrap = frm.sidebar.sidebar.parent();
|
||||||
|
if (!wrap || !wrap.length) return;
|
||||||
|
localStorage.setItem(STORAGE_KEY, wrap.is(":visible") ? "visible" : "hidden");
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
/* ==========================================================================
|
/* ==========================================================================
|
||||||
Reload button next to Notifications in sidebar
|
Reload button next to Notifications in sidebar
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
@ -2272,3 +2315,94 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Sprite icon swaps
|
||||||
|
Frappe hard-codes #icon-heart for the "like" action and #es-line-chat-alt
|
||||||
|
for the comment count in list/form templates. Rewrite the <use href=...>
|
||||||
|
on render so lists/forms show a star and a comment bubble instead.
|
||||||
|
|
||||||
|
For the comment icon we inject our own sprite symbol (#jey-icon-comment)
|
||||||
|
because Frappe's bundled #icon-message-square-text is the newer lucide
|
||||||
|
variant with 3 text lines, and we want the older 2-line version.
|
||||||
|
========================================================================== */
|
||||||
|
(function () {
|
||||||
|
var SWAPS = {
|
||||||
|
"#icon-heart": "#icon-star",
|
||||||
|
"#es-line-chat-alt": "#jey-icon-comment",
|
||||||
|
};
|
||||||
|
|
||||||
|
function injectSprite() {
|
||||||
|
if (document.getElementById("jey-icon-sprite")) return;
|
||||||
|
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
|
svg.id = "jey-icon-sprite";
|
||||||
|
svg.setAttribute("width", "0");
|
||||||
|
svg.setAttribute("height", "0");
|
||||||
|
svg.setAttribute("aria-hidden", "true");
|
||||||
|
svg.style.position = "absolute";
|
||||||
|
svg.innerHTML =
|
||||||
|
'<symbol viewBox="0 0 24 24" id="jey-icon-comment">' +
|
||||||
|
'<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>' +
|
||||||
|
'<path d="M13 8H7"/>' +
|
||||||
|
'<path d="M17 12H7"/>' +
|
||||||
|
'</symbol>';
|
||||||
|
(document.body || document.documentElement).insertBefore(
|
||||||
|
svg, (document.body || document.documentElement).firstChild
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function swapIn(root) {
|
||||||
|
if (!root || root.nodeType !== 1) return;
|
||||||
|
Object.keys(SWAPS).forEach(function (from) {
|
||||||
|
var to = SWAPS[from];
|
||||||
|
// href= and xlink:href= both appear in the wild
|
||||||
|
var nodes = root.querySelectorAll(
|
||||||
|
'use[href="' + from + '"], use[*|href="' + from + '"]'
|
||||||
|
);
|
||||||
|
nodes.forEach(function (u) {
|
||||||
|
if (u.getAttribute("href") === from) u.setAttribute("href", to);
|
||||||
|
if (u.getAttributeNS("http://www.w3.org/1999/xlink", "href") === from) {
|
||||||
|
u.setAttributeNS("http://www.w3.org/1999/xlink", "href", to);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
injectSprite();
|
||||||
|
swapIn(document.body);
|
||||||
|
var obs = new MutationObserver(function (mutations) {
|
||||||
|
for (var i = 0; i < mutations.length; i++) {
|
||||||
|
var m = mutations[i];
|
||||||
|
if (m.type === "childList") {
|
||||||
|
m.addedNodes.forEach(function (n) {
|
||||||
|
if (n.nodeType !== 1) return;
|
||||||
|
// If the added node itself is a <use>, handle it directly
|
||||||
|
if (n.tagName && n.tagName.toLowerCase() === "use") {
|
||||||
|
var href = n.getAttribute("href");
|
||||||
|
if (href && SWAPS[href]) n.setAttribute("href", SWAPS[href]);
|
||||||
|
}
|
||||||
|
swapIn(n);
|
||||||
|
});
|
||||||
|
} else if (m.type === "attributes" && m.target && m.target.tagName &&
|
||||||
|
m.target.tagName.toLowerCase() === "use") {
|
||||||
|
var href2 = m.target.getAttribute("href");
|
||||||
|
if (href2 && SWAPS[href2]) m.target.setAttribute("href", SWAPS[href2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
obs.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ["href", "xlink:href"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
||||||
|
} else {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue