// $Id: window-controlling.js 4726 2006-10-12 14:21:15Z shacka $
/**
 *
 * Copyright (c) 2006 by SouthProjects
 * http://www.southprojects.com
 * Santiago, Chile,
 * Version 1.2 Dec 2006.
 * All rights reserved.
 */

/**
 * Gets the window container.
 */
southprojects.Window.prototype.getContainer = function() {
	return this.container;
};

/**
 * Sets default state values of the widget.
 */
southprojects.Window.prototype.setDefaultState = function() {
	//stores the properties which describe the state of the widget
	this.state = {};
	//is window minimized, maximized or simple
	this.state.state = "simple";
	//the width of the title text element
	this.state.titleWidth = 0;
	//the width of southprojects.Pane object
	this.state.contentWidth = 0;
	//the width of status area element
	this.state.statusWidth = 0;
	//difference between the full height of the window and content area's height
	this.state.heightDiff = 0;
	//X coordinate
	this.state.left = 0;
	//Y coordinate
	this.state.top = 0;
	//the width of the window
	this.state.width = 0;
	//the height of the window
	this.state.height = 0;
	//the content type of the window
	this.state.contentType = "";
	//the content of the window
	this.state.content = "";
};

/** 
 * Gets the state of the window.
 * @return object with the following properties:
 * \code
 *    prop. name     | description
 *  -------------------------------------------------------------------------------------------------
 *   x       | left coordinate.
 *   y       | top coordinate.
 *   width   | width of container.
 *   height  | height of container.
 *   url     | if content is set from URL, than it contains that URL, otherwise null
 *   div     | if content is set from DIV element, than it contains it id, if it has no id its null.
 *   text    | if content is set as text string, than it contains that text, otherwise null
 * \endcode
 */
southprojects.Window.prototype.getState = function() {
	var state = {};
	state.x = this.state.left;
	state.y = this.state.top;
	state.width = this.state.width;
	state.height = this.state.height;
	state.zIndex = this.container.style.zIndex;
	state.valor=this.valor;

	switch(this.state.contentType) {
		case "html/text" : state.text = this.state.content; break;
		case "html" : state.div = this.state.content; break;
		case "html/url" : state.url = this.state.content; break;
	}
	
	return state;
};

/** 
 * Sets the state of the window.
 * @param state [object] with the following properties:
 * \code
 *    prop. name     | description
 *  -------------------------------------------------------------------------------------------------
 *   x       | left coordinate.
 *   y       | top coordinate.
 *   width   | width of container.
 *   height  | height of container.
 *   url     | URL content.
 *   div     | content is set from DIV element.
 *   text    | content is set as text string.
 * \endcode
 */
southprojects.Window.prototype.setState = function(state) {
    var self = this;
	if (!this.fireOnState("ready", function() {self.setState(state);})) return;

	if (state.x || state.y || state.width || state.height) {
		this.setPosAndSize(state.x, state.y, state.width, state.height);
	}

	if (state.zIndex) {
		this.container.style.zIndex = state.zIndex;

		if(state.zIndex > southprojects.Window.maxNumber){
			southprojects.Window.maxNumber = state.zIndex + 1;
		}

		if (this.WCH) {
			this.WCH.style.zIndex = state.zIndex - 1;
		}

		if(this.config.modal){
			this.modal.container.style.zIndex = state.zIndex - 2;
		}
	}
	
	if(state.url || state.div || state.text){
		this.setContent("");
		if (state.url) {
			this.setContentUrl(state.url);
		} else if (state.div) {
			this.setDivContent(state.div);
		} else if (state.text) {
			this.setContent(state.text);
		}
	}

	return true;
};

/**
 * Sets the position of the window. 
 *
 * @param left [integer] - X coordinate.
 * @param top [integer] - Y coordinate.
 * @param first [boolean] - should it be called first
 */
