Files
html/opus-antioverlap-doctrine.js
opus 609c0ee30f
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
auto-sync via WEVIA git_sync_all intent 2026-04-21T14:49:42+02:00
2026-04-21 14:49:42 +02:00

153 lines
5.9 KiB
JavaScript

// OPUS_v932u_UNIVERSAL_X_DOCTRINE v4
// Add X close button to EVERY fixed/sticky/absolute element
// Hide on click + persist in localStorage + auto-stack overlaps
(function(){
if (window.__opus_x_v4) return;
window.__opus_x_v4 = true;
var NEVER_CLOSE_IDS = ['wevia-chat','weval-chatbot','chat-launcher','nav-main'];
var NEVER_CLOSE_TAGS = ['NAV','HEADER','HTML','BODY','MAIN','FOOTER'];
var NEVER_CLOSE_SELECTORS = ['[role="navigation"]','header','footer'];
function shouldGetX(el){
if (!el || !el.tagName) return false;
if (el.dataset && el.dataset.opusNoX === '1') return false;
if (NEVER_CLOSE_TAGS.indexOf(el.tagName) >= 0) return false;
if (el.id && NEVER_CLOSE_IDS.indexOf(el.id) >= 0) return false;
for (var i=0; i<NEVER_CLOSE_SELECTORS.length; i++){
try { if (el.matches(NEVER_CLOSE_SELECTORS[i])) return false; } catch(e){}
}
var s = getComputedStyle(el);
if (s.display === 'none' || s.visibility === 'hidden') return false;
if (parseFloat(s.opacity) < 0.1) return false;
if (s.position !== 'fixed' && s.position !== 'sticky' && s.position !== 'absolute') return false;
var r = el.getBoundingClientRect();
// Only meaningful-size elements
if (r.width < 80 || r.height < 24) return false;
// Don't add if parent already has X
var p = el.parentElement;
while (p){
if (p.dataset && p.dataset.opusXAdded === '1') return false;
p = p.parentElement;
}
return true;
}
function makeX(el){
var btn = document.createElement('button');
btn.className = 'opus-x-btn';
btn.innerHTML = '\u00d7';
btn.setAttribute('aria-label','Masquer cet element');
btn.title = 'Masquer';
btn.style.cssText = 'position:absolute;top:2px;right:3px;width:22px;height:22px;background:rgba(239,68,68,0.18);color:#ef4444;border:1px solid rgba(239,68,68,0.35);border-radius:50%;font-size:17px;font-weight:700;line-height:1;cursor:pointer;z-index:999999;display:flex;align-items:center;justify-content:center;padding:0;transition:all .15s;backdrop-filter:blur(4px)';
btn.onmouseover = function(){this.style.background='rgba(239,68,68,0.4)';this.style.color='#fff';this.style.transform='scale(1.1)';};
btn.onmouseout = function(){this.style.background='rgba(239,68,68,0.18)';this.style.color='#ef4444';this.style.transform='scale(1)';};
btn.onclick = function(e){
e.stopPropagation();
e.preventDefault();
el.style.transition = 'opacity .2s, transform .2s';
el.style.opacity = '0';
el.style.transform = 'scale(0.95)';
setTimeout(function(){ el.style.display='none'; }, 220);
try {
var k = 'opus-x-hide-' + (el.id || el.className.toString().substring(0,30) || el.tagName);
localStorage.setItem(k, Date.now());
} catch(_){}
};
return btn;
}
function addXButtons(){
// ALL elements that might need X
document.querySelectorAll('div,aside,section,article,a,span').forEach(function(el){
if (el.dataset.opusXAdded === '1') return;
if (!shouldGetX(el)) return;
// Ensure relative positioning for child absolute
var s = getComputedStyle(el);
if (s.position === 'static') el.style.position = 'relative';
el.appendChild(makeX(el));
el.dataset.opusXAdded = '1';
});
}
function restoreHidden(){
try {
document.querySelectorAll('[id]').forEach(function(el){
var k = 'opus-x-hide-' + el.id;
var t = localStorage.getItem(k);
if (t && (Date.now() - parseInt(t)) < 86400000) {
el.style.display = 'none';
}
});
} catch(_){}
}
function resolveCollisions(){
// Find all fixed/sticky
var fixedEls = [];
document.querySelectorAll('*').forEach(function(el){
var s = getComputedStyle(el);
if ((s.position === 'fixed' || s.position === 'sticky') && s.display !== 'none'){
var r = el.getBoundingClientRect();
if (r.width > 30 && r.height > 12) fixedEls.push({el:el, r:r, s:s});
}
});
// Auto-shift small elements that overlap bigger ones
for (var i=0; i<fixedEls.length; i++){
for (var j=i+1; j<fixedEls.length; j++){
var a = fixedEls[i], b = fixedEls[j];
if (a.el === b.el) continue;
// skip parent-child
if (a.el.contains(b.el) || b.el.contains(a.el)) continue;
var ox = Math.max(0, Math.min(a.r.right, b.r.right) - Math.max(a.r.left, b.r.left));
var oy = Math.max(0, Math.min(a.r.bottom, b.r.bottom) - Math.max(a.r.top, b.r.top));
var oa = ox * oy;
var min_area = Math.min(a.r.width*a.r.height, b.r.width*b.r.height);
if (oa > 400 && oa/min_area > 0.25){
// Smaller one moves
var smaller = (a.r.width*a.r.height < b.r.width*b.r.height) ? a : b;
var bigger = (smaller === a) ? b : a;
// Move smaller out of the way
// If smaller is at top-right area, push down
if (smaller.r.top < 100 && smaller.r.right > window.innerWidth - 300){
smaller.el.style.top = (bigger.r.bottom + 10) + 'px';
}
// If right, push further right or down
else {
smaller.el.style.right = '12px';
smaller.el.style.top = (bigger.r.bottom + 10) + 'px';
}
}
}
}
}
function run(){
try { addXButtons(); } catch(e){}
try { restoreHidden(); } catch(e){}
try { resolveCollisions(); } catch(e){}
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', run);
} else {
run();
}
setTimeout(run, 800);
setTimeout(run, 2500);
setTimeout(run, 5000);
try {
var obs = new MutationObserver(function(muts){
var need = false;
muts.forEach(function(m){ if (m.addedNodes && m.addedNodes.length) need = true; });
if (need) setTimeout(run, 100);
});
obs.observe(document.body, {childList:true, subtree:true});
} catch(e){}
})();