(function(){
if (window.__OS_WINDOW_REGULATOR__) return;
window.__OS_WINDOW_REGULATOR__ = true;
var CFG = {
BASE_Z: 10000,
Z_STEP: 1,
MIN_W: 260,
MIN_H: 180,
MOBILE_MARGIN: 8,
TOP_MARGIN: 0.05
};
// Используем глобальный объект для состояния
window.WinManagerGlobalState = window.WinManagerGlobalState || { z: CFG.BASE_Z };
function isVisible(el){
if(!el) return false;
var cs = window.getComputedStyle(el);
return cs.display !== 'none' && cs.visibility !== 'hidden';
}
function setOpenState(win, open){
if(!win) return;
if(open){
win.classList.add('os-on');
win.style.display = 'flex';
win.style.visibility = 'visible';
} else {
win.classList.remove('os-on');
win.style.display = 'none';
}
}
function bringToFront(win){
if(!win) return;
window.WinManagerGlobalState.z += CFG.Z_STEP;
win.style.zIndex = window.WinManagerGlobalState.z;
}
function centerWindow(win){
if(!win) return;
var vw = window.innerWidth;
var vh = window.innerHeight;
var r = win.getBoundingClientRect();
var w = r.width || win.offsetWidth;
var h = r.height || win.offsetHeight;
var left = Math.max(CFG.MOBILE_MARGIN, Math.round((vw - w) / 2));
var top = Math.max(CFG.MOBILE_MARGIN, Math.round(vh * CFG.TOP_MARGIN));
if(vw < 768){
left = CFG.MOBILE_MARGIN;
w = Math.min(w, vw - CFG.MOBILE_MARGIN*2);
h = Math.min(h, vh - CFG.MOBILE_MARGIN*2);
win.style.width = w + 'px';
win.style.height = h + 'px';
}
win.style.left = left + 'px';
win.style.top = top + 'px';
}
function openWindow(win, opts){
if(!win) return;
opts = opts || {};
setOpenState(win, true);
if(!win.dataset.positionedOnce || opts.forceCenter){
centerWindow(win);
win.dataset.positionedOnce = '1';
}
if(opts.width) win.style.width = opts.width + 'px';
if(opts.height) win.style.height = opts.height + 'px';
bringToFront(win);
try {
win.dispatchEvent(new CustomEvent('os:open', { detail: opts }));
} catch(e){}
}
function closeWindow(win){
if(!win) return;
setOpenState(win, false);
var iframe = win.querySelector('iframe');
if(iframe && iframe.src){
iframe.dataset.savedSrc = iframe.src;
iframe.src = '';
}
try {
win.dispatchEvent(new CustomEvent('os:close'));
} catch(e){}
}
function startResize(win, dir, startX, startY){
var r = win.getBoundingClientRect();
var ow = r.width;
var oh = r.height;
var ox = r.left;
var oy = r.top;
win.style.transform = 'none';
win.style.left = ox + 'px';
win.style.top = oy + 'px';
win.style.width = ow + 'px';
win.style.height = oh + 'px';
document.body.style.userSelect = 'none';
document.body.style.webkitUserSelect = 'none';
document.body.style.cursor = {
n:'n-resize', s:'s-resize', e:'e-resize', w:'w-resize',
ne:'ne-resize', nw:'nw-resize', se:'se-resize', sw:'sw-resize'
}[dir] || 'default';
function onMove(cx, cy){
var dx = cx - startX;
var dy = cy - startY;
var nW = ow;
var nH = oh;
var nX = ox;
var nY = oy;
if(dir.indexOf('e') !== -1){
nW = Math.max(CFG.MIN_W, ow + dx);
}
if(dir.indexOf('w') !== -1){
nW = Math.max(CFG.MIN_W, ow - dx);
nX = dx < ow - CFG.MIN_W ? ox + dx : ox + ow - CFG.MIN_W;
}
if(dir.indexOf('s') !== -1){
nH = Math.max(CFG.MIN_H, oh + dy);
}
if(dir.indexOf('n') !== -1){
nH = Math.max(CFG.MIN_H, oh - dy);
nY = dy < oh - CFG.MIN_H ? oy + dy : oy + oh - CFG.MIN_H;
}
win.style.width = nW + 'px';
win.style.height = nH + 'px';
win.style.left = nX + 'px';
win.style.top = nY + 'px';
}
function endResize(){
document.body.style.userSelect = '';
document.body.style.webkitUserSelect = '';
document.body.style.cursor = '';
document.removeEventListener('mousemove', onMM);
document.removeEventListener('mouseup', onMU);
document.removeEventListener('touchmove', onTM);
document.removeEventListener('touchend', onTE);
}
function onMM(e){ onMove(e.clientX, e.clientY); }
function onMU(){ endResize(); }
function onTM(e){ if(e.touches[0]) onMove(e.touches[0].clientX, e.touches[0].clientY); }
function onTE(){ endResize(); }
document.addEventListener('mousemove', onMM);
document.addEventListener('mouseup', onMU);
document.addEventListener('touchmove', onTM, { passive: true });
document.addEventListener('touchend', onTE);
}
function addResizeHandles(win, prefix){
prefix = prefix || 'os-rsz';
if(win.querySelector('.' + prefix)) return;
['n','ne','e','se','s','sw','w','nw'].forEach(function(dir){
var h = document.createElement('div');
h.className = prefix + ' ' + prefix + '-' + dir;
win.appendChild(h);
h.addEventListener('mousedown', function(e){
e.preventDefault();
e.stopPropagation();
bringToFront(win);
startResize(win, dir, e.clientX, e.clientY);
});
h.addEventListener('touchstart', function(e){
if(!e.touches[0]) return;
e.stopPropagation();
bringToFront(win);
startResize(win, dir, e.touches[0].clientX, e.touches[0].clientY);
}, { passive: true });
});
}
function makeDraggable(win, tbar){
if(!win || !tbar) return;
if(tbar.__dragBound) return;
tbar.__dragBound = true;
var dragging = false;
var ox = 0;
var oy = 0;
function startDrag(clientX, clientY){
var r = win.getBoundingClientRect();
dragging = true;
ox = clientX - r.left;
oy = clientY - r.top;
win.style.transform = 'none';
win.style.left = r.left + 'px';
win.style.top = r.top + 'px';
bringToFront(win);
}
tbar.addEventListener('mousedown', function(e){
if(e.target.closest('button, a, input, textarea, select')) return;
e.preventDefault();
startDrag(e.clientX, e.clientY);
});
document.addEventListener('mousemove', function(e){
if(!dragging) return;
win.style.left = (e.clientX - ox) + 'px';
win.style.top = (e.clientY - oy) + 'px';
});
document.addEventListener('mouseup', function(){
dragging = false;
});
tbar.addEventListener('touchstart', function(e){
if(e.target.closest('button, a, input, textarea, select')) return;
if(!e.touches[0]) return;
startDrag(e.touches[0].clientX, e.touches[0].clientY);
}, { passive: true });
document.addEventListener('touchmove', function(e){
if(!dragging || !e.touches[0]) return;
win.style.left = (e.touches[0].clientX - ox) + 'px';
win.style.top = (e.touches[0].clientY - oy) + 'px';
}, { passive: true });
document.addEventListener('touchend', function(){
dragging = false;
});
}
function bindOpenTriggers(){
document.querySelectorAll('[data-open-win]').forEach(function(trigger){
if(trigger.__openBound) return;
trigger.__openBound = true;
trigger.style.cursor = 'pointer';
trigger.addEventListener('click', function(e){
e.preventDefault();
e.stopPropagation();
var targetId = trigger.getAttribute('data-open-win') || '';
targetId = targetId.replace(/^#/, '');
var win = document.getElementById(targetId);
if(!win) return;
openWindow(win);
});
});
}
function bindExistingWindows(){
var wins = document.querySelectorAll(
'.os-win, .win98, #cookie-win, #quiz-win, #folder-win, #free-folder-win, #trash-win, #images-win'
);
wins.forEach(function(win){
if(win.__osBound) return;
win.__osBound = true;
// Поднять окно на передний план при клике
win.addEventListener('mousedown', function(){
bringToFront(win);
}, true);
win.addEventListener('touchstart', function(){
bringToFront(win);
}, { capture: true, passive: true });
// Кнопки закрытия
var closeBtns = win.querySelectorAll(
'.os-close, .w-close, #cookie-close-btn, #quiz-close-btn, #folder-close-btn, #free-folder-close-btn, #trash-close-btn'
);
closeBtns.forEach(function(btn){
if(btn.__closeBound) return;
btn.__closeBound = true;
btn.addEventListener('click', function(e){
e.preventDefault();
e.stopPropagation();
closeWindow(win);
});
});
// Триггеры внутри окна тоже могут открывать окна
bindOpenTriggers();
// Титульная панель для drag
var tbar =
win.querySelector('.os-tbar') ||
win.querySelector('.w-tbar') ||
win.querySelector('#cookie-tbar') ||
win.querySelector('#quiz-tbar') ||
win.querySelector('#folder-tbar') ||
win.querySelector('#free-folder-tbar') ||
win.querySelector('#trash-tbar') ||
win.querySelector('#images-tbar') ||
win.querySelector('#ie-tbar');
if(tbar) makeDraggable(win, tbar);
addResizeHandles(win, 'os-rsz');
});
}
function fitWindowsToViewport(){
var isMobile = window.innerWidth < 768;
document.querySelectorAll('.os-win, .win98, #cookie-win, #quiz-win, #folder-win, #free-folder-win, #trash-win, #images-win').forEach(function(win){
if(!isVisible(win)) return;
if(isMobile){
var maxW = window.innerWidth - CFG.MOBILE_MARGIN * 2;
var maxH = window.innerHeight - CFG.MOBILE_MARGIN * 2;
if(win.offsetWidth > maxW){
win.style.width = maxW + 'px';
win.style.left = CFG.MOBILE_MARGIN + 'px';
}
if(win.offsetHeight > maxH){
win.style.height = maxH + 'px';
win.style.top = CFG.MOBILE_MARGIN + 'px';
}
var r = win.getBoundingClientRect();
if(r.left < CFG.MOBILE_MARGIN) win.style.left = CFG.MOBILE_MARGIN + 'px';
if(r.top < CFG.MOBILE_MARGIN) win.style.top = CFG.MOBILE_MARGIN + 'px';
if(r.right > window.innerWidth - CFG.MOBILE_MARGIN) win.style.left = Math.max(CFG.MOBILE_MARGIN, window.innerWidth - r.width - CFG.MOBILE_MARGIN) + 'px';
if(r.bottom > window.innerHeight - CFG.MOBILE_MARGIN) win.style.top = Math.max(CFG.MOBILE_MARGIN, window.innerHeight - r.height - CFG.MOBILE_MARGIN) + 'px';
}
});
}
function init(){
bindExistingWindows();
bindOpenTriggers();
fitWindowsToViewport();
}
window.WinManager = {
open: openWindow,
close: closeWindow,
front: bringToFront
};
if(document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
setTimeout(init, 500);
setTimeout(init, 1500);
setTimeout(init, 3000);
window.addEventListener('resize', fitWindowsToViewport);
})();