southprojects.Window.prototype.setPos = function(left, top) {
	var self = this;
	if (!this.fireOnState("shown", function() {self.setPos(left, top);})) return;
	if (southprojects.Utils.moveElementTo(this.container, left, top)) {
		//need to save our position
		var pos = southprojects.Utils.getElementPos(this.getContainer());
		this.state.left = pos.x;
		this.state.top = pos.y;
		return true;
	} else {
		return false;
	}
}

/**
 * Sets the width of the window. Needed to synchronize some variables in
 * one place. Also updates the WCH for IE.
 *
 * @param width [integer] - width of the window.
 * @param first [boolean] - should it be called first
 */
southprojects.Window.prototype.setWidth = function(width) {
	var self = this;
	if (!this.fireOnState("shown", function() {self.setWidth(width);})) return;

	//checking if the passed argument is a valid value
	if (typeof width != "number") return false;
	if (width < this.config.minWidth) width = this.config.minWidth;
	var diff = this.state.width - width;
	//trying to set titleText elements width
	if (this.titleText) {
		this.titleText.style.width = (this.state.titleWidth -= diff) + "px";
		if (this.titleText.offsetWidth != this.state.titleWidth) {
			this.titleText.style.width = (this.state.titleWidth - (this.titleText.offsetWidth - this.state.titleWidth)) + "px";
		}
	}
	//trying to set content elements width
	if (this.content) {
		this.content.setWidth(this.state.contentWidth -= diff);
	}
	//trying to set statusText elements width
	if (this.config.showStatus) {
		this.statusText.style.width = (this.state.statusWidth -= diff) + "px";
		if (this.statusText.offsetWidth != this.state.statusWidth) {
			this.statusText.style.width = (this.state.statusWidth - (this.statusText.offsetWidth - this.state.statusWidth)) + "px";
		}
	}
	//setting the whole width
	this.container.style.width = (this.state.width = width) + "px";
	this.updateWCH();
	this.fireEvent("onWidthChange", this);
	return true;
}

/**
 * Sets the height of the window. Needed to synchronize some variables in
 * one place. Also updates the WCH for IE.
 *
 * @param height [integer] - height of the window.
 * @param first [boolean] - should it be called first
 */
southprojects.Window.prototype.setHeight = function(height) {
	var self = this;
	if (!this.fireOnState("shown", function() {self.setHeight(height);})) return;

	//checking if the passed argument is a valid value
	if (typeof height != "number") return false;
	if (height < this.config.minHeight) height = this.config.minHeight;
	//trying to set elements width
	var diff = height - this.state.height;
	this.content.setHeight(this.state.height = height);
	this.updateWCH();
	this.fireEvent("onHeightChange", this);
	return true;
}

/**
 * Sets the sizes of the window. 
 *
 * @param width [integer] - width of the window.
 * @param height [integer] - height of the window.
 * @param first [boolean] - should it be called first
 */
southprojects.Window.prototype.setSize = function(width, height) {
	var res = true;
	if (!this.setWidth(width)) {
		res = false;
	}
	if (!this.setHeight(height)) {
		res = false;
	}
	return res;
}


/**
 * Sets the sizes and position of the window. 
 *
 * @param left [integer] - X coordinate.
 * @param top [integer] - Y coordinate.
 * @param width [integer] - width of the window.
 * @param height [integer] - height of the window.
 * @param first [boolean] - should it be called first
 */
southprojects.Window.prototype.setPosAndSize = function(left, top, width, height) {
	var res = true;
	if (!this.setSize(width, height)) {
		res = false;
	}
	if (!this.setPos(left, top)) {
		res = false;
	}
	return res;
}

/*
 * Set the title of the window
 * @param type [string] the title to set to
 */ 
southprojects.Window.prototype.setTitle = function(text) {
	var self = this;
	if (!this.fireOnState("ready", function() {self.setTitle(text);})) return;

	if (text != '') {
		this.titleText.innerHTML = text;
	}
	return true;
}

