function spcWindow(settings)
{
	var config =
		{ name:           ''
		, title:          '(no title)'
		, className:      ''
		
		, content:        null

		// behaviour
		, canclose:       true
		, candrag:        true // for future use
		, modal:          false
		, visible:        true
		, preferredWidth: null
		
		// size & position
		, fullscreen:     false
		, center:         true	
/*		, left:           null
		, right:          null
		, top:            null
		, bottom:         null
		, width:          null
		, height:         null
*/
		, anchoredge:		''
		, anchorishorcentre:	false
		, anchorisvercentre:	false

		//, widthmin:       100
		//, width:          null // null = auto
		//, widthmax:       null
		//, heightmin:      100
		//, height:         null // null = auto
		//, heightmax:      null

		// events
		, onresize:       null
		, onbeforeclose:  null
		, onclose:        null
		};

	// override default settings with given settings
    for(var prop in settings)
    	config[prop] = settings[prop];

	this.id = settings.id;

	var _this = this;
	this.isclosing = false;

	this.config = config;


	var wndclasses = [];
	wndclasses.push('wndContainer');
	wndclasses.push('vizWindow');

	if (config.candrag)
		wndclasses.push('canbedragged');
	
	if (config.className != '')
		wndclasses.push(config.className);

	if (config.fullscreen)
		wndclasses.push('vizWindowFullscreen');


		
	var wnd = document.createElement('div');
	wnd.className = wndclasses.join(' ');

	// we don't need borders in fullscreen
	// (if we want to support going out of fullscreen, we can add these borders later)
	if (!config.fullscreen)
      wnd.innerHTML = '<div class="wndBorderTL"></div><div class="wndBorderT"></div><div class="wndBorderTR"></div><div class="wndBorderML"></div><div class="wndBorderMR"></div><div class="wndBorderBL"></div><div class="wndBorderB"></div><div class="wndBorderBR"></div>';

	this.window = wnd;
	
	
	/*
	// shim frame ..
	var frame = document.createElement("iframe");
	//frame.style.cssText = "position: absolute; top: 0px; left: 0px; bottom: 0; right: 0; z-index: -1; background-color: #FFF;";
	frame.style.cssText = "position: absolute; top: 0px; left: -15px; width: 100%; height: 100%; z-index: -1; background-color: #FFF;";
	this.window.appendChild(frame);
	*/

	
	// NOTE: dragging will not work correctly if the topleft corner is not the anchorposition
	if (config.anchoredge != '')
	{
		this.anchor = document.createElement('div');
		this.anchor.style.position = 'absolute';
		this.anchor.appendChild(this.window);

		var hposvalue = config.anchorishorcentre ? '50%' : '0'; // NOT WORKING
		var vposvalue = config.anchorisvercentre ? '50%' : '0'; // NOT WORKING

		this.setAnchor(config.anchoredge, hposvalue, vposvalue);
		// is the anchor to be used a centre?
		//if(config.anchorishorcentre)
			//this.window.style.top
	}
	else
	{
		this.anchor = this.window;
	}

	this.container = wnd;// obsolete??



	var wndHeader = document.createElement('div');
	wndHeader.className = 'wndHeader';
	this.header = wndHeader;


	wndHeader.onmousedown = function(e)
	{
		if (_this.config.candrag)
		{
			_this.toFront();

			addClass(_this.window, 'isbeingdragged');
		
			toddSetupMouseMoveHandler(_this, _this.ondrag, _this.ondragend);

			if(!e) e=this.parentWindow ? this.parentWindow.event : window.event;

			_this.posbeforedrag = getOffsetToViewport(_this.window);

			//console.log('Beginpos of window '+_this.beforedrag.x+
			
			toddMMH.startx = getMouseX(e);
			toddMMH.starty = getMouseY(e);
			//console.log('Started at '+toddMMH.startx+' x '+toddMMH.starty);
		}
	};
	this.window.onclick = function() { _this.toFront(); };

	
	this.title = document.createElement('div');
	this.title.className = "wndTitle";
	this.title.innerHTML = config.title;

	this.header.appendChild(this.title);
	
	if (config.canclose)
	{
		var btnClose = document.createElement('div');
		btnClose.className = 'btnClose';
		btnClose.onclick   = function(evt) { _this.close(); stopEvent(evt); };
		this.header.appendChild(btnClose);
	}

	if (!useragent.inIE || !config.preferredWidth)
	{
		var wndBody = document.createElement('div');
		wndBody.className = 'wndBody';
		this.body = wndBody;
		this.bodycontainer = this.body;

		// Spellcoder's sneaky shrink-to-fit trick
		if (config.preferredWidth) // FIXME: width for FF2... FF3+ needs min-width"... other browsers???.. FF3.6 can use CSS3?
			this.body.style.cssText = 'display: table-cell; min-width: '+config.preferredWidth+'px;';
	}
	else
	{
		var pTable = document.createElement('table');
		var ptbody = document.createElement('tbody');
		var ptr    = document.createElement('tr');
		var ptd    = document.createElement('td');

		pTable.appendChild(ptbody);
		ptbody.appendChild(ptr);
		ptr.appendChild(ptd);

		// force min-width with an element
//		var minw   = document.createElement('div');
//		minw.style.cssText = config.preferredWidth+'px; height: 0px; margin-top: -5px;';
//		ptd.appendChild(minw);

//		ptd.style.width = config.preferredWidth+'px';
		ptd.className = 'wndBody';
		ptd.style.position = 'static'; // make children use it's parent not itself as container
//		ptd.style.minWidth = config.preferredWidth+'px'; // IE7 known minWidth
		ptd.style.width = config.preferredWidth+'px';
		
		this.bodycontainer = pTable;
		this.body = ptd;
	}

	this.window.appendChild(this.header);
	this.window.appendChild(this.bodycontainer);

	if (config.zindex)
		wnd.style.zIndex = config.zindex;

	if (config.modal)
	{
		this.applyGreyout();
		greyout.style.zIndex = 500;//config.zindex-1;
	}
/*
	if (config.modal || config.fullscreen)
		wnd.style.zIndex = 501; // FIXME
*/	
	if (config.content)
		this.body.appendChild(config.content);
		
	if (config.visible)
	{
		wnd.style.visibility = 'hidden';
		wnd.style.display = 'block';
	//		wnd.style.cssText = 'visibility: hidden; display: block;'; // temp workaround for IE
	}

	//if (useragent.isIE)
	//	wnd.style.cssText = 'visibility: hidden; display: block;'; // temp workaround for IE
	//else
	//	wnd.style.cssText = 'visibility: hidden; display: none;';
		
	// FIXME for non-default window styles
	this.borderWidth  = 18+24;
	this.borderHeight = 49+39;

	if (config.width)
		wnd.style.width = config.width+'px';

	if (config.height)
		wnd.style.height = config.height+'px';
	
	if (config.center)
	{
		// the setTimeout helps to do the centering after other functions finished
		// filling content (and hopefully after onload)
		setTimeout( function()
					{
						_this.centeronscreen();

						if (_this.config.visible)
							_this.show();
					} , 1);
	}
	else
	{
		var viewport = getViewPortDimensions();

		if (config.left)
			wnd.style.left = config.left+'px';
		if (config.right)
			wnd.style.right = config.right+'px';

		if (config.top)
			wnd.style.top = config.top+'px';
		if (config.bottom)
			wnd.style.bottom = config.bottom+'px';

		if (config.visible)
			this.show();
	}

	document.body.appendChild(this.anchor);
}

