assets/js/JSWindow.js

958 lines
46 KiB
JavaScript

// Alg. Funktionen
function getTickCount () {
var T = new Date();
return T.getMilliseconds() + T.getSeconds() * 1000 + T.getMinutes() * 60000 + T.getHours() * 3600000 + T.getDay() * 86400000;
}
function clone (obj, runConstructors, chain) { // Abgeaendert von http://forum.de.selfhtml.org/archiv/2009/3/t185276/
if (obj == null || typeof(obj) != 'object') return obj;
if (!chain) chain = new Array(obj);
else {
for (var i = 0; i < chain.length; i++) if (chain[i] == obj) return obj;
chain.push(obj);
}
if (runConstructors) var c = new obj.constructor(); else var c = new Object();
for (var key in obj) if (typeof(obj) == 'object') c[key] = clone(obj[key], runConstructors, chain); else c[key] = obj[key];
return c;
}
function JSWEffect_terminate (win, _break) {
if (!win.effect) return;
if (win.effect['interval']) window.clearInterval(win.effect['interval']);
win.effect['interval'] = null;
win.effect['stop'] = Number.NaN;
var b = false;
if (!_break) b = win.effect['fkt'](win);
win.effect = null;
return b;
}
// Effekte
function JSWEffect_Blend (win, duration, onTerminate, opacity) {
if (duration) { // start
if (!window.getComputedStyle) return; // Keinen Effekt fuer alten IE
var style = window.getComputedStyle(win.el['OuterBox']);
if (JSWEffect_terminate(win, (win.effect && win.effect['fkt'] == JSWEffect_Blend && !win.effect.onTerminate)?true:false)) return; // Falls aktiv, laufenden Effekt beenden; falls laufender Effekt JSWEffect_Blend ist, nur abbrechen
win.effect = new Object();
win.effect['fkt'] = JSWEffect_Blend;
win.effect['onTerminate'] = onTerminate;
win.effect['start'] = getTickCount();
win.effect['stop'] = win.effect['start'] + duration;
if (style && style['visibility'] == 'visible') win.effect['startOP'] = parseFloat(style['opacity']);
else {
win.effect['startOP'] = 0;
win.el['OuterBox'].style.opacity = 0;
win.el['OuterBox'].style.visibility = 'visible';
}
win.effect['stopOP'] = opacity;
win.effect['interval'] = window.setInterval(JSWEffect_Blend, 20, win);
}
var t = getTickCount();
if (isNaN(win.effect['stop']) || t >= win.effect['stop']) { // stop
if (win.effect['interval']) window.clearInterval(win.effect['interval']);
win.effect['interval'] = null;
win.el['OuterBox'].style.opacity = win.effect['stopOP'];
var onTerm = win.effect['onTerminate'];
win.effect = null;
if (onTerm) return onTerm(win);
} else { // effect
var s = (t - win.effect['start']) / (win.effect['stop'] - win.effect['start']);
win.el['OuterBox'].style.opacity = s * win.effect['stopOP'] + (1-s) * win.effect['startOP'];
}
}
function JSWEffect_ThrowBorder (win, duration, onTerminate, top, left, width, height, reverse) {
if (duration) { // start
if (JSWEffect_terminate(win)) return; // Falls aktiv, laufenden Effekt beenden
win.effect = new Object();
win.effect['fkt'] = JSWEffect_ThrowBorder;
win.effect['start'] = getTickCount();
win.effect['stop'] = win.effect['start'] + duration;
win.effect['onTerminate'] = onTerminate;
var p = win.getWindowPos();
win.effect['startTop'] = (reverse)?top:p[1];
win.effect['startLeft'] = (reverse)?left:p[0];
win.effect['startWidth'] = (reverse)?width:win.el['OuterBox'].offsetWidth;
win.effect['startHeight'] = (reverse)?height:win.el['OuterBox'].offsetHeight;
win.effect['stopTop'] = (reverse)?p[1]:top;
win.effect['stopLeft'] = (reverse)?p[0]:left;
win.effect['stopWidth'] = (reverse)?win.el['OuterBox'].offsetWidth:width;
win.effect['stopHeight'] = (reverse)?win.el['OuterBox'].offsetHeight:height;
win.effect['border'] = document.createElement('div');
win.effect['border'].className = 'JSW ThrowingBorder';
document.body.appendChild(win.effect['border']);
win.effect['border'].style.top = win.effect['startTop'] + 'px';
win.effect['border'].style.left = win.effect['startLeft'] + 'px';
win.effect['border'].style.width = win.effect['startWidth'] + 'px';
win.effect['border'].style.height = win.effect['startHeight'] + 'px';
if (win.mgr) win.effect['border'].style.zIndex = win.mgr.maxZ + 1;
win.effect['interval'] = window.setInterval(JSWEffect_ThrowBorder, 20, win);
}
var t = getTickCount();
if (isNaN(win.effect['stop']) || t >= win.effect['stop']) { // stop
if (win.effect['interval']) window.clearInterval(win.effect['interval']);
win.effect['interval'] = null;
document.body.removeChild(win.effect['border']);
win.effect['border'] = null;
win.setOffsetPosition(win.effect['stopTop'], win.effect['stopLeft'], win.effect['stopWidth'], win.effect['stopHeight']);
var onTerm = win.effect['onTerminate'];
win.effect = null;
if (onTerm) return onTerm(win);
} else { // effect
var s = (t - win.effect['start']) / (win.effect['stop'] - win.effect['start']);
win.effect['border'].style.top = s * win.effect['stopTop'] + (1-s) * win.effect['startTop'] + 'px';
win.effect['border'].style.left = s * win.effect['stopLeft'] + (1-s) * win.effect['startLeft'] + 'px';
win.effect['border'].style.width = s * win.effect['stopWidth'] + (1-s) * win.effect['startWidth'] + 'px';
win.effect['border'].style.height = s * win.effect['stopHeight'] + (1-s) * win.effect['startHeight'] + 'px';
}
}
// JSWindow
function JSWindow (_el) {
// Objekte/Arrays initialisieren
this.eventListeners = new Array();
this.selfEventListeners = new Object();
this.parentElement = (_el)?_el.parentElement:null;
this.appended = (this.parentElement)?true:false;
this.el = new Object();
this.el['OuterBox'] = _el;
this.visible = this.appended;
this.pos = new Object();
this.pos['position'] = 'absolute';
// Alle Elemente verlinken/erstellen
var search = true; // falls (spaeter) auf falls gesetzt, so spart sich autoCreateEl die Suche und erstellt das ELement sofort.
var _this = this;
function autoCreateEl(tag, className, parentEl) { // versucht, ein Element vom typ tag und mit entsprechendem className in parentEl zu finden. Wenn nicht vorhanden, wird ein entsprechendes Element erstellt.
if (search) for (var i = 0; i < parentEl.childNodes.length; i++) {
if (parentEl.childNodes[i].nodeType != 1) continue;
if (parentEl.childNodes[i].nodeName.toLowerCase() != tag) continue;
var _className = ' '+parentEl.childNodes[i].className+' ';
if (_className.indexOf(' '+className+' ') < 0) continue;
if (_className.indexOf(' JSW ') < 0) continue;
_this.el[className] = parentEl.childNodes[i];
return;
}
_this.el[className] = document.createElement(tag);
_this.el[className].className = 'JSW ' + className;
if (parentEl) parentEl.appendChild(_this.el[className]);
}
if (!this.el['OuterBox']) {
search = false;
this.el['OuterBox'] = document.createElement('div');
this.el['OuterBox'].className = 'JSW OuterBox';
}
this.el['OuterBox'].jswLinkedWindow = this;
autoCreateEl('div', 'InnerBox', this.el['OuterBox']);
autoCreateEl('div', 'BorderTop', this.el['OuterBox']);
autoCreateEl('div', 'BorderLeft', this.el['OuterBox']);
autoCreateEl('div', 'BorderRight', this.el['OuterBox']);
autoCreateEl('div', 'BorderBottom', this.el['OuterBox']);
autoCreateEl('div', 'EdgeTopLeft', this.el['OuterBox']);
autoCreateEl('div', 'EdgeTopRight', this.el['OuterBox']);
autoCreateEl('div', 'EdgeBottomLeft', this.el['OuterBox']);
autoCreateEl('div', 'EdgeBottomRight', this.el['OuterBox']);
autoCreateEl('div', 'Bar', this.el['OuterBox']);
autoCreateEl('span', 'Title', this.el['Bar']);
autoCreateEl('div', 'Buttons', this.el['Bar']);
autoCreateEl('a', 'ButtonExclude', this.el['Buttons']); this.el['ButtonExclude'].href = 'javascript: \/* '+this.lang.get('newWin')+' *\/';
autoCreateEl('a', 'ButtonMinimize', this.el['Buttons']); this.el['ButtonMinimize'].href = 'javascript: \/* '+this.lang.get('minimize')+' *\/';
autoCreateEl('a', 'ButtonMaximize', this.el['Buttons']); this.el['ButtonMaximize'].href = 'javascript: \/* '+this.lang.get('maximize')+' *\/';
autoCreateEl('a', 'ButtonClose', this.el['Buttons']); this.el['ButtonClose'].href = 'javascript: \/* '+this.lang.get('close')+' *\/';
// Kontextmenue
this.el['Bar'].contextmenu = new Array(
{'text':this.lang.get('newWin'), 'obj':this, 'fkt':this.exclude, 'isenabled':function(){return _this.excludable;}},
{'text':this.lang.get('minimize'), 'obj':this, 'fkt':this.minimize, 'isenabled':function(){return _this.minimizable;}},
{'text':this.lang.get('maximize'), 'obj':this, 'fkt':this.maximize, 'isenabled':function(){return _this.maximizable;}},
{'text':this.lang.get('close'), 'obj':this, 'fkt':this.hide, 'isenabled':function(){return _this.closable;}}
);
// Positionsstyle feststellen
if (_el) {
this.offsetParent = this.el['OuterBox'].offsetParent;
var style = (window.getComputedStyle)?window.getComputedStyle(this.el['OuterBox'], null):this.el['OuterBox'].currentStyle;
if (!style) throw 'Existing Element is not completely initialized. This can be the case, if the element is not inserted into the document or sometimes if the site is in an iframe.';
var realStyle = new Object();
var s = this.el['OuterBox'].getAttribute('style', false).replace(/\s/g, '').toLowerCase().split(';');
for (var i = 0; i < s.length; i++) { s[i] = s[i].split(':'); if (!s[i][0]) continue; realStyle[s[i][0]] = s[i][1]; }
var posNumX = 0;
var posNumY = 0;
this.pos['position'] = style.position;
function positionToInt (p, x) {
if (realStyle[p] && realStyle[p] != 'auto') {
if (x) posNumX++; else posNumY++;
_this.pos[p] = parseInt(style[p]);
if (realStyle[p].indexOf('%') > 0) _this.pos[p+'Percent'] = true;
else _this.pos[p+'Percent'] = false;
} else {
_this.pos[p] = Number.NaN;
_this.pos[p+'Percent'] = false;
}
}
positionToInt('top', false);
positionToInt('left', true);
positionToInt('right', true);
positionToInt('bottom', false);
positionToInt('width', true);
positionToInt('height', false);
if (posNumX == 0) { posNumX++; this.pos['left'] = this.el['OuterBox'].offsetLeft; }
if (posNumY == 0) { posNumY++; this.pos['top'] = this.el['OuterBox'].offsetTop; }
if (posNumX == 1) { if (isNaN(this.pos['width'])) this.pos['width'] = this.el['OuterBox'].offsetWidth; else this.pos['left'] = this.el['OuterBox'].offsetLeft; }
if (posNumY == 1) { if (isNaN(this.pos['height'])) this.pos['height'] = this.el['OuterBox'].offsetHeight; else this.pos['top'] = this.el['OuterBox'].offsetTop; }
if (posNumX == 3) this.pos['right'] = Number.NaN;
if (posNumY == 3) this.pos['bottom'] = Number.NaN;
} else {
this.pos.top = 0;
this.pos.left = 0;
this.pos.width = this.minWidth;
this.pos.height = this.minHeight;
}
// Event-Listener setzen
this.onEvent(this.el['OuterBox'], 'mousedown', this.mouseDown);
this.onEvent(document, 'resize', this.documentResize);
this.onEvent(this.el['ButtonExclude'], 'click', function () { this.exclude(true); });
this.onEvent(this.el['ButtonMinimize'], 'click', this.minimize);
this.onEvent(this.el['ButtonMaximize'], 'click', function () { if (this.maximized) this.normalize(); else this.maximize(); });
this.onEvent(this.el['ButtonClose'], 'click', this.hide);
// setter aufrufen
var s = ' '+this.el['Buttons'].className+' ';
if (s.indexOf(' nonmaximizable ') >= 0) this.maximizable = false;
if (s.indexOf(' nonminimizable ') >= 0) this.minimizable = false;
if (s.indexOf(' nonclosable ') >= 0) this.closable = false;
if (s.indexOf(' nonexcludable ') >= 0) this.excludable = false;
s = ' '+this.el['OuterBox'].className+' ';
if (s.indexOf(' nonresizable ') >= 0) this.resizable = false;
if (s.indexOf(' nonmovable ') >= 0) this.movable = false;
if (s.indexOf(' autoheight ') >= 0) this.autoHeight = true;
if (s.indexOf(' autowidth ') >= 0) this.autoWidth = true;
if (this.el['Title'].innerHTML != '') this.title = this.el['Title'].innerHTML;
for (var i = 0; i < this.el['Bar'].getElementsByTagName('img'); i++) {
var ic = this.el['Bar'].getElementsByTagName('img')[i];
if ((' '+ic.className+' ').indexOf('Icon') >= 0) {
this.el['Bar'].removeChild(ic);
this.icon = ic.src;
}
}
// sonstiges
if (this.hasAtr(this.el['OuterBox'], 'maximized')) this.maximize();
this.setOrRmAtr(this.el['Buttons'], 'nonexcludable', !this._excludable);
if (_el) this.freeOnHide = false;
}
JSWindow.prototype = {
lang : {
de : { minimize:'Minimieren', maximize:'Maximieren', close:'Schliessen', newWin:'In neuem Fenster oeffnen' },
en : { minimize:'minimize', maximize:'maximize', close:'close', newWin:'open in new window' },
get : function (key) {
if (!this.l) {
this.l = navigator.language;
if (!this[this.l]) this.l = 'en';
}
return (this[this.l][key])?this[this.l][key]:key;
}
},
// private
eventListeners : null, // EventListener, die von diesem Objekt gesetzt wurden
selfEventListeners : null, // EventListener, die auf dieses Objekt gesetzt wurden
disabledCount : 0,
// public readonly (darf von public gelesen werden, aber nur von ausgewaehlten Scripts geschrieben)
parentElement : null,
appended : false,
el : null,
visible : false,
pos : null,
effect : null,
maximized : false,
minimized : false,
excluded : false,
freed : false,
// public
_resizable : true, get resizable () { return this._resizable; }, set resizable (v) { this._resizable = v; this.setOrRmAtr(this.el['OuterBox'], 'nonresizable', !v); },
_movable : true, get movable () { return this._movable; }, set movable (v) { this._movable = v; this.setOrRmAtr(this.el['OuterBox'], 'nonmovable', !v); },
effects : null,
mainFrame : null,
minWidth : 40,
minHeight : 25,
freeOnHide : true,
_maximizable : true, get maximizable () { return this._maximizable; }, set maximizable (v) { this._maximizable = v; this.setOrRmAtr(this.el['Buttons'], 'nonmaximizable', !v); },
_minimizable : true, get minimizable () { return this._minimizable; }, set minimizable (v) { this._minimizable = v; this.setOrRmAtr(this.el['Buttons'], 'nonminimizable', !v); },
_closable : true, get closable () { return this._closable; }, set closable (v) { this._closable = v; this.setOrRmAtr(this.el['Buttons'], 'nonclosable', !v); },
_excludable : false, get excludable () { return this._excludable; }, set excludable (v) { this._excludable = v; this.setOrRmAtr(this.el['Buttons'], 'nonexcludable', !v); },
minimizePoint : function () { return new Array(0, 0); },
minimalVisible : new Array(0, -10, -10, -10),
_title : '', get title () { return this._title; }, set title (v) { this.setTitle(v); },
_icon : '', get icon () { return this._icon; }, set icon (v) { this.setIcon(v); },
_autoHeight : false, get autoHeight () { return this._autoHeight; }, set autoHeight (v) {
if (this.freed) throw 'Object is freed';
if (v == this._autoHeight) return;
this._autoHeight = v;
this.setOrRmAtr(this.el['OuterBox'], 'autoheight', v);
if (this.mainFrame && this.mainFrame.communicator) this.mainFrame.communicator.autoHeight = v;
if (v) {
if (isNaN(this.pos.height)) this.el['OuterBox'].style.bottom = 'auto'; else this.el['OuterBox'].style.height = 'auto';
} else {
this.actualizePos();
this.setPos();
if (this.mainFrame) this.mainFrame.style.height = '100%';
}
},
_autoWidth : false, get autoWidth () { return this._autoWidth; }, set autoWidth (v) {
if (this.freed) throw 'Object is freed';
if (v == this._autoWidth) return;
this._autoWidth = v;
this.setOrRmAtr(this.el['OuterBox'], 'autowidth', v);
if (this.mainFrame && this.mainFrame.communicator) this.mainFrame.communicator.autoWidth = v;
if (v) {
if (isNaN(this.pos.width)) this.el['OuterBox'].style.right = 'auto'; else this.el['OuterBox'].style.width = 'auto';
} else {
this.actualizePos();
this.setPos();
if (this.mainFrame) this.mainFrame.style.width = '100%';
}
},
extendBar : /* public */ function () {
if (this.el.BarExtension) return this.el.BarExtension;
this.el.BarExtension = document.createElement('div');
this.el.BarExtension.className = 'JSW BarExtension';
function onResize () {
this.el.BarExtension.style.height = this.el.BarExtension.scrollHeight + 'px';
this.el.OuterBox.style.paddingTop = (this.el.BorderTop.offsetHeight + this.el.Bar.offsetHeight + this.el.BarExtension.offsetHeight) + 'px';
}
this.onEvent(this.el.BarExtension, 'overflow', onResize);
this.onEvent(this.el.BarExtension, 'underflow', onResize);
this.el.OuterBox.appendChild(this.el.BarExtension);
return this.el.BarExtension;
},
setIcon : /* protected */ function (v) { // to be overridden
if (v == '' && this.el['Icon']) {
this.el['Bar'].removeChild(this.el['Icon']);
delete this.el['Icon'];
}
if (v != '' && !this.el['Icon']) {
this.el['Icon'] = document.createElement('img');
this.el['Icon'].className = 'JSW Icon';
this.el['Bar'].insertBefore(this.el['Icon'], this.el['Title']);
}
this._icon = v;
if (v != '') this.el['Icon'].src = v;
},
setTitle : /* protected */ function (v) { // to be overridden
if (this.freed) throw 'Object is freed';
this.el['Title'].innerHTML = v;
this._title = v;
},
addEventListener : /* public */ function (type, fkt) {
if (this.freed) throw 'Object is freed';
if (!this.selfEventListeners[type]) this.selfEventListeners[type] = new Array();
this.selfEventListeners[type].push(fkt);
},
removeEventListener : /* public */ function (type, fkt) {
if (this.freed) throw 'Object is freed';
if (!this.selfEventListeners[type]) return;
var i = 0;
while (i < this.selfEventListeners[type].length) if (this.selfEventListeners[type][i] == fkt) this.selfEventListeners[type].splice(i, 1); else i++;
if (this.selfEventListeners[type].length == 0) delete this.selfEventListeners[type];
},
callEventListener : /* protected */ function (type, param) {
try { // try notwendig, weil Fenster durch einen EventListener freigegeben werden koennte
if (this.selfEventListeners[type]) for (var i = 0; i < this.selfEventListeners[type].length; i++) this.selfEventListeners[type][i](this, param);
if (this.mgr && this.mgr.eventListeners[type]) for (var i = 0; i < this.mgr.eventListeners[type].length; i++) this.mgr.eventListeners[type][i](this, param);
} catch (e) {}
},
disable : /* public */ function () {
if (this.freed) throw 'Object is freed';
if (this.disabledCount == 0) {
this.el['Disabled'] = document.createElement('div');
this.el['Disabled'].className = 'JSW Disabled';
this.el['OuterBox'].appendChild(this.el['Disabled']);
}
this.disabledCount++;
},
enable : /* public */ function () {
if (this.freed) throw 'Object is freed';
this.disabledCount--;
if (this.disabledCount <= 0) {
this.disabledCount = 0;
this.el['OuterBox'].removeChild(this.el['Disabled']);
}
},
hiddenCover : /* protected */ function (covered) {
if (covered) {
if (this.el['FrameCover']) return;
this.el['FrameCover'] = document.createElement('div');
this.el['FrameCover'].className = 'JSW FrameCover';
this.el['OuterBox'].appendChild(this.el['FrameCover']);
} else if (this.el['FrameCover']) {
this.el['OuterBox'].removeChild(this.el['FrameCover']);
this.el['FrameCover'] = null;
}
},
showFrameload : /* public */ function (parent) {
if (this.freed) throw 'Object is freed';
if (this.appended) return;
if (parent) this.parentElement = parent;
this.el['OuterBox'].style.visibility = 'hidden';
this.parentElement.appendChild(this.el['OuterBox']);
this.appended = true;
},
show : /* public */ function (parent) {
if (this.freed) throw 'Object is freed';
JSWEffect_terminate(this); // falls gerade ein hide-Effekt laeuft, muss dieser beendet werden, damit appended auf false gesetzt wird, bevor show durchlaeuft!
if ((this.visible && (!parent || parent == this.parentElement)) || (!this.parentElement && !parent)) return;
if (parent) {
if (this.parentElement && (this.parentElement != parent)) this.appended = false;
this.parentElement = parent;
}
this.visible = true;
if (!this.excluded) this.el['OuterBox'].style.visibility = 'hidden';
if (!this.appended) {
if (!this.parentElement) throw 'Parent element of the window is not specified!';
try { this.parentElement.appendChild(this.el['OuterBox']); }
catch (e) {
// Fuer IE: Alle Elemente neu erstellen statt umhaengen
this.parentElement.innerHTML = this.el['OuterBox'].outerHTML;
var oldEl = this.el;
this.el = new Object();
this.el['OuterBox'] = this.parentElement.getElementsByTagName('div')[0];
var found;
do {
found = false;
for (var key in oldEl) {
if (this.el[key]) continue;
var n = oldEl[key].nodeName;
for (var i = 0; i < oldEl['OuterBox'].getElementsByTagName(n).length; i++) if (oldEl['OuterBox'].getElementsByTagName(n)[i] == oldEl[key]) {
this.el[key] = this.el['OuterBox'].getElementsByTagName(n)[i];
found = true;
break;
}
}
} while (found);
}
this.appended = true;
}
if (!this.excluded) {
this.setPos();
if (this.effects && this.effects['Show']) this.effects['Show'](this, this.effects['duration'], null, this.effects['ShowParams']);
else this.el['OuterBox'].style.visibility = 'visible';
}
this.documentResize();
this.callEventListener('show');
this.callEventListener('move');
},
hide : /* public */ function () {
if (this.freed) throw 'Object is freed';
if (!this.visible || !this.closable) return;
this.visible = false;
if (this.excluded) {
this.excludedWindow.close();
return;
}
var onEffectTerminate = function (win) {
win.el['OuterBox'].style.visibility = 'hidden';
win.callEventListener('hide');
if (win.parentElement /* ToDo: wenn win.effects = null tritt hier ohne if ein Fehler auf */) win.parentElement.removeChild(win.el['OuterBox']);
win.appended = false;
var b = win.freeOnHide;
if (b) win.free();
return b;
}
if (this.effects && this.effects['Hide']) this.effects['Hide'](this, this.effects['duration'], onEffectTerminate, this.effects['HideParams']);
else window.setTimeout(onEffectTerminate, 0, this);
},
setPos : /* public */ function (newPos) { // Wendet den in Pos gespeicherten Style auf OuterBox an
// Hinweis: Neben setPos greift auch mouseMove:applyChange auf die Positionsstyles von OuterBox zu!
if (this.freed) throw 'Object is freed';
var pw = this.parentOffsetWidth();
var ph = this.parentOffsetHeight();
if (newPos) {
var _this = this;
var i, s;
var rect = function (site) { if (site == -1) return 0; if (_this.minimalVisible[site] < 0) return 0; else return _this.minimalVisible[site]; }
var interpret = function (type, ps, site) {
i = newPos.indexOf(';' + type + ':');
if (i == -1) _this.pos[type] = Number.NaN; else {
s = newPos.substring(i+2+type.length, newPos.indexOf(';', i+2+type.length));
if (s.indexOf('%') == -1) _this.pos[type+'Percent'] = false; else { s = ps*parseFloat(s)/100; _this.pos[type+'Percent'] = true; }
_this.pos[type] = parseFloat(s) + rect(site);
}
}
newPos = ';'+newPos.split(' ').join('');
interpret('top', ph, 0);
interpret('left', pw, 1);
interpret('right', pw, 2);
interpret('bottom', ph, 3);
interpret('width', pw, -1);
interpret('height', ph, -1);
i = newPos.indexOf(';position:'); if (i >= 0 && newPos.substring(i+10, newPos.indexOf(';', i+10)).indexOf('fixed') >= 0) this.pos.position = 'fixed'; else this.pos.position = 'absolute';
}
if (this.excluded) {
// ToDo
return;
}
if (!this.appended) return;
if (!this.pos['position']) this.pos['position'] = 'absolute';
this.el['OuterBox'].style.position = this.pos['position'];
if (this.maximized) {
this.el['OuterBox'].style.top = ((this.minimalVisible[0] > 0)?this.minimalVisible[0]:0) + 'px';
this.el['OuterBox'].style.left = ((this.minimalVisible[1] > 0)?this.minimalVisible[1]:0) + 'px';
this.el['OuterBox'].style.right = ((this.minimalVisible[2] > 0)?this.minimalVisible[2]:0) + 'px';
this.el['OuterBox'].style.bottom = ((this.minimalVisible[3] > 0)?this.minimalVisible[3]:0) + 'px';
this.el['OuterBox'].style.width = 'auto';
this.el['OuterBox'].style.height = 'auto';
return;
}
this.el['OuterBox'].style.top = (isNaN(this.pos['top'])) ?'auto':((this.pos['topPercent']) ?(this.pos['top'] / ph * 100 + '%'):(this.pos['top'] + 'px'));
this.el['OuterBox'].style.left = (isNaN(this.pos['left'])) ?'auto':((this.pos['leftPercent']) ?(this.pos['left'] / pw * 100 + '%'):(this.pos['left'] + 'px'));
if (!this.autoWidth || isNaN(this.pos.left)) this.el['OuterBox'].style.right = (isNaN(this.pos['right'])) ?'auto':((this.pos['rightPercent']) ?(this.pos['right'] / pw * 100 + '%'):(this.pos['right'] + 'px'));
else this.el['OuterBox'].style.right = 'auto';
if (!this.autoHeight || isNaN(this.pos.top)) this.el['OuterBox'].style.bottom = (isNaN(this.pos['bottom']))?'auto':((this.pos['bottomPercent'])?(this.pos['bottom'] / ph * 100 + '%'):(this.pos['bottom'] + 'px'));
else this.el['OuterBox'].style.bottom = 'auto';
if (!this.autoWidth) this.el['OuterBox'].style.width = (isNaN(this.pos['width'])) ?'auto':((this.pos['widthPercent']) ?(this.pos['width'] / pw * 100 + '%'):(this.pos['width'] + 'px'));
if (!this.autoHeight) this.el['OuterBox'].style.height = (isNaN(this.pos['height']))?'auto':((this.pos['heightPercent'])?(this.pos['height'] / ph * 100 + '%'):(this.pos['height'] + 'px'));
this.callEventListener('move');
},
getWindowPos : /* protected */ function () { // Returns an Array, that contains the Position of OuterBox, seen from the inner Window
if (this.freed) throw 'Object is freed';
var pos;
if (window.getComputedStyle(this.el['OuterBox']).position == 'fixed') pos = new Array(this.el['OuterBox'].offsetLeft, this.el['OuterBox'].offsetTop);
else pos = new Array(this.offsetLeftFrom(this.el['OuterBox'], document.body) - window.pageXOffset, this.offsetTopFrom(this.el['OuterBox'], document.body) - window.pageYOffset);
return pos;
},
hasAtr : /* private */ function (el, atr) {
if (!el) return false;
if ((' '+el.className+' ').indexOf(' '+atr+' ') >= 0) return true;
else return false;
},
setAtr : /* private */ function (el, atr) {
if (!el) return;
if ((' '+el.className+' ').indexOf(' '+atr+' ') >= 0) return;
el.className += ' '+atr;
},
rmAtr : /* private */ function (el, atr) {
if (!el) return;
var a = el.className.split(' ');
var s = '';
for (var i = 0; i < a.length; i++) {
if (!a[i] || a[i] == atr) continue;
if (i > 0) s += ' ';
s += a[i];
}
el.className = s;
},
setOrRmAtr : /* private */ function (el, atr, set) { if (this.freed) throw 'Object is freed'; if (set) this.setAtr(el, atr); else this.rmAtr(el, atr); },
onEvent : /* private */ function (el, event, fkt, bubbles) { // provides easy eventListeners. el: Element to set the listener; event: string-name of the event(without "on"); fkt: a Function to call if the event occours, fkt is called in the scope of _this
if (!el) return;
var _this = this;
var oev = new Object();
oev['f'] = function (ev) {
// Browseruebergreifende Kompatibilitaet
if (!ev) ev = window.event;
if (!ev.target) ev.target = ev.srcElement;
if (!ev.offsetX && ev.pageX) {
ev.offsetX = ev.pageX - _this.offsetLeftFrom(ev.target, document.body);
ev.offsetY = ev.pageY - _this.offsetTopFrom(ev.target, document.body);
}
fkt.call(_this, ev);
}
oev['event'] = event;
oev['el'] = el;
el.addEventListener(event, oev['f'], bubbles);
this.eventListeners.push(oev);
return oev;
},
rmEvent : function (oev) { // oev wird von onEvent zurueckgegeben
var nr = oev;
if (isNaN(nr)) {
nr = 0;
while (nr < this.eventListeners.length) if (this.eventListeners[nr] == oev) break; else nr++;
if (nr >= this.eventListeners.length || this.eventListeners[nr] != oev) return;
} else {
if (nr < 0 || nr >= this.eventListeners.length) return;
oev = this.eventListeners[nr];
}
if (document.removeEventListener) oev['el'].removeEventListener(oev['event'], oev['f'], false); else oev['el'].detachEvent('on'+oev['event'], oev['f']);
this.eventListeners.splice(nr, 1);
},
actualizePos : /* private */ function () { // falls prozentuale Angaben oder autoHeight/autoWidth verwendet werden, wird die Pixelposition neu berechnet
// Falls prozentuale Angaben verwendet werden, Position aktualisieren
if (!this.visible || this.excluded || this.minimized || this.maximized) return;
var style = null;
var _this = this;
function checkStyle (type) {
if (isNaN(_this.pos[type])) return;
if (!style) style = window.getComputedStyle(_this.el['OuterBox']);
_this.pos[type] = parseInt(style[type]);
}
checkStyle('top');
checkStyle('left');
checkStyle('right');
checkStyle('bottom');
checkStyle('width');
checkStyle('height');
},
offsetLeftFrom : /* private */ function (el, offsetEl) { // Ermittelt den Linken Abstand eines Elements bis zu einem bestimmten Eltern-ELement
var r = 0;
do {
r += el.offsetLeft;
el = el.offsetParent;
} while (el && el != offsetEl);
return r;
},
offsetTopFrom : /* private */ function (el, offsetEl) { // Ermittelt den Oberen Abstand eines Elements bis zu einem bestimmten Eltern-ELement
var r = 0;
do {
r += el.offsetTop;
el = el.offsetParent;
} while (el && el != offsetEl);
return r;
},
parentOffsetWidth : /* private */ function () { // Gibt die Breite des fuer das Fenster verfuegbaren Anzeigebereiches zurueck
if (this.excluded) return screen.availWidth;
if (!this.el['OuterBox'].offsetParent || this.el['OuterBox'].offsetParent == document.body) return window.innerWidth;
else return this.el['OuterBox'].offsetParent.offsetWidth;
},
parentOffsetHeight : /* private */ function () { // Gibt die Hoehe des fuer das Fenster verfuegbaren Anzeigebereiches zurueck
if (this.excluded) return screen.availHeight;
if (!this.el['OuterBox'].offsetParent || this.el['OuterBox'].offsetParent == document.body) return window.innerHeight;
else return this.el['OuterBox'].offsetParent.offsetHeight;
},
offsetTop : /* private */ function () { // Gibt den Abstand von oben bis zum offsetParent des normalisierten Fensters in Pixeln zurueck
if (!isNaN(this.pos.top)) return this.pos.top;
return this.parentOffsetHeight() - this.pos.height - this.pos.bottom;
},
offsetLeft : /* private */ function () { // Gibt den Abstand von links bis zum offsetParent des normalisierten Fensters in Pixeln zurueck
if (!isNaN(this.pos.left)) return this.pos.left;
return this.parentOffsetWidth() - this.pos.width - this.pos.right;
},
offsetWidth : /* private */ function () { // Gibt die Breite des normalisierten Fensters in Pixeln zurueck
if (!isNaN(this.pos.width)) return this.pos.width;
return this.parentOffsetWidth() - this.pos.left - this.pos.right;
},
offsetHeight : /* private */ function () { // Gibt die Hoehe des normalisierten Fensters in Pixeln zurueck
if (!isNaN(this.pos.height)) return this.pos.height;
return this.parentOffsetHeight() - this.pos.top - this.pos.bottom;
},
setOffsetPosition : /* public */ function (top, left, width, height) { // rechnet die gegebenen Parameter auf die Positionierung des Fensters um, sodass Anker und prozentuale Angaben erhalten bleiben
if (this.freed) throw 'Object is freed';
if (!this.visible || this.maximized || this.minimized) return;
if (this.excluded) {
// ToDo
return;
}
var pw = this.parentOffsetWidth();
var ph = this.parentOffsetHeight();
if (!isNaN(this.pos['top'])) this.pos['top'] = top;
if (!isNaN(this.pos['left'])) this.pos['left'] = left;
if (!isNaN(this.pos['right'])) this.pos['right'] = (isNaN(pw))?0:(pw - width - left);
if (!isNaN(this.pos['bottom'])) this.pos['bottom'] = (isNaN(ph))?0:(ph - height - top);
if (!isNaN(this.pos['width'])) this.pos['width'] = width;
if (!isNaN(this.pos['height'])) this.pos['height'] = height;
this.setPos();
},
mouseDown : /* private */ function (ev) {
if (ev.button && ev.button != 0) return;
this.lastMouseDown = ev;
if (this.maximized) return;
// Aktion fuer move und resize einrichten
var p = ev.target;
var target = p;
ev.target = null;
do {
p = p.parentElement;
if (p == this.el['Bar'] || p == this.el['Buttons']) {
target = p;
break;
}
} while (p);
var b = false;
if ((target == this.el['EdgeTopLeft'] || target == this.el['EdgeTopRight'] || target == this.el['EdgeBottomLeft'] || target == this.el['EdgeBottomRight']) && this.resizable) { this.autoHeight = false; this.autoWidth = false; b = true; }
else if ((target == this.el['BorderTop'] || target == this.el['BorderBottom']) && this.resizable) { this.autoHeight = false; b = true; }
else if ((target == this.el['BorderLeft'] || target == this.el['BorderRight']) && this.resizable) { this.autoWidth = false; b = true; }
else if (target == this.el['Bar'] && this.movable) b = true;
if (b) { // Ein Element fuer resize/move wurde angeklickt
this.actualizePos();
// Startposition festhalten
this.startPos = clone(this.pos);
this.startPos['mausX'] = ev.clientX;
this.startPos['mausY'] = ev.clientY;
this.startPos['target'] = target;
// Cursor-Element und Events setzen
this.hiddenCover(true);
this.el['FrameCover'].style.margin = '-50px';
this.startPos['oldMouseDown'] = document.onmousedown;
document.onmousedown = function () { return false; }
this.startPos['mouseUpOev'] = this.onEvent(document, 'mouseup', this.mouseUp);
this.startPos['mouseMoveOev'] = this.onEvent(document, 'mousemove', this.mouseMove, true);
}
},
documentResize : /* private */ function () {
if (!this.visible || this.excluded || this.maximized || this.minimized) return;
// falls ausserhalb von Anzeigebereich, zuruecksetzen
if (this.minimalVisible) {
if (this.minimalVisible[0] >= 0) { if (this.el['OuterBox'].offsetTop < this.minimalVisible[0]) this.setOffsetPosition(this.minimalVisible[0], this.el['OuterBox'].offsetLeft, this.el['OuterBox'].offsetWidth, this.el['OuterBox'].offsetHeight); }
else { /* ToDo */ }
if (this.minimalVisible[1] >= 0) { /* ToDo */ }
else { if (this.el['OuterBox'].offsetLeft + this.el['OuterBox'].offsetWidth < - this.minimalVisible[1]) this.setOffsetPosition(this.el['OuterBox'].offsetTop, - this.minimalVisible[1] - this.el['OuterBox'].offsetWidth, this.el['OuterBox'].offsetWidth, this.el['OuterBox'].offsetHeight); }
if (this.minimalVisible[2] >= 0) { /* ToDo */ }
else { if (this.el['OuterBox'].offsetLeft > this.parentOffsetWidth() + this.minimalVisible[2] && (window.getComputedStyle(this.el['OuterBox'].offsetParent).overflow == 'hidden' || this.pos.position == 'fixed')) this.setOffsetPosition(this.el['OuterBox'].offsetTop, this.parentOffsetWidth() + this.minimalVisible[2], this.el['OuterBox'].offsetWidth, this.el['OuterBox'].offsetHeight); }
if (this.minimalVisible[3] >= 0) { /* ToDo */ }
else { if (this.el['OuterBox'].offsetTop > this.parentOffsetHeight() + this.minimalVisible[3] && (window.getComputedStyle(this.el['OuterBox'].offsetParent).overflow == 'hidden' || this.pos.position == 'fixed')) this.setOffsetPosition(this.parentOffsetHeight() + this.minimalVisible[3], this.el['OuterBox'].offsetLeft, this.el['OuterBox'].offsetWidth, this.el['OuterBox'].offsetHeight); }
}
},
mouseUp : /* private */ function (ev) {
if (this.startPos) {
// Move-Events und Einstellungen zuruecknehmen
this.el['FrameCover'].style.margin = '0px';
this.hiddenCover(false);
this.rmEvent(this.startPos['mouseUpOev']);
this.rmEvent(this.startPos['mouseMoveOev']);
document.onmousedown = this.startPos['oldMouseDown'];
this.startPos = null;
this.documentResize();
}
},
mouseMove : /* private */ function (ev) {
if (!this.startPos) return;
// OuterBox bewegen
var _this = this;
function applyChange (type, horizontal, invert) {
_this.pos[type] = _this.startPos[type] + (-_this.startPos['maus'+(horizontal?'X':'Y')] + (horizontal?ev.clientX:ev.clientY)) * (invert?(-1):(1));
if (_this.startPos[type+'Percent']) {
var size;
size = (horizontal?_this.parentOffsetWidth():_this.parentOffsetHeight());
_this.el['OuterBox'].style[type] = _this.pos[type] / size * 100 + '%';
} else _this.el['OuterBox'].style[type] = _this.pos[type] + 'px';
}
if (this.startPos['target'] == this.el['Bar']) {
if (isNaN(this.startPos['right'])) { applyChange('left', true, false); }
else if (isNaN(this.startPos['left'])) { applyChange('right', true, true); }
else if (isNaN(this.startPos['width'])) { applyChange('left', true, false); if (!this.autoWidth) applyChange('right', true, true); }
if (isNaN(this.startPos['bottom'])) { applyChange('top', false, false); }
else if (isNaN(this.startPos['top'])) { applyChange('bottom', false, true); }
else if (isNaN(this.startPos['height'])) { applyChange('top', false, false); if (!this.autoHeight) applyChange('bottom', false, true); }
}
if (this.startPos['target'] == this.el['BorderTop'] || this.startPos['target'] == this.el['EdgeTopLeft'] || this.startPos['target'] == this.el['EdgeTopRight']) {
if (isNaN(this.startPos['bottom'])) { applyChange('top', false, false); applyChange('height', false, true); }
else if (isNaN(this.startPos['top'])) { applyChange('height', false, true); }
else if (isNaN(this.startPos['height'])) { applyChange('top', false, false); }
this.autoHeight = false;
}
if (this.startPos['target'] == this.el['BorderLeft'] || this.startPos['target'] == this.el['EdgeTopLeft'] || this.startPos['target'] == this.el['EdgeBottomLeft']) {
if (isNaN(this.startPos['right'])) { applyChange('left', true, false); applyChange('width', true, true); }
else if (isNaN(this.startPos['left'])) { applyChange('width', true, true); }
else if (isNaN(this.startPos['width'])) { applyChange('left', true, false); }
this.autoWidth = false;
}
if (this.startPos['target'] == this.el['BorderRight'] || this.startPos['target'] == this.el['EdgeTopRight'] || this.startPos['target'] == this.el['EdgeBottomRight']) {
if (isNaN(this.startPos['right'])) { applyChange('width', true, false); }
else if (isNaN(this.startPos['left'])) { applyChange('width', true, false); applyChange('right', true, true); }
else if (isNaN(this.startPos['width'])) { applyChange('right', true, true); }
this.autoWidth = false;
}
if (this.startPos['target'] == this.el['BorderBottom'] || this.startPos['target'] == this.el['EdgeBottomLeft'] || this.startPos['target'] == this.el['EdgeBottomRight']) {
if (isNaN(this.startPos['bottom'])) { applyChange('height', false, false); }
else if (isNaN(this.startPos['top'])) { applyChange('height', false, false); applyChange('bottom', false, true); }
else if (isNaN(this.startPos['height'])) { applyChange('bottom', false, true); }
this.autoHeight = false;
}
this.callEventListener('move');
},
exclude : /* public */ function (click) {
if (this.freed) throw 'Object is freed';
if (!this.excludable || this.excluded) return;
// Fenster oeffnen
var p = this.getWindowPos();
var pos = new Array(this.el['OuterBox'].offsetWidth, this.el['OuterBox'].offsetHeight, p[0], p[1]);
var w = window.open('', '', 'width='+pos[0]+',height='+pos[1]+',left='+pos[2]+',top='+pos[3]);
if (!w) return; // Popup blockiert!
if (click) {
if (window.opera) { // Nur im echten Opera kann die Position pixelgenau berechnet werden!
var zoom = pos[0] / w.innerWidth;
pos[2] = pos[2] * zoom + (w.outerWidth - w.innerWidth * zoom) / 2;
pos[3] = pos[3] * zoom + w.outerHeight - w.innerHeight * zoom - (w.outerWidth - w.innerWidth * zoom) / 2;
pos[0] = pos[0] * zoom;
pos[1] = pos[1] * zoom;
w.resizeTo(pos[0], pos[1]);
} else if (w.innerWidth > 0) {
var zoom = w.innerWidth / pos[0]; // Annahme: Neues Fenster hat gleichen Zoomfaktor, wie Hauptfenster
pos[2] = this.lastMouseDown.screenX - (this.lastMouseDown.clientX - pos[2]) * zoom;
pos[3] = this.lastMouseDown.screenY - (this.lastMouseDown.clientY - pos[3]) * zoom;
}
w.moveTo(pos[2], pos[3]);
}
this.excludedWindow = w;
// Fenster umhaengen
this.parentElement.removeChild(this.el['OuterBox']);
this.appended = false;
this.el['OuterBox'].className += ' excluded';
this.el['OuterBox'].style.position = 'absolute';
this.el['OuterBox'].style.top = '0px';
this.el['OuterBox'].style.left = '0px';
this.el['OuterBox'].style.width = '100%';
this.el['OuterBox'].style.height = '100%';
for (var i = 0; i < this.el['OuterBox'].childNodes.length; i++)
if (this.el['OuterBox'].childNodes[i].nodeType == 1)
this.el['OuterBox'].childNodes[i].style.display = 'none';
this.el['InnerBox'].style.display = 'block';
this.el['InnerBox'].style.position = 'absolute';
this.el['InnerBox'].style.top = '0px';
this.el['InnerBox'].style.left = '0px';
this.el['InnerBox'].style.right = '0px';
this.el['InnerBox'].style.bottom = '0px';
w.document.title = this.el['Title'].innerHTML;
var sty = document.getElementsByTagName('head')[0].getElementsByTagName('link');
for (var i = 0; i < sty.length; i++) {
if (sty[i].rel.toLowerCase() != 'stylesheet') continue;
var cloneSty = document.createElement('link');
cloneSty.rel = 'stylesheet';
cloneSty.href = sty[i].href;
w.document.getElementsByTagName('head')[0].appendChild(cloneSty);
}
sty = document.getElementsByTagName('head')[0].getElementsByTagName('style');
for (var i = 0; i < sty.length; i++)
w.document.getElementsByTagName('head')[0].innerHTML += sty[i].outerHTML;
this.excluded = true;
this.show(w.document.body);
var _this = this;
this.onEvent(w, 'beforeunload', function () { _this.free(); });
this.excludedClosedTimer = window.setInterval(function () { if (w.closed) _this.free(); }, 100);
this.callEventListener('exclude');
},
maximize : /* public */ function () {
if (this.freed) throw 'Object is freed';
if (!this.maximizable) return;
if (this.excluded) {
// Todo
return;
}
this.maximized = true;
var t = (this.minimalVisible[0] > 0)?this.minimalVisible[0]:0;
var l = (this.minimalVisible[1] > 0)?this.minimalVisible[1]:0;
var r = (this.minimalVisible[2] > 0)?this.minimalVisible[2]:0;
var b = (this.minimalVisible[3] > 0)?this.minimalVisible[3]:0;
var onEffectTerminate = function (win) {
win.el['OuterBox'].style.top = t+'px';
win.el['OuterBox'].style.left = l+'px';
win.el['OuterBox'].style.right = r+'px';
win.el['OuterBox'].style.bottom = b+'px';
win.el['OuterBox'].style.width = 'auto';
win.el['OuterBox'].style.height = 'auto';
win.el['OuterBox'].style.position = (this.parentElement == document.body)?'fixed':'absolute';
win.setAtr(win.el['OuterBox'], 'maximized');
win.callEventListener('move');
}
if (this.visible && this.effects && this.effects['Maximize']) this.effects['Maximize'](this, this.effects['duration'], onEffectTerminate, t, l, this.parentOffsetWidth()-r, this.parentOffsetHeight()-b, this.effects['MaximizeParams']);
else onEffectTerminate(this);
this.callEventListener('maximize');
},
normalize : /* public */ function () {
if (this.freed) throw 'Object is freed';
if (!this.visible) { this.maximized = false; return; }
if (this.excluded) {
// ToDo
return;
}
var onEffectTerminate = function (win) {
win.maximized = false;
win.rmAtr(win.el['OuterBox'], 'maximized');
win.setPos();
}
var fixed = this.pos['position'] == 'fixed';
if (this.effects && this.effects['Normalize']) this.effects['Normalize'](this, this.effects['duration'], onEffectTerminate, this.offsetTop() - ((fixed)?0:window.pageYOffset), this.offsetLeft() - ((fixed)?0:window.pageXOffset), this.offsetWidth(), this.offsetHeight(), this.effects['NormalizeParams']);
else onEffectTerminate(this);
this.callEventListener('normalize');
},
minimize : /* public */ function () {
if (this.freed) throw 'Object is freed';
if (!this.visible || !this.minimizable) return;
if (this.excluded) {
// ToDo
return;
}
this.minimized = true;
var p = this.minimizePoint();
var onEffectTerminate = function (win) {
win.el['OuterBox'].style.visibility = 'hidden';
}
if (this.effects && this.effects['Minimize']) this.effects['Minimize'](this, this.effects['duration'], onEffectTerminate, p[0], p[1], this.effects['MinimizeParams']);
else onEffectTerminate(this);
this.callEventListener('minimize');
},
unminimize : /* public */ function () {
if (this.freed) throw 'Object is freed';
if (!this.visible || !this.minimized) return;
if (this.excluded) {
// ToDo
return;
}
var p = this.minimizePoint();
var onEffectTerminate = function (win) {
win.minimized = false;
win.el['OuterBox'].style.visibility = 'visible';
}
if (this.effects && this.effects['Unminimize']) this.effects['Unminimize'](this, this.effects['duration'], onEffectTerminate, p[0], p[1], this.effects['UnminimizeParams']);
else onEffectTerminate(this);
this.callEventListener('unminimize');
},
free : /* public */ function () {
try {
if (this.excludedClosedTimer) window.clearInterval(this.excludedClosedTimer);
for (var i = this.eventListeners.length-1; i >= 0; i--) this.rmEvent(i);
JSWEffect_terminate(this);
if (this.scrollRectListener) this.scrollRectListener.free();
if (this.appended) this.parentElement.removeChild(this.el['OuterBox']);
} catch (e) {}
this.callEventListener('free');
this.freed = true;
for (var key in this) if (typeof this[key] == 'object') this[key] = null;
}
}