southprojects.Window.prototype.setTheme = function(text) {
	var self = this;
	this.theme=text;
	return true;
}
southprojects.Window.prototype.setValor = function(text) {
	var self = this;
	this.valor=text;
	return true;
}
/**
 * Sets the status text of the window. 
 *
 * @param mesage [string] - text to be shown.
 * @param mode [string] - currently mode forces to do some additional action when seting the text.
 *                        For example, "temp" means to store the previous value.
 */
southprojects.Window.prototype.setStatus = function(message, mode) {
	var self = this;
	if (!this.fireOnState("ready", function() {self.setStatus(message, mode);})) return;

	//to be able to use different mods of setting status text we use mode var
	if (this.config.showStatus) {
		switch (mode) {
			//if mode "temp" current value is saved and overwritten by new one
			case "temp" : {
				this.prevStText = this.statusText.innerHTML;
				break;
			}
			
			//in case of "restore" we just restore old value saved before
			case "restore" : {
				message = this.prevStText || message;
				delete this.prevStText;
				break;
			}
			
		}
		this.statusText.innerHTML = message;
	}
	return true;
}

/* 
 * Set the content of a window.
 * @param type [string] the HTML data to set the content to.
 */

southprojects.Window.prototype.setContent = function(text) {
	var self = this;
	if (!this.fireOnState("shown", function() {self.setContent(text);})) return;
	this.setModeOn("delayed_execution");
	var diff = this.state.width - this.state.contentWidth;
	this.content.addEventListener("contentLoaded", function(pane) {
		self.setWidth(pane.getWidth() + diff);
		self.setHeight(pane.getHeight());
		self.setModeOff("delayed_execution");
		self.fireEvent('onContentLoad');
	});
	this.content.setPaneContent(text, "html/text");
	this.state.contentType = "html/text";
	this.state.content = text;
}

/* 
 * Set the content of a window from HTML element(DIV).
 * @param div [string]or [object] the HTML data to set the content to.
 */

southprojects.Window.prototype.setDivContent = function(div) {
	var self = this;
	if (!this.fireOnState("shown", function() {self.setDivContent(div);})) return;
	this.setModeOn("delayed_execution");
	var diff = this.state.width - this.state.contentWidth;
	this.content.addEventListener("contentLoaded", function(pane) {
		self.setWidth(pane.getWidth() + diff);
		self.setHeight(pane.getHeight());
		self.setModeOff("delayed_execution");
		self.fireEvent('onContentLoad');
	});
	this.content.setPaneContent(div, "html");
	this.state.contentType = "html";
	if (typeof div == "string") {
		this.state.content = div;
	} else {
		this.state.content = null;
	}
}

/* 
 * Set the content of a window from url.
 * @param div [string]or [object] the HTML data to set the content to.
 */

southprojects.Window.prototype.setContentUrl = function(url) {
	var self = this;
	if (!this.fireOnState("shown", function() {self.setContentUrl(url);})) return;
	this.setModeOn("delayed_execution");
	var diff = this.state.width - this.state.contentWidth;
	this.content.addEventListener("contentLoaded", function(pane) {
		self.setWidth(pane.getWidth() + diff);
		self.setHeight(pane.getHeight());
		self.setModeOff("delayed_execution");
		self.fireEvent('onContentLoad');
	});
	this.content.setPaneContent(url, "html/url");
	this.state.contentType = "html/url";
	this.state.content = url;
}

/**
 * Activates the window.
 */
southprojects.Window.prototype.activate = function() {
	var self = this;
	if (!this.fireOnState("shown", function() {self.activate();})) return;

	var prevWin = southprojects.Window.currentWindow;
	//set the current window
	southprojects.Window.currentWindow = this;
	southprojects.Utils.removeClass(this.face, 'spWinBack');
	southprojects.Utils.addClass(this.face, 'spWinFront');
	if (this.WCH) this.WCH.style.zIndex = southprojects.Window.maxNumber++;
	if (this.modal) this.modal.container.style.zIndex = southprojects.Window.maxNumber++;
	this.container.style.zIndex = southprojects.Window.maxNumber++;
	//if it is not the first one and it is not the same one as before
	if (prevWin && this != prevWin) { 
		//Show the previous window as not being the current window anymore
		prevWin.deactivate();
	}
	
	this.fireEvent("onRaise", this);
};

