[Mapbender-commits] r6328 - trunk/mapbender/http/extensions/jquery.layout.all-1.2.0

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Fri Jun 18 05:16:29 EDT 2010


Author: christoph
Date: 2010-06-18 09:16:29 +0000 (Fri, 18 Jun 2010)
New Revision: 6328

Modified:
   trunk/mapbender/http/extensions/jquery.layout.all-1.2.0/jquery.layout.js
Log:


Modified: trunk/mapbender/http/extensions/jquery.layout.all-1.2.0/jquery.layout.js
===================================================================
--- trunk/mapbender/http/extensions/jquery.layout.all-1.2.0/jquery.layout.js	2010-06-18 09:14:40 UTC (rev 6327)
+++ trunk/mapbender/http/extensions/jquery.layout.all-1.2.0/jquery.layout.js	2010-06-18 09:16:29 UTC (rev 6328)
@@ -1,7 +1,7 @@
 /*
  * jquery.layout 1.2.0
  *
- * Copyright (c) 2008 
+ * Copyright (c) 2008
  *   Fabrizio Balliano (http://www.fabrizioballiano.net)
  *   Kevin Dalman (http://allpro.net)
  *
@@ -10,2501 +10,2534 @@
  *
  * $Date: 2008-12-27 02:17:22 +0100 (sab, 27 dic 2008) $
  * $Rev: 203 $
- * 
+ *
  * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
  */