/***************************

	Stacking

***************************/

spcWindow.prototype.toFront = function()
{
	//console.log('Setting window to front.');
	product.setWindowToFront(this);
}

spcWindow.prototype.toBack = function()
{
}

/***************************

	Size & Positioning

***************************/

spcWindow.prototype.setSizeAndPositionByEdgeDistance = function(edges)
{
	var viewport = getViewPortDimensions();

	this.anchor.style.left = edges.left+'px';
	this.anchor.style.top = edges.top+'px';
//	this.anchor.style.width = (viewport.width-right)+'px';
//	this.anchor.style.height = (viewport.height-bottom)+'px';
	this.setSize(viewport.width-edges.right-edges.left, viewport.height-edges.bottom-edges.top);
}

spcWindow.prototype.setSize = function(newwidth,newheight)
{
	this.window.style.width  = (newwidth  - this.borderWidth)+'px';
	this.window.style.height = (newheight - this.borderHeight)+'px';

//	if (this.config.onresize)
//		this.config.onresize();
}

spcWindow.prototype.setOuterSize = function(width, height)
{
	//this.window.style.width  = width+'px';
	//this.window.style.height = height+'px';

	// Compensate for the borders (which we place into the padding)
	this.window.style.width  = (width  - this.borderWidth)+'px';
	this.window.style.height = (height - this.borderHeight)+'px';
}