/**
 * Deactivates the window.
 */
southprojects.Window.prototype.deactivate = function() {
	var self = this;
	if (!this.fireOnState("shown", function() {self.deactivate();})) return;

	var prevWin = southprojects.Window.currentWindow;
	southprojects.Utils.removeClass(this.face, 'spWinFront');
	southprojects.Utils.addClass(this.face, 'spWinBack');
	//activate the lastActive if this was not called by another activate method
	if (prevWin == this) {
		southprojects.Window.currentWindow = southprojects.Window.lastActive;
		if (southprojects.Window.lastActive) southprojects.Window.lastActive.activate();
	}
	//need to remember the last active window to activate it when current is minimized
	//we either reference to the window we are deactivateing or seek in the array of all widgets, 
	//the window with the highest zIndex.
	if (this.state.state != "min" && prevWin == this) {
		southprojects.Window.lastActive = prevWin;
	} else {
		var zIndex = 0;
		southprojects.Window.lastActive = null;
		for(i in southprojects.Widget.all) {
			if (southprojects.Widget.all[i] && 
			    southprojects.Widget.all[i].widgetType == "window" &&
			    southprojects.Widget.all[i].stateReached("ready") && 
			    (parseInt(southprojects.Widget.all[i].container.style.zIndex, 10) > zIndex) && 
			    (southprojects.Widget.all[i].state.state != "min") && 
			    (southprojects.Widget.all[i] != southprojects.Window.currentWindow)) {
					zIndex = parseInt(southprojects.Widget.all[i].container.style.zIndex, 10);
					southprojects.Window.lastActive = southprojects.Widget.all[i];
			}
		}
	}
};

/**
 * Returns the visibility of the vindow.
 */
southprojects.Window.prototype.isVisible = function() {
	return this.widgetState == "shown" ? true : false;
};

/**
 * Shows the window.
 */ 
southprojects.Window.prototype.show = function() {
	var self = this;
	if (!this.fireOnState("ready", function() {self.show();})) return;

	this.container.style.display = "block";
	if (this.config.modal == true && this.modal) {
		this.modal.show();
	}
	this.updateWCH();
	this.activate();
	this.changeState("shown");
	this.fireEvent("onShow", this);
	return true;
}

/**
 * Hides the window.
 */ 
southprojects.Window.prototype.hide = function() {
	var self = this;
	if (!this.fireOnState("ready", function() {self.hide();})) return;

	this.container.style.display = "none";
	if (this.config.modal == true && this.modal) {
		this.modal.hide();
	}
	southprojects.Utils.hideWCH(this.WCH);
	this.deactivate();
	this.changeState("hidden");
	this.fireEvent("onHide", this);
	return true;
}

/**
 * This function displays the calendar near a given "anchor" element, according
 * to some rules passed in \em opts.  The \em opts argument is a string
 * containing one or 2 letters.  The first letter decides the vertical
 * alignment, and the second letter decides the horizontal alignment relative
 * to the anchor element.  Following we will describe these options; in parens
 * we will use simple descriptions like "top to bottom" which means that the
 * top margin of the calendar is aligned with the bottom margin of the object.
 *
 * \b Vertical align:
 *
 * - T -- the calendar is completely above the element (bottom to top)
 * - t -- the calendar is above the element but might overlap it (bottom to bottom)
 * - C -- the calendar is vertically centered to the element
 * - b -- the calendar is below the element but might overlap it (top to top)
 * - B -- the calendar is completely below the element (top to bottom)
 *
 * \b Horizontal align (defaults to 'l' if no letter passed):
 *
 * - L -- the calendar is completely to the left of the element (right to left)
 * - l -- the calendar is to the left of the element but might overlap it (right to right)
 * - C -- the calendar is horizontally centered to the element
 * - r -- the calendar is to the right of the element but might overlap it (left to left)
 * - R -- the calendar is completely to the right of the element (left to right)
 *
 * @param el [HTMLElement] the anchor element
 * @param opts [string, optional] the align options, as described above.  Defaults to "Bl" if nothing passed.
 */