-(function($) {
+(function($){
 
-$.fn.layout = function (opts) {
-
-/*
- * ###########################
- *   WIDGET CONFIG & OPTIONS
- * ###########################
- */
-
-	// DEFAULTS for options
-	var 
-		prefix = "ui-layout-" // prefix for ALL selectors and classNames
-	,	defaults = { //	misc default values
-			paneClass:				prefix+"pane"		// ui-layout-pane
-		,	resizerClass:			prefix+"resizer"	// ui-layout-resizer
-		,	togglerClass:			prefix+"toggler"	// ui-layout-toggler
-		,	togglerInnerClass:		prefix+""			// ui-layout-open / ui-layout-closed
-		,	buttonClass:			prefix+"button"		// ui-layout-button
-		,	contentSelector:		"."+prefix+"content"// ui-layout-content
-		,	contentIgnoreSelector:	"."+prefix+"ignore"	// ui-layout-mask 
-		}
-	;
-
-	// DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
-	var options = {
-		name:						""			// FUTURE REFERENCE - not used right now
-	,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
-	,	defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
-			applyDefaultStyles: 	false		// apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
-		,	closable:				true		// pane can open & close
-		,	resizable:				true		// when open, pane can be resized 
-		,	slidable:				true		// when closed, pane can 'slide' open over other panes - closes on mouse-out
-		//,	paneSelector:			[ ]			// MUST be pane-specific!
-		,	contentSelector:		defaults.contentSelector	// INNER div/element to auto-size so only it scrolls, not the entire pane!
-		,	contentIgnoreSelector:	defaults.contentIgnoreSelector	// elem(s) to 'ignore' when measuring 'content'
-		,	paneClass:				defaults.paneClass		// border-Pane - default: 'ui-layout-pane'
-		,	resizerClass:			defaults.resizerClass	// Resizer Bar		- default: 'ui-layout-resizer'
-		,	togglerClass:			defaults.togglerClass	// Toggler Button	- default: 'ui-layout-toggler'
-		,	buttonClass:			defaults.buttonClass	// CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
-		,	resizerDragOpacity:		1			// option for ui.draggable
-		//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
-		,	maskIframesOnResize:	true		// true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
-		//,	size:					100			// inital size of pane - defaults are set 'per pane'
-		,	minSize:				0			// when manually resizing a pane
-		,	maxSize:				0			// ditto, 0 = no limit
-		,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
-		,	spacing_closed:			6			// ditto - when pane is 'closed'
-		,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
-		,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
-		,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
-		,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
-		,	togglerTip_open:		"Close"		// Toggler tool-tip (title)
-		,	togglerTip_closed:		"Open"		// ditto
-		,	resizerTip:				"Resize"	// Resizer tool-tip (title)
-		,	sliderTip:				"Slide Open" // resizer-bar triggers 'sliding' when pane is closed
-		,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
-		,	slideTrigger_open:		"click"		// click, dblclick, mouseover
-		,	slideTrigger_close:		"mouseout"	// click, mouseout
-		,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
-		,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
-		,	togglerContent_closed:	""			// ditto
-		,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
-		,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
-		//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
-		,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
-		//	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
-		,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale
-		,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
-		,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
-		,	initClosed:				false		// true = init pane as 'closed'
-		,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer or spacing
-		
-		/*	callback options do not have to be set - listed here for reference only
-		,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
-		,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
-		,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
-		,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
-		,	onopen_start:			""			// CALLBACK when pane STARTS to Open
-		,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
-		,	onclose_start:			""			// CALLBACK when pane STARTS to Close
-		,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
-		,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
-		,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
-		*/
-		}
-	,	north: {
-			paneSelector:			"."+prefix+"north" // default = .ui-layout-north
-		,	size:					"auto"
-		,	resizerCursor:			"n-resize"
-		}
-	,	south: {
-			paneSelector:			"."+prefix+"south" // default = .ui-layout-south
-		,	size:					"auto"
-		,	resizerCursor:			"s-resize"
-		}
-	,	east: {
-			paneSelector:			"."+prefix+"east" // default = .ui-layout-east
-		,	size:					200
-		,	resizerCursor:			"e-resize"
-		}
-	,	west: {
-			paneSelector:			"."+prefix+"west" // default = .ui-layout-west
-		,	size:					200
-		,	resizerCursor:			"w-resize"
-		}
-	,	center: {
-			paneSelector:			"."+prefix+"center" // default = .ui-layout-center
-		}
-
-	};
-
-
-	var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
-		slide:	{
-			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
-		,	north:	{ direction: "up"	}
-		,	south:	{ direction: "down"	}
-		,	east:	{ direction: "right"}
-		,	west:	{ direction: "left"	}
-		}
-	,	drop:	{
-			all:	{ duration:  "slow"	} // eg: duration: 1000, easing: "easeOutQuint"
-		,	north:	{ direction: "up"	}
-		,	south:	{ direction: "down"	}
-		,	east:	{ direction: "right"}
-		,	west:	{ direction: "left"	}
-		}
-	,	scale:	{
-			all:	{ duration:  "fast"	}
-		}
-	};
-
-
-	// STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
-	var config = {
-		allPanes:		"north,south,east,west,center"
-	,	borderPanes:	"north,south,east,west"
-	,	zIndex: { // set z-index values here
-			resizer_normal:	1		// normal z-index for resizer-bars
-		,	pane_normal:	2		// normal z-index for panes
-		,	mask:			4		// overlay div used to mask pane(s) during resizing
-		,	sliding:		100		// applied to both the pane and its resizer when a pane is 'slid open'
-		,	resizing:		10000	// applied to the CLONED resizer-bar when being 'dragged'
-		,	animation:		10000	// applied to the pane when being animated - not applied to the resizer
-		}
-	,	resizers: {
-			cssReq: {
-				position: 	"absolute"
-			,	padding: 	0
-			,	margin: 	0
-			,	fontSize:	"1px"
-			,	textAlign:	"left" // to counter-act "center" alignment!
-			,	overflow: 	"hidden" // keep toggler button from overflowing
-			,	zIndex: 	1
-			}
-		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
-				background: "#DDD"
-			,	border:		"none"
-			}
-		}
-	,	togglers: {
-			cssReq: {
-				position: 	"absolute"
-			,	display: 	"block"
-			,	padding: 	0
-			,	margin: 	0
-			,	overflow:	"hidden"
-			,	textAlign:	"center"
-			,	fontSize:	"1px"
-			,	cursor: 	"pointer"
-			,	zIndex: 	1
-			}
-		,	cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
-				background: "#AAA"
-			}
-		}
-	,	content: {
-			cssReq: {
-				overflow:	"auto"
-			}
-		,	cssDef: {}
-		}
-	,	defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
-			cssReq: {
-				position: 	"absolute"
-			,	margin:		0
-			,	zIndex: 	2
-			}
-		,	cssDef: {
-				padding:	"10px"
-			,	background:	"#FFF"
-			,	border:		"1px solid #BBB"
-			,	overflow:	"auto"
-			}
-		}
-	,	north: {
-			edge:			"top"
-		,	sizeType:		"height"
-		,	dir:			"horz"
-		,	cssReq: {
-				top: 		0
-			,	bottom: 	"auto"
-			,	left: 		0
-			,	right: 		0
-			,	width: 		"auto"
-			//	height: 	DYNAMIC
-			}
-		}
-	,	south: {
-			edge:			"bottom"
-		,	sizeType:		"height"
-		,	dir:			"horz"
-		,	cssReq: {
-				top: 		"auto"
-			,	bottom: 	0
-			,	left: 		0
-			,	right: 		0
-			,	width: 		"auto"
-			//	height: 	DYNAMIC
-			}
-		}
-	,	east: {
-			edge:			"right"
-		,	sizeType:		"width"
-		,	dir:			"vert"
-		,	cssReq: {
-				left: 		"auto"
-			,	right: 		0
-			,	top: 		"auto" // DYNAMIC
-			,	bottom: 	"auto" // DYNAMIC
-			,	height: 	"auto"
-			//	width: 		DYNAMIC
-			}
-		}
-	,	west: {
-			edge:			"left"
-		,	sizeType:		"width"
-		,	dir:			"vert"
-		,	cssReq: {
-				left: 		0
-			,	right: 		"auto"
-			,	top: 		"auto" // DYNAMIC
-			,	bottom: 	"auto" // DYNAMIC
-			,	height: 	"auto"
-			//	width: 		DYNAMIC
-			}
-		}
-	,	center: {
-			dir:			"center"
-		,	cssReq: {
-				left: 		"auto" // DYNAMIC
-			,	right: 		"auto" // DYNAMIC
-			,	top: 		"auto" // DYNAMIC
-			,	bottom: 	"auto" // DYNAMIC
-			,	height: 	"auto"
-			,	width: 		"auto"
-			}
-		}
-	};
-
-
-	// DYNAMIC DATA
-	var state = {
-		// generate random 'ID#' to identify layout - used to create global namespace for timers
-		id:			Math.floor(Math.random() * 10000)
-	,	container:	{}
-	,	north:		{}
-	,	south:		{}
-	,	east:		{}
-	,	west:		{}
-	,	center:		{}
-	};
-
-
-	var 
-		altEdge = {
-			top:	"bottom"
-		,	bottom: "top"
-		,	left:	"right"
-		,	right:	"left"
-		}
-	,	altSide = {
-			north:	"south"
-		,	south:	"north"
-		,	east: 	"west"
-		,	west: 	"east"
-		}
-	;
-
-
-/*
- * ###########################
- *  INTERNAL HELPER FUNCTIONS
- * ###########################
- */
-
-	/**
-	 * isStr
-	 *
-	 * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
-	 */
-	var isStr = function (o) {
-		if (typeof o == "string")
-			return true;
-		else if (typeof o == "object") {
-			try {
-				var match = o.constructor.toString().match(/string/i); 
-				return (match !== null);
-			} catch (e) {} 
-		}
-		return false;
-	};
-
-	/**
-	 * str
-	 *
-	 * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
-	 *  else returns the original object
-	 */
-	var str = function (o) {
-		if (typeof o == "string" || isStr(o)) return $.trim(o); // trim converts 'String object' to a simple string
-		else return o;
-	};
-
-	/**
-	 * min / max
-	 *
-	 * Alias for Math.min/.max to simplify coding
-	 */
-	var min = function (x,y) { return Math.min(x,y); };
-	var max = function (x,y) { return Math.max(x,y); };
-
-	/**
-	 * transformData
-	 *
-	 * Processes the options passed in and transforms them into the format used by layout()
-	 * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
-	 * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
-	 * To update effects, options MUST use nested-keys format, with an effects key
-	 *
-	 * @callers  initOptions()
-	 * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
-	 * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
-	 */
-	var transformData = function (d) {
-		var json = { defaults:{fxSettings:{}}, north:{fxSettings:{}}, south:{fxSettings:{}}, east:{fxSettings:{}}, west:{fxSettings:{}}, center:{fxSettings:{}} };
-		d = d || {};
-		if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center)
-			json = $.extend( json, d ); // already in json format - add to base keys
-		else
-			// convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
-			$.each( d, function (key,val) {
-				a = key.split("__");
-				json[ a[1] ? a[0] : "defaults" ][ a[1] ? a[1] : a[0] ] = val;
-			});
-		return json;
-	};
-
-	/**
-	 * setFlowCallback
-	 *
-	 * Set an INTERNAL callback to avoid simultaneous animation
-	 * Runs only if needed and only if all callbacks are not 'already set'!
-	 *
-	 * @param String   action  Either 'open' or 'close'
-	 * @pane  String   pane    A valid border-pane name, eg 'west'
-	 * @pane  Boolean  param   Extra param for callback (optional)
-	 */
-	var setFlowCallback = function (action, pane, param) {
-		var
-			cb = action +","+ pane +","+ (param ? 1 : 0)
-		,	cP, cbPane
-		;
-		$.each(c.borderPanes.split(","), function (i,p) {
-			if (c[p].isMoving) {
-				bindCallback(p); // TRY to bind a callback
-				return false; // BREAK
-			}
-		});
-
-		function bindCallback (p, test) {
-			cP = c[p];
-			if (!cP.doCallback) {
-				cP.doCallback = true;
-				cP.callback = cb;
-			}
-			else { // try to 'chain' this callback
-				cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
-				if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
-					bindCallback (cpPane, true); // RECURSE
-			}
-		}
-	};
-
-	/**
-	 * execFlowCallback
-	 *
-	 * RUN the INTERNAL callback for this pane - if one exists
-	 *
-	 * @param String   action  Either 'open' or 'close'
-	 * @pane  String   pane    A valid border-pane name, eg 'west'
-	 * @pane  Boolean  param   Extra param for callback (optional)
-	 */
-	var execFlowCallback = function (pane) {
-		var cP = c[pane];
-
-		// RESET flow-control flaGs
-		c.isLayoutBusy = false;
-		delete cP.isMoving;
-		if (!cP.doCallback || !cP.callback) return;
-
-		cP.doCallback = false; // RESET logic flag
-
-		// EXECUTE the callback
-		var
-			cb = cP.callback.split(",")
-		,	param = (cb[2] > 0 ? true : false)
-		;
-		if (cb[0] == "open")
-			open( cb[1], param  );
-		else if (cb[0] == "close")
-			close( cb[1], param );
-
-		if (!cP.doCallback) cP.callback = null; // RESET - unless callback above enabled it again!
-	};
-
-	/**
-	 * execUserCallback
-	 *
-	 * Executes a Callback function after a trigger event, like resize, open or close
-	 *
-	 * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
-	 * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
-	 */
-	var execUserCallback = function (pane, v_fn) {
-		if (!v_fn) return;
-		var fn;
-		try {
-			if (typeof v_fn == "function")
-				fn = v_fn;	
-			else if (typeof v_fn != "string")
-				return;
-			else if (v_fn.indexOf(",") > 0) {
-				// function name cannot contain a comma, so must be a function name AND a 'name' parameter
-				var
-					args = v_fn.split(",")
-				,	fn = eval(args[0])
-				;
-				if (typeof fn=="function" && args.length > 1)
-					return fn(args[1]); // pass the argument parsed from 'list'
-			}
-			else // just the name of an external function?
-				fn = eval(v_fn);
-
-			if (typeof fn=="function")
-				// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
-				return fn( pane, $Ps[pane], $.extend({},state[pane]), $.extend({},options[pane]), options.name );
-		}
-		catch (ex) {}
-	};
-
-	/**
-	 * cssNum
-	 *
-	 * Returns the 'current CSS value' for an element - returns 0 if property does not exist
-	 *
-	 * @callers  Called by many methods
-	 * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
-	 * @param String  property  The name of the CSS property, eg: top, width, etc.
-	 * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
-	 */
-	var cssNum = function ($E, prop) {
-		var
-			val = 0
-		,	hidden = false
-		,	visibility = ""
-		;
-		if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
-			if ($.curCSS($E[0], "display", true) == "none") {
-				hidden = true;
-				visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
-				$E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so we can measure it
-			}
-		}
-
-		val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
-
-		if (hidden) { // WAS hidden, so put back the way it was
-			$E.css({ display: "none" });
-			if (visibility && visibility != "hidden")
-				$E.css({ visibility: visibility }); // reset 'visibility'
-		}
-
-		return val;
-	};
-
-	/**
-	 * cssW / cssH / cssSize
-	 *
-	 * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
-	 *
-	 * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
-	 * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
-	 * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
-	 * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
-	 *
-	 * @TODO  May need to add additional logic to handle more browser/doctype variations?
-	 */
-	var cssW = function (e, outerWidth) {
-		var $E;
-		if (isStr(e)) {
-			e = str(e);
-			$E = $Ps[e];
-		}
-		else
-			$E = $(e);
-
-		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
-		if (outerWidth <= 0)
-			return 0;
-		else if (!(outerWidth>0))
-			outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
-
-		if (!$.boxModel)
-			return outerWidth;
-
-		else // strip border and padding size from outerWidth to get CSS Width
-			return outerWidth
-				- cssNum($E, "paddingLeft")		
-				- cssNum($E, "paddingRight")
-				- ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth"))
-				- ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"))
-			;
-	};
-	var cssH = function (e, outerHeight) {
-		var $E;
-		if (isStr(e)) {
-			e = str(e);
-			$E = $Ps[e];
-		}
-		else
-			$E = $(e);
-
-		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
-		if (outerHeight <= 0)
-			return 0;
-		else if (!(outerHeight>0))
-			outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
-
-		if (!$.boxModel)
-			return outerHeight;
-
-		else // strip border and padding size from outerHeight to get CSS Height
-			return outerHeight
-				- cssNum($E, "paddingTop")
-				- cssNum($E, "paddingBottom")
-				- ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth"))
-				- ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"))
-			;
-	};
-	var cssSize = function (pane, outerSize) {
-		if (c[pane].dir=="horz") // pane = north or south
-			return cssH(pane, outerSize);
-		else // pane = east or west
-			return cssW(pane, outerSize);
-	};
-
-	/**
-	 * getPaneSize
-	 *
-	 * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
-	 *
-	 * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
-	 */
-	var getPaneSize = function (pane, inclSpace) {
-		var 
-			$P	= $Ps[pane]
-		,	o	= options[pane]
-		,	s	= state[pane]
-		,	oSp	= (inclSpace ? o.spacing_open : 0)
-		,	cSp	= (inclSpace ? o.spacing_closed : 0)
-		;
-		if (!$P || s.isHidden)
-			return 0;
-		else if (s.isClosed || (s.isSliding && inclSpace))
-			return cSp;
-		else if (c[pane].dir == "horz")
-			return $P.outerHeight() + oSp;
-		else // dir == "vert"
-			return $P.outerWidth() + oSp;
-	};
-
-	var setPaneMinMaxSizes = function (pane) {
-		var 
-			d				= cDims
-		,	edge			= c[pane].edge
-		,	dir				= c[pane].dir
-		,	o				= options[pane]
-		,	s				= state[pane]
-		,	$P				= $Ps[pane]
-		,	$altPane		= $Ps[ altSide[pane] ]
-		,	paneSpacing		= o.spacing_open
-		,	altPaneSpacing	= options[ altSide[pane] ].spacing_open
-		,	altPaneSize		= (!$altPane ? 0 : (dir=="horz" ? $altPane.outerHeight() : $altPane.outerWidth()))
-		,	containerSize	= (dir=="horz" ? d.innerHeight : d.innerWidth)
-		//	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
-		,	limitSize		= containerSize - paneSpacing - altPaneSize - altPaneSpacing
-		,	minSize			= s.minSize || 0
-		,	maxSize			= Math.min(s.maxSize || 9999, limitSize)
-		,	minPos, maxPos	// used to set resizing limits
-		;
-		switch (pane) {
-			case "north":	minPos = d.offsetTop + minSize;
-							maxPos = d.offsetTop + maxSize;
-							break;
-			case "west":	minPos = d.offsetLeft + minSize;
-							maxPos = d.offsetLeft + maxSize;
-							break;
-			case "south":	minPos = d.offsetTop + d.innerHeight - maxSize;
-							maxPos = d.offsetTop + d.innerHeight - minSize;
-							break;
-			case "east":	minPos = d.offsetLeft + d.innerWidth - maxSize;
-							maxPos = d.offsetLeft + d.innerWidth - minSize;
-							break;
-		}
-		// save data to pane-state
-		$.extend(s, { minSize: minSize, maxSize: maxSize, minPosition: minPos, maxPosition: maxPos });
-	};
-
-	/**
-	 * getPaneDims
-	 *
-	 * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
-	 *
-	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
-	 */
-	var getPaneDims = function () {
-		var d = {
-			top:	getPaneSize("north", true) // true = include 'spacing' value for p
-		,	bottom:	getPaneSize("south", true)
-		,	left:	getPaneSize("west", true)
-		,	right:	getPaneSize("east", true)
-		,	width:	0
-		,	height:	0
-		};
-
-		with (d) {
-			width 	= cDims.innerWidth - left - right;
-			height 	= cDims.innerHeight - bottom - top;
-			// now add the 'container border/padding' to get final positions - relative to the container
-			top		+= cDims.top;
-			bottom	+= cDims.bottom;
-			left	+= cDims.left;
-			right	+= cDims.right;
-		}
-
-		return d;
-	};
-
-
-	/**
-	 * getElemDims
-	 *
-	 * Returns data for setting size of an element (container or a pane).
-	 *
-	 * @callers  create(), onWindowResize() for container, plus others for pane
-	 * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
-	 */
-	var getElemDims = function ($E) {
-		var
-			d = {} // dimensions hash
-		,	e, b, p // edge, border, padding
-		;
-
-		$.each("Left,Right,Top,Bottom".split(","), function () {
-			e = str(this);
-			b = d["border" +e] = cssNum($E, "border"+e+"Width");
-			p = d["padding"+e] = cssNum($E, "padding"+e);
-			d["offset" +e] = b + p; // total offset of content from outer edge
-			// if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
-			if ($E == $Container)
-				d[e.toLowerCase()] = ($.boxModel ? p : 0); 
-		});
-
-		d.innerWidth  = d.outerWidth  = $E.outerWidth();
-		d.innerHeight = d.outerHeight = $E.outerHeight();
-		if ($.boxModel) {
-			d.innerWidth  -= (d.offsetLeft + d.offsetRight);
-			d.innerHeight -= (d.offsetTop  + d.offsetBottom);
-		}
-
-		return d;
-	};
-
-
-	var setTimer = function (pane, action, fn, ms) {
-		var
-			Layout = window.layout = window.layout || {}
-		,	Timers = Layout.timers = Layout.timers || {}
-		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
-		;
-		if (Timers[name]) return; // timer already set!
-		else Timers[name] = setTimeout(fn, ms);
-	};
-
-	var clearTimer = function (pane, action) {
-		var
-			Layout = window.layout = window.layout || {}
-		,	Timers = Layout.timers = Layout.timers || {}
-		,	name = "layout_"+ state.id +"_"+ pane +"_"+ action // UNIQUE NAME for every layout-pane-action
-		;
-		if (Timers[name]) {
-			clearTimeout( Timers[name] );
-			delete Timers[name];
-			return true;
-		}
-		else
-			return false;
-	};
-
-
-/*
- * ###########################
- *   INITIALIZATION METHODS
- * ###########################
- */
-
-	/**
-	 * create
-	 *
-	 * Initialize the layout - called automatically whenever an instance of layout is created
-	 *
-	 * @callers  NEVER explicity called
-	 * @returns  An object pointer to the instance created
-	 */
-	var create = function () {
-		// initialize config/options
-		initOptions();
-
-		// initialize all objects
-		initContainer();	// set CSS as needed and init state.container dimensions
-		initPanes();		// size & position all panes
-		initHandles();		// create and position all resize bars & togglers buttons
-		initResizable();	// activate resizing on all panes where resizable=true
-		sizeContent("all");	// AFTER panes & handles have been initialized, size 'content' divs
-
-		if (options.scrollToBookmarkOnLoad)
-			with (self.location) if (hash) replace( hash ); // scrollTo Bookmark
-
-		// bind hotkey function - keyDown - if required
-		initHotkeys();
-
-		// bind resizeAll() for 'this layout instance' to window.resize event
-		$(window).resize(function () {
-			var timerID = "timerLayout_"+state.id;
-			if (window[timerID]) clearTimeout(window[timerID]);
-			window[timerID] = null;
-			if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
-				window[timerID] = setTimeout(resizeAll, 100);
-			else // most other browsers have a built-in delay before firing the resize event
-				resizeAll(); // resize all layout elements NOW!
-		});
-	};
-
-	/**
-	 * initContainer
-	 *
-	 * Validate and initialize container CSS and events
-	 *
-	 * @callers  create()
-	 */
-	var initContainer = function () {
-		try { // format html/body if this is a full page layout
-			if ($Container[0].tagName == "BODY") {
-				$("html").css({
-					height:		"100%"
-				,	overflow:	"hidden"
-				});
-				$("body").css({
-					position:	"relative"
-				,	height:		"100%"
-				,	overflow:	"hidden"
-				,	margin:		0
-				,	padding:	0		// TODO: test whether body-padding could be handled?
-				,	border:		"none"	// a body-border creates problems because it cannot be measured!
-				});
-			}
-			else { // set required CSS - overflow and position
-				var
-					CSS	= { overflow: "hidden" } // make sure container will not 'scroll'
-				,	p	= $Container.css("position")
-				,	h	= $Container.css("height")
-				;
-				// if this is a NESTED layout, then outer-pane ALREADY has position and height
-				if (!$Container.hasClass("ui-layout-pane")) {
-					if (!p || "fixed,absolute,relative".indexOf(p) < 0)
-						CSS.position = "relative"; // container MUST have a 'position'
-					if (!h || h=="auto")
-						CSS.height = "100%"; // container MUST have a 'height'
-				}
-				$Container.css( CSS );
-			}
-		} catch (ex) {}
-
-		// get layout-container dimensions (updated when necessary)
-		cDims = state.container = getElemDims( $Container ); // update data-pointer too
-	};
-
-	/**
-	 * initHotkeys
-	 *
-	 * Bind layout hotkeys - if options enabled
-	 *
-	 * @callers  create()
-	 */
-	var initHotkeys = function () {
-		// bind keyDown to capture hotkeys, if option enabled for ANY pane
-		$.each(c.borderPanes.split(","), function (i,pane) {
-			var o = options[pane];
-			if (o.enableCursorHotkey || o.customHotkey) {
-				$(document).keydown( keyDown ); // only need to bind this ONCE
-				return false; // BREAK - binding was done
-			}
-		});
-	};
-
-	/**
-	 * initOptions
-	 *
-	 * Build final CONFIG and OPTIONS data
-	 *
-	 * @callers  create()
-	 */
-	var initOptions = function () {
-		// simplify logic by making sure passed 'opts' var has basic keys
-		opts = transformData( opts );
-
-		// update default effects, if case user passed key
-		if (opts.effects) {
-			$.extend( effects, opts.effects );
-			delete opts.effects;
-		}
-
-		// see if any 'global options' were specified
-		$.each("name,scrollToBookmarkOnLoad".split(","), function (idx,key) {
-			if (opts[key] !== undefined)
-				options[key] = opts[key];
-			else if (opts.defaults[key] !== undefined) {
-				options[key] = opts.defaults[key];
-				delete opts.defaults[key];
-			}
-		});
-
-		// remove any 'defaults' that MUST be set 'per-pane'
-		$.each("paneSelector,resizerCursor,customHotkey".split(","),
-			function (idx,key) { delete opts.defaults[key]; } // is OK if key does not exist
-		);
-
-		// now update options.defaults
-		$.extend( options.defaults, opts.defaults );
-		// make sure required sub-keys exist
-		//if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
-
-		// merge all config & options for the 'center' pane
-		c.center = $.extend( true, {}, c.defaults, c.center );
-		$.extend( options.center, opts.center );
-		// Most 'default options' do not apply to 'center', so add only those that DO
-		var o_Center = $.extend( true, {}, options.defaults, opts.defaults, options.center ); // TEMP data
-		$.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","),
-			function (idx,key) { options.center[key] = o_Center[key]; }
-		);
-
-		var defs = options.defaults;
-
-		// create a COMPLETE set of options for EACH border-pane
-		$.each(c.borderPanes.split(","), function(i,pane) {
-			// apply 'pane-defaults' to CONFIG.PANE
-			c[pane] = $.extend( true, {}, c.defaults, c[pane] );
-			// apply 'pane-defaults' +  user-options to OPTIONS.PANE
-			o = options[pane] = $.extend( true, {}, options.defaults, options[pane], opts.defaults, opts[pane] );
-
-			// make sure we have base-classes
-			if (!o.paneClass)		o.paneClass		= defaults.paneClass;
-			if (!o.resizerClass)	o.resizerClass	= defaults.resizerClass;
-			if (!o.togglerClass)	o.togglerClass	= defaults.togglerClass;
-
-			// create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
-			$.each(["_open","_close",""], function (i,n) { 
-				var
-					sName		= "fxName"+n
-				,	sSpeed		= "fxSpeed"+n
-				,	sSettings	= "fxSettings"+n
-				;
-				// recalculate fxName according to specificity rules
-				o[sName] =
-					opts[pane][sName]		// opts.west.fxName_open
-				||	opts[pane].fxName		// opts.west.fxName
-				||	opts.defaults[sName]	// opts.defaults.fxName_open
-				||	opts.defaults.fxName	// opts.defaults.fxName
-				||	o[sName]				// options.west.fxName_open
-				||	o.fxName				// options.west.fxName
-				||	defs[sName]				// options.defaults.fxName_open
-				||	defs.fxName				// options.defaults.fxName
-				||	"none"
-				;
-				// validate fxName to be sure is a valid effect
-				var fxName = o[sName];
-				if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings))
-					fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
-				// set vars for effects subkeys to simplify logic
-				var
-					fx = effects[fxName]	|| {} // effects.slide
-				,	fx_all	= fx.all		|| {} // effects.slide.all
-				,	fx_pane	= fx[pane]		|| {} // effects.slide.west
-				;
-				// RECREATE the fxSettings[_open|_close] keys using specificity rules
-				o[sSettings] = $.extend(
-					{}
-				,	fx_all						// effects.slide.all
-				,	fx_pane						// effects.slide.west
-				,	defs.fxSettings || {}		// options.defaults.fxSettings
-				,	defs[sSettings] || {}		// options.defaults.fxSettings_open
-				,	o.fxSettings				// options.west.fxSettings
-				,	o[sSettings]				// options.west.fxSettings_open
-				,	opts.defaults.fxSettings	// opts.defaults.fxSettings
-				,	opts.defaults[sSettings] || {} // opts.defaults.fxSettings_open
-				,	opts[pane].fxSettings		// opts.west.fxSettings
-				,	opts[pane][sSettings] || {}	// opts.west.fxSettings_open
-				);
-				// recalculate fxSpeed according to specificity rules
-				o[sSpeed] =
-					opts[pane][sSpeed]		// opts.west.fxSpeed_open
-				||	opts[pane].fxSpeed		// opts.west.fxSpeed (pane-default)
-				||	opts.defaults[sSpeed]	// opts.defaults.fxSpeed_open
-				||	opts.defaults.fxSpeed	// opts.defaults.fxSpeed
-				||	o[sSpeed]				// options.west.fxSpeed_open
-				||	o[sSettings].duration	// options.west.fxSettings_open.duration
-				||	o.fxSpeed				// options.west.fxSpeed
-				||	o.fxSettings.duration	// options.west.fxSettings.duration
-				||	defs.fxSpeed			// options.defaults.fxSpeed
-				||	defs.fxSettings.duration// options.defaults.fxSettings.duration
-				||	fx_pane.duration		// effects.slide.west.duration
-				||	fx_all.duration			// effects.slide.all.duration
-				||	"normal"				// DEFAULT
-				;
-				// DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
-			});
-		});
-	};
-
-	/**
-	 * initPanes
-	 *
-	 * Initialize module objects, styling, size and position for all panes
-	 *
-	 * @callers  create()
-	 */
-	var initPanes = function () {
-		// NOTE: do north & south FIRST so we can measure their height - do center LAST
-		$.each(c.allPanes.split(","), function() {
-			var 
-				pane	= str(this)
-			,	o		= options[pane]
-			,	s		= state[pane]
-			,	fx		= s.fx
-			,	dir		= c[pane].dir
-			//	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
-			,	size	= o.size=="auto" || isNaN(o.size) ? 0 : o.size
-			,	minSize	= o.minSize || 1
-			,	maxSize	= o.maxSize || 9999
-			,	spacing	= o.spacing_open || 0
-			,	sel		= o.paneSelector
-			,	isIE6	= ($.browser.msie && $.browser.version < 7)
-			,	CSS		= {}
-			,	$P, $C
-			;
-			$Cs[pane] = false; // init
-
-			if (sel.substr(0,1)==="#") // ID selector
-				// NOTE: elements selected 'by ID' DO NOT have to be 'children'
-				$P = $Ps[pane] = $Container.find(sel+":first");
-			else { // class or other selector
-				$P = $Ps[pane] = $Container.children(sel+":first");
-				// look for the pane nested inside a 'form' element
-				if (!$P.length) $P = $Ps[pane] = $Container.children("form:first").children(sel+":first");
-			}
-
-			if (!$P.length) {
-				$Ps[pane] = false; // logic
-				return true; // SKIP to next
-			}
-
-			// add basic classes & attributes
-			$P
-				.attr("pane", pane) // add pane-identifier
-				.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
-			;
-
-			// init pane-logic vars, etc.
-			if (pane != "center") {
-				s.isClosed  = false; // true = pane is closed
-				s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
-				s.isResizing= false; // true = pane is in process of being resized
-				s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
-				s.noRoom	= false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
-				// create special keys for internal use
-				c[pane].pins = [];   // used to track and sync 'pin-buttons' for border-panes
-			}
-
-			CSS = $.extend({ visibility: "visible", display: "block" }, c.defaults.cssReq, c[pane].cssReq );
-			if (o.applyDefaultStyles) $.extend( CSS, c.defaults.cssDef, c[pane].cssDef ); // cosmetic defaults
-			$P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
-			CSS = {};	// reset var
-
-			// set css-position to account for container borders & padding
-			switch (pane) {
-				case "north": 	CSS.top 	= cDims.top;
-								CSS.left 	= cDims.left;
-								CSS.right	= cDims.right;
-								break;
-				case "south": 	CSS.bottom	= cDims.bottom;
-								CSS.left 	= cDims.left;
-								CSS.right 	= cDims.right;
-								break;
-				case "west": 	CSS.left 	= cDims.left; // top, bottom & height set by sizeMidPanes()
-								break;
-				case "east": 	CSS.right 	= cDims.right; // ditto
-								break;
-				case "center":	// top, left, width & height set by sizeMidPanes()
-			}
-
-			if (dir == "horz") { // north or south pane
-				if (size === 0 || size == "auto") {
-					$P.css({ height: "auto" });
-					size = $P.outerHeight();
-				}
-				size = max(size, minSize);
-				size = min(size, maxSize);
-				size = min(size, cDims.innerHeight - spacing);
-				CSS.height = max(1, cssH(pane, size));
-				s.size = size; // update state
-				// make sure minSize is sufficient to avoid errors
-				s.maxSize = maxSize; // init value
-				s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
-				// handle IE6
-				//if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
-				$P.css(CSS); // apply size & position
-			}
-			else if (dir == "vert") { // east or west pane
-				if (size === 0 || size == "auto") {
-					$P.css({ width: "auto", float: "left" }); // float = FORCE pane to auto-size
-					size = $P.outerWidth();
-					$P.css({ float: "none" }); // RESET
-				}
-				size = max(size, minSize);
-				size = min(size, maxSize);
-				size = min(size, cDims.innerWidth - spacing);
-				CSS.width = max(1, cssW(pane, size));
-				s.size = size; // update state
-				s.maxSize = maxSize; // init value
-				// make sure minSize is sufficient to avoid errors
-				s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
-				$P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
-				sizeMidPanes(pane, null, true); // true = onInit
-			}
-			else if (pane == "center") {
-				$P.css(CSS); // top, left, width & height set by sizeMidPanes...
-				sizeMidPanes("center", null, true); // true = onInit
-			}
-
-			// close or hide the pane if specified in settings
-			if (o.initClosed && o.closable) {
-				$P.hide().addClass("closed");
-				s.isClosed = true;
-			}
-			else if (o.initHidden || o.initClosed) {
-				hide(pane, true); // will be completely invisible - no resizer or spacing
-				s.isHidden = true;
-			}
-			else
-				$P.addClass("open");
-
-			// check option for auto-handling of pop-ups & drop-downs
-			if (o.showOverflowOnHover)
-				$P.hover( allowOverflow, resetOverflow );
-
-			/*
-			 *	see if this pane has a 'content element' that we need to auto-size
-			 */
-			if (o.contentSelector) {
-				$C = $Cs[pane] = $P.children(o.contentSelector+":first"); // match 1-element only
-				if (!$C.length) {
-					$Cs[pane] = false;
-					return true; // SKIP to next
-				}
-				$C.css( c.content.cssReq );
-				if (o.applyDefaultStyles) $C.css( c.content.cssDef ); // cosmetic defaults
-				// NO PANE-SCROLLING when there is a content-div
-				$P.css({ overflow: "hidden" });
-			}
-		});
-	};
-
-	/**
-	 * initHandles
-	 *
-	 * Initialize module objects, styling, size and position for all resize bars and toggler buttons
-	 *
-	 * @callers  create()
-	 */
-	var initHandles = function () {
-		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
-		$.each(c.borderPanes.split(","), function() {
-			var 
-				pane	= str(this)
-			,	o		= options[pane]
-			,	s		= state[pane]
-			,	rClass	= o.resizerClass
-			,	tClass	= o.togglerClass
-			,	$P		= $Ps[pane]
-			;
-			$Rs[pane] = false; // INIT
-			$Ts[pane] = false;
-
-			if (!$P || (!o.closable && !o.resizable)) return; // pane does not exist - skip
-
-			var 
-				edge	= c[pane].edge
-			,	isOpen	= $P.is(":visible")
-			,	spacing	= (isOpen ? o.spacing_open : o.spacing_closed)
-			,	_pane	= "-"+ pane // used for classNames
-			,	_state	= (isOpen ? "-open" : "-closed") // used for classNames
-			,	$R, $T
-			;
-			// INIT RESIZER BAR
-			$R = $Rs[pane] = $("<span></span>");
-	
-			if (isOpen && o.resizable)
-				; // this is handled by initResizable
-			else if (!isOpen && o.slidable)
-				$R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
-	
-			$R
-				// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
-				.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
-				.attr("resizer", pane) // so we can read this from the resizer
-				.css(c.resizers.cssReq) // add base/required styles
-				// POSITION of resizer bar - allow for container border & padding
-				.css(edge, cDims[edge] + getPaneSize(pane))
-				// ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
-				.addClass( rClass +" "+ rClass+_pane +" "+ rClass+_state +" "+ rClass+_pane+_state )
-				.appendTo($Container) // append DIV to container
-			;
-			 // ADD VISUAL STYLES
-			if (o.applyDefaultStyles)
-				$R.css(c.resizers.cssDef);
-
-			if (o.closable) {
-				// INIT COLLAPSER BUTTON
-				$T = $Ts[pane] = $("<div></div>");
-				$T
-					// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
-					.attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
-					.css(c.togglers.cssReq) // add base/required styles
-					.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed))
-					.click(function(evt){ toggle(pane); evt.stopPropagation(); })
-					.mouseover(function(evt){ evt.stopPropagation(); }) // prevent resizer event
-					// ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
-					.addClass( tClass +" "+ tClass+_pane +" "+ tClass+_state +" "+ tClass+_pane+_state )
-					.appendTo($R) // append SPAN to resizer DIV
-				;
-
-				// ADD INNER-SPANS TO TOGGLER
-				if (o.togglerContent_open) // ui-layout-open
-					$("<span>"+ o.togglerContent_open +"</span>")
-						.addClass("content content-open")
-						.css("display", s.isClosed ? "none" : "block")
-						.appendTo( $T )
-					;
-				if (o.togglerContent_closed) // ui-layout-closed
-					$("<span>"+ o.togglerContent_closed +"</span>")
-						.addClass("content content-closed")
-						.css("display", s.isClosed ? "block" : "none")
-						.appendTo( $T )
-					;
-
-				 // ADD BASIC VISUAL STYLES
-				if (o.applyDefaultStyles)
-					$T.css(c.togglers.cssDef);
-
-				if (!isOpen) bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
-			}
-
-		});
-
-		// SET ALL HANDLE SIZES & LENGTHS
-		sizeHandles("all", true); // true = onInit
-	};
-
-	/**
-	 * initResizable
-	 *
-	 * Add resize-bars to all panes that specify it in options
-	 *
-	 * @dependancies  $.fn.resizable - will abort if not found
-	 * @callers  create()
-	 */
-	var initResizable = function () {
-		var
-			draggingAvailable = (typeof $.fn.draggable == "function")
-		,	minPosition, maxPosition, edge // set in start()
-		;
-
-		$.each(c.borderPanes.split(","), function() {
-			var 
-				pane	= str(this)
-			,	o		= options[pane]
-			,	s		= state[pane]
-			;
-			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
-				o.resizable = false;
-				return true; // skip to next
-			}
-
-			var 
-				rClass				= o.resizerClass
-			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
-			,	dragClass			= rClass+"-drag"			// resizer-drag
-			,	dragPaneClass		= rClass+"-"+pane+"-drag"	// resizer-north-drag
-			//	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
-			,	draggingClass		= rClass+"-dragging"		// resizer-dragging
-			,	draggingPaneClass	= rClass+"-"+pane+"-dragging" // resizer-north-dragging
-			,	draggingClassSet	= false 					// logic var
-			,	$P 					= $Ps[pane]
-			,	$R					= $Rs[pane]
-			;
-
-			if (!s.isClosed)
-				$R
-					.attr("title", o.resizerTip)
-					.css("cursor", o.resizerCursor) // n-resize, s-resize, etc
-				;
-
-			$R.draggable({
-				containment:	$Container[0] // limit resizing to layout container
-			,	axis:			(c[pane].dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
-			,	delay:			200
-			,	distance:		1
-			//	basic format for helper - style it using class: .ui-draggable-dragging
-			,	helper:			"clone"
-			,	opacity:		o.resizerDragOpacity
-			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
-			,	zIndex:			c.zIndex.resizing
-
-			,	start: function (e, ui) {
-					// onresize_start callback - will CANCEL hide if returns false
-					// TODO: CONFIRM that dragging can be cancelled like this???
-					if (false === execUserCallback(pane, o.onresize_start)) return false;
-
-					s.isResizing = true; // prevent pane from closing while resizing
-					clearTimer(pane, "closeSlider"); // just in case already triggered
-
-					$R.addClass( dragClass +" "+ dragPaneClass ); // add drag classes
-					draggingClassSet = false; // reset logic var - see drag()
-
-					// SET RESIZING LIMITS - used in drag()
-					var resizerWidth = (pane=="east" || pane=="south" ? o.spacing_open : 0);
-					setPaneMinMaxSizes(pane); // update pane-state
-					s.minPosition -= resizerWidth;
-					s.maxPosition -= resizerWidth;
-					edge = (c[pane].dir=="horz" ? "top" : "left");
-
-					// MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
-					$(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function() {					
-						$('<div class="ui-layout-mask"/>')
-							.css({
-								background:	"#fff"
-							,	opacity:	"0.001"
-							,	zIndex:		9
-							,	position:	"absolute"
-							,	width:		this.offsetWidth+"px"
-							,	height:		this.offsetHeight+"px"
-							})
-							.css($(this).offset()) // top & left
-							.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
-						;
-					});
-				}
-
-			,	drag: function (e, ui) {
-					if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
-						$(".ui-draggable-dragging")
-							.addClass( draggingClass +" "+ draggingPaneClass ) // add dragging classes
-							.children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
-						;
-						draggingClassSet = true;
-						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
-						if (s.isSliding) $Ps[pane].css("zIndex", c.zIndex.sliding);
-					}
-					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
-					if		(ui.position[edge] < s.minPosition) ui.position[edge] = s.minPosition;
-					else if (ui.position[edge] > s.maxPosition) ui.position[edge] = s.maxPosition;
-				}
-
-			,	stop: function (e, ui) {
-					var 
-						dragPos	= ui.position
-					,	resizerPos
-					,	newSize
-					;
-					$R.removeClass( dragClass +" "+ dragPaneClass ); // remove drag classes
-	
-					switch (pane) {
-						case "north":	resizerPos = dragPos.top; break;
-						case "west":	resizerPos = dragPos.left; break;
-						case "south":	resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight(); break;
-						case "east":	resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth(); break;
-					}
-					// remove container margin from resizer position to get the pane size
-					newSize = resizerPos - cDims[ c[pane].edge ];
-
-					sizePane(pane, newSize);
-
-					// UN-MASK PANES MASKED IN drag.start
-					$("div.ui-layout-mask").remove(); // Remove iframe masks	
-
-					s.isResizing = false;
-				}
-
-			});
-		});
-	};
-
-
-
-/*
- * ###########################
- *       ACTION METHODS
- * ###########################
- */
-
-	/**
-	 * hide / show
-	 *
-	 * Completely 'hides' a pane, including its spacing - as if it does not exist
-	 * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
-	 *
-	 * @param String  pane   The pane being hidden, ie: north, south, east, or west
-	 */
-	var hide = function (pane, onInit) {
-		var
-			o	= options[pane]
-		,	s	= state[pane]
-		,	$P	= $Ps[pane]
-		,	$R	= $Rs[pane]
-		;
-		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
-
-		// onhide_start callback - will CANCEL hide if returns false
-		if (false === execUserCallback(pane, o.onhide_start)) return;
-
-		s.isSliding = false; // just in case
-
-		// now hide the elements
-		if ($R) $R.hide(); // hide resizer-bar
-		if (onInit || s.isClosed) {
-			s.isClosed = true; // to trigger open-animation on show()
-			s.isHidden  = true;
-			$P.hide(); // no animation when loading page
-			sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
-			execUserCallback(pane, o.onhide_end || o.onhide);
-		}
-		else {
-			s.isHiding = true; // used by onclose
-			close(pane, false); // adjust all panes to fit
-			//s.isHidden  = true; - will be set by close - if not cancelled
-		}
-	};
-
-	var show = function (pane, openPane) {
-		var
-			o	= options[pane]
-		,	s	= state[pane]
-		,	$P	= $Ps[pane]
-		,	$R	= $Rs[pane]
-		;
-		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
-
-		// onhide_start callback - will CANCEL hide if returns false
-		if (false === execUserCallback(pane, o.onshow_start)) return;
-
-		s.isSliding = false; // just in case
-		s.isShowing = true; // used by onopen/onclose
-		//s.isHidden  = false; - will be set by open/close - if not cancelled
-
-		// now show the elements
-		if ($R && o.spacing_open > 0) $R.show();
-		if (openPane === false)
-			close(pane, true); // true = force
-		else
-			open(pane); // adjust all panes to fit
-	};
-
-
-	/**
-	 * toggle
-	 *
-	 * Toggles a pane open/closed by calling either open or close
-	 *
-	 * @param String  pane   The pane being toggled, ie: north, south, east, or west
-	 */
-	var toggle = function (pane) {
-		var s = state[pane];
-		if (s.isHidden)
-			show(pane); // will call 'open' after unhiding it
-		else if (s.isClosed)
-			open(pane);
-		else
-			close(pane);
-	};
-
-	/**
-	 * close
-	 *
-	 * Close the specified pane (animation optional), and resize all other panes as needed
-	 *
-	 * @param String  pane   The pane being closed, ie: north, south, east, or west
-	 */
-	var close = function (pane, force, noAnimation) {
-		var 
-			$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		,	$T		= $Ts[pane]
-		,	o		= options[pane]
-		,	s		= state[pane]
-		,	doFX	= !noAnimation && !s.isClosed && (o.fxName_close != "none")
-		,	edge	= c[pane].edge
-		,	rClass	= o.resizerClass
-		,	tClass	= o.togglerClass
-		,	_pane	= "-"+ pane // used for classNames
-		,	_open	= "-open"
-		,	_sliding= "-sliding"
-		,	_closed	= "-closed"
-		// 	transfer logic vars to temp vars
-		,	isShowing = s.isShowing
-		,	isHiding = s.isHiding
-		;
-		// now clear the logic vars
-		delete s.isShowing;
-		delete s.isHiding;
-
-		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
-		else if (!force && s.isClosed && !isShowing) return; // already closed
-
-		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
-			setFlowCallback("close", pane, force); // set a callback for this action, if possible
-			return; // ABORT 
-		}
-
-		// onclose_start callback - will CANCEL hide if returns false
-		// SKIP if just 'showing' a hidden pane as 'closed'
-		if (!isShowing && false === execUserCallback(pane, o.onclose_start)) return;
-
-		// SET flow-control flags
-		c[pane].isMoving = true;
-		c.isLayoutBusy = true;
-
-		s.isClosed = true;
-		// update isHidden BEFORE sizing panes
-		if (isHiding) s.isHidden = true;
-		else if (isShowing) s.isHidden = false;
-
-		// sync any 'pin buttons'
-		syncPinBtns(pane, false);
-
-		// resize panes adjacent to this one
-		if (!s.isSliding) sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
-
-		// if this pane has a resizer bar, move it now
-		if ($R) {
-			$R
-				.css(edge, cDims[edge]) // move the resizer bar
-				.removeClass( rClass+_open +" "+ rClass+_pane+_open )
-				.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
-				.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
-			;
-			// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
-			if (o.resizable)
-				$R
-					.draggable("disable")
-					.css("cursor", "default")
-					.attr("title","")
-				;
-			// if pane has a toggler button, adjust that too
-			if ($T) {
-				$T
-					.removeClass( tClass+_open +" "+ tClass+_pane+_open )
-					.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
-					.attr("title", o.togglerTip_closed) // may be blank
-				;
-			}
-			sizeHandles(); // resize 'length' and position togglers for adjacent panes
-		}
-
-		// ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
-		if (doFX) {
-			lockPaneForFX(pane, true); // need to set left/top so animation will work
-			$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
-				lockPaneForFX(pane, false); // undo
-				if (!s.isClosed) return; // pane was opened before animation finished!
-				close_2();
-			});
-		}
-		else {
-			$P.hide(); // just hide pane NOW
-			close_2();
-		}
-
-		// SUBROUTINE
-		function close_2 () {
-			bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
-
-			// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
-			if (!isShowing)	execUserCallback(pane, o.onclose_end || o.onclose);
-			// onhide OR onshow callback
-			if (isShowing)	execUserCallback(pane, o.onshow_end || o.onshow);
-			if (isHiding)	execUserCallback(pane, o.onhide_end || o.onhide);
-
-			// internal flow-control callback
-			execFlowCallback(pane);
-		}
-	};
-
-	/**
-	 * open
-	 *
-	 * Open the specified pane (animation optional), and resize all other panes as needed
-	 *
-	 * @param String  pane   The pane being opened, ie: north, south, east, or west
-	 */
-	var open = function (pane, slide, noAnimation) {
-		var 
-			$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		,	$T		= $Ts[pane]
-		,	o		= options[pane]
-		,	s		= state[pane]
-		,	doFX	= !noAnimation && s.isClosed && (o.fxName_open != "none")
-		,	edge	= c[pane].edge
-		,	rClass	= o.resizerClass
-		,	tClass	= o.togglerClass
-		,	_pane	= "-"+ pane // used for classNames
-		,	_open	= "-open"
-		,	_closed	= "-closed"
-		,	_sliding= "-sliding"
-		// 	transfer logic var to temp var
-		,	isShowing = s.isShowing
-		;
-		// now clear the logic var
-		delete s.isShowing;
-
-		if (!$P || (!o.resizable && !o.closable)) return; // invalid request
-		else if (!s.isClosed && !s.isSliding) return; // already open
-
-		// pane can ALSO be unhidden by just calling show(), so handle this scenario
-		if (s.isHidden && !isShowing) {
-			show(pane, true);
-			return;
-		}
-
-		if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
-			setFlowCallback("open", pane, slide); // set a callback for this action, if possible
-			return; // ABORT
-		}
-
-		// onopen_start callback - will CANCEL hide if returns false
-		if (false === execUserCallback(pane, o.onopen_start)) return;
-
-		// SET flow-control flags
-		c[pane].isMoving = true;
-		c.isLayoutBusy = true;
-
-		// 'PIN PANE' - stop sliding
-		if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
-			bindStopSlidingEvents(pane, false); // will set isSliding=false
-
-		s.isClosed = false;
-		// update isHidden BEFORE sizing panes
-		if (isShowing) s.isHidden = false;
-
-		// Container size may have changed - shrink the pane if now 'too big'
-		setPaneMinMaxSizes(pane); // update pane-state
-		if (s.size > s.maxSize) // pane is too big! resize it before opening
-			$P.css( c[pane].sizeType, max(1, cssSize(pane, s.maxSize)) );
-
-		bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
-
-		if (doFX) { // ANIMATE
-			lockPaneForFX(pane, true); // need to set left/top so animation will work
-			$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
-				lockPaneForFX(pane, false); // undo
-				if (s.isClosed) return; // pane was closed before animation finished!
-				open_2(); // continue
-			});
-		}
-		else {// no animation
-			$P.show();	// just show pane and...
-			open_2();	// continue
-		}
-
-		// SUBROUTINE
-		function open_2 () {
-			// NOTE: if isSliding, then other panes are NOT 'resized'
-			if (!s.isSliding) // resize all panes adjacent to this one
-				sizeMidPanes(c[pane].dir=="vert" ? "center" : "all");
-
-			// if this pane has a toggler, move it now
-			if ($R) {
-				$R
-					.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
-					.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
-					.addClass( rClass+_open +" "+ rClass+_pane+_open )
-					.addClass( !s.isSliding ? "" : rClass+_sliding +" "+ rClass+_pane+_sliding )
-				;
-				if (o.resizable)
-					$R
-						.draggable("enable")
-						.css("cursor", o.resizerCursor)
-						.attr("title", o.resizerTip)
-					;
-				else
-					$R.css("cursor", "default"); // n-resize, s-resize, etc
-				// if pane also has a toggler button, adjust that too
-				if ($T) {
-					$T
-						.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
-						.addClass( tClass+_open +" "+ tClass+_pane+_open )
-						.attr("title", o.togglerTip_open) // may be blank
-					;
-				}
-				sizeHandles("all"); // resize resizer & toggler sizes for all panes
-			}
-
-			// resize content every time pane opens - to be sure
-			sizeContent(pane);
-
-			// sync any 'pin buttons'
-			syncPinBtns(pane, !s.isSliding);
-
-			// onopen callback
-			execUserCallback(pane, o.onopen_end || o.onopen);
-
-			// onshow callback
-			if (isShowing) execUserCallback(pane, o.onshow_end || o.onshow);
-
-			// internal flow-control callback
-			execFlowCallback(pane);
-		}
-	};
-	
-
-	/**
-	 * lockPaneForFX
-	 *
-	 * Must set left/top on East/South panes so animation will work properly
-	 *
-	 * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
-	 * @param Boolean  doLock  true = set left/top, false = remove
-	 */
-	var lockPaneForFX = function (pane, doLock) {
-		var $P = $Ps[pane];
-		if (doLock) {
-			$P.css({ zIndex: c.zIndex.animation }); // overlay all elements during animation
-			if (pane=="south")
-				$P.css({ top: cDims.top + cDims.innerHeight - $P.outerHeight() });
-			else if (pane=="east")
-				$P.css({ left: cDims.left + cDims.innerWidth - $P.outerWidth() });
-		}
-		else {
-			if (!state[pane].isSliding) $P.css({ zIndex: c.zIndex.pane_normal });
-			if (pane=="south")
-				$P.css({ top: "auto" });
-			else if (pane=="east")
-				$P.css({ left: "auto" });
-		}
-	};
-
-
-	/**
-	 * bindStartSlidingEvent
-	 *
-	 * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
-	 *
-	 * @callers  open(), close()
-	 * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
-	 * @param Boolean  enable  Enable or Disable sliding?
-	 */
-	var bindStartSlidingEvent = function (pane, enable) {
-		var 
-			o		= options[pane]
-		,	$R		= $Rs[pane]
-		,	trigger	= o.slideTrigger_open
-		;
-		if (!$R || !o.slidable) return;
-		// make sure we have a valid event
-		if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") trigger = "click";
-		$R
-			// add or remove trigger event
-			[enable ? "bind" : "unbind"](trigger, slideOpen)
-			// set the appropriate cursor & title/tip
-			.css("cursor", (enable ? o.sliderCursor: "default"))
-			.attr("title", (enable ? o.sliderTip : ""))
-		;
-	};
-
-	/**
-	 * bindStopSlidingEvents
-	 *
-	 * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
-	 * Also increases zIndex when pane is sliding open
-	 * See bindStartSlidingEvent for code to control 'slide open'
-	 *
-	 * @callers  slideOpen(), slideClosed()
-	 * @param String  pane  The pane to process, 'north', 'south', etc.
-	 * @param Boolean  isOpen  Is pane open or closed?
-	 */
-	var bindStopSlidingEvents = function (pane, enable) {
-		var 
-			o		= options[pane]
-		,	s		= state[pane]
-		,	trigger	= o.slideTrigger_close
-		,	action	= (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
-		,	$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		;
-
-		s.isSliding = enable; // logic
-		clearTimer(pane, "closeSlider"); // just in case
-
-		// raise z-index when sliding
-		$P.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal) });
-		$R.css({ zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal) });
-
-		// make sure we have a valid event
-		if (trigger != "click" && trigger != "mouseout") trigger = "mouseout";
-
-		// when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
-		if (enable) { // BIND trigger events
-			$P.bind(trigger, slideClosed );
-			$R.bind(trigger, slideClosed );
-			if (trigger = "mouseout") {
-				$P.bind("mouseover", cancelMouseOut );
-				$R.bind("mouseover", cancelMouseOut );
-			}
-		}
-		else { // UNBIND trigger events
-			// TODO: why does unbind of a 'single function' not work reliably?
-			//$P[action](trigger, slideClosed );
-			$P.unbind(trigger);
-			$R.unbind(trigger);
-			if (trigger = "mouseout") {
-				//$P[action]("mouseover", cancelMouseOut );
-				$P.unbind("mouseover");
-				$R.unbind("mouseover");
-				clearTimer(pane, "closeSlider");
-			}
-		}
-
-		// SUBROUTINE for mouseout timer clearing
-		function cancelMouseOut (evt) {
-			clearTimer(pane, "closeSlider");
-			evt.stopPropagation();
-		}
-	};
-
-	var slideOpen = function () {
-		var pane = $(this).attr("resizer"); // attr added by initHandles
-		if (state[pane].isClosed) { // skip if already open!
-			bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
-			open(pane, true); // true = slide - ie, called from here!
-		}
-	};
-
-	var slideClosed = function () {
-		var
-			$E = $(this)
-		,	pane = $E.attr("pane") || $E.attr("resizer")
-		,	o = options[pane]
-		,	s = state[pane]
-		;
-		if (s.isClosed || s.isResizing)
-			return; // skip if already closed OR in process of resizing
-		else if (o.slideTrigger_close == "click")
-			close_NOW(); // close immediately onClick
-		else // trigger = mouseout - use a delay
-			setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
-
-		// SUBROUTINE for timed close
-		function close_NOW () {
-			bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
-			if (!s.isClosed) close(pane); // skip if already closed!
-		}
-	};
-
-
-	/**
-	 * sizePane
-	 *
-	 * @callers  initResizable.stop()
-	 * @param String  pane   The pane being resized - usually west or east, but potentially north or south
-	 * @param Integer  newSize  The new size for this pane - will be validated
-	 */
-	var sizePane = function (pane, size) {
-		// TODO: accept "auto" as size, and size-to-fit pane content
-		var 
-			edge	= c[pane].edge
-		,	dir		= c[pane].dir
-		,	o		= options[pane]
-		,	s		= state[pane]
-		,	$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		;
-		// calculate 'current' min/max sizes
-		setPaneMinMaxSizes(pane); // update pane-state
-		// compare/update calculated min/max to user-options
-		s.minSize = max(s.minSize, o.minSize);
-		if (o.maxSize > 0) s.maxSize = min(s.maxSize, o.maxSize);
-		// validate passed size
-		size = max(size, s.minSize);
-		size = min(size, s.maxSize);
-		s.size = size; // update state
-
-		// move the resizer bar and resize the pane
-		$R.css( edge, size + cDims[edge] );
-		$P.css( c[pane].sizeType, max(1, cssSize(pane, size)) );
-
-		// resize all the adjacent panes, and adjust their toggler buttons
-		if (!s.isSliding) sizeMidPanes(dir=="horz" ? "all" : "center");
-		sizeHandles();
-		sizeContent(pane);
-		execUserCallback(pane, o.onresize_end || o.onresize);
-	};
-
-	/**
-	 * sizeMidPanes
-	 *
-	 * @callers  create(), open(), close(), onWindowResize()
-	 */
-	var sizeMidPanes = function (panes, overrideDims, onInit) {
-		if (!panes || panes == "all") panes = "east,west,center";
-
-		var d = getPaneDims();
-		if (overrideDims) $.extend( d, overrideDims );
-
-		$.each(panes.split(","), function() {
-			if (!$Ps[this]) return; // NO PANE - skip
-			var 
-				pane	= str(this)
-			,	o		= options[pane]
-			,	s		= state[pane]
-			,	$P		= $Ps[pane]
-			,	$R		= $Rs[pane]
-			,	hasRoom	= true
-			,	CSS		= {}
-			;
-
-			if (pane == "center") {
-				d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
-				CSS = $.extend( {}, d ); // COPY ALL of the paneDims
-				CSS.width  = max(1, cssW(pane, CSS.width));
-				CSS.height = max(1, cssH(pane, CSS.height));
-				hasRoom = (CSS.width > 1 && CSS.height > 1);
-				/*
-				 * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
-				 * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
-				 */
-				if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
-					if ($Ps.north) $Ps.north.css({ width: cssW($Ps.north, cDims.innerWidth) });
-					if ($Ps.south) $Ps.south.css({ width: cssW($Ps.south, cDims.innerWidth) });
-				}
-			}
-			else { // for east and west, set only the height
-				CSS.top = d.top;
-				CSS.bottom = d.bottom;
-				CSS.height = max(1, cssH(pane, d.height));
-				hasRoom = (CSS.height > 1);
-			}
-
-			if (hasRoom) {
-				$P.css(CSS);
-				if (s.noRoom) {
-					s.noRoom = false;
-					if (s.isHidden) return;
-					else show(pane, !s.isClosed);
-					/* OLD CODE - keep until sure line above works right!
-					if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
-					if ($R) $R.show();
-					*/
-				}
-				if (!onInit) {
-					sizeContent(pane);
-					execUserCallback(pane, o.onresize_end || o.onresize);
-				}
-			}
-			else if (!s.noRoom) { // no room for pane, so just hide it (if not already)
-				s.noRoom = true; // update state
-				if (s.isHidden) return;
-				if (onInit) { // skip onhide callback and other logic onLoad
-					$P.hide();
-					if ($R) $R.hide();
-				}
-				else hide(pane);
-			}
-		});
-	};
-
-
-	var sizeContent = function (panes) {
-		if (!panes || panes == "all") panes = c.allPanes;
-
-		$.each(panes.split(","), function() {
-			if (!$Cs[this]) return; // NO CONTENT - skip
-			var 
-				pane	= str(this)
-			,	ignore	= options[pane].contentIgnoreSelector
-			,	$P		= $Ps[pane]
-			,	$C		= $Cs[pane]
-			,	e_C		= $C[0]		// DOM element
-			,	height	= cssH($P);	// init to pane.innerHeight
-			;
-			$P.children().each(function() {
-				if (this == e_C) return; // Content elem - skip
-				var $E = $(this);
-				if (!ignore || !$E.is(ignore))
-					height -= $E.outerHeight();
-			});
-			if (height > 0)
-				height = cssH($C, height);
-			if (height < 1)
-				$C.hide(); // no room for content!
-			else
-				$C.css({ height: height }).show();
-		});
-	};
-
-
-	/**
-	 * sizeHandles
-	 *
-	 * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
-	 *
-	 * @callers  initHandles(), open(), close(), resizeAll()
-	 */
-	var sizeHandles = function (panes, onInit) {
-		if (!panes || panes == "all") panes = c.borderPanes;
-
-		$.each(panes.split(","), function() {
-			var 
-				pane	= str(this)
-			,	o		= options[pane]
-			,	s		= state[pane]
-			,	$P		= $Ps[pane]
-			,	$R		= $Rs[pane]
-			,	$T		= $Ts[pane]
-			;
-			if (!$P || !$R || (!o.resizable && !o.closable)) return; // skip
-
-			var 
-				dir			= c[pane].dir
-			,	_state		= (s.isClosed ? "_closed" : "_open")
-			,	spacing		= o["spacing"+ _state]
-			,	togAlign	= o["togglerAlign"+ _state]
-			,	togLen		= o["togglerLength"+ _state]
-			,	paneLen
-			,	offset
-			,	CSS = {}
-			;
-			if (spacing == 0) {
-				$R.hide();
-				return;
-			}
-			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
-				$R.show(); // in case was previously hidden
-
-			// Resizer Bar is ALWAYS same width/height of pane it is attached to
-			if (dir == "horz") { // north/south
-				paneLen = $P.outerWidth();
-				$R.css({
-					width:	max(1, cssW($R, paneLen)) // account for borders & padding
-				,	height:	max(1, cssH($R, spacing)) // ditto
-				,	left:	cssNum($P, "left")
-				});
-			}
-			else { // east/west
-				paneLen = $P.outerHeight();
-				$R.css({
-					height:	max(1, cssH($R, paneLen)) // account for borders & padding
-				,	width:	max(1, cssW($R, spacing)) // ditto
-				,	top:	cDims.top + getPaneSize("north", true)
-				//,	top:	cssNum($Ps["center"], "top")
-				});
-				
-			}
-
-			if ($T) {
-				if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
-					$T.hide(); // always HIDE the toggler when 'sliding'
-					return;
-				}
-				else
-					$T.show(); // in case was previously hidden
-
-				if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
-					togLen = paneLen;
-					offset = 0;
-				}
-				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
-					if (typeof togAlign == "string") {
-						switch (togAlign) {
-							case "top":
-							case "left":	offset = 0;
-											break;
-							case "bottom":
-							case "right":	offset = paneLen - togLen;
-											break;
-							case "middle":
-							case "center":
-							default:		offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
-						}
-					}
-					else { // togAlign = number
-						var x = parseInt(togAlign); //
-						if (togAlign >= 0) offset = x;
-						else offset = paneLen - togLen + x; // NOTE: x is negative!
-					}
-				}
-
-				var
-					$TC_o = (o.togglerContent_open   ? $T.children(".content-open") : false)
-				,	$TC_c = (o.togglerContent_closed ? $T.children(".content-closed")   : false)
-				,	$TC   = (s.isClosed ? $TC_c : $TC_o)
-				;
-				if ($TC_o) $TC_o.css("display", s.isClosed ? "none" : "block");
-				if ($TC_c) $TC_c.css("display", s.isClosed ? "block" : "none");
-
-				if (dir == "horz") { // north/south
-					var width = cssW($T, togLen);
-					$T.css({
-						width:	max(0, width)  // account for borders & padding
-					,	height:	max(1, cssH($T, spacing)) // ditto
-					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
-					});
-					if ($TC) // CENTER the toggler content SPAN
-						$TC.css("marginLeft", Math.floor((width-$TC.outerWidth())/2)); // could be negative
-				}
-				else { // east/west
-					var height = cssH($T, togLen);
-					$T.css({
-						height:	max(0, height)  // account for borders & padding
-					,	width:	max(1, cssW($T, spacing)) // ditto
-					,	top:	offset // POSITION the toggler
-					});
-					if ($TC) // CENTER the toggler content SPAN
-						$TC.css("marginTop", Math.floor((height-$TC.outerHeight())/2)); // could be negative
-				}
-
-
-			}
-
-			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
-			if (onInit && o.initHidden) {
-				$R.hide();
-				if ($T) $T.hide();
-			}
-		});
-	};
-
-
-	/**
-	 * resizeAll
-	 *
-	 * @callers  window.onresize(), callbacks or custom code
-	 */
-	var resizeAll = function () {
-		
-		console.log("RESIZE!");
-		console.log($Container);
-		var
-			oldW	= cDims.innerWidth
-		,	oldH	= cDims.innerHeight
-		;
-		cDims = state.container = getElemDims($Container); // UPDATE container dimensions
-
-		var
-			checkH	= (cDims.innerHeight < oldH)
-		,	checkW	= (cDims.innerWidth < oldW)
-		,	s, dir
-		;
-
-//		if (checkH || checkW)
-			// NOTE special order for sizing: S-N-E-W
-			$.each(["south","north","east","west"], function(i,pane) {
-				s = state[pane];
-				dir = c[pane].dir;
-				if (!s.isClosed && ((checkH && dir=="horz") || (checkW && dir=="vert"))) {
-					setPaneMinMaxSizes(pane); // update pane-state
-					// shrink pane if 'too big' to fit
-					if (s.size > s.maxSize)
-						sizePane(pane, s.maxSize);
-				}
-			});
-
-		sizeMidPanes("all");
-		sizeHandles("all"); // reposition the toggler elements
-	};
-
-
-	/**
-	 * keyDown
-	 *
-	 * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
-	 *
-	 * @callers  document.keydown()
-	 */
-	function keyDown (evt) {
-		if (!evt) return true;
-		var code = evt.keyCode;
-		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
-
-		var
-			PANE = {
-				38: "north" // Up Cursor
-			,	40: "south" // Down Cursor
-			,	37: "west"  // Left Cursor
-			,	39: "east"  // Right Cursor
-			}
-		,	isCursorKey = (code >= 37 && code <= 40)
-		,	ALT = evt.altKey // no worky!
-		,	SHIFT = evt.shiftKey
-		,	CTRL = evt.ctrlKey
-		,	pane = false
-		,	s, o, k, m, el
-		;
-
-		if (!CTRL && !SHIFT)
-			return true; // no modifier key - abort
-		else if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
-			pane = PANE[code];
-		else // check to see if this matches a custom-hotkey
-			$.each(c.borderPanes.split(","), function(i,p) { // loop each pane to check its hotkey
-				o = options[p];
-				k = o.customHotkey;
-				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
-				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
-					if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
-						pane = p;
-						return false; // BREAK
-					}
-				}
-			});
-
-		if (!pane) return true; // no hotkey - abort
-
-		// validate pane
-		o = options[pane]; // get pane options
-		s = state[pane]; // get pane options
-		if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) return true;
-
-		// see if user is in a 'form field' because may be 'selecting text'!
-		el = evt.target || evt.srcElement;
-		if (el && SHIFT && isCursorKey && (el.tagName=="TEXTAREA" || (el.tagName=="INPUT" && (code==37 || code==39))))
-			return true; // allow text-selection
-
-		// SYNTAX NOTES
-		// use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
-		// use "return false" to abort keystroke AND abort function
-		toggle(pane);
-		evt.stopPropagation();
-		evt.returnValue = false; // CANCEL key
-		return false;
-	};
-
-
-/*
- * ###########################
- *     UTILITY METHODS
- *   called externally only
- * ###########################
- */
-
-	function allowOverflow (elem) {
-		if (this && this.tagName) elem = this; // BOUND to element
-		var $P;
-		if (typeof elem=="string")
-			$P = $Ps[elem];
-		else {
-			if ($(elem).attr("pane")) $P = $(elem);
-			else $P = $(elem).parents("div[pane]:first");
-		}
-		if (!$P.length) return; // INVALID
-
-		var
-			pane	= $P.attr("pane")
-		,	s		= state[pane]
-		;
-
-		// if pane is already raised, then reset it before doing it again!
-		// this would happen if allowOverflow is attached to BOTH the pane and an element 
-		if (s.cssSaved)
-			resetOverflow(pane); // reset previous CSS before continuing
-
-		// if pane is raised by sliding or resizing, or it's closed, then abort
-		if (s.isSliding || s.isResizing || s.isClosed) {
-			s.cssSaved = false;
-			return;
-		}
-
-		var
-			newCSS	= { zIndex: (c.zIndex.pane_normal + 1) }
-		,	curCSS	= {}
-		,	of		= $P.css("overflow")
-		,	ofX		= $P.css("overflowX")
-		,	ofY		= $P.css("overflowY")
-		;
-		// determine which, if any, overflow settings need to be changed
-		if (of != "visible") {
-			curCSS.overflow = of;
-			newCSS.overflow = "visible";
-		}
-		if (ofX && ofX != "visible" && ofX != "auto") {
-			curCSS.overflowX = ofX;
-			newCSS.overflowX = "visible";
-		}
-		if (ofY && ofY != "visible" && ofY != "auto") {
-			curCSS.overflowY = ofX;
-			newCSS.overflowY = "visible";
-		}
-
-		// save the current overflow settings - even if blank!
-		s.cssSaved = curCSS;
-
-		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
-		$P.css( newCSS );
-
-		// make sure the zIndex of all other panes is normal
-		$.each(c.allPanes.split(","), function(i, p) {
-			if (p != pane) resetOverflow(p);
-		});
-
-	};
-
-	function resetOverflow (elem) {
-		if (this && this.tagName) elem = this; // BOUND to element
-		var $P;
-		if (typeof elem=="string")
-			$P = $Ps[elem];
-		else {
-			if ($(elem).hasClass("ui-layout-pane")) $P = $(elem);
-			else $P = $(elem).parents("div[pane]:first");
-		}
-		if (!$P.length) return; // INVALID
-
-		var
-			pane	= $P.attr("pane")
-		,	s		= state[pane]
-		,	CSS		= s.cssSaved || {}
-		;
-		// reset the zIndex
-		if (!s.isSliding && !s.isResizing)
-			$P.css("zIndex", c.zIndex.pane_normal);
-
-		// reset Overflow - if necessary
-		$P.css( CSS );
-
-		// clear var
-		s.cssSaved = false;
-	};
-
-
-	/**
-	* getBtn
-	*
-	* Helper function to validate params received by addButton utilities
-	*
-	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
-	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
-	* @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
-	*/
-	function getBtn(selector, pane, action) {
-		var
-			$E = $(selector)
-		,	err = "Error Adding Button \n\nInvalid "
-		;
-		if (!$E.length) // element not found
-			alert(err+"selector: "+ selector);
-		else if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
-			alert(err+"pane: "+ pane);
-		else { // VALID
-			var btn = options[pane].buttonClass +"-"+ action;
-			$E.addClass( btn +" "+ btn +"-"+ pane );
-			return $E;
-		}
-		return false;  // INVALID
-	};
-
-
-	/**
-	* addToggleBtn
-	*
-	* Add a custom Toggler button for a pane
-	*
-	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
-	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
-	*/
-	function addToggleBtn (selector, pane) {
-		var $E = getBtn(selector, pane, "toggle");
-		if ($E)
-			$E
-				.attr("title", state[pane].isClosed ? "Open" : "Close")
-				.click(function (evt) {
-					toggle(pane);
-					evt.stopPropagation();
-				})
-			;
-	};
-
-	/**
-	* addOpenBtn
-	*
-	* Add a custom Open button for a pane
-	*
-	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
-	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
-	*/
-	function addOpenBtn (selector, pane) {
-		var $E = getBtn(selector, pane, "open");
-		if ($E)
-			$E
-				.attr("title", "Open")
-				.click(function (evt) {
-					open(pane);
-					evt.stopPropagation();
-				})
-			;
-	};
-
-	/**
-	* addCloseBtn
-	*
-	* Add a custom Close button for a pane
-	*
-	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
-	* @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
-	*/
-	function addCloseBtn (selector, pane) {
-		var $E = getBtn(selector, pane, "close");
-		if ($E)
-			$E
-				.attr("title", "Close")
-				.click(function (evt) {
-					close(pane);
-					evt.stopPropagation();
-				})
-			;
-	};
-
-	/**
-	* addPinBtn
-	*
-	* Add a custom Pin button for a pane
-	*
-	* Four classes are added to the element, based on the paneClass for the associated pane...
-	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
-	*  - ui-layout-pane-pin
-	*  - ui-layout-pane-west-pin
-	*  - ui-layout-pane-pin-up
-	*  - ui-layout-pane-west-pin-up
-	*
-	* @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
-	* @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
-	*/
-	function addPinBtn (selector, pane) {
-		var $E = getBtn(selector, pane, "pin");
-		if ($E) {
-			var s = state[pane];
-			$E.click(function (evt) {
-				setPinState($(this), pane, (s.isSliding || s.isClosed));
-				if (s.isSliding || s.isClosed) open( pane ); // change from sliding to open
-				else close( pane ); // slide-closed
-				evt.stopPropagation();
-			});
-			// add up/down pin attributes and classes
-			setPinState ($E, pane, (!s.isClosed && !s.isSliding));
-			// add this pin to the pane data so we can 'sync it' automatically
-			// PANE.pins key is an array so we can store multiple pins for each pane
-			c[pane].pins.push( selector ); // just save the selector string
-		}
-	};
-
-	/**
-	* syncPinBtns
-	*
-	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
-	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
-	*
-	* @callers  open(), close()
-	* @params  pane   These are the params returned to callbacks by layout()
-	* @params  doPin  True means set the pin 'down', False means 'up'
-	*/
-	function syncPinBtns (pane, doPin) {
-		$.each(c[pane].pins, function (i, selector) {
-			setPinState($(selector), pane, doPin);
-		});
-	};
-
-	/**
-	* setPinState
-	*
-	* Change the class of the pin button to make it look 'up' or 'down'
-	*
-	* @callers  addPinBtn(), syncPinBtns()
-	* @param Element  $Pin		The pin-span element in a jQuery wrapper
-	* @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
-	* @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
-	*/
-	function setPinState ($Pin, pane, doPin) {
-		var updown = $Pin.attr("pin");
-		if (updown && doPin == (updown=="down")) return; // already in correct state
-		var
-			root	= options[pane].buttonClass
-		,	class1	= root +"-pin"
-		,	class2	= class1 +"-"+ pane
-		,	UP1		= class1 + "-up"
-		,	UP2		= class2 + "-up"
-		,	DN1		= class1 + "-down"
-		,	DN2		= class2 + "-down"
-		;
-		$Pin
-			.attr("pin", doPin ? "down" : "up") // logic
-			.attr("title", doPin ? "Un-Pin" : "Pin")
-			.removeClass( doPin ? UP1 : DN1 ) 
-			.removeClass( doPin ? UP2 : DN2 ) 
-			.addClass( doPin ? DN1 : UP1 ) 
-			.addClass( doPin ? DN2 : UP2 ) 
-		;
-	};
-
-
-/*
- * ###########################
- * CREATE/RETURN BORDER-LAYOUT
- * ###########################
- */
-
-	// init global vars
-	var 
-		$Container = $(this).css({ overflow: "hidden" }) // Container elem
-	,	$Ps		= {} // Panes x4	- set in initPanes()
-	,	$Cs		= {} // Content x4	- set in initPanes()
-	,	$Rs		= {} // Resizers x4	- set in initHandles()
-	,	$Ts		= {} // Togglers x4	- set in initHandles()
-	//	object aliases
-	,	c		= config // alias for config hash
-	,	cDims	= state.container // alias for easy access to 'container dimensions'
-	;
-
-	// create the border layout NOW
-	create();
-
-	// return object pointers to expose data & option Properties, and primary action Methods
-	return {
-		options:		options			// property - options hash
-	,	state:			state			// property - dimensions hash
-	,	panes:			$Ps				// property - object pointers for ALL panes: panes.north, panes.center
-	,	toggle:			toggle			// method - pass a 'pane' ("north", "west", etc)
-	,	open:			open			// method - ditto
-	,	close:			close			// method - ditto
-	,	hide:			hide			// method - ditto
-	,	show:			show			// method - ditto
-	,	resizeContent:	sizeContent		// method - ditto
-	,	sizePane:		sizePane		// method - pass a 'pane' AND a 'size' in pixels
-	,	resizeAll:		resizeAll		// method - no parameters
-	,	addToggleBtn:	addToggleBtn	// utility - pass element selector and 'pane'
-	,	addOpenBtn:		addOpenBtn		// utility - ditto
-	,	addCloseBtn:	addCloseBtn		// utility - ditto
-	,	addPinBtn:		addPinBtn		// utility - ditto
-	,	allowOverflow:	allowOverflow	// utility - pass calling element
-	,	resetOverflow:	resetOverflow	// utility - ditto
-	,	cssWidth:		cssW
-	,	cssHeight:		cssH
-	};
-
-}
-})( jQuery );
\ No newline at end of file
+    $.fn.layout = function(opts){
+    
+        /*
+         * ###########################
+         *   WIDGET CONFIG & OPTIONS
+         * ###########################
+         */
+        // DEFAULTS for options
+        var prefix = "ui-layout-" // prefix for ALL selectors and classNames
+, defaults = { //	misc default values
+            paneClass: prefix + "pane" // ui-layout-pane
+            ,
+            resizerClass: prefix + "resizer" // ui-layout-resizer
+            ,
+            togglerClass: prefix + "toggler" // ui-layout-toggler
+            ,
+            togglerInnerClass: prefix + "" // ui-layout-open / ui-layout-closed
+            ,
+            buttonClass: prefix + "button" // ui-layout-button
+            ,
+            contentSelector: "." + prefix + "content"// ui-layout-content
+            ,
+            contentIgnoreSelector: "." + prefix + "ignore" // ui-layout-mask 
+        };
+        
+        // DEFAULT PANEL OPTIONS - CHANGE IF DESIRED
+        var options = {
+            name: "" // FUTURE REFERENCE - not used right now
+            ,
+            scrollToBookmarkOnLoad: true // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
+            ,
+            defaults: { // default options for 'all panes' - will be overridden by 'per-pane settings'
+                applyDefaultStyles: false // apply basic styles directly to resizers & buttons? If not, then stylesheet must handle it
+                ,
+                closable: true // pane can open & close
+                ,
+                resizable: true // when open, pane can be resized 
+                ,
+                slidable: true // when closed, pane can 'slide' open over other panes - closes on mouse-out
+                //,	paneSelector:			[ ]			// MUST be pane-specific!
+                ,
+                contentSelector: defaults.contentSelector // INNER div/element to auto-size so only it scrolls, not the entire pane!
+                ,
+                contentIgnoreSelector: defaults.contentIgnoreSelector // elem(s) to 'ignore' when measuring 'content'
+                ,
+                paneClass: defaults.paneClass // border-Pane - default: 'ui-layout-pane'
+                ,
+                resizerClass: defaults.resizerClass // Resizer Bar		- default: 'ui-layout-resizer'
+                ,
+                togglerClass: defaults.togglerClass // Toggler Button	- default: 'ui-layout-toggler'
+                ,
+                buttonClass: defaults.buttonClass // CUSTOM Buttons	- default: 'ui-layout-button-toggle/-open/-close/-pin'
+                ,
+                resizerDragOpacity: 1 // option for ui.draggable
+                //,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
+                ,
+                maskIframesOnResize: true // true = all iframes OR = iframe-selector(s) - adds masking-div during resizing/dragging
+                //,	size:					100			// inital size of pane - defaults are set 'per pane'
+                ,
+                minSize: 0 // when manually resizing a pane
+                ,
+                maxSize: 0 // ditto, 0 = no limit
+                ,
+                spacing_open: 6 // space between pane and adjacent panes - when pane is 'open'
+                ,
+                spacing_closed: 6 // ditto - when pane is 'closed'
+                ,
+                togglerLength_open: 50 // Length = WIDTH of toggler button on north/south edges - HEIGHT on east/west edges
+                ,
+                togglerLength_closed: 50 // 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
+                ,
+                togglerAlign_open: "center" // top/left, bottom/right, center, OR...
+                ,
+                togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
+                ,
+                togglerTip_open: "Close" // Toggler tool-tip (title)
+                ,
+                togglerTip_closed: "Open" // ditto
+                ,
+                resizerTip: "Resize" // Resizer tool-tip (title)
+                ,
+                sliderTip: "Slide Open" // resizer-bar triggers 'sliding' when pane is closed
+                ,
+                sliderCursor: "pointer" // cursor when resizer-bar will trigger 'sliding'
+                ,
+                slideTrigger_open: "click" // click, dblclick, mouseover
+                ,
+                slideTrigger_close: "mouseout" // click, mouseout
+                ,
+                hideTogglerOnSlide: false // when pane is slid-open, should the toggler show?
+                ,
+                togglerContent_open: "" // text or HTML to put INSIDE the toggler
+                ,
+                togglerContent_closed: "" // ditto
+                ,
+                showOverflowOnHover: false // will bind allowOverflow() utility to pane.onMouseOver
+                ,
+                enableCursorHotkey: true // enabled 'cursor' hotkeys
+                //,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
+                ,
+                customHotkeyModifier: "SHIFT" // either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
+                //	NOTE: fxSss_open & fxSss_close options (eg: fxName_open) are auto-generated if not passed
+                ,
+                fxName: "slide" // ('none' or blank), slide, drop, scale
+                ,
+                fxSpeed: null // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
+                ,
+                fxSettings: {} // can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
+                ,
+                initClosed: false // true = init pane as 'closed'
+                ,
+                initHidden: false // true = init pane as 'hidden' - no resizer or spacing
+                /*	callback options do not have to be set - listed here for reference only
+                 ,	onshow_start:			""			// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
+                 ,	onshow_end:				""			// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
+                 ,	onhide_start:			""			// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
+                 ,	onhide_end:				""			// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
+                 ,	onopen_start:			""			// CALLBACK when pane STARTS to Open
+                 ,	onopen_end:				""			// CALLBACK when pane ENDS being Opened
+                 ,	onclose_start:			""			// CALLBACK when pane STARTS to Close
+                 ,	onclose_end:			""			// CALLBACK when pane ENDS being Closed
+                 ,	onresize_start:			""			// CALLBACK when pane STARTS to be ***MANUALLY*** Resized
+                 ,	onresize_end:			""			// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
+                 */
+            },
+            north: {
+                paneSelector: "." + prefix + "north" // default = .ui-layout-north
+                ,
+                size: "auto",
+                resizerCursor: "n-resize"
+            },
+            south: {
+                paneSelector: "." + prefix + "south" // default = .ui-layout-south
+                ,
+                size: "auto",
+                resizerCursor: "s-resize"
+            },
+            east: {
+                paneSelector: "." + prefix + "east" // default = .ui-layout-east
+                ,
+                size: 200,
+                resizerCursor: "e-resize"
+            },
+            west: {
+                paneSelector: "." + prefix + "west" // default = .ui-layout-west
+                ,
+                size: 200,
+                resizerCursor: "w-resize"
+            },
+            center: {
+                paneSelector: "." + prefix + "center" // default = .ui-layout-center
+            }
+        
+        };
+        
+        
+        var effects = { // LIST *PREDEFINED EFFECTS* HERE, even if effect has no settings
+            slide: {
+                all: {
+                    duration: "fast"
+                } // eg: duration: 1000, easing: "easeOutBounce"
+                ,
+                north: {
+                    direction: "up"
+                },
+                south: {
+                    direction: "down"
+                },
+                east: {
+                    direction: "right"
+                },
+                west: {
+                    direction: "left"
+                }
+            },
+            drop: {
+                all: {
+                    duration: "slow"
+                } // eg: duration: 1000, easing: "easeOutQuint"
+                ,
+                north: {
+                    direction: "up"
+                },
+                south: {
+                    direction: "down"
+                },
+                east: {
+                    direction: "right"
+                },
+                west: {
+                    direction: "left"
+                }
+            },
+            scale: {
+                all: {
+                    duration: "fast"
+                }
+            }
+        };
+        
+        
+        // STATIC, INTERNAL CONFIG - DO NOT CHANGE THIS!
+        var config = {
+            allPanes: "north,south,east,west,center",
+            borderPanes: "north,south,east,west",
+            zIndex: { // set z-index values here
+                resizer_normal: 1 // normal z-index for resizer-bars
+                ,
+                pane_normal: 2 // normal z-index for panes
+                ,
+                mask: 4 // overlay div used to mask pane(s) during resizing
+                ,
+                sliding: 100 // applied to both the pane and its resizer when a pane is 'slid open'
+                ,
+                resizing: 10000 // applied to the CLONED resizer-bar when being 'dragged'
+                ,
+                animation: 10000 // applied to the pane when being animated - not applied to the resizer
+            },
+            resizers: {
+                cssReq: {
+                    position: "absolute",
+                    padding: 0,
+                    margin: 0,
+                    fontSize: "1px",
+                    textAlign: "left" // to counter-act "center" alignment!
+                    ,
+                    overflow: "hidden" // keep toggler button from overflowing
+                    ,
+                    zIndex: 1
+                },
+                cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
+                    background: "#DDD",
+                    border: "none"
+                }
+            },
+            togglers: {
+                cssReq: {
+                    position: "absolute",
+                    display: "block",
+                    padding: 0,
+                    margin: 0,
+                    overflow: "hidden",
+                    textAlign: "center",
+                    fontSize: "1px",
+                    cursor: "pointer",
+                    zIndex: 1
+                },
+                cssDef: { // DEFAULT CSS - applied if: options.PANE.applyDefaultStyles=true
+                    background: "#AAA"
+                }
+            },
+            content: {
+                cssReq: {
+                    overflow: "auto"
+                },
+                cssDef: {}
+            },
+            defaults: { // defaults for ALL panes - overridden by 'per-pane settings' below
+                cssReq: {
+                    position: "absolute",
+                    margin: 0,
+                    zIndex: 2
+                },
+                cssDef: {
+                    padding: "10px",
+                    background: "#FFF",
+                    border: "1px solid #BBB",
+                    overflow: "auto"
+                }
+            },
+            north: {
+                edge: "top",
+                sizeType: "height",
+                dir: "horz",
+                cssReq: {
+                    top: 0,
+                    bottom: "auto",
+                    left: 0,
+                    right: 0,
+                    width: "auto"
+                    //	height: 	DYNAMIC
+                }
+            },
+            south: {
+                edge: "bottom",
+                sizeType: "height",
+                dir: "horz",
+                cssReq: {
+                    top: "auto",
+                    bottom: 0,
+                    left: 0,
+                    right: 0,
+                    width: "auto"
+                    //	height: 	DYNAMIC
+                }
+            },
+            east: {
+                edge: "right",
+                sizeType: "width",
+                dir: "vert",
+                cssReq: {
+                    left: "auto",
+                    right: 0,
+                    top: "auto" // DYNAMIC
+                    ,
+                    bottom: "auto" // DYNAMIC
+                    ,
+                    height: "auto"
+                    //	width: 		DYNAMIC
+                }
+            },
+            west: {
+                edge: "left",
+                sizeType: "width",
+                dir: "vert",
+                cssReq: {
+                    left: 0,
+                    right: "auto",
+                    top: "auto" // DYNAMIC
+                    ,
+                    bottom: "auto" // DYNAMIC
+                    ,
+                    height: "auto"
+                    //	width: 		DYNAMIC
+                }
+            },
+            center: {
+                dir: "center",
+                cssReq: {
+                    left: "auto" // DYNAMIC
+                    ,
+                    right: "auto" // DYNAMIC
+                    ,
+                    top: "auto" // DYNAMIC
+                    ,
+                    bottom: "auto" // DYNAMIC
+                    ,
+                    height: "auto",
+                    width: "auto"
+                }
+            }
+        };
+        
+        
+        // DYNAMIC DATA
+        var state = {
+            // generate random 'ID#' to identify layout - used to create global namespace for timers
+            id: Math.floor(Math.random() * 10000),
+            container: {},
+            north: {},
+            south: {},
+            east: {},
+            west: {},
+            center: {}
+        };
+        
+        
+        var altEdge = {
+            top: "bottom",
+            bottom: "top",
+            left: "right",
+            right: "left"
+        }, altSide = {
+            north: "south",
+            south: "north",
+            east: "west",
+            west: "east"
+        };
+        
+        
+        /*
+         * ###########################
+         *  INTERNAL HELPER FUNCTIONS
+         * ###########################
+         */
+        /**
+         * isStr
+         *
+         * Returns true if passed param is EITHER a simple string OR a 'string object' - otherwise returns false
+         */
+        var isStr = function(o){
+            if (typeof o == "string") 
+                return true;
+            else 
+                if (typeof o == "object") {
+                    try {
+                        var match = o.constructor.toString().match(/string/i);
+                        return (match !== null);
+                    } 
+                    catch (e) {
+                    }
+                }
+            return false;
+        };
+        
+        /**
+         * str
+         *
+         * Returns a simple string if the passed param is EITHER a simple string OR a 'string object',
+         *  else returns the original object
+         */
+        var str = function(o){
+            if (typeof o == "string" || isStr(o)) 
+                return $.trim(o); // trim converts 'String object' to a simple string
+            else 
+                return o;
+        };
+        
+        /**
+         * min / max
+         *
+         * Alias for Math.min/.max to simplify coding
+         */
+        var min = function(x, y){
+            return Math.min(x, y);
+        };
+        var max = function(x, y){
+            return Math.max(x, y);
+        };
+        
+        /**
+         * transformData
+         *
+         * Processes the options passed in and transforms them into the format used by layout()
+         * Missing keys are added, and converts the data if passed in 'flat-format' (no sub-keys)
+         * In flat-format, pane-specific-settings are prefixed like: north__optName  (2-underscores)
+         * To update effects, options MUST use nested-keys format, with an effects key
+         *
+         * @callers  initOptions()
+         * @params  JSON  d  Data/options passed by user - may be a single level or nested levels
+         * @returns JSON  Creates a data struture that perfectly matches 'options', ready to be imported
+         */
+        var transformData = function(d){
+            var json = {
+                defaults: {
+                    fxSettings: {}
+                },
+                north: {
+                    fxSettings: {}
+                },
+                south: {
+                    fxSettings: {}
+                },
+                east: {
+                    fxSettings: {}
+                },
+                west: {
+                    fxSettings: {}
+                },
+                center: {
+                    fxSettings: {}
+                }
+            };
+            d = d ||
+            {};
+            if (d.effects || d.defaults || d.north || d.south || d.west || d.east || d.center) 
+                json = $.extend(json, d); // already in json format - add to base keys
+            else 
+                // convert 'flat' to 'nest-keys' format - also handles 'empty' user-options
+                $.each(d, function(key, val){
+                    a = key.split("__");
+                    json[a[1] ? a[0] : "defaults"][a[1] ? a[1] : a[0]] = val;
+                });
+            return json;
+        };
+        
+        /**
+         * setFlowCallback
+         *
+         * Set an INTERNAL callback to avoid simultaneous animation
+         * Runs only if needed and only if all callbacks are not 'already set'!
+         *
+         * @param String   action  Either 'open' or 'close'
+         * @pane  String   pane    A valid border-pane name, eg 'west'
+         * @pane  Boolean  param   Extra param for callback (optional)
+         */
+        var setFlowCallback = function(action, pane, param){
+            var cb = action + "," + pane + "," + (param ? 1 : 0), cP, cbPane;
+            $.each(c.borderPanes.split(","), function(i, p){
+                if (c[p].isMoving) {
+                    bindCallback(p); // TRY to bind a callback
+                    return false; // BREAK
+                }
+            });
+            
+            function bindCallback(p, test){
+                cP = c[p];
+                if (!cP.doCallback) {
+                    cP.doCallback = true;
+                    cP.callback = cb;
+                }
+                else { // try to 'chain' this callback
+                    cpPane = cP.callback.split(",")[1]; // 2nd param is 'pane'
+                    if (cpPane != p && cpPane != pane) // callback target NOT 'itself' and NOT 'this pane'
+                        bindCallback(cpPane, true); // RECURSE
+                }
+            }
+        };
+        
+        /**
+         * execFlowCallback
+         *
+         * RUN the INTERNAL callback for this pane - if one exists
+         *
+         * @param String   action  Either 'open' or 'close'
+         * @pane  String   pane    A valid border-pane name, eg 'west'
+         * @pane  Boolean  param   Extra param for callback (optional)
+         */
+        var execFlowCallback = function(pane){
+            var cP = c[pane];
+            
+            // RESET flow-control flaGs
+            c.isLayoutBusy = false;
+            delete cP.isMoving;
+            if (!cP.doCallback || !cP.callback) 
+                return;
+            
+            cP.doCallback = false; // RESET logic flag
+            // EXECUTE the callback
+            var cb = cP.callback.split(","), param = (cb[2] > 0 ? true : false);
+            if (cb[0] == "open") 
+                open(cb[1], param);
+            else 
+                if (cb[0] == "close") 
+                    close(cb[1], param);
+            
+            if (!cP.doCallback) 
+                cP.callback = null; // RESET - unless callback above enabled it again!
+        };
+        
+        /**
+         * execUserCallback
+         *
+         * Executes a Callback function after a trigger event, like resize, open or close
+         *
+         * @param String  pane   This is passed only so we can pass the 'pane object' to the callback
+         * @param String  v_fn  Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
+         */
+        var execUserCallback = function(pane, v_fn){
+            if (!v_fn) 
+                return;
+            var fn;
+            try {
+                if (typeof v_fn == "function") 
+                    fn = v_fn;
+                else 
+                    if (typeof v_fn != "string") 
+                        return;
+                    else 
+                        if (v_fn.indexOf(",") > 0) {
+                            // function name cannot contain a comma, so must be a function name AND a 'name' parameter
+                            var args = v_fn.split(","), fn = eval(args[0]);
+                            if (typeof fn == "function" && args.length > 1) 
+                                return fn(args[1]); // pass the argument parsed from 'list'
+                        }
+                        else // just the name of an external function?
+                             fn = eval(v_fn);
+                
+                if (typeof fn == "function") 
+                    // pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
+                    return fn(pane, $Ps[pane], $.extend({}, state[pane]), $.extend({}, options[pane]), options.name);
+            } 
+            catch (ex) {
+            }
+        };
+        
+        /**
+         * cssNum
+         *
+         * Returns the 'current CSS value' for an element - returns 0 if property does not exist
+         *
+         * @callers  Called by many methods
+         * @param jQuery  $Elem  Must pass a jQuery object - first element is processed
+         * @param String  property  The name of the CSS property, eg: top, width, etc.
+         * @returns Variant  Usually is used to get an integer value for position (top, left) or size (height, width)
+         */
+        var cssNum = function($E, prop){
+            var val = 0, hidden = false, visibility = "";
+            if (!$.browser.msie) { // IE CAN read dimensions of 'hidden' elements - FF CANNOT
+                if ($.curCSS($E[0], "display", true) == "none") {
+                    hidden = true;
+                    visibility = $.curCSS($E[0], "visibility", true); // SAVE current setting
+                    $E.css({
+                        display: "block",
+                        visibility: "hidden"
+                    }); // show element 'invisibly' so we can measure it
+                }
+            }
+            
+            val = parseInt($.curCSS($E[0], prop, true), 10) || 0;
+            
+            if (hidden) { // WAS hidden, so put back the way it was
+                $E.css({
+                    display: "none"
+                });
+                if (visibility && visibility != "hidden") 
+                    $E.css({
+                        visibility: visibility
+                    }); // reset 'visibility'
+            }
+            
+            return val;
+        };
+        
+        /**
+         * cssW / cssH / cssSize
+         *
+         * Contains logic to check boxModel & browser, and return the correct width/height for the current browser/doctype
+         *
+         * @callers  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
+         * @param Variant  elem  Can accept a 'pane' (east, west, etc) OR a DOM object OR a jQuery object
+         * @param Integer  outerWidth/outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
+         * @returns Integer  Returns the innerHeight of the elem by subtracting padding and borders
+         *
+         * @TODO  May need to add additional logic to handle more browser/doctype variations?
+         */
+        var cssW = function(e, outerWidth){
+            var $E;
+            if (isStr(e)) {
+                e = str(e);
+                $E = $Ps[e];
+            }
+            else 
+                $E = $(e);
+            
+            // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
+            if (outerWidth <= 0) 
+                return 0;
+            else 
+                if (!(outerWidth > 0)) 
+                    outerWidth = isStr(e) ? getPaneSize(e) : $E.outerWidth();
+            
+            if (!$.boxModel) 
+                return outerWidth;
+            
+            else // strip border and padding size from outerWidth to get CSS Width
+                 return outerWidth -
+                cssNum($E, "paddingLeft") -
+                cssNum($E, "paddingRight") -
+                ($.curCSS($E[0], "borderLeftStyle", true) == "none" ? 0 : cssNum($E, "borderLeftWidth")) -
+                ($.curCSS($E[0], "borderRightStyle", true) == "none" ? 0 : cssNum($E, "borderRightWidth"));
+        };
+        var cssH = function(e, outerHeight){
+            var $E;
+            if (isStr(e)) {
+                e = str(e);
+                $E = $Ps[e];
+            }
+            else 
+                $E = $(e);
+            
+            // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
+            if (outerHeight <= 0) 
+                return 0;
+            else 
+                if (!(outerHeight > 0)) 
+                    outerHeight = (isStr(e)) ? getPaneSize(e) : $E.outerHeight();
+            
+            if (!$.boxModel) 
+                return outerHeight;
+            
+            else // strip border and padding size from outerHeight to get CSS Height
+                 return outerHeight -
+                cssNum($E, "paddingTop") -
+                cssNum($E, "paddingBottom") -
+                ($.curCSS($E[0], "borderTopStyle", true) == "none" ? 0 : cssNum($E, "borderTopWidth")) -
+                ($.curCSS($E[0], "borderBottomStyle", true) == "none" ? 0 : cssNum($E, "borderBottomWidth"));
+        };
+        var cssSize = function(pane, outerSize){
+            if (c[pane].dir == "horz") // pane = north or south
+                return cssH(pane, outerSize);
+            else // pane = east or west
+                 return cssW(pane, outerSize);
+        };
+        
+        /**
+         * getPaneSize
+         *
+         * Calculates the current 'size' (width or height) of a border-pane - optionally with 'pane spacing' added
+         *
+         * @returns Integer  Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
+         */
+        var getPaneSize = function(pane, inclSpace){
+            var $P = $Ps[pane], o = options[pane], s = state[pane], oSp = (inclSpace ? o.spacing_open : 0), cSp = (inclSpace ? o.spacing_closed : 0);
+            if (!$P || s.isHidden) 
+                return 0;
+            else 
+                if (s.isClosed || (s.isSliding && inclSpace)) 
+                    return cSp;
+                else 
+                    if (c[pane].dir == "horz") 
+                        return $P.outerHeight() + oSp;
+                    else // dir == "vert"
+                         return $P.outerWidth() + oSp;
+        };
+        
+        var setPaneMinMaxSizes = function(pane){
+            var d = cDims, edge = c[pane].edge, dir = c[pane].dir, o = options[pane], s = state[pane], $P = $Ps[pane], $altPane = $Ps[altSide[pane]], paneSpacing = o.spacing_open, altPaneSpacing = options[altSide[pane]].spacing_open, altPaneSize = (!$altPane ? 0 : (dir == "horz" ? $altPane.outerHeight() : $altPane.outerWidth())), containerSize = (dir == "horz" ? d.innerHeight : d.innerWidth)            //	limitSize prevents this pane from 'overlapping' opposite pane - even if opposite pane is currently closed
+            , limitSize = containerSize - paneSpacing - altPaneSize - altPaneSpacing, minSize = s.minSize || 0, maxSize = Math.min(s.maxSize || 9999, limitSize), minPos, maxPos // used to set resizing limits
+;
+            switch (pane) {
+                case "north":
+                    minPos = d.offsetTop + minSize;
+                    maxPos = d.offsetTop + maxSize;
+                    break;
+                case "west":
+                    minPos = d.offsetLeft + minSize;
+                    maxPos = d.offsetLeft + maxSize;
+                    break;
+                case "south":
+                    minPos = d.offsetTop + d.innerHeight - maxSize;
+                    maxPos = d.offsetTop + d.innerHeight - minSize;
+                    break;
+                case "east":
+                    minPos = d.offsetLeft + d.innerWidth - maxSize;
+                    maxPos = d.offsetLeft + d.innerWidth - minSize;
+                    break;
+            }
+            // save data to pane-state
+            $.extend(s, {
+                minSize: minSize,
+                maxSize: maxSize,
+                minPosition: minPos,
+                maxPosition: maxPos
+            });
+        };
+        
+        /**
+         * getPaneDims
+         *
+         * Returns data for setting the size/position of center pane. Date is also used to set Height for east/west panes
+         *
+         * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
+         */
+        var getPaneDims = function(){
+            var d = {
+                top: getPaneSize("north", true) // true = include 'spacing' value for p
+                ,
+                bottom: getPaneSize("south", true),
+                left: getPaneSize("west", true),
+                right: getPaneSize("east", true),
+                width: 0,
+                height: 0
+            };
+            
+            with (d) {
+                width = cDims.innerWidth - left - right;
+                height = cDims.innerHeight - bottom - top;
+                // now add the 'container border/padding' to get final positions - relative to the container
+                top += cDims.top;
+                bottom += cDims.bottom;
+                left += cDims.left;
+                right += cDims.right;
+            }
+            
+            return d;
+        };
+        
+        
+        /**
+         * getElemDims
+         *
+         * Returns data for setting size of an element (container or a pane).
+         *
+         * @callers  create(), onWindowResize() for container, plus others for pane
+         * @returns JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
+         */
+        var getElemDims = function($E){
+            var d = {} // dimensions hash
+, e, b, p // edge, border, padding
+;
+            
+            $.each("Left,Right,Top,Bottom".split(","), function(){
+                e = str(this);
+                b = d["border" + e] = cssNum($E, "border" + e + "Width");
+                p = d["padding" + e] = cssNum($E, "padding" + e);
+                d["offset" + e] = b + p; // total offset of content from outer edge
+                // if BOX MODEL, then 'position' = PADDING (ignore borderWidth)
+                if ($E == $Container) 
+                    d[e.toLowerCase()] = ($.boxModel ? p : 0);
+            });
+            
+            d.innerWidth = d.outerWidth = $E.outerWidth();
+            d.innerHeight = d.outerHeight = $E.outerHeight();
+            if ($.boxModel) {
+                d.innerWidth -= (d.offsetLeft + d.offsetRight);
+                d.innerHeight -= (d.offsetTop + d.offsetBottom);
+            }
+            
+            return d;
+        };
+        
+        
+        var setTimer = function(pane, action, fn, ms){
+            var Layout = window.layout = window.layout ||
+            {}, Timers = Layout.timers = Layout.timers ||
+            {}, name = "layout_" + state.id + "_" + pane + "_" + action // UNIQUE NAME for every layout-pane-action
+;
+            if (Timers[name]) 
+                return; // timer already set!
+            else 
+                Timers[name] = setTimeout(fn, ms);
+        };
+        
+        var clearTimer = function(pane, action){
+            var Layout = window.layout = window.layout ||
+            {}, Timers = Layout.timers = Layout.timers ||
+            {}, name = "layout_" + state.id + "_" + pane + "_" + action // UNIQUE NAME for every layout-pane-action
+;
+            if (Timers[name]) {
+                clearTimeout(Timers[name]);
+                delete Timers[name];
+                return true;
+            }
+            else 
+                return false;
+        };
+        
+        
+        /*
+         * ###########################
+         *   INITIALIZATION METHODS
+         * ###########################
+         */
+        /**
+         * create
+         *
+         * Initialize the layout - called automatically whenever an instance of layout is created
+         *
+         * @callers  NEVER explicity called
+         * @returns  An object pointer to the instance created
+         */
+        var create = function(){
+            // initialize config/options
+            initOptions();
+            
+            // initialize all objects
+            initContainer(); // set CSS as needed and init state.container dimensions
+            initPanes(); // size & position all panes
+            initHandles(); // create and position all resize bars & togglers buttons
+            initResizable(); // activate resizing on all panes where resizable=true
+            sizeContent("all"); // AFTER panes & handles have been initialized, size 'content' divs
+            if (options.scrollToBookmarkOnLoad) 
+                with (self.location) 
+if (hash) 
+                    replace(hash); // scrollTo Bookmark
+            // bind hotkey function - keyDown - if required
+            initHotkeys();
+            
+            // bind resizeAll() for 'this layout instance' to window.resize event
+            $(window).resize(function(){
+                var timerID = "timerLayout_" + state.id;
+                if (window[timerID]) 
+                    clearTimeout(window[timerID]);
+                window[timerID] = null;
+                if (true || $.browser.msie) // use a delay for IE because the resize event fires repeatly
+                    window[timerID] = setTimeout(resizeAll, 100);
+                else // most other browsers have a built-in delay before firing the resize event
+                     resizeAll(); // resize all layout elements NOW!
+            });
+        };
+        
+        /**
+         * initContainer
+         *
+         * Validate and initialize container CSS and events
+         *
+         * @callers  create()
+         */
+        var initContainer = function(){
+            try { // format html/body if this is a full page layout
+                if ($Container[0].tagName == "BODY") {
+                    $("html").css({
+                        height: "100%",
+                        overflow: "hidden"
+                    });
+                    $("body").css({
+                        position: "relative",
+                        height: "100%",
+                        overflow: "hidden",
+                        margin: 0,
+                        padding: 0 // TODO: test whether body-padding could be handled?
+                        ,
+                        border: "none" // a body-border creates problems because it cannot be measured!
+                    });
+                }
+                else { // set required CSS - overflow and position
+                    var CSS = {
+                        overflow: "hidden"
+                    } // make sure container will not 'scroll'
+, p = $Container.css("position"), h = $Container.css("height");
+                    // if this is a NESTED layout, then outer-pane ALREADY has position and height
+                    if (!$Container.hasClass("ui-layout-pane")) {
+                        if (!p || "fixed,absolute,relative".indexOf(p) < 0) 
+                            CSS.position = "relative"; // container MUST have a 'position'
+                        if (!h || h == "auto") 
+                            CSS.height = "100%"; // container MUST have a 'height'
+                    }
+                    $Container.css(CSS);
+                }
+            } 
+            catch (ex) {
+            }
+            
+            // get layout-container dimensions (updated when necessary)
+            cDims = state.container = getElemDims($Container); // update data-pointer too
+        };
+        
+        /**
+         * initHotkeys
+         *
+         * Bind layout hotkeys - if options enabled
+         *
+         * @callers  create()
+         */
+        var initHotkeys = function(){
+            // bind keyDown to capture hotkeys, if option enabled for ANY pane
+            $.each(c.borderPanes.split(","), function(i, pane){
+                var o = options[pane];
+                if (o.enableCursorHotkey || o.customHotkey) {
+                    $(document).keydown(keyDown); // only need to bind this ONCE
+                    return false; // BREAK - binding was done
+                }
+            });
+        };
+        
+        /**
+         * initOptions
+         *
+         * Build final CONFIG and OPTIONS data
+         *
+         * @callers  create()
+         */
+        var initOptions = function(){
+            // simplify logic by making sure passed 'opts' var has basic keys
+            opts = transformData(opts);
+            
+            // update default effects, if case user passed key
+            if (opts.effects) {
+                $.extend(effects, opts.effects);
+                delete opts.effects;
+            }
+            
+            // see if any 'global options' were specified
+            $.each("name,scrollToBookmarkOnLoad".split(","), function(idx, key){
+                if (opts[key] !== undefined) 
+                    options[key] = opts[key];
+                else 
+                    if (opts.defaults[key] !== undefined) {
+                        options[key] = opts.defaults[key];
+                        delete opts.defaults[key];
+                    }
+            });
+            
+            // remove any 'defaults' that MUST be set 'per-pane'
+            $.each("paneSelector,resizerCursor,customHotkey".split(","), function(idx, key){
+                delete opts.defaults[key];
+            } // is OK if key does not exist
+);
+            
+            // now update options.defaults
+            $.extend(options.defaults, opts.defaults);
+            // make sure required sub-keys exist
+            //if (typeof options.defaults.fxSettings != "object") options.defaults.fxSettings = {};
+            
+            // merge all config & options for the 'center' pane
+            c.center = $.extend(true, {}, c.defaults, c.center);
+            $.extend(options.center, opts.center);
+            // Most 'default options' do not apply to 'center', so add only those that DO
+            var o_Center = $.extend(true, {}, options.defaults, opts.defaults, options.center); // TEMP data
+            $.each("paneClass,contentSelector,contentIgnoreSelector,applyDefaultStyles,showOverflowOnHover".split(","), function(idx, key){
+                options.center[key] = o_Center[key];
+            });
+            
+            var defs = options.defaults;
+            
+            // create a COMPLETE set of options for EACH border-pane
+            $.each(c.borderPanes.split(","), function(i, pane){
+                // apply 'pane-defaults' to CONFIG.PANE
+                c[pane] = $.extend(true, {}, c.defaults, c[pane]);
+                // apply 'pane-defaults' +  user-options to OPTIONS.PANE
+                o = options[pane] = $.extend(true, {}, options.defaults, options[pane], opts.defaults, opts[pane]);
+                
+                // make sure we have base-classes
+                if (!o.paneClass) 
+                    o.paneClass = defaults.paneClass;
+                if (!o.resizerClass) 
+                    o.resizerClass = defaults.resizerClass;
+                if (!o.togglerClass) 
+                    o.togglerClass = defaults.togglerClass;
+                
+                // create FINAL fx options for each pane, ie: options.PANE.fxName/fxSpeed/fxSettings[_open|_close]
+                $.each(["_open", "_close", ""], function(i, n){
+                    var sName = "fxName" + n, sSpeed = "fxSpeed" + n, sSettings = "fxSettings" + n;
+                    // recalculate fxName according to specificity rules
+                    o[sName] = opts[pane][sName] // opts.west.fxName_open
+ ||
+                    opts[pane].fxName // opts.west.fxName
+ ||
+                    opts.defaults[sName] // opts.defaults.fxName_open
+ ||
+                    opts.defaults.fxName // opts.defaults.fxName
+ ||
+                    o[sName] // options.west.fxName_open
+ ||
+                    o.fxName // options.west.fxName
+ ||
+                    defs[sName] // options.defaults.fxName_open
+ ||
+                    defs.fxName // options.defaults.fxName
+ ||
+                    "none";
+                    // validate fxName to be sure is a valid effect
+                    var fxName = o[sName];
+                    if (fxName == "none" || !$.effects || !$.effects[fxName] || (!effects[fxName] && !o[sSettings] && !o.fxSettings)) 
+                        fxName = o[sName] = "none"; // effect not loaded, OR undefined FX AND fxSettings not passed
+                    // set vars for effects subkeys to simplify logic
+                    var fx = effects[fxName] ||
+                    {} // effects.slide
+, fx_all = fx.all ||
+                    {} // effects.slide.all
+, fx_pane = fx[pane] ||
+                    {} // effects.slide.west
+;
+                    // RECREATE the fxSettings[_open|_close] keys using specificity rules
+                    o[sSettings] = $.extend({}, fx_all // effects.slide.all
+, fx_pane // effects.slide.west
+, defs.fxSettings ||
+                    {} // options.defaults.fxSettings
+, defs[sSettings] ||
+                    {} // options.defaults.fxSettings_open
+, o.fxSettings // options.west.fxSettings
+, o[sSettings] // options.west.fxSettings_open
+, opts.defaults.fxSettings // opts.defaults.fxSettings
+, opts.defaults[sSettings] ||
+                    {} // opts.defaults.fxSettings_open
+, opts[pane].fxSettings // opts.west.fxSettings
+, opts[pane][sSettings] ||
+                    {} // opts.west.fxSettings_open
+);
+                    // recalculate fxSpeed according to specificity rules
+                    o[sSpeed] = opts[pane][sSpeed] // opts.west.fxSpeed_open
+ ||
+                    opts[pane].fxSpeed // opts.west.fxSpeed (pane-default)
+ ||
+                    opts.defaults[sSpeed] // opts.defaults.fxSpeed_open
+ ||
+                    opts.defaults.fxSpeed // opts.defaults.fxSpeed
+ ||
+                    o[sSpeed] // options.west.fxSpeed_open
+ ||
+                    o[sSettings].duration // options.west.fxSettings_open.duration
+ ||
+                    o.fxSpeed // options.west.fxSpeed
+ ||
+                    o.fxSettings.duration // options.west.fxSettings.duration
+ ||
+                    defs.fxSpeed // options.defaults.fxSpeed
+ ||
+                    defs.fxSettings.duration// options.defaults.fxSettings.duration
+ ||
+                    fx_pane.duration // effects.slide.west.duration
+ ||
+                    fx_all.duration // effects.slide.all.duration
+ ||
+                    "normal" // DEFAULT
+;
+                    // DEBUG: if (pane=="east") debugData( $.extend({}, {speed: o[sSpeed], fxSettings_duration: o[sSettings].duration}, o[sSettings]), pane+"."+sName+" = "+fxName );
+                });
+            });
+        };
+        
+        /**
+         * initPanes
+         *
+         * Initialize module objects, styling, size and position for all panes
+         *
+         * @callers  create()
+         */
+        var initPanes = function(){
+            // NOTE: do north & south FIRST so we can measure their height - do center LAST
+            $.each(c.allPanes.split(","), function(){
+                var pane = str(this), o = options[pane], s = state[pane], fx = s.fx, dir = c[pane].dir                //	if o.size is not > 0, then we will use MEASURE the pane and use that as it's 'size'
+                , size = o.size == "auto" || isNaN(o.size) ? 0 : o.size, minSize = o.minSize || 1, maxSize = o.maxSize || 9999, spacing = o.spacing_open || 0, sel = o.paneSelector, isIE6 = ($.browser.msie && $.browser.version < 7), CSS = {}, $P, $C;
+                $Cs[pane] = false; // init
+                if (sel.substr(0, 1) === "#") // ID selector
+                    // NOTE: elements selected 'by ID' DO NOT have to be 'children'
+                    $P = $Ps[pane] = $Container.find(sel + ":first");
+                else { // class or other selector
+                    $P = $Ps[pane] = $Container.children(sel + ":first");
+                    // look for the pane nested inside a 'form' element
+                    if (!$P.length) 
+                        $P = $Ps[pane] = $Container.children("form:first").children(sel + ":first");
+                }
+                
+                if (!$P.length) {
+                    $Ps[pane] = false; // logic
+                    return true; // SKIP to next
+                }
+                
+                // add basic classes & attributes
+                $P.attr("pane", pane) // add pane-identifier
+.addClass(o.paneClass + " " + o.paneClass + "-" + pane) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
+;
+                
+                // init pane-logic vars, etc.
+                if (pane != "center") {
+                    s.isClosed = false; // true = pane is closed
+                    s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
+                    s.isResizing = false; // true = pane is in process of being resized
+                    s.isHidden = false; // true = pane is hidden - no spacing, resizer or toggler is visible!
+                    s.noRoom = false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
+                    // create special keys for internal use
+                    c[pane].pins = []; // used to track and sync 'pin-buttons' for border-panes
+                }
+                
+                CSS = $.extend({
+                    visibility: "visible",
+                    display: "block"
+                }, c.defaults.cssReq, c[pane].cssReq);
+                if (o.applyDefaultStyles) 
+                    $.extend(CSS, c.defaults.cssDef, c[pane].cssDef); // cosmetic defaults
+                $P.css(CSS); // add base-css BEFORE 'measuring' to calc size & position
+                CSS = {}; // reset var
+                // set css-position to account for container borders & padding
+                switch (pane) {
+                    case "north":
+                        CSS.top = cDims.top;
+                        CSS.left = cDims.left;
+                        CSS.right = cDims.right;
+                        break;
+                    case "south":
+                        CSS.bottom = cDims.bottom;
+                        CSS.left = cDims.left;
+                        CSS.right = cDims.right;
+                        break;
+                    case "west":
+                        CSS.left = cDims.left; // top, bottom & height set by sizeMidPanes()
+                        break;
+                    case "east":
+                        CSS.right = cDims.right; // ditto
+                        break;
+                    case "center": // top, left, width & height set by sizeMidPanes()
+                }
+                
+                if (dir == "horz") { // north or south pane
+                    if (size === 0 || size == "auto") {
+                        $P.css({
+                            height: "auto"
+                        });
+                        size = $P.outerHeight();
+                    }
+                    size = max(size, minSize);
+                    size = min(size, maxSize);
+                    size = min(size, cDims.innerHeight - spacing);
+                    CSS.height = max(1, cssH(pane, size));
+                    s.size = size; // update state
+                    // make sure minSize is sufficient to avoid errors
+                    s.maxSize = maxSize; // init value
+                    s.minSize = max(minSize, size - CSS.height + 1); // = pane.outerHeight when css.height = 1px
+                    // handle IE6
+                    //if (isIE6) CSS.width = cssW($P, cDims.innerWidth);
+                    $P.css(CSS); // apply size & position
+                }
+                else 
+                    if (dir == "vert") { // east or west pane
+                        if (size === 0 || size == "auto") {
+                            $P.css({
+                                width: "auto",
+                                float: "left"
+                            }); // float = FORCE pane to auto-size
+                            size = $P.outerWidth();
+                            $P.css({
+                                float: "none"
+                            }); // RESET
+                        }
+                        size = max(size, minSize);
+                        size = min(size, maxSize);
+                        size = min(size, cDims.innerWidth - spacing);
+                        CSS.width = max(1, cssW(pane, size));
+                        s.size = size; // update state
+                        s.maxSize = maxSize; // init value
+                        // make sure minSize is sufficient to avoid errors
+                        s.minSize = max(minSize, size - CSS.width + 1); // = pane.outerWidth when css.width = 1px
+                        $P.css(CSS); // apply size - top, bottom & height set by sizeMidPanes
+                        sizeMidPanes(pane, null, true); // true = onInit
+                    }
+                    else 
+                        if (pane == "center") {
+                            $P.css(CSS); // top, left, width & height set by sizeMidPanes...
+                            sizeMidPanes("center", null, true); // true = onInit
+                        }
+                
+                // close or hide the pane if specified in settings
+                if (o.initClosed && o.closable) {
+                    $P.hide().addClass("closed");
+                    s.isClosed = true;
+                }
+                else 
+                    if (o.initHidden || o.initClosed) {
+                        hide(pane, true); // will be completely invisible - no resizer or spacing
+                        s.isHidden = true;
+                    }
+                    else 
+                        $P.addClass("open");
+                
+                // check option for auto-handling of pop-ups & drop-downs
+                if (o.showOverflowOnHover) 
+                    $P.hover(allowOverflow, resetOverflow);
+                
+                /*
+                 *	see if this pane has a 'content element' that we need to auto-size
+                 */
+                if (o.contentSelector) {
+                    $C = $Cs[pane] = $P.children(o.contentSelector + ":first"); // match 1-element only
+                    if (!$C.length) {
+                        $Cs[pane] = false;
+                        return true; // SKIP to next
+                    }
+                    $C.css(c.content.cssReq);
+                    if (o.applyDefaultStyles) 
+                        $C.css(c.content.cssDef); // cosmetic defaults
+                    // NO PANE-SCROLLING when there is a content-div
+                    $P.css({
+                        overflow: "hidden"
+                    });
+                }
+            });
+        };
+        
+        /**
+         * initHandles
+         *
+         * Initialize module objects, styling, size and position for all resize bars and toggler buttons
+         *
+         * @callers  create()
+         */
+        var initHandles = function(){
+            // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
+            $.each(c.borderPanes.split(","), function(){
+                var pane = str(this), o = options[pane], s = state[pane], rClass = o.resizerClass, tClass = o.togglerClass, $P = $Ps[pane];
+                $Rs[pane] = false; // INIT
+                $Ts[pane] = false;
+                
+                if (!$P || (!o.closable && !o.resizable)) 
+                    return; // pane does not exist - skip
+                var edge = c[pane].edge, isOpen = $P.is(":visible"), spacing = (isOpen ? o.spacing_open : o.spacing_closed), _pane = "-" + pane // used for classNames
+, _state = (isOpen ? "-open" : "-closed") // used for classNames
+, $R, $T;
+                // INIT RESIZER BAR
+                $R = $Rs[pane] = $("<span></span>");
+                
+                if (isOpen && o.resizable) 
+                    ; // this is handled by initResizable
+                else 
+                    if (!isOpen && o.slidable) 
+                        $R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
+                
+                $R                // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
+                .attr("id", (o.paneSelector.substr(0, 1) == "#" ? o.paneSelector.substr(1) + "-resizer" : "")).attr("resizer", pane) // so we can read this from the resizer
+.css(c.resizers.cssReq) // add base/required styles
+                // POSITION of resizer bar - allow for container border & padding
+                .css(edge, cDims[edge] + getPaneSize(pane))                // ADD CLASSNAMES - eg: class="resizer resizer-west resizer-open"
+                .addClass(rClass + " " + rClass + _pane + " " + rClass + _state + " " + rClass + _pane + _state).appendTo($Container) // append DIV to container
+;
+                // ADD VISUAL STYLES
+                if (o.applyDefaultStyles) 
+                    $R.css(c.resizers.cssDef);
+                
+                if (o.closable) {
+                    // INIT COLLAPSER BUTTON
+                    $T = $Ts[pane] = $("<div></div>");
+                    $T                    // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-toggler"
+                    .attr("id", (o.paneSelector.substr(0, 1) == "#" ? o.paneSelector.substr(1) + "-toggler" : "")).css(c.togglers.cssReq) // add base/required styles
+.attr("title", (isOpen ? o.togglerTip_open : o.togglerTip_closed)).click(function(evt){
+                        toggle(pane);
+                        evt.stopPropagation();
+                    }).mouseover(function(evt){
+                        evt.stopPropagation();
+                    }) // prevent resizer event
+                    // ADD CLASSNAMES - eg: class="toggler toggler-west toggler-west-open"
+                    .addClass(tClass + " " + tClass + _pane + " " + tClass + _state + " " + tClass + _pane + _state).appendTo($R) // append SPAN to resizer DIV
+;
+                    
+                    // ADD INNER-SPANS TO TOGGLER
+                    if (o.togglerContent_open) // ui-layout-open
+                        $("<span>" + o.togglerContent_open + "</span>").addClass("content content-open").css("display", s.isClosed ? "none" : "block").appendTo($T);
+                    if (o.togglerContent_closed) // ui-layout-closed
+                        $("<span>" + o.togglerContent_closed + "</span>").addClass("content content-closed").css("display", s.isClosed ? "block" : "none").appendTo($T);
+                    
+                    // ADD BASIC VISUAL STYLES
+                    if (o.applyDefaultStyles) 
+                        $T.css(c.togglers.cssDef);
+                    
+                    if (!isOpen) 
+                        bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
+                }
+                
+            });
+            
+            // SET ALL HANDLE SIZES & LENGTHS
+            sizeHandles("all", true); // true = onInit
+        };
+        
+        /**
+         * initResizable
+         *
+         * Add resize-bars to all panes that specify it in options
+         *
+         * @dependancies  $.fn.resizable - will abort if not found
+         * @callers  create()
+         */
+        var initResizable = function(){
+            var draggingAvailable = (typeof $.fn.draggable == "function"), minPosition, maxPosition, edge // set in start()
+;
+            
+            $.each(c.borderPanes.split(","), function(){
+                var pane = str(this), o = options[pane], s = state[pane];
+                if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
+                    o.resizable = false;
+                    return true; // skip to next
+                }
+                
+                var rClass = o.resizerClass                //	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
+                , dragClass = rClass + "-drag" // resizer-drag
+, dragPaneClass = rClass + "-" + pane + "-drag" // resizer-north-drag
+                //	'dragging' class is applied to the CLONED resizer-bar while it is being dragged
+                , draggingClass = rClass + "-dragging" // resizer-dragging
+, draggingPaneClass = rClass + "-" + pane + "-dragging" // resizer-north-dragging
+, draggingClassSet = false // logic var
+, $P = $Ps[pane], $R = $Rs[pane];
+                
+                if (!s.isClosed) 
+                    $R.attr("title", o.resizerTip).css("cursor", o.resizerCursor) // n-resize, s-resize, etc
+;
+                
+                $R.draggable({
+                    containment: $Container[0] // limit resizing to layout container
+                    ,
+                    axis: (c[pane].dir == "horz" ? "y" : "x") // limit resizing to horz or vert axis
+                    ,
+                    delay: 200,
+                    distance: 1                    //	basic format for helper - style it using class: .ui-draggable-dragging
+                    ,
+                    helper: "clone",
+                    opacity: o.resizerDragOpacity                    //,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
+                    ,
+                    zIndex: c.zIndex.resizing,
+                    start: function(e, ui){
+                        // onresize_start callback - will CANCEL hide if returns false
+                        // TODO: CONFIRM that dragging can be cancelled like this???
+                        if (false === execUserCallback(pane, o.onresize_start)) 
+                            return false;
+                        
+                        s.isResizing = true; // prevent pane from closing while resizing
+                        clearTimer(pane, "closeSlider"); // just in case already triggered
+                        $R.addClass(dragClass + " " + dragPaneClass); // add drag classes
+                        draggingClassSet = false; // reset logic var - see drag()
+                        // SET RESIZING LIMITS - used in drag()
+                        var resizerWidth = (pane == "east" || pane == "south" ? o.spacing_open : 0);
+                        setPaneMinMaxSizes(pane); // update pane-state
+                        s.minPosition -= resizerWidth;
+                        s.maxPosition -= resizerWidth;
+                        edge = (c[pane].dir == "horz" ? "top" : "left");
+                        
+                        // MASK PANES WITH IFRAMES OR OTHER TROUBLESOME ELEMENTS
+                        $(o.maskIframesOnResize === true ? "iframe" : o.maskIframesOnResize).each(function(){
+                            $('<div class="ui-layout-mask"/>').css({
+                                background: "#fff",
+                                opacity: "0.001",
+                                zIndex: 9,
+                                position: "absolute",
+                                width: this.offsetWidth + "px",
+                                height: this.offsetHeight + "px"
+                            }).css($(this).offset()) // top & left
+.appendTo(this.parentNode) // put div INSIDE pane to avoid zIndex issues
+;
+                        });
+                    },
+                    drag: function(e, ui){
+                        if (!draggingClassSet) { // can only add classes after clone has been added to the DOM
+                            $(".ui-draggable-dragging").addClass(draggingClass + " " + draggingPaneClass) // add dragging classes
+.children().css("visibility", "hidden") // hide toggler inside dragged resizer-bar
+;
+                            draggingClassSet = true;
+                            // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
+                            if (s.isSliding) 
+                                $Ps[pane].css("zIndex", c.zIndex.sliding);
+                        }
+                        // CONTAIN RESIZER-BAR TO RESIZING LIMITS
+                        if (ui.position[edge] < s.minPosition) 
+                            ui.position[edge] = s.minPosition;
+                        else 
+                            if (ui.position[edge] > s.maxPosition) 
+                                ui.position[edge] = s.maxPosition;
+                    },
+                    stop: function(e, ui){
+                        var dragPos = ui.position, resizerPos, newSize;
+                        $R.removeClass(dragClass + " " + dragPaneClass); // remove drag classes
+                        switch (pane) {
+                            case "north":
+                                resizerPos = dragPos.top;
+                                break;
+                            case "west":
+                                resizerPos = dragPos.left;
+                                break;
+                            case "south":
+                                resizerPos = cDims.outerHeight - dragPos.top - $R.outerHeight();
+                                break;
+                            case "east":
+                                resizerPos = cDims.outerWidth - dragPos.left - $R.outerWidth();
+                                break;
+                        }
+                        // remove container margin from resizer position to get the pane size
+                        newSize = resizerPos - cDims[c[pane].edge];
+                        
+                        sizePane(pane, newSize);
+                        
+                        // UN-MASK PANES MASKED IN drag.start
+                        $("div.ui-layout-mask").remove(); // Remove iframe masks	
+                        s.isResizing = false;
+                    }
+                    
+                });
+            });
+        };
+        
+        
+        
+        /*
+         * ###########################
+         *       ACTION METHODS
+         * ###########################
+         */
+        /**
+         * hide / show
+         *
+         * Completely 'hides' a pane, including its spacing - as if it does not exist
+         * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
+         *
+         * @param String  pane   The pane being hidden, ie: north, south, east, or west
+         */
+        var hide = function(pane, onInit){
+            var o = options[pane], s = state[pane], $P = $Ps[pane], $R = $Rs[pane];
+            if (!$P || s.isHidden) 
+                return; // pane does not exist OR is already hidden
+            // onhide_start callback - will CANCEL hide if returns false
+            if (false === execUserCallback(pane, o.onhide_start)) 
+                return;
+            
+            s.isSliding = false; // just in case
+            // now hide the elements
+            if ($R) 
+                $R.hide(); // hide resizer-bar
+            if (onInit || s.isClosed) {
+                s.isClosed = true; // to trigger open-animation on show()
+                s.isHidden = true;
+                $P.hide(); // no animation when loading page
+                sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
+                execUserCallback(pane, o.onhide_end || o.onhide);
+            }
+            else {
+                s.isHiding = true; // used by onclose
+                close(pane, false); // adjust all panes to fit
+                //s.isHidden  = true; - will be set by close - if not cancelled
+            }
+        };
+        
+        var show = function(pane, openPane){
+            var o = options[pane], s = state[pane], $P = $Ps[pane], $R = $Rs[pane];
+            if (!$P || !s.isHidden) 
+                return; // pane does not exist OR is not hidden
+            // onhide_start callback - will CANCEL hide if returns false
+            if (false === execUserCallback(pane, o.onshow_start)) 
+                return;
+            
+            s.isSliding = false; // just in case
+            s.isShowing = true; // used by onopen/onclose
+            //s.isHidden  = false; - will be set by open/close - if not cancelled
+            
+            // now show the elements
+            if ($R && o.spacing_open > 0) 
+                $R.show();
+            if (openPane === false) 
+                close(pane, true); // true = force
+            else 
+                open(pane); // adjust all panes to fit
+        };
+        
+        
+        /**
+         * toggle
+         *
+         * Toggles a pane open/closed by calling either open or close
+         *
+         * @param String  pane   The pane being toggled, ie: north, south, east, or west
+         */
+        var toggle = function(pane){
+            var s = state[pane];
+            if (s.isHidden) 
+                show(pane); // will call 'open' after unhiding it
+            else 
+                if (s.isClosed) 
+                    open(pane);
+                else 
+                    close(pane);
+        };
+        
+        /**
+         * close
+         *
+         * Close the specified pane (animation optional), and resize all other panes as needed
+         *
+         * @param String  pane   The pane being closed, ie: north, south, east, or west
+         */
+        var close = function(pane, force, noAnimation){
+            var $P = $Ps[pane], $R = $Rs[pane], $T = $Ts[pane], o = options[pane], s = state[pane], doFX = !noAnimation && !s.isClosed && (o.fxName_close != "none"), edge = c[pane].edge, rClass = o.resizerClass, tClass = o.togglerClass, _pane = "-" + pane // used for classNames
+, _open = "-open", _sliding = "-sliding", _closed = "-closed"            // 	transfer logic vars to temp vars
+            , isShowing = s.isShowing, isHiding = s.isHiding;
+            // now clear the logic vars
+            delete s.isShowing;
+            delete s.isHiding;
+            
+            if (!$P || (!o.resizable && !o.closable)) 
+                return; // invalid request
+            else 
+                if (!force && s.isClosed && !isShowing) 
+                    return; // already closed
+            if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
+                setFlowCallback("close", pane, force); // set a callback for this action, if possible
+                return; // ABORT 
+            }
+            
+            // onclose_start callback - will CANCEL hide if returns false
+            // SKIP if just 'showing' a hidden pane as 'closed'
+            if (!isShowing && false === execUserCallback(pane, o.onclose_start)) 
+                return;
+            
+            // SET flow-control flags
+            c[pane].isMoving = true;
+            c.isLayoutBusy = true;
+            
+            s.isClosed = true;
+            // update isHidden BEFORE sizing panes
+            if (isHiding) 
+                s.isHidden = true;
+            else 
+                if (isShowing) 
+                    s.isHidden = false;
+            
+            // sync any 'pin buttons'
+            syncPinBtns(pane, false);
+            
+            // resize panes adjacent to this one
+            if (!s.isSliding) 
+                sizeMidPanes(c[pane].dir == "horz" ? "all" : "center");
+            
+            // if this pane has a resizer bar, move it now
+            if ($R) {
+                $R.css(edge, cDims[edge]) // move the resizer bar
+.removeClass(rClass + _open + " " + rClass + _pane + _open).removeClass(rClass + _sliding + " " + rClass + _pane + _sliding).addClass(rClass + _closed + " " + rClass + _pane + _closed);
+                // DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent
+                if (o.resizable) 
+                    $R.draggable("disable").css("cursor", "default").attr("title", "");
+                // if pane has a toggler button, adjust that too
+                if ($T) {
+                    $T.removeClass(tClass + _open + " " + tClass + _pane + _open).addClass(tClass + _closed + " " + tClass + _pane + _closed).attr("title", o.togglerTip_closed) // may be blank
+;
+                }
+                sizeHandles(); // resize 'length' and position togglers for adjacent panes
+            }
+            
+            // ANIMATE 'CLOSE' - if no animation, then was ALREADY shown above
+            if (doFX) {
+                lockPaneForFX(pane, true); // need to set left/top so animation will work
+                $P.hide(o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function(){
+                    lockPaneForFX(pane, false); // undo
+                    if (!s.isClosed) 
+                        return; // pane was opened before animation finished!
+                    close_2();
+                });
+            }
+            else {
+                $P.hide(); // just hide pane NOW
+                close_2();
+            }
+            
+            // SUBROUTINE
+            function close_2(){
+                bindStartSlidingEvent(pane, true); // will enable if state.PANE.isSliding = true
+                // onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
+                if (!isShowing) 
+                    execUserCallback(pane, o.onclose_end || o.onclose);
+                // onhide OR onshow callback
+                if (isShowing) 
+                    execUserCallback(pane, o.onshow_end || o.onshow);
+                if (isHiding) 
+                    execUserCallback(pane, o.onhide_end || o.onhide);
+                
+                // internal flow-control callback
+                execFlowCallback(pane);
+            }
+        };
+        
+        /**
+         * open
+         *
+         * Open the specified pane (animation optional), and resize all other panes as needed
+         *
+         * @param String  pane   The pane being opened, ie: north, south, east, or west
+         */
+        var open = function(pane, slide, noAnimation){
+            var $P = $Ps[pane], $R = $Rs[pane], $T = $Ts[pane], o = options[pane], s = state[pane], doFX = !noAnimation && s.isClosed && (o.fxName_open != "none"), edge = c[pane].edge, rClass = o.resizerClass, tClass = o.togglerClass, _pane = "-" + pane // used for classNames
+, _open = "-open", _closed = "-closed", _sliding = "-sliding"            // 	transfer logic var to temp var
+            , isShowing = s.isShowing;
+            // now clear the logic var
+            delete s.isShowing;
+            
+            if (!$P || (!o.resizable && !o.closable)) 
+                return; // invalid request
+            else 
+                if (!s.isClosed && !s.isSliding) 
+                    return; // already open
+            // pane can ALSO be unhidden by just calling show(), so handle this scenario
+            if (s.isHidden && !isShowing) {
+                show(pane, true);
+                return;
+            }
+            
+            if (c.isLayoutBusy) { // layout is 'busy' - probably with an animation
+                setFlowCallback("open", pane, slide); // set a callback for this action, if possible
+                return; // ABORT
+            }
+            
+            // onopen_start callback - will CANCEL hide if returns false
+            if (false === execUserCallback(pane, o.onopen_start)) 
+                return;
+            
+            // SET flow-control flags
+            c[pane].isMoving = true;
+            c.isLayoutBusy = true;
+            
+            // 'PIN PANE' - stop sliding
+            if (s.isSliding && !slide) // !slide = 'open pane normally' - NOT sliding
+                bindStopSlidingEvents(pane, false); // will set isSliding=false
+            s.isClosed = false;
+            // update isHidden BEFORE sizing panes
+            if (isShowing) 
+                s.isHidden = false;
+            
+            // Container size may have changed - shrink the pane if now 'too big'
+            setPaneMinMaxSizes(pane); // update pane-state
+            if (s.size > s.maxSize) // pane is too big! resize it before opening
+                $P.css(c[pane].sizeType, max(1, cssSize(pane, s.maxSize)));
+            
+            bindStartSlidingEvent(pane, false); // remove trigger event from resizer-bar
+            if (doFX) { // ANIMATE
+                lockPaneForFX(pane, true); // need to set left/top so animation will work
+                $P.show(o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function(){
+                    lockPaneForFX(pane, false); // undo
+                    if (s.isClosed) 
+                        return; // pane was closed before animation finished!
+                    open_2(); // continue
+                });
+            }
+            else {// no animation
+                $P.show(); // just show pane and...
+                open_2(); // continue
+            }
+            
+            // SUBROUTINE
+            function open_2(){
+                // NOTE: if isSliding, then other panes are NOT 'resized'
+                if (!s.isSliding) // resize all panes adjacent to this one
+                    sizeMidPanes(c[pane].dir == "vert" ? "center" : "all");
+                
+                // if this pane has a toggler, move it now
+                if ($R) {
+                    $R.css(edge, cDims[edge] + getPaneSize(pane)) // move the toggler
+.removeClass(rClass + _closed + " " + rClass + _pane + _closed).addClass(rClass + _open + " " + rClass + _pane + _open).addClass(!s.isSliding ? "" : rClass + _sliding + " " + rClass + _pane + _sliding);
+                    if (o.resizable) 
+                        $R.draggable("enable").css("cursor", o.resizerCursor).attr("title", o.resizerTip);
+                    else 
+                        $R.css("cursor", "default"); // n-resize, s-resize, etc
+                    // if pane also has a toggler button, adjust that too
+                    if ($T) {
+                        $T.removeClass(tClass + _closed + " " + tClass + _pane + _closed).addClass(tClass + _open + " " + tClass + _pane + _open).attr("title", o.togglerTip_open) // may be blank
+;
+                    }
+                    sizeHandles("all"); // resize resizer & toggler sizes for all panes
+                }
+                
+                // resize content every time pane opens - to be sure
+                sizeContent(pane);
+                
+                // sync any 'pin buttons'
+                syncPinBtns(pane, !s.isSliding);
+                
+                // onopen callback
+                execUserCallback(pane, o.onopen_end || o.onopen);
+                
+                // onshow callback
+                if (isShowing) 
+                    execUserCallback(pane, o.onshow_end || o.onshow);
+                
+                // internal flow-control callback
+                execFlowCallback(pane);
+            }
+        };
+        
+        
+        /**
+         * lockPaneForFX
+         *
+         * Must set left/top on East/South panes so animation will work properly
+         *
+         * @param String  pane  The pane to lock, 'east' or 'south' - any other is ignored!
+         * @param Boolean  doLock  true = set left/top, false = remove
+         */
+        var lockPaneForFX = function(pane, doLock){
+            var $P = $Ps[pane];
+            if (doLock) {
+                $P.css({
+                    zIndex: c.zIndex.animation
+                }); // overlay all elements during animation
+                if (pane == "south") 
+                    $P.css({
+                        top: cDims.top + cDims.innerHeight - $P.outerHeight()
+                    });
+                else 
+                    if (pane == "east") 
+                        $P.css({
+                            left: cDims.left + cDims.innerWidth - $P.outerWidth()
+                        });
+            }
+            else {
+                if (!state[pane].isSliding) 
+                    $P.css({
+                        zIndex: c.zIndex.pane_normal
+                    });
+                if (pane == "south") 
+                    $P.css({
+                        top: "auto"
+                    });
+                else 
+                    if (pane == "east") 
+                        $P.css({
+                            left: "auto"
+                        });
+            }
+        };
+        
+        
+        /**
+         * bindStartSlidingEvent
+         *
+         * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
+         *
+         * @callers  open(), close()
+         * @param String  pane  The pane to enable/disable, 'north', 'south', etc.
+         * @param Boolean  enable  Enable or Disable sliding?
+         */
+        var bindStartSlidingEvent = function(pane, enable){
+            var o = options[pane], $R = $Rs[pane], trigger = o.slideTrigger_open;
+            if (!$R || !o.slidable) 
+                return;
+            // make sure we have a valid event
+            if (trigger != "click" && trigger != "dblclick" && trigger != "mouseover") 
+                trigger = "click";
+            $R            // add or remove trigger event
+            [enable ? "bind" : "unbind"](trigger, slideOpen)            // set the appropriate cursor & title/tip
+            .css("cursor", (enable ? o.sliderCursor : "default")).attr("title", (enable ? o.sliderTip : ""));
+        };
+        
+        /**
+         * bindStopSlidingEvents
+         *
+         * Add or remove 'mouseout' events to 'slide close' when pane is 'sliding' open or closed
+         * Also increases zIndex when pane is sliding open
+         * See bindStartSlidingEvent for code to control 'slide open'
+         *
+         * @callers  slideOpen(), slideClosed()
+         * @param String  pane  The pane to process, 'north', 'south', etc.
+         * @param Boolean  isOpen  Is pane open or closed?
+         */
+        var bindStopSlidingEvents = function(pane, enable){
+            var o = options[pane], s = state[pane], trigger = o.slideTrigger_close, action = (enable ? "bind" : "unbind") // can't make 'unbind' work! - see disabled code below
+, $P = $Ps[pane], $R = $Rs[pane];
+            
+            s.isSliding = enable; // logic
+            clearTimer(pane, "closeSlider"); // just in case
+            // raise z-index when sliding
+            $P.css({
+                zIndex: (enable ? c.zIndex.sliding : c.zIndex.pane_normal)
+            });
+            $R.css({
+                zIndex: (enable ? c.zIndex.sliding : c.zIndex.resizer_normal)
+            });
+            
+            // make sure we have a valid event
+            if (trigger != "click" && trigger != "mouseout") 
+                trigger = "mouseout";
+            
+            // when trigger is 'mouseout', must cancel timer when mouse moves between 'pane' and 'resizer'
+            if (enable) { // BIND trigger events
+                $P.bind(trigger, slideClosed);
+                $R.bind(trigger, slideClosed);
+                if (trigger = "mouseout") {
+                    $P.bind("mouseover", cancelMouseOut);
+                    $R.bind("mouseover", cancelMouseOut);
+                }
+            }
+            else { // UNBIND trigger events
+                // TODO: why does unbind of a 'single function' not work reliably?
+                //$P[action](trigger, slideClosed );
+                $P.unbind(trigger);
+                $R.unbind(trigger);
+                if (trigger = "mouseout") {
+                    //$P[action]("mouseover", cancelMouseOut );
+                    $P.unbind("mouseover");
+                    $R.unbind("mouseover");
+                    clearTimer(pane, "closeSlider");
+                }
+            }
+            
+            // SUBROUTINE for mouseout timer clearing
+            function cancelMouseOut(evt){
+                clearTimer(pane, "closeSlider");
+                evt.stopPropagation();
+            }
+        };
+        
+        var slideOpen = function(){
+            var pane = $(this).attr("resizer"); // attr added by initHandles
+            if (state[pane].isClosed) { // skip if already open!
+                bindStopSlidingEvents(pane, true); // pane is opening, so BIND trigger events to close it
+                open(pane, true); // true = slide - ie, called from here!
+            }
+        };
+        
+        var slideClosed = function(){
+            var $E = $(this), pane = $E.attr("pane") || $E.attr("resizer"), o = options[pane], s = state[pane];
+            if (s.isClosed || s.isResizing) 
+                return; // skip if already closed OR in process of resizing
+            else 
+                if (o.slideTrigger_close == "click") 
+                    close_NOW(); // close immediately onClick
+                else // trigger = mouseout - use a delay
+                     setTimer(pane, "closeSlider", close_NOW, 300); // .3 sec delay
+            // SUBROUTINE for timed close
+            function close_NOW(){
+                bindStopSlidingEvents(pane, false); // pane is being closed, so UNBIND trigger events
+                if (!s.isClosed) 
+                    close(pane); // skip if already closed!
+            }
+        };
+        
+        
+        /**
+         * sizePane
+         *
+         * @callers  initResizable.stop()
+         * @param String  pane   The pane being resized - usually west or east, but potentially north or south
+         * @param Integer  newSize  The new size for this pane - will be validated
+         */
+        var sizePane = function(pane, size){
+            // TODO: accept "auto" as size, and size-to-fit pane content
+            var edge = c[pane].edge, dir = c[pane].dir, o = options[pane], s = state[pane], $P = $Ps[pane], $R = $Rs[pane];
+            // calculate 'current' min/max sizes
+            setPaneMinMaxSizes(pane); // update pane-state
+            // compare/update calculated min/max to user-options
+            s.minSize = max(s.minSize, o.minSize);
+            if (o.maxSize > 0) 
+                s.maxSize = min(s.maxSize, o.maxSize);
+            // validate passed size
+            size = max(size, s.minSize);
+            size = min(size, s.maxSize);
+            s.size = size; // update state
+            // move the resizer bar and resize the pane
+            $R.css(edge, size + cDims[edge]);
+            $P.css(c[pane].sizeType, max(1, cssSize(pane, size)));
+            
+            // resize all the adjacent panes, and adjust their toggler buttons
+            if (!s.isSliding) 
+                sizeMidPanes(dir == "horz" ? "all" : "center");
+            sizeHandles();
+            sizeContent(pane);
+            execUserCallback(pane, o.onresize_end || o.onresize);
+        };
+        
+        /**
+         * sizeMidPanes
+         *
+         * @callers  create(), open(), close(), onWindowResize()
+         */
+        var sizeMidPanes = function(panes, overrideDims, onInit){
+            if (!panes || panes == "all") 
+                panes = "east,west,center";
+            
+            var d = getPaneDims();
+            if (overrideDims) 
+                $.extend(d, overrideDims);
+            
+            $.each(panes.split(","), function(){
+                if (!$Ps[this]) 
+                    return; // NO PANE - skip
+                var pane = str(this), o = options[pane], s = state[pane], $P = $Ps[pane], $R = $Rs[pane], hasRoom = true, CSS = {};
+                
+                if (pane == "center") {
+                    d = getPaneDims(); // REFRESH Dims because may have just 'unhidden' East or West pane after a 'resize'
+                    CSS = $.extend({}, d); // COPY ALL of the paneDims
+                    CSS.width = max(1, cssW(pane, CSS.width));
+                    CSS.height = max(1, cssH(pane, CSS.height));
+                    hasRoom = (CSS.width > 1 && CSS.height > 1);
+                    /*
+                     * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
+                     * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
+                     */
+                    if ($.browser.msie && (!$.boxModel || $.browser.version < 7)) {
+                        if ($Ps.north) 
+                            $Ps.north.css({
+                                width: cssW($Ps.north, cDims.innerWidth)
+                            });
+                        if ($Ps.south) 
+                            $Ps.south.css({
+                                width: cssW($Ps.south, cDims.innerWidth)
+                            });
+                    }
+                }
+                else { // for east and west, set only the height
+                    CSS.top = d.top;
+                    CSS.bottom = d.bottom;
+                    CSS.height = max(1, cssH(pane, d.height));
+                    hasRoom = (CSS.height > 1);
+                }
+                
+                if (hasRoom) {
+                    $P.css(CSS);
+                    if (s.noRoom) {
+                        s.noRoom = false;
+                        if (s.isHidden) 
+                            return;
+                        else 
+                            show(pane, !s.isClosed);
+                        /* OLD CODE - keep until sure line above works right!
+                         if (!s.isClosed) $P.show(); // in case was previously hidden due to NOT hasRoom
+                         if ($R) $R.show();
+                         */
+                    }
+                    if (!onInit) {
+                        sizeContent(pane);
+                        execUserCallback(pane, o.onresize_end || o.onresize);
+                    }
+                }
+                else 
+                    if (!s.noRoom) { // no room for pane, so just hide it (if not already)
+                        s.noRoom = true; // update state
+                        if (s.isHidden) 
+                            return;
+                        if (onInit) { // skip onhide callback and other logic onLoad
+                            $P.hide();
+                            if ($R) 
+                                $R.hide();
+                        }
+                        else 
+                            hide(pane);
+                    }
+            });
+        };
+        
+        
+        var sizeContent = function(panes){
+            if (!panes || panes == "all") 
+                panes = c.allPanes;
+            
+            $.each(panes.split(","), function(){
+                if (!$Cs[this]) 
+                    return; // NO CONTENT - skip
+                var pane = str(this), ignore = options[pane].contentIgnoreSelector, $P = $Ps[pane], $C = $Cs[pane], e_C = $C[0] // DOM element
+, height = cssH($P); // init to pane.innerHeight
+                ;
+                $P.children().each(function(){
+                    if (this == e_C) 
+                        return; // Content elem - skip
+                    var $E = $(this);
+                    if (!ignore || !$E.is(ignore)) 
+                        height -= $E.outerHeight();
+                });
+                if (height > 0) 
+                    height = cssH($C, height);
+                if (height < 1) 
+                    $C.hide(); // no room for content!
+                else 
+                    $C.css({
+                        height: height
+                    }).show();
+            });
+        };
+        
+        
+        /**
+         * sizeHandles
+         *
+         * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
+         *
+         * @callers  initHandles(), open(), close(), resizeAll()
+         */
+        var sizeHandles = function(panes, onInit){
+            if (!panes || panes == "all") 
+                panes = c.borderPanes;
+            
+            $.each(panes.split(","), function(){
+                var pane = str(this), o = options[pane], s = state[pane], $P = $Ps[pane], $R = $Rs[pane], $T = $Ts[pane];
+                if (!$P || !$R || (!o.resizable && !o.closable)) 
+                    return; // skip
+                var dir = c[pane].dir, _state = (s.isClosed ? "_closed" : "_open"), spacing = o["spacing" + _state], togAlign = o["togglerAlign" + _state], togLen = o["togglerLength" + _state], paneLen, offset, CSS = {};
+                if (spacing == 0) {
+                    $R.hide();
+                    return;
+                }
+                else 
+                    if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
+                        $R.show(); // in case was previously hidden
+                // Resizer Bar is ALWAYS same width/height of pane it is attached to
+                if (dir == "horz") { // north/south
+                    paneLen = $P.outerWidth();
+                    $R.css({
+                        width: max(1, cssW($R, paneLen)) // account for borders & padding
+                        ,
+                        height: max(1, cssH($R, spacing)) // ditto
+                        ,
+                        left: cssNum($P, "left")
+                    });
+                }
+                else { // east/west
+                    paneLen = $P.outerHeight();
+                    $R.css({
+                        height: max(1, cssH($R, paneLen)) // account for borders & padding
+                        ,
+                        width: max(1, cssW($R, spacing)) // ditto
+                        ,
+                        top: cDims.top + getPaneSize("north", true)
+                        //,	top:	cssNum($Ps["center"], "top")
+                    });
+                    
+                }
+                
+                if ($T) {
+                    if (togLen == 0 || (s.isSliding && o.hideTogglerOnSlide)) {
+                        $T.hide(); // always HIDE the toggler when 'sliding'
+                        return;
+                    }
+                    else 
+                        $T.show(); // in case was previously hidden
+                    if (!(togLen > 0) || togLen == "100%" || togLen > paneLen) {
+                        togLen = paneLen;
+                        offset = 0;
+                    }
+                    else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
+                        if (typeof togAlign == "string") {
+                            switch (togAlign) {
+                                case "top":
+                                case "left":
+                                    offset = 0;
+                                    break;
+                                case "bottom":
+                                case "right":
+                                    offset = paneLen - togLen;
+                                    break;
+                                case "middle":
+                                case "center":
+                                default:
+                                    offset = Math.floor((paneLen - togLen) / 2); // 'default' catches typos
+                            }
+                        }
+                        else { // togAlign = number
+                            var x = parseInt(togAlign); //
+                            if (togAlign >= 0) 
+                                offset = x;
+                            else 
+                                offset = paneLen - togLen + x; // NOTE: x is negative!
+                        }
+                    }
+                    
+                    var $TC_o = (o.togglerContent_open ? $T.children(".content-open") : false), $TC_c = (o.togglerContent_closed ? $T.children(".content-closed") : false), $TC = (s.isClosed ? $TC_c : $TC_o);
+                    if ($TC_o) 
+                        $TC_o.css("display", s.isClosed ? "none" : "block");
+                    if ($TC_c) 
+                        $TC_c.css("display", s.isClosed ? "block" : "none");
+                    
+                    if (dir == "horz") { // north/south
+                        var width = cssW($T, togLen);
+                        $T.css({
+                            width: max(0, width) // account for borders & padding
+                            ,
+                            height: max(1, cssH($T, spacing)) // ditto
+                            ,
+                            left: offset // TODO: VERIFY that toggler  positions correctly for ALL values
+                        });
+                        if ($TC) // CENTER the toggler content SPAN
+                            $TC.css("marginLeft", Math.floor((width - $TC.outerWidth()) / 2)); // could be negative
+                    }
+                    else { // east/west
+                        var height = cssH($T, togLen);
+                        $T.css({
+                            height: max(0, height) // account for borders & padding
+                            ,
+                            width: max(1, cssW($T, spacing)) // ditto
+                            ,
+                            top: offset // POSITION the toggler
+                        });
+                        if ($TC) // CENTER the toggler content SPAN
+                            $TC.css("marginTop", Math.floor((height - $TC.outerHeight()) / 2)); // could be negative
+                    }
+                    
+                    
+                }
+                
+                // DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
+                if (onInit && o.initHidden) {
+                    $R.hide();
+                    if ($T) 
+                        $T.hide();
+                }
+            });
+        };
+        
+        
+        /**
+         * resizeAll
+         *
+         * @callers  window.onresize(), callbacks or custom code
+         */
+        var resizeAll = function(){
+        
+            console.log("RESIZE!");
+            console.log($Container);
+            var oldW = cDims.innerWidth, oldH = cDims.innerHeight;
+            cDims = state.container = getElemDims($Container); // UPDATE container dimensions
+            var checkH = (cDims.innerHeight < oldH), checkW = (cDims.innerWidth < oldW), s, dir;
+            
+            if (checkH || checkW) 
+                // NOTE special order for sizing: S-N-E-W
+                $.each(["south", "north", "east", "west"], function(i, pane){
+                    console.log(this);
+                    s = state[pane];
+                    dir = c[pane].dir;
+                    if (!s.isClosed && ((checkH && dir == "horz") || (checkW && dir == "vert"))) {
+                        setPaneMinMaxSizes(pane); // update pane-state
+                        // shrink pane if 'too big' to fit
+                        if (s.size > s.maxSize) 
+                            console.log("sizePane: " + pane);
+                        sizePane(pane, s.maxSize);
+                    }
+                });
+            
+            sizeMidPanes("all");
+            sizeHandles("all"); // reposition the toggler elements
+        };
+        
+        
+        /**
+         * keyDown
+         *
+         * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
+         *
+         * @callers  document.keydown()
+         */
+        function keyDown(evt){
+            if (!evt) 
+                return true;
+            var code = evt.keyCode;
+            if (code < 33) 
+                return true; // ignore special keys: ENTER, TAB, etc
+            var PANE = {
+                38: "north" // Up Cursor
+                ,
+                40: "south" // Down Cursor
+                ,
+                37: "west" // Left Cursor
+                ,
+                39: "east" // Right Cursor
+            }, isCursorKey = (code >= 37 && code <= 40), ALT = evt.altKey // no worky!
+, SHIFT = evt.shiftKey, CTRL = evt.ctrlKey, pane = false, s, o, k, m, el;
+            
+            if (!CTRL && !SHIFT) 
+                return true; // no modifier key - abort
+            else 
+                if (isCursorKey && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
+                    pane = PANE[code];
+                else // check to see if this matches a custom-hotkey
+                     $.each(c.borderPanes.split(","), function(i, p){ // loop each pane to check its hotkey
+                        o = options[p];
+                        k = o.customHotkey;
+                        m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
+                        if ((SHIFT && m == "SHIFT") || (CTRL && m == "CTRL") || (CTRL && SHIFT)) { // Modifier matches
+                            if (k && code == (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
+                                pane = p;
+                                return false; // BREAK
+                            }
+                        }
+                    });
+            
+            if (!pane) 
+                return true; // no hotkey - abort
+            // validate pane
+            o = options[pane]; // get pane options
+            s = state[pane]; // get pane options
+            if (!o.enableCursorHotkey || s.isHidden || !$Ps[pane]) 
+                return true;
+            
+            // see if user is in a 'form field' because may be 'selecting text'!
+            el = evt.target || evt.srcElement;
+            if (el && SHIFT && isCursorKey && (el.tagName == "TEXTAREA" || (el.tagName == "INPUT" && (code == 37 || code == 39)))) 
+                return true; // allow text-selection
+            // SYNTAX NOTES
+            // use "returnValue=false" to abort keystroke but NOT abort function - can run another command afterwards
+            // use "return false" to abort keystroke AND abort function
+            toggle(pane);
+            evt.stopPropagation();
+            evt.returnValue = false; // CANCEL key
+            return false;
+        };
+        
+        
+        /*
+         * ###########################
+         *     UTILITY METHODS
+         *   called externally only
+         * ###########################
+         */
+        function allowOverflow(elem){
+            if (this && this.tagName) 
+                elem = this; // BOUND to element
+            var $P;
+            if (typeof elem == "string") 
+                $P = $Ps[elem];
+            else {
+                if ($(elem).attr("pane")) 
+                    $P = $(elem);
+                else 
+                    $P = $(elem).parents("div[pane]:first");
+            }
+            if (!$P.length) 
+                return; // INVALID
+            var pane = $P.attr("pane"), s = state[pane];
+            
+            // if pane is already raised, then reset it before doing it again!
+            // this would happen if allowOverflow is attached to BOTH the pane and an element 
+            if (s.cssSaved) 
+                resetOverflow(pane); // reset previous CSS before continuing
+            // if pane is raised by sliding or resizing, or it's closed, then abort
+            if (s.isSliding || s.isResizing || s.isClosed) {
+                s.cssSaved = false;
+                return;
+            }
+            
+            var newCSS = {
+                zIndex: (c.zIndex.pane_normal + 1)
+            }, curCSS = {}, of = $P.css("overflow"), ofX = $P.css("overflowX"), ofY = $P.css("overflowY");
+            // determine which, if any, overflow settings need to be changed
+            if (of != "visible") {
+                curCSS.overflow = of;
+                newCSS.overflow = "visible";
+            }
+            if (ofX && ofX != "visible" && ofX != "auto") {
+                curCSS.overflowX = ofX;
+                newCSS.overflowX = "visible";
+            }
+            if (ofY && ofY != "visible" && ofY != "auto") {
+                curCSS.overflowY = ofX;
+                newCSS.overflowY = "visible";
+            }
+            
+            // save the current overflow settings - even if blank!
+            s.cssSaved = curCSS;
+            
+            // apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
+            $P.css(newCSS);
+            
+            // make sure the zIndex of all other panes is normal
+            $.each(c.allPanes.split(","), function(i, p){
+                if (p != pane) 
+                    resetOverflow(p);
+            });
+            
+        };
+        
+        function resetOverflow(elem){
+            if (this && this.tagName) 
+                elem = this; // BOUND to element
+            var $P;
+            if (typeof elem == "string") 
+                $P = $Ps[elem];
+            else {
+                if ($(elem).hasClass("ui-layout-pane")) 
+                    $P = $(elem);
+                else 
+                    $P = $(elem).parents("div[pane]:first");
+            }
+            if (!$P.length) 
+                return; // INVALID
+            var pane = $P.attr("pane"), s = state[pane], CSS = s.cssSaved ||
+            {};
+            // reset the zIndex
+            if (!s.isSliding && !s.isResizing) 
+                $P.css("zIndex", c.zIndex.pane_normal);
+            
+            // reset Overflow - if necessary
+            $P.css(CSS);
+            
+            // clear var
+            s.cssSaved = false;
+        };
+        
+        
+        /**
+         * getBtn
+         *
+         * Helper function to validate params received by addButton utilities
+         *
+         * @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
+         * @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
+         * @returns  If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise 'false'
+         */
+        function getBtn(selector, pane, action){
+            var $E = $(selector), err = "Error Adding Button \n\nInvalid ";
+            if (!$E.length) // element not found
+                alert(err + "selector: " + selector);
+            else 
+                if (c.borderPanes.indexOf(pane) == -1) // invalid 'pane' sepecified
+                    alert(err + "pane: " + pane);
+                else { // VALID
+                    var btn = options[pane].buttonClass + "-" + action;
+                    $E.addClass(btn + " " + btn + "-" + pane);
+                    return $E;
+                }
+            return false; // INVALID
+        };
+        
+        
+        /**
+         * addToggleBtn
+         *
+         * Add a custom Toggler button for a pane
+         *
+         * @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .toggle-button"
+         * @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
+         */
+        function addToggleBtn(selector, pane){
+            var $E = getBtn(selector, pane, "toggle");
+            if ($E) 
+                $E.attr("title", state[pane].isClosed ? "Open" : "Close").click(function(evt){
+                    toggle(pane);
+                    evt.stopPropagation();
+                });
+        };
+        
+        /**
+         * addOpenBtn
+         *
+         * Add a custom Open button for a pane
+         *
+         * @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .open-button"
+         * @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
+         */
+        function addOpenBtn(selector, pane){
+            var $E = getBtn(selector, pane, "open");
+            if ($E) 
+                $E.attr("title", "Open").click(function(evt){
+                    open(pane);
+                    evt.stopPropagation();
+                });
+        };
+        
+        /**
+         * addCloseBtn
+         *
+         * Add a custom Close button for a pane
+         *
+         * @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .close-button"
+         * @param String   pane 		Name of the pane the button is for: 'north', 'south', etc.
+         */
+        function addCloseBtn(selector, pane){
+            var $E = getBtn(selector, pane, "close");
+            if ($E) 
+                $E.attr("title", "Close").click(function(evt){
+                    close(pane);
+                    evt.stopPropagation();
+                });
+        };
+        
+        /**
+         * addPinBtn
+         *
+         * Add a custom Pin button for a pane
+         *
+         * Four classes are added to the element, based on the paneClass for the associated pane...
+         * Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
+         *  - ui-layout-pane-pin
+         *  - ui-layout-pane-west-pin
+         *  - ui-layout-pane-pin-up
+         *  - ui-layout-pane-west-pin-up
+         *
+         * @param String   selector 	jQuery selector for button, eg: ".ui-layout-north .ui-layout-pin"
+         * @param String   pane 		Name of the pane the pin is for: 'north', 'south', etc.
+         */
+        function addPinBtn(selector, pane){
+            var $E = getBtn(selector, pane, "pin");
+            if ($E) {
+                var s = state[pane];
+                $E.click(function(evt){
+                    setPinState($(this), pane, (s.isSliding || s.isClosed));
+                    if (s.isSliding || s.isClosed) 
+                        open(pane); // change from sliding to open
+                    else 
+                        close(pane); // slide-closed
+                    evt.stopPropagation();
+                });
+                // add up/down pin attributes and classes
+                setPinState($E, pane, (!s.isClosed && !s.isSliding));
+                // add this pin to the pane data so we can 'sync it' automatically
+                // PANE.pins key is an array so we can store multiple pins for each pane
+                c[pane].pins.push(selector); // just save the selector string
+            }
+        };
+        
+        /**
+         * syncPinBtns
+         *
+         * INTERNAL function to sync 'pin buttons' when pane is opened or closed
+         * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
+         *
+         * @callers  open(), close()
+         * @params  pane   These are the params returned to callbacks by layout()
+         * @params  doPin  True means set the pin 'down', False means 'up'
+         */
+        function syncPinBtns(pane, doPin){
+            $.each(c[pane].pins, function(i, selector){
+                setPinState($(selector), pane, doPin);
+            });
+        };
+        
+        /**
+         * setPinState
+         *
+         * Change the class of the pin button to make it look 'up' or 'down'
+         *
+         * @callers  addPinBtn(), syncPinBtns()
+         * @param Element  $Pin		The pin-span element in a jQuery wrapper
+         * @param Boolean  doPin		True = set the pin 'down', False = set it 'up'
+         * @param String   pinClass	The root classname for pins - will add '-up' or '-down' suffix
+         */
+        function setPinState($Pin, pane, doPin){
+            var updown = $Pin.attr("pin");
+            if (updown && doPin == (updown == "down")) 
+                return; // already in correct state
+            var root = options[pane].buttonClass, class1 = root + "-pin", class2 = class1 + "-" + pane, UP1 = class1 + "-up", UP2 = class2 + "-up", DN1 = class1 + "-down", DN2 = class2 + "-down";
+            $Pin.attr("pin", doPin ? "down" : "up") // logic
+.attr("title", doPin ? "Un-Pin" : "Pin").removeClass(doPin ? UP1 : DN1).removeClass(doPin ? UP2 : DN2).addClass(doPin ? DN1 : UP1).addClass(doPin ? DN2 : UP2);
+        };
+        
+        
+        /*
+         * ###########################
+         * CREATE/RETURN BORDER-LAYOUT
+         * ###########################
+         */
+        // init global vars
+        var $Container = $(this).css({
+            overflow: "hidden"
+        }) // Container elem
+, $Ps = {} // Panes x4	- set in initPanes()
+, $Cs = {} // Content x4	- set in initPanes()
+, $Rs = {} // Resizers x4	- set in initHandles()
+, $Ts = {} // Togglers x4	- set in initHandles()
+        //	object aliases
+        , c = config // alias for config hash
+, cDims = state.container // alias for easy access to 'container dimensions'
+;
+        
+        // create the border layout NOW
+        create();
+        
+        // return object pointers to expose data & option Properties, and primary action Methods
+        return {
+            options: options // property - options hash
+            ,
+            state: state // property - dimensions hash
+            ,
+            panes: $Ps // property - object pointers for ALL panes: panes.north, panes.center
+            ,
+            toggle: toggle // method - pass a 'pane' ("north", "west", etc)
+            ,
+            open: open // method - ditto
+            ,
+            close: close // method - ditto
+            ,
+            hide: hide // method - ditto
+            ,
+            show: show // method - ditto
+            ,
+            resizeContent: sizeContent // method - ditto
+            ,
+            sizePane: sizePane // method - pass a 'pane' AND a 'size' in pixels
+            ,
+            resizeAll: resizeAll // method - no parameters
+            ,
+            addToggleBtn: addToggleBtn // utility - pass element selector and 'pane'
+            ,
+            addOpenBtn: addOpenBtn // utility - ditto
+            ,
+            addCloseBtn: addCloseBtn // utility - ditto
+            ,
+            addPinBtn: addPinBtn // utility - ditto
+            ,
+            allowOverflow: allowOverflow // utility - pass calling element
+            ,
+            resetOverflow: resetOverflow // utility - ditto
+            ,
+            cssWidth: cssW,
+            cssHeight: cssH
+        };
+        
+    }
+})(jQuery);



More information about the Mapbender_commits mailing list