spcWindow.prototype.getBodyHeight = function()
{
	return this.body.clientHeight;
}

spcWindow.prototype.getOuterSize = function()
{
	// NOTE: FF can also get width/height from getBoundingClientRect
	return { width:  this.window.offsetWidth
	       , height: this.window.offsetHeight
		   };
}

spcWindow.prototype.setAnchor = function(anchoredge, hposvalue, vposvalue)
{
	var hposvalue = 0; // ADDME
	var vposvalue = 0; // ADDME

	switch(anchoredge) // '' has the same effect as 'topleft'
	{
		case 'topleft':		this.window.style.left = hposvalue; this.window.style.right = 'auto';
							this.window.style.top = vposvalue; this.window.style.bottom = 'auto';
							break;
		case 'topright':	this.window.style.left = 'auto'; this.window.style.right = "-"+hposvalue;
							this.window.style.top = vposvalue; this.window.style.bottom = 'auto';
							break;
		case 'bottomleft':	this.window.style.left = hposvalue; this.window.style.right = 'auto';
							this.window.style.top = 'auto'; this.window.style.bottom = "-"+vposvalue;
							break;
		case 'bottomright':	this.window.style.left = 'auto'; this.window.style.right = "-"+hposvalue;
							this.window.style.top = 'auto'; this.window.style.bottom = "-"+vposvalue;
							break;
	}
}

spcWindow.prototype.setPosition = function(xpos, ypos)
{
	var edge = { top: 0, left: 0, right: 0, bottom: 0 };

	var viewport = getViewPortDimensions();

	var windowsize = { width: this.window.clientWidth
					, height: this.window.clientHeight
					};

	var maxx = viewport.width-edge.right-windowsize.width;
	var maxy = viewport.height-edge.bottom-windowsize.height;

	if (xpos > maxx)
		xpos = maxx;
		
	if (ypos > maxy)
		ypos = maxy;

	/* the top edges are more important (because we need to see the titlebar for the title and dragging)
	   so check for going over the topleft border last in case we need to override the decision to move
	   the window up because it touches the bottom or right of the screen)
	*/	
	if (xpos < edge.left)
		xpos = edge.left;

	if (ypos < edge.top)
		ypos = edge.top;

	this.anchor.style.left = xpos+'px';
	this.anchor.style.top = ypos+'px';
}
/*
spcWindow.prototype.setHeight = function(height) {
	this.window.style.height = (height-wndMedia.borderHeight)+'px';
//wndMedia.borderHeight
}
*/
spcWindow.prototype.centeronscreen = function()
{
	var viewport = getViewPortDimensions();

	var windowsize = { width: this.window.clientWidth
					, height: this.window.clientHeight
					};

	var newx = (viewport.width-windowsize.width)/2;
	var newy = (viewport.height-windowsize.height)/2;
	
	this.setPosition(newx, newy);
}