southprojects.Window.prototype.showAtElement = function (el, opts) {
	var self = this;
	if (!this.fireOnState("ready", function() {self.showAtElement(el, opts);})) return;

	var p = southprojects.Utils.getAbsolutePos(el);
	if (!opts || typeof opts != "string") {
		this.showAt(p.x, p.y + el.offsetHeight);
		return true;
	}
	this.container.style.display = "block";
	var w = this.container.offsetWidth;
	var h = this.container.offsetHeight;
	this.container.style.display = "none";
	var valign = opts.substr(0, 1);
	var halign = "l";
	if (opts.length > 1) {
		halign = opts.substr(1, 1);
	}
	// vertical alignment
	switch (valign) {
	    case "T": p.y -= h; break;
	    case "B": p.y += el.offsetHeight; break;
	    case "C": p.y += (el.offsetHeight - h) / 2; break;
	    case "t": p.y += el.offsetHeight - h; break;
	    case "b": break; // already there
	}
	// horizontal alignment
	switch (halign) {
	    case "L": p.x -= w; break;
	    case "R": p.x += el.offsetWidth; break;
	    case "C": p.x += (el.offsetWidth - w) / 2; break;
	    case "l": p.x += el.offsetWidth - w; break;
	    case "r": break; // already there
	}
	p.width = w;
	p.height = h;
	//southprojects.Utils.fixBoxPosition(p);
	this.showAt(p.x, p.y);
	return true;
}

/**
 * Shows the calendar at a given absolute position (beware that, depending on
 * the calendar element style -- position property -- this might be relative to
 * the parent's containing rectangle).
 *
 * @param x [int] the X position
 * @param y [int] the Y position
 */
southprojects.Window.prototype.showAt = function (x, y) {
	var self = this;
	if (!this.fireOnState("ready", function() {self.showAt(x, y);})) return;

	this.setPos(x, y);
	this.show();
	return true;
}

/**
 * Minimizes the window.
 */ 
southprojects.Window.prototype.minimize = function() {
	if (!this.config.showMinButton) {
		return false;
	}
	var self = this;
	if (!this.fireOnState("ready", function() {self.minimize();})) return;

	//Do we really need to minimize
	if (this.state.state != "min" && this.titleArea) {
		var self = this;
		//this function recursively hides all the elements in the Window except title and its parents
		function hideExcept(el, exc) {
			if (el != self.container) {
				var first = el.firstChild;
				while(first) {
					if (first && first.style && first != exc) {
						if (!first.restorer) {
							first.restorer = new southprojects.Utils.SRProp(first);
						}
						first.restorer.saveProp("style.display");
						first.style.display = "none";
					}
					first = first.nextSibling;
				}
				hideExcept(el.parentNode, el);
			}
		}
		hideExcept(this.titleArea.parentNode, this.titleArea);
		if (this.config.bottomMinimize) {
			//Now setting new width which is equal for all minimized Windows
			var diff = this.state.width - this.state.titleWidth;
			this.titleText.style.width = (southprojects.Window.minWinWidth - diff) + "px";
			if ((southprojects.Window.minWinWidth - diff) != this.titleText.offsetWidth) {
				this.titleText.style.width = parseInt(this.titleText.style.width, 10) - (this.titleText.offsetWidth - (southprojects.Window.minWinWidth - diff)) + "px";
			}
			this.container.style.width = southprojects.Window.minWinWidth + "px";
			//Putting it to the left bottom corner in the appropriate order
			this.container.style.left = southprojects.Window.minimizeLeft + "px";
			southprojects.Window.minimizeLeft += southprojects.Window.minWinWidth + 5;
			this.container.style.top = (southprojects.Utils.getWindowSize().height - this.container.offsetHeight) + "px";
		}
		//lets disable dragging
		if (this.draggable && !this.config.dragMin) {
			this.draggable.disabled = true;
		} else if (this.draggable && this.config.dragMin) {
			this.draggable.disabled = false;
		}
		//Need to hide some buttons and show restore one
		if (this.state.state == "max") {
			this.restorer.restoreProp("maxButton.getContainer().style.display");
		} else {
			this.restorer.restoreProp("restoreButton.getContainer().style.display");
		}
		this.restorer.saveProp("minButton.getContainer().style.display");
		this.minButton.getContainer().style.display = "none";
		//updateing WCH
		this.updateWCH();
		//storing old state for restore
		this.state.prevState = this.state.state;
		//setting new state
		this.state.state = "min";
		//activateing last active window
		if (southprojects.Window.lastActive && this.config.bottomMinimize) {
			southprojects.Window.lastActive.activate();
		}
	} else {
		return false;
	}
	//calling handler
	this.fireEvent("onMinimize", this);
	if (southprojects.is_khtml) {
		this.hide();
		setTimeout(function() {
			self.show();
		}, 0);
	}

	return true;
}

