Repository navigation
Expand file tree
/
Copy pathtitle.js
More file actions
137 lines (118 loc) · 3.92 KB
/
Copy pathtitle.js
File metadata and controls
137 lines (118 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Jellyfin Title Changer
* Handles multiple scenarios and edge cases
*/
(function() {
'use strict';
// Configuration
const CONFIG = {
FROM_TITLE: 'Jellyfin',
TO_TITLE: 'Jellyfish',
CASE_SENSITIVE: false,
TRIM_WHITESPACE: true,
DEBUG: false
};
// Utility functions
const log = CONFIG.DEBUG ? console.log.bind(console, '[TitleChanger]') : () => {};
const titleElement = document.querySelector('title');
let observer = null;
let isProcessing = false;
// Normalize title for comparison
function normalizeTitle(title) {
if (!title) return '';
let normalized = CONFIG.TRIM_WHITESPACE ? title.trim() : title;
return CONFIG.CASE_SENSITIVE ? normalized : normalized.toLowerCase();
}
// Check if title should be changed
function shouldChangeTitle(title) {
const normalizedTitle = normalizeTitle(title);
const normalizedFrom = normalizeTitle(CONFIG.FROM_TITLE);
return normalizedTitle === normalizedFrom;
}
// Safely change the title
function changeTitle(newTitle = CONFIG.TO_TITLE) {
if (isProcessing) return;
isProcessing = true;
try {
if (titleElement) {
titleElement.textContent = newTitle;
log(`Title changed to: ${newTitle}`);
}
} catch (error) {
log('Error changing title:', error);
} finally {
isProcessing = false;
}
}
// Process title change
function processTitle() {
const currentTitle = titleElement?.textContent || document.title;
if (shouldChangeTitle(currentTitle)) {
changeTitle();
}
}
// Initialize title processing
function init() {
if (!titleElement) {
log('Title element not found');
return;
}
// Initial title check
processTitle();
// Enhanced MutationObserver
observer = new MutationObserver((mutations) => {
let shouldProcess = false;
mutations.forEach((mutation) => {
if (mutation.type === 'childList' || mutation.type === 'characterData') {
shouldProcess = true;
}
});
if (shouldProcess) {
requestAnimationFrame(processTitle);
}
});
// Observe with comprehensive options
observer.observe(titleElement, {
childList: true,
characterData: true,
subtree: true
});
// Enhanced property descriptor
const originalDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'title') ||
Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'title');
if (originalDescriptor) {
Object.defineProperty(document, 'title', {
get: function() {
return titleElement?.textContent || '';
},
set: function(value) {
if (titleElement) {
titleElement.textContent = shouldChangeTitle(value) ? CONFIG.TO_TITLE : value;
}
},
configurable: true,
enumerable: true
});
}
// Periodic check as fallback
const intervalId = setInterval(() => {
processTitle();
}, 1000);
// Cleanup on page unload
window.addEventListener('beforeunload', () => {
if (observer) {
observer.disconnect();
observer = null;
}
clearInterval(intervalId);
log('Cleanup completed');
});
log('Title changer initialized');
}
// Start when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();