Harden Lildra layout and refresh branding
This commit is contained in:
@@ -1,41 +1,47 @@
|
||||
(() => {
|
||||
"use strict";
|
||||
|
||||
const VERSION = "0.2.3";
|
||||
const ROOT_CLASS = "lildra-active";
|
||||
const STYLE_ID = "lildra-layout-style";
|
||||
const HEADER_ID = "lildra-page-header";
|
||||
const FOOTER_ID = "lildra-product-footer";
|
||||
const STYLE_ID = "lildra-style";
|
||||
const TITLE_BAR_ID = "lildra-title-bar";
|
||||
const TITLE_ID = "lildra-title";
|
||||
const VERSION_LABEL_ID = "lildra-version-label";
|
||||
const STATE_KEY = "__lildraState";
|
||||
|
||||
function removeLildra() {
|
||||
document.documentElement.classList.remove(ROOT_CLASS);
|
||||
document.getElementById(STYLE_ID)?.remove();
|
||||
document.getElementById(HEADER_ID)?.remove();
|
||||
document.getElementById(FOOTER_ID)?.remove();
|
||||
}
|
||||
|
||||
// Toggle off when run a second time.
|
||||
if (document.documentElement.classList.contains(ROOT_CLASS)) {
|
||||
removeLildra();
|
||||
const existingState = window[STATE_KEY];
|
||||
if (existingState) {
|
||||
existingState.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
function isSupportedRoute() {
|
||||
return location.protocol === "https:" &&
|
||||
/^\/courses\/[^/]+\/(?:pages|wiki)\/[^/]+\/?$/.test(location.pathname);
|
||||
}
|
||||
|
||||
function isCanvasContentPage() {
|
||||
return isSupportedRoute() && Boolean(
|
||||
document.querySelector("#application #wrapper") &&
|
||||
document.querySelector("#wiki_page_show")
|
||||
);
|
||||
}
|
||||
|
||||
if (!isCanvasContentPage()) return;
|
||||
|
||||
function getPageTitle() {
|
||||
const candidates = [
|
||||
document.querySelector("#breadcrumbs [aria-current='page'] .ellipsible")?.textContent,
|
||||
document.querySelector("#breadcrumbs [aria-current='page']")?.textContent,
|
||||
document.querySelector(".mobile-header-title div:last-child")?.textContent,
|
||||
document.querySelector("#wiki_page_show .page-title")?.textContent,
|
||||
document.querySelector("#content h1.page-title")?.textContent
|
||||
const selectors = [
|
||||
"#breadcrumbs [aria-current='page'] .ellipsible",
|
||||
"#breadcrumbs [aria-current='page']",
|
||||
"#wiki_page_show .page-title",
|
||||
"#content h1.page-title",
|
||||
"#mobile-header .mobile-header-title div:last-child"
|
||||
];
|
||||
|
||||
const found = candidates
|
||||
.map((value) => value?.trim())
|
||||
.find((value) => value && value.length > 0);
|
||||
for (const selector of selectors) {
|
||||
const title = document.querySelector(selector)?.textContent?.trim();
|
||||
if (title) return title;
|
||||
}
|
||||
|
||||
if (found) return found;
|
||||
|
||||
// Canvas document titles normally end with ": Course name".
|
||||
const browserTitle = document.title.trim();
|
||||
const separator = browserTitle.lastIndexOf(":");
|
||||
return separator > 0 ? browserTitle.slice(0, separator).trim() : browserTitle;
|
||||
@@ -44,7 +50,6 @@
|
||||
const style = document.createElement("style");
|
||||
style.id = STYLE_ID;
|
||||
style.textContent = `
|
||||
/* Hide Canvas/QLearn navigation only. */
|
||||
html.${ROOT_CLASS} #header,
|
||||
html.${ROOT_CLASS} #mobile-header,
|
||||
html.${ROOT_CLASS} #mobileContextNavContainer,
|
||||
@@ -53,84 +58,65 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Remove navigation offsets while keeping a normal, centred reading width. */
|
||||
html.${ROOT_CLASS} #wrapper {
|
||||
margin-left: 0 !important;
|
||||
padding-top: 42px !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #wrapper,
|
||||
html.${ROOT_CLASS} body.primary-nav-expanded #wrapper,
|
||||
html.${ROOT_CLASS} body.course-menu-expanded #wrapper,
|
||||
html.${ROOT_CLASS} body.with-left-side #wrapper {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #wrapper {
|
||||
box-sizing: border-box !important;
|
||||
padding-top: 42px !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #main {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
max-width: none !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #not_right_side {
|
||||
display: block !important;
|
||||
width: min(1100px, calc(100% - 32px)) !important;
|
||||
box-sizing: border-box !important;
|
||||
width: calc(100% - 32px) !important;
|
||||
max-width: 1100px !important;
|
||||
margin: 0 auto !important;
|
||||
float: none !important;
|
||||
margin-right: auto !important;
|
||||
margin-left: auto !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #content-wrapper,
|
||||
html.${ROOT_CLASS} #content {
|
||||
width: 100% !important;
|
||||
max-width: none !important;
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
/* Small fixed title bar. */
|
||||
html.${ROOT_CLASS} #${HEADER_ID} {
|
||||
html.${ROOT_CLASS} #${TITLE_BAR_ID} {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
left: 0 !important;
|
||||
z-index: 2147483646 !important;
|
||||
box-sizing: border-box !important;
|
||||
height: 42px !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
height: 42px !important;
|
||||
padding: 0 18px !important;
|
||||
margin: 0 !important;
|
||||
overflow: hidden !important;
|
||||
white-space: nowrap !important;
|
||||
text-overflow: ellipsis !important;
|
||||
text-align: center !important;
|
||||
background: #ffffff !important;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.14) !important;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07) !important;
|
||||
background: #fff !important;
|
||||
border-bottom: 1px solid rgb(0 0 0 / 14%) !important;
|
||||
box-shadow: 0 1px 3px rgb(0 0 0 / 7%) !important;
|
||||
color: #1d2733 !important;
|
||||
font-family: Lato, "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
||||
font-size: 16px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1 !important;
|
||||
font: 700 16px/1 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #${FOOTER_ID} {
|
||||
html.${ROOT_CLASS} #${TITLE_ID} {
|
||||
min-width: 0 !important;
|
||||
overflow: hidden !important;
|
||||
text-align: center !important;
|
||||
text-overflow: ellipsis !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #${VERSION_LABEL_ID} {
|
||||
position: fixed !important;
|
||||
right: 14px !important;
|
||||
bottom: 9px !important;
|
||||
right: 10px !important;
|
||||
bottom: 8px !important;
|
||||
z-index: 2147483646 !important;
|
||||
padding: 4px 7px !important;
|
||||
padding: 3px 6px !important;
|
||||
border-radius: 4px !important;
|
||||
background: rgba(255, 255, 255, 0.9) !important;
|
||||
background: rgb(255 255 255 / 88%) !important;
|
||||
box-shadow: 0 1px 3px rgb(0 0 0 / 10%) !important;
|
||||
color: #5f259f !important;
|
||||
font-family: Lato, "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1 !important;
|
||||
font: 700 11px/1 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
||||
pointer-events: none !important;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
@@ -138,25 +124,72 @@
|
||||
padding-top: 38px !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #${HEADER_ID} {
|
||||
html.${ROOT_CLASS} #main {
|
||||
width: calc(100% - 20px) !important;
|
||||
}
|
||||
|
||||
html.${ROOT_CLASS} #${TITLE_BAR_ID} {
|
||||
height: 38px !important;
|
||||
padding: 0 12px !important;
|
||||
padding: 0 10px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const header = document.createElement("div");
|
||||
header.id = HEADER_ID;
|
||||
header.setAttribute("role", "banner");
|
||||
header.textContent = getPageTitle();
|
||||
const titleBar = document.createElement("div");
|
||||
titleBar.id = TITLE_BAR_ID;
|
||||
titleBar.setAttribute("aria-hidden", "true");
|
||||
|
||||
const footer = document.createElement("div");
|
||||
footer.id = FOOTER_ID;
|
||||
footer.textContent = `Lildra v${VERSION}`;
|
||||
const title = document.createElement("div");
|
||||
title.id = TITLE_ID;
|
||||
title.textContent = getPageTitle();
|
||||
titleBar.append(title);
|
||||
|
||||
document.documentElement.appendChild(style);
|
||||
document.body.appendChild(header);
|
||||
document.body.appendChild(footer);
|
||||
const versionLabel = document.createElement("div");
|
||||
versionLabel.id = VERSION_LABEL_ID;
|
||||
versionLabel.setAttribute("aria-hidden", "true");
|
||||
versionLabel.textContent = `Lildra v${chrome.runtime.getManifest().version}`;
|
||||
|
||||
let updatePending = false;
|
||||
let updateFrame = 0;
|
||||
const observer = new MutationObserver(() => {
|
||||
if (updatePending) return;
|
||||
updatePending = true;
|
||||
|
||||
updateFrame = requestAnimationFrame(() => {
|
||||
updateFrame = 0;
|
||||
updatePending = false;
|
||||
if (!isSupportedRoute()) {
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
|
||||
const nextTitle = getPageTitle();
|
||||
if (nextTitle && title.textContent !== nextTitle) title.textContent = nextTitle;
|
||||
});
|
||||
});
|
||||
|
||||
function remove() {
|
||||
observer.disconnect();
|
||||
if (updateFrame) cancelAnimationFrame(updateFrame);
|
||||
document.documentElement.classList.remove(ROOT_CLASS);
|
||||
style.remove();
|
||||
titleBar.remove();
|
||||
versionLabel.remove();
|
||||
delete window[STATE_KEY];
|
||||
}
|
||||
|
||||
window[STATE_KEY] = { remove };
|
||||
document.documentElement.append(style);
|
||||
document.body.append(titleBar, versionLabel);
|
||||
document.documentElement.classList.add(ROOT_CLASS);
|
||||
observer.observe(document.querySelector("#application"), {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
characterData: true
|
||||
});
|
||||
observer.observe(document.querySelector("head > title"), {
|
||||
childList: true,
|
||||
characterData: true
|
||||
});
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user