/**
 * Maximizes the window.
 */ 
southprojects.Window.prototype.maximize = function() {
	if (!this.config.showMaxButton) {
		return false;
	}
	var self = this;
	if (!this.fireOnState("ready", function() {self.maximize();})) return;

	if (this.state.state != "max") {
		var self = this;
		//this function recursively hides all the elements in the Window except title and its parents
		function showAll(el) {
			if (el != self.container) {
				var first = el.firstChild;
				while(first) {
					if (first && first.restorer) {
						first.restorer.restoreProp("style.display");
						first.restorer = null;
					}
					first = first.nextSibling;
				}
				showAll(el.parentNode);
			}
		}
		var sizes = southprojects.Utils.getWindowSize();
		//Need to hide some buttons and show restore one, restore some properties of the window, etc.
		if (this.state.state == "min") {
			//sorting all minimized windows after this one was maximized
			if (!this.config.dragMin) {
				southprojects.Window.sortMin(this);
			} else if (this.config.bottomMinimize) {
				southprojects.Window.minimizeLeft -= southprojects.Window.minWinWidth + 5;
			}
			showAll(this.titleArea);
			this.restorer.restoreProps(
				"container.style.width", 
				"titleText.style.width", 
				"minButton.getContainer().style.display"
			);
		} else {
			this.restorer.restoreProp("restoreButton.getContainer().style.display");
		}
		this.restorer.saveProp("maxButton.getContainer().style.display");
		this.maxButton.getContainer().style.display = "none";
		//lets disable dragging
		if (this.draggable) this.draggable.disabled = true;
		this.restorer.saveProps(
			"state.width", 
			"state.height", 
			"state.left", 
			"state.top", 
			"state.titleWidth", 
			"state.contentWidth", 
			"state.statusWidth", 
			"state.heightDiff"
		);
		
		this.setPosAndSize(0, 0, sizes.width-20, sizes.height - this.state.heightDiff-3);
		this.restorer.restoreProps(
			"state.width", 
			"state.height", 
			"state.left", 
			"state.top", 
			"state.titleWidth", 
			"state.contentWidth", 
			"state.statusWidth", 
			"state.heightDiff"
		);
		//updateing WCH
		this.updateWCH();
		//setting previous state to be restored correctly
		this.state.prevState = "simple";
		//setting new state
		this.state.state = "max";
		this.activate();
	} else {
		return false;
	}
	this.fireEvent("onMaximize", this);
	if (southprojects.is_khtml) {
		this.hide();
		setTimeout(function() {
			self.show();
		}, 0);
	}
	
	return true;
}

/**
 * Restores the window.
 */ 