/***************************

	Dragging

***************************/

spcWindow.prototype.ondrag = function(instance, x, y)
{
	//console.log('drag to '+x+'x'+y);
	instance.moverelative(x,y);
}
spcWindow.prototype.ondragend = function(instance, x, y)
{
	//console.log('dragend at '+x+'x'+y);
	instance.moverelative(x,y);
	removeClass(instance.window, 'isbeingdragged');
}
spcWindow.prototype.moverelative = function(x,y)
{
	//instance.window.style.left = instance.posbeforedrag.left + (x - toddMMH.startx)+'px';
	//instance.window.style.top = instance.posbeforedrag.top + (y - toddMMH.starty)+'px';

	var newx = this.posbeforedrag.left + (x - toddMMH.startx);
	var newy = this.posbeforedrag.top + (y - toddMMH.starty);

	this.setPosition(newx, newy);
}

/***************************

	Greyout/Modal

***************************/

spcWindow.prototype.applyGreyout = function()
{
	// global
	greyout = document.createElement('div');
	greyout.className = 'greyout';
	document.body.appendChild(greyout);
}

spcWindow.prototype.removeGreyout = function()
{
	if (greyout)
	{
		greyout.parentNode.removeChild(greyout);
		greyout = null;
	}
}




spcWindow.prototype.setTitle = function(title)
{
	this.title.innerHTML = title;
}

spcWindow.prototype.show = function()
{
	if (this.container == null)
	{
		console.error('Trying to show a closed window.');
		return;
	}
		
	// 1. to allow showing after the window is fully setup (no flickering, moving etc)
	// 2. to prevent Firefox freaking on width changes on complex (table) HTML
	this.container.style.visibility = 'visible';
	this.container.style.display = 'block';
//	this.container.style.cssText = 'vibility: visible; display: block;';

}

spcWindow.prototype.hide = function()
{
	if (this.container == null)
	{
		console.error('Trying to hide a closed window.');
		return;
	}
		
	this.container.style.display = 'none';
}

spcWindow.prototype.close = function()
{
	if (this.window == null)
	{
		console.error('Trying to close an allready closed window!');
		return;
	}

	// prevent recursion due to onbeforeclose/onclose calling
	// another function which also might call close()
	if (this.isclosing)
		return;

	this.isclosing = true;

	// ADDME: allow onbeforeclose to cancel closing
	if (this.config.onbeforeclose)
		this.config.onbeforeclose();//this.config.name);

	if (this.config.modal)
		this.removeGreyout();

	// For Internet Explorer kill the content or any Flash movies may continue playing in the background
	this.body.innerHTML = '';
	
//	if (!this.fadeout) {
		this.container.parentNode.removeChild(this.container);
		this.window = null; // destroy reference
		this.container = null;
//	}

	this.header = null;
	this.title = null;
	this.body = null;

	if (/*this.config.onclose &&*/ this.config.onclose != null)
	{
		//console.log('Running onclose handler on window');
		this.config.onclose();
	}
		
	this.config.onbeforeclose = null;
	this.config.onclose = null;

/*
	if (this.fadeout) {
		var _this = this;
		this.fadecount  = 0;
		this.tmrFadeOut = setTimeout( function() { _this.dofade() } , 10 );
	}
*/
}
/*
spcWindow.prototype.dofade = function() {

	this.fadecount++;
	var partyVal = Math.PI / 2 / 10; // quarter of sinus in 10 steps
	var mult = 1 - Math.sin(this.fadecount * partyVal);

	this.window.style.opacity = mult;

	var _this = this;

	if (this.fadecount < 10) {
		this.tmrFadeOut = setTimeout( function() { _this.dofade() } , 10 );
	} else {
		this.container.parentNode.removeChild(this.container);
		this.window = null; // destroy reference
	}

}
*/
