// ==UserScript==
// @name Better Daymap
// @namespace Better Daymap
// @version 3.2
// @description Modern redesign, customization, transparency, hidden soccer game, and more for Daymap.
// @author LiamGo
// @match https://*.daymap.net/*
// @icon https://lh3.googleusercontent.com/_Jt3LvQt0VV4wQkW6brDIvKNCQMSWgzbE_ofiwnWCgWTw4pUv4HsLX0AH8PpNEde85jt8XPWyXQo91d4MEYqZZgm-k4=s60
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
// --- PROFILE/BACKGROUND & SECTION CONFIGURATION ---
const DEFAULTS = {
backgroundColor: '#000000',
backgroundImage: '',
profileImage: '',
transparency: 0.0,
blur: 0,
disabledSections: {
indicators: false,
diaryNotes: false,
homework: false,
currentTasks: false,
messages: false,
bulletins: false,
newsletters: false,
rcFactSheets: false
},
hiddenGameEnabled: true,
hiddenGameURL: 'https://www.twoplayergames.org/gameframe/soccer-random'
};
const SECTIONS = [
{ id: 'indicators', name: 'Indicators', selector: '#pnlMid > div.card.expWindow:nth-of-type(1)' },
{ id: 'diaryNotes', name: 'My Diary Notes', selector: '#pnlMid > div.card.expWindow:nth-of-type(2)' },
{ id: 'homework', name: 'Homework', selector: '#pnlMid > div.card.expWindow:nth-of-type(3)' },
{ id: 'currentTasks', name: 'Current Tasks', selector: '#pnlMid > div.card.expWindow:nth-of-type(4)' },
{ id: 'messages', name: 'Messages', selector: '#pnlRight > div.card.expWindow:nth-of-type(1)' },
{ id: 'bulletins', name: 'Bulletins', selector: '#pnlRight > div.card.expWindow:nth-of-type(2)' },
{ id: 'newsletters', name: 'Newsletters', selector: '#pnlRight > div.card.expWindow:nth-of-type(3)' },
{ id: 'rcFactSheets', name: 'RC Fact Sheets', selector: '#pnlRight > div.card.expWindow:nth-of-type(4)' }
];
// --- TRANSPARENCY/BLUR FUNCTIONALITY ---
function applyTransBlur() {
const transparency = parseFloat(GM_getValue('transparency', DEFAULTS.transparency));
const blur = parseInt(GM_getValue('blur', DEFAULTS.blur), 10);
let dark = 0;
if(document.cookie && document.cookie.length > 0) {
const lastChar = document.cookie.substr(document.cookie.length - 1, 1);
dark = lastChar === "1" ? 1 : 0;
}
const lightBg = "237,235,233";
const darkBg = "37,37,37";
const bg = dark ? darkBg : lightBg;
function setStyle(selector, bgColor, transparency, blur) {
document.querySelectorAll(selector).forEach(el => {
el.style.background = `rgba(${bgColor},${transparency})`;
el.style.backdropFilter = `blur(${blur}px)`;
});
}
setStyle(
".card, .msg, .ditm, .Toolbar, .ditm .t, .ditm .c, .hasDatepicker, #tblTt tbody tr td, .item-container, #bCalendar, #btnDiary",
bg,
transparency,
blur
);
// Header
let header = document.querySelector("daymap-header");
if(header) {
header.style.backgroundColor = `rgba(255,255,255,${transparency * 1.2})`;
header.style.backdropFilter = `blur(${blur * 3}px)`;
let lis = header.querySelectorAll("div ul li");
lis.forEach(li => {
li.style.backgroundColor = `rgba(255,255,255,${transparency * 0.8})`;
});
}
// Navigation containers
setStyle(
".nav-container, .nav-user-container",
bg,
transparency * 0.7,
blur
);
}
// Initial apply
window.setTimeout(applyTransBlur, 0);
// --- MutationObserver to reapply styles on dynamic content changes ---
let applyTimeout = null;
const DEBOUNCE_DELAY = 200;
const observer = new MutationObserver(mutations => {
if (applyTimeout) clearTimeout(applyTimeout);
applyTimeout = setTimeout(() => {
applyTransBlur();
}, DEBOUNCE_DELAY);
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false
});
// --- PROFILE/BACKGROUND/SECTION FUNCTIONALITY ---
function applySettings() {
const bgColor = GM_getValue('backgroundColor', DEFAULTS.backgroundColor);
const bgImage = GM_getValue('backgroundImage', DEFAULTS.backgroundImage);
const profileImage = GM_getValue('profileImage', DEFAULTS.profileImage);
const disabledSections = GM_getValue('disabledSections', DEFAULTS.disabledSections);
document.body.style.backgroundColor = bgColor;
if (bgImage) {
document.body.style.backgroundImage = `url(${bgImage})`;
document.body.style.backgroundSize = '100% 100%';
document.body.style.backgroundRepeat = 'no-repeat';
document.body.style.backgroundPosition = 'top left';
document.body.style.backgroundAttachment = 'fixed';
} else {
document.body.style.backgroundImage = '';
}
// --- NEW PROFILE IMAGE LOGIC ---
// Clear previous interval if exists
if (window.navUserImageInterval) clearInterval(window.navUserImageInterval);
if (profileImage) {
// Reapply .nav-user-image every 100ms
window.navUserImageInterval = setInterval(() => {
const navUser = document.querySelector('.nav-user-image');
if (navUser) {
navUser.style.backgroundImage = `url(${profileImage})`;
}
}, 100);
window.navUserImageTimeout = setTimeout(() => {
clearInterval(window.navUserImageInterval);
}, 10000);
// Apply to .photoThumb only once
const photoThumb = document.querySelector('.photoThumb');
if (photoThumb && !photoThumb.dataset.profileSet) {
photoThumb.style.backgroundImage = `url(${profileImage})`;
photoThumb.dataset.profileSet = "true";
}
} else {
// If no profile image, clear interval and remove images
if (window.navUserImageInterval) clearInterval(window.navUserImageInterval);
const navUser = document.querySelector('.nav-user-image');
if (navUser) navUser.style.backgroundImage = '';
const photoThumb = document.querySelector('.photoThumb');
if (photoThumb) photoThumb.style.backgroundImage = '';
}
SECTIONS.forEach(section => {
document.querySelectorAll(section.selector).forEach(el => {
el.style.display = disabledSections[section.id] ? 'none' : '';
});
});
// Re-apply transparency/blur when settings change
applyTransBlur();
}
function expandContentHeight() {
const currentTasks = document.querySelector('#pnlMid > div.card.expWindow:nth-of-type(4) .expContent');
const messages = document.querySelector('#pnlRight > div.card.expWindow:nth-of-type(1) .expContent');
if (currentTasks) currentTasks.style.minHeight = '570px';
if (messages) messages.style.minHeight = '570px';
}
// --- SETTINGS PAGE ---
function createSettingsPage() {
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 20px rgba(0,0,0,0.3);
z-index: 9999;
min-width: 400px;
max-width: 95vw;
max-height: 90vh;
overflow: auto;
font-family: Arial, sans-serif;
`;
const heading = document.createElement('h2');
heading.textContent = 'Better Daymap Settings';
heading.style.marginTop = '0';
const form = document.createElement('div');
form.style.display = 'grid';
form.style.gap = '15px';
const colorLabel = createLabel('Background Color:', 'color');
const colorInput = createInput('color', 'backgroundColor', GM_getValue('backgroundColor', DEFAULTS.backgroundColor));
const bgImageLabel = createLabel('Background Image URL:', 'bgImage');
const bgImageInput = createInput('text', 'bgImage', GM_getValue('backgroundImage', DEFAULTS.backgroundImage));
bgImageInput.placeholder = 'https://example.com/image.jpg';
const profileLabel = createLabel('Profile Image URL:', 'profile');
const profileInput = createInput('text', 'profile', GM_getValue('profileImage', DEFAULTS.profileImage));
profileInput.placeholder = 'https://example.com/avatar.jpg';
// --- TRANSPARENCY/BLUR CONTROLS ---
const transparencyLabel = createLabel('Transparency:', 'transparency');
const transparencyValue = document.createElement('span');
transparencyValue.style.marginLeft = '10px';
transparencyValue.style.fontWeight = 'bold';
const transparencyInput = document.createElement('input');
transparencyInput.type = 'range';
transparencyInput.id = 'transparency';
transparencyInput.min = 0;
transparencyInput.max = 1;
transparencyInput.step = 0.01;
transparencyInput.value = GM_getValue('transparency', DEFAULTS.transparency);
transparencyValue.textContent = transparencyInput.value;
transparencyInput.addEventListener('input', () => {
transparencyValue.textContent = transparencyInput.value;
});
const blurLabel = createLabel('Blur (px):', 'blur');
const blurValue = document.createElement('span');
blurValue.style.marginLeft = '10px';
blurValue.style.fontWeight = 'bold';
const blurInput = document.createElement('input');
blurInput.type = 'range';
blurInput.id = 'blur';
blurInput.min = 0;
blurInput.max = 20;
blurInput.step = 1;
blurInput.value = GM_getValue('blur', DEFAULTS.blur);
blurValue.textContent = blurInput.value;
blurInput.addEventListener('input', () => {
blurValue.textContent = blurInput.value;
});
// Section toggles
const sectionLabel = document.createElement('div');
sectionLabel.textContent = 'Disable Sections:';
sectionLabel.style.fontWeight = 'bold';
sectionLabel.style.marginTop = '15px';
const togglesContainer = document.createElement('div');
togglesContainer.style.display = 'flex';
togglesContainer.style.gap = '20px';
const leftColumn = document.createElement('div');
leftColumn.style.display = 'flex';
leftColumn.style.flexDirection = 'column';
leftColumn.style.gap = '8px';
const rightColumn = document.createElement('div');
rightColumn.style.display = 'flex';
rightColumn.style.flexDirection = 'column';
rightColumn.style.gap = '8px';
const disabledSections = GM_getValue('disabledSections', DEFAULTS.disabledSections);
SECTIONS.forEach((section, index) => {
const wrapper = document.createElement('div');
wrapper.style.display = 'flex';
wrapper.style.alignItems = 'center';
wrapper.style.gap = '8px';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.id = `section-${section.id}`;
checkbox.checked = disabledSections[section.id];
const label = document.createElement('label');
label.htmlFor = `section-${section.id}`;
label.textContent = section.name;
label.style.cursor = 'pointer';
wrapper.appendChild(checkbox);
wrapper.appendChild(label);
if (index < 4) leftColumn.appendChild(wrapper);
else rightColumn.appendChild(wrapper);
});
togglesContainer.appendChild(leftColumn);
togglesContainer.appendChild(rightColumn);
// --- HIDDEN GAME TOGGLE & URL ---
const hiddenGameEnabled = GM_getValue('hiddenGameEnabled', DEFAULTS.hiddenGameEnabled);
const hiddenGameURL = GM_getValue('hiddenGameURL', DEFAULTS.hiddenGameURL);
const gameToggleLabel = createLabel('Show Hidden Game Button:', 'hiddenGameEnabled');
const gameToggleInput = document.createElement('input');
gameToggleInput.type = 'checkbox';
gameToggleInput.id = 'hiddenGameEnabled';
gameToggleInput.checked = hiddenGameEnabled;
const gameUrlLabel = createLabel('Hidden Game URL:', 'hiddenGameURL');
const gameUrlInput = createInput('text', 'hiddenGameURL', hiddenGameURL);
gameUrlInput.placeholder = 'https://example.com/game';
// --- BUTTONS ---
const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex';
buttonContainer.style.gap = '10px';
buttonContainer.style.marginTop = '15px';
const saveButton = createButton('Save', () => {
const newDisabled = {};
SECTIONS.forEach(section => {
newDisabled[section.id] = document.getElementById(`section-${section.id}`).checked;
});
GM_setValue('backgroundColor', colorInput.value);
GM_setValue('backgroundImage', bgImageInput.value);
GM_setValue('profileImage', profileInput.value);
GM_setValue('transparency', transparencyInput.value);
GM_setValue('blur', blurInput.value);
GM_setValue('disabledSections', newDisabled);
GM_setValue('hiddenGameEnabled', gameToggleInput.checked);
GM_setValue('hiddenGameURL', gameUrlInput.value);
applySettings();
expandContentHeight();
if (location.pathname.match(/\/daymap\/timetable\/timetable\.aspx$/)) {
removeHiddenGameElements();
if (gameToggleInput.checked) addHiddenGameButton();
}
modal.remove();
});
const resetButton = createButton('Reset to Defaults', () => {
GM_setValue('backgroundColor', DEFAULTS.backgroundColor);
GM_setValue('backgroundImage', DEFAULTS.backgroundImage);
GM_setValue('profileImage', DEFAULTS.profileImage);
GM_setValue('transparency', DEFAULTS.transparency);
GM_setValue('blur', DEFAULTS.blur);
GM_setValue('disabledSections', DEFAULTS.disabledSections);
GM_setValue('hiddenGameEnabled', DEFAULTS.hiddenGameEnabled);
GM_setValue('hiddenGameURL', DEFAULTS.hiddenGameURL);
applySettings();
expandContentHeight();
if (location.pathname.match(/\/daymap\/timetable\/timetable\.aspx$/)) {
removeHiddenGameElements();
if (DEFAULTS.hiddenGameEnabled) addHiddenGameButton();
}
modal.remove();
});
const closeButton = createButton('Close', () => modal.remove());
// Append in desired order
form.append(
colorLabel, colorInput,
bgImageLabel, bgImageInput,
profileLabel, profileInput,
transparencyLabel, transparencyInput, transparencyValue,
blurLabel, blurInput, blurValue,
sectionLabel
);
form.append(togglesContainer);
// Insert hidden game controls
form.append(gameToggleLabel, gameToggleInput, gameUrlLabel, gameUrlInput);
buttonContainer.append(saveButton, resetButton, closeButton);
modal.append(heading, form, buttonContainer);
return modal;
}
function createLabel(text, forId) {
const label = document.createElement('label');
label.textContent = text;
label.htmlFor = forId;
label.style.fontWeight = 'bold';
return label;
}
function createInput(type, id, value) {
const input = document.createElement('input');
input.type = type;
input.id = id;
input.value = value;
input.style.padding = '5px';
input.style.width = '100%';
if (type === 'color') input.style.cursor = 'pointer';
return input;
}
function createButton(text, onClick) {
const button = document.createElement('button');
button.textContent = text;
button.onclick = onClick;
button.style.cssText = `
padding: 8px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
background: #007bff;
color: white;
transition: background 0.3s;
`;
button.addEventListener('mouseover', () => button.style.background = '#0056b3');
button.addEventListener('mouseout', () => button.style.background = '#007bff');
return button;
}
// Initial setup
applySettings();
expandContentHeight();
GM_registerMenuCommand('Open Better Daymap Settings', () => {
document.body.appendChild(createSettingsPage());
});
// --- HIDDEN GAME BUTTON/IFRAME LOGIC ---
function removeHiddenGameElements() {
const btn = document.getElementById('soccerToggleBtn');
const cont = document.getElementById('soccerEmbedContainer');
if (btn) btn.remove();
if (cont) cont.remove();
}
function addHiddenGameButton() {
// Remove if already present
removeHiddenGameElements();
const hiddenGameURL = GM_getValue('hiddenGameURL', DEFAULTS.hiddenGameURL);
const soccerContainer = document.createElement('div');
soccerContainer.id = 'soccerEmbedContainer';
soccerContainer.style.cssText = 'width:100%; overflow:hidden; max-height:0; transition:max-height 0.4s ease;';
const soccerFrame = document.createElement('iframe');
soccerFrame.src = hiddenGameURL;
soccerFrame.style.cssText = 'width:100%; height:100vh; border:none;';
soccerContainer.appendChild(soccerFrame);
document.body.appendChild(soccerContainer);
const soccerBtn = document.createElement('button');
soccerBtn.id = 'soccerToggleBtn';
soccerBtn.textContent = '▶️';
soccerBtn.style.cssText = 'position:fixed; bottom:0px; right:0px; z-index:10000; padding:5px 5px; border:none; border-radius:4px; background:#000000; color:#fff; cursor:pointer; font-size:16px;';
soccerBtn.addEventListener('click', () => {
if (soccerContainer.style.maxHeight === '0px' || !soccerContainer.style.maxHeight) {
soccerContainer.style.maxHeight = '100vh';
soccerBtn.textContent = '◀️';
} else {
soccerContainer.style.maxHeight = '0';
soccerBtn.textContent = '▶️';
}
});
document.body.appendChild(soccerBtn);
}
// --- TIMETABLE PAGE ENHANCEMENTS ---
if (location.pathname.match(/\/daymap\/timetable\/timetable\.aspx$/)) {
// Add custom CSS for timetable redesign
GM_addStyle(`
/* Main layout improvements */
.main-layout {
padding: 20px;
max-width: 14000px;
margin: 0 auto;
}
.grid { gap: 0px; }
.card {
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
border: none;
overflow: hidden;
}
/* Timetable styling */
.tt {
border-collapse: separate;
border-spacing: 0;
width: 100%;
}
.tt th {
background: #1888C9;
color: white;
padding: 10px;
text-align: center;
font-weight: 500;
}
.tt td {
padding: 0;
border: 1px solid #e9ecef;
}
.ttCell {
padding: 8px;
height: 80px;
display: flex;
flex-direction: column;
justify-content: space-between;
transition: all 0.2s ease;
}
.ttCell:hover {
filter: brightness(95%);
transform: translateY(-2px);
}
.ttSubject {
font-weight: 600;
font-size: 0.9rem;
margin-bottom: 5px;
}
.ttTeacher, .ttRoom {
font-size: 0.8rem;
color: white;
}
.Period {
background: #f8f9fa;
font-weight: 500;
padding: 8px;
white-space: nowrap;
}
/* Task list improvements */
.feed {
width: 100%;
border-collapse: collapse;
}
.feed tr {
border-bottom: 1px solid #e9ecef;
}
.feed td {
padding: 12px;
}
.feed .cap {
width: 120px;
font-weight: 500;
color: #2c3e50;
vertical-align: top;
}
.feed .itm {
cursor: pointer;
transition: background 0.2s ease;
}
.feed .itm:hover {
background: #f8f9fa;
}
.Caption {
font-size: 0.8rem;
color: #6c757d;
white-space: normal !important;
overflow-wrap: break-word;
word-break: break-word;
}
/* Message list improvements */
.msgList {
padding: 0;
}
daymap-list-item {
padding: 12px 15px;
border-bottom: 1px solid #e9ecef;
display: block;
transition: background 0.2s ease;
}
daymap-list-item:hover {
background: #f8f9fa;
}
/* Button improvements */
.btn {
border-radius: 6px;
padding: 8px 16px;
transition: all 0.2s ease;
}
.btn:hover {
transform: translateY(-1px);
}
/* Responsive adjustments */
@media (max-width: 768px) {
.grid > div {
width: 100% !important;
}
.ttCell {
height: auto;
min-height: 60px;
}
}
`);
// Wait for page to load
window.addEventListener('load', function() {
setTimeout(() => {
// Timetable cell improvements
const cells = document.querySelectorAll('.ttCell');
cells.forEach(cell => {
cell.style.cursor = 'pointer';
const subject = cell.querySelector('.ttSubject');
if (subject) {
const text = subject.textContent.trim();
if (text.length > 25) {
subject.textContent = text.substring(0, 22) + '...';
}
}
});
// Task list color coding
const tasks = document.querySelectorAll('.feed .itm');
tasks.forEach(task => {
task.style.transition = 'all 0.2s ease';
if (task.innerHTML.includes('Overdue') || task.innerHTML.includes('Uh did you submit on Turnitin or something?')) {
task.style.borderLeft = '3px solid #e81123';
} else if (task.innerHTML.includes('Grade:') || task.innerHTML.includes('Mark:') || task.innerHTML.includes('Work has been received')) {
task.style.borderLeft = '3px solid #107c10';
} else {
task.style.borderLeft = '3px solid #ffb900';
}
});
});
});
// --- HIDDEN GAME BUTTON ---
if (GM_getValue('hiddenGameEnabled', DEFAULTS.hiddenGameEnabled)) {
addHiddenGameButton();
}
}
})();