southprojects.Window.prototype.restore = function() {
	if (!this.config.showMaxButton && !this.config.showMinButton) {
		return false;
	}
	var self = this;
	if (!this.fireOnState("ready", function() {self.restore();})) return;
	
	if (this.state.prevState == "max") {
		return this.maximize();
	}
	if (this.state.state != "simple") {
		var self = this;
		//this function recursively hides all the elements in the Window except title and its parents
		function showAll(el) {
			if (el != self.container) {
				var first = el.firstChild;
				while(first) {
					if (first && first.restorer) {
						first.restorer.restoreProp("style.display");
						first.restorer = null;
					}
					first = first.nextSibling;
				}
				showAll(el.parentNode);
			}
		}
		if (this.state.state == "min") {
			if (this.state.state == "min" && !this.config.dragMin) {
				southprojects.Window.sortMin(this);
			} else if (this.config.bottomMinimize) {
				southprojects.Window.minimizeLeft -= southprojects.Window.minWinWidth + 5;
			}
			showAll(this.titleArea);
		}
		//Need to hide some buttons and show restore one
		if (this.config.showMaxButton) {
			this.restorer.restoreProp("maxButton.getContainer().style.display"); 
		}
		if (this.config.showMinButton) {
			this.restorer.restoreProp("minButton.getContainer().style.display");
		}
		this.restorer.saveProp("restoreButton.getContainer().style.display");
		this.restoreButton.getContainer().style.display = "none";
		//seting the initial pos and sizes
		if (!(this.state.state == "min" && !this.config.bottomMinimize)) {
			this.setPosAndSize(this.state.left, this.state.top, this.state.width, this.state.height);
		}
		//updateing WCH
		this.updateWCH();
		//setting new state
		this.state.state = "simple";
		//enable dragging if needed
		if (this.draggable) this.draggable.disabled = false;
		//activateing this window
		this.activate();
	}

	this.fireEvent("onRestore", this);
	if (southprojects.is_khtml) {
		this.hide();
		setTimeout(function() {
			self.show();
		}, 0);
	}
	return true;
}

/**
 * Closes the window. Currently does not destroys the window object, just the HTML part of it
 */ 
southprojects.Window.prototype.close = function() {
	var self = this;
	
	if (!this.fireOnState("ready", function() {self.close();})) return;
	// safari fix?
	//this.restore();
	
	// Return content back to the place it was taken from
	// Destroy window
	this.fireEvent("onClose", this);
	if (!this.config.hideOnClose) {
		if (this.content.destroy) this.content.destroy();
		this.content = null;
		
		if (this.draggable) this.draggable = this.draggable.destroy();
		if (this.minButton.destroy) this.minButton = this.minButton.destroy();
		if (this.maxButton.destroy) this.maxButton = this.maxButton.destroy();
		if (this.closeButton.destroy) this.closeButton = this.closeButton.destroy();
		if (this.restoreButton.destroy) this.restoreButton = this.restoreButton.destroy();

		for(var iEl in this) {
			if (this[iEl] && typeof this[iEl] == "object" && this[iEl].nodeType && iEl != "container" && iEl != "WCH") {
				this[iEl] = null;
			}
		}
		if (this.config.modal == true && this.modal) {
			this.modal.hide(true);
			delete this.modal;
		}
		this.config = null;
		this.restorer = this.restorer.destroy();
		if (this.container.outerHTML) {
			this.container.outerHTML = "";
		} else {
			southprojects.Utils.destroy(this.container);
		}
		if (this.WCH && this.WCH.outerHTML) {
			this.WCH.outerHTML = "";
		} else if (this.WCH) {
			southprojects.Utils.destroy(this.WCH);
		}
		delete this.container;
		delete this.WCH;
		this.changeState("destroyed");
	} else {
		
		this.hide();
		
	}
	if (southprojects.Window.lastActive) {
		southprojects.Window.lastActive.activate();
	}
	this.events = [];
	return true;
}
