You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by je...@apache.org on 2012/04/04 10:55:13 UTC

svn commit: r1309292 [7/8] - in /chemistry/playground/chemistry-opencmis-javascript-relax: ./ src/ src/main/ src/main/webapp/ src/main/webapp/WEB-INF/ src/main/webapp/css/ src/main/webapp/css/eggplant/ src/main/webapp/css/eggplant/images/ src/main/weba...

Added: chemistry/playground/chemistry-opencmis-javascript-relax/src/main/webapp/js/jquery.layout-1.3.0-rc30.4.js
URL: http://svn.apache.org/viewvc/chemistry/playground/chemistry-opencmis-javascript-relax/src/main/webapp/js/jquery.layout-1.3.0-rc30.4.js?rev=1309292&view=auto
==============================================================================
--- chemistry/playground/chemistry-opencmis-javascript-relax/src/main/webapp/js/jquery.layout-1.3.0-rc30.4.js (added)
+++ chemistry/playground/chemistry-opencmis-javascript-relax/src/main/webapp/js/jquery.layout-1.3.0-rc30.4.js Wed Apr  4 08:55:11 2012
@@ -0,0 +1,5183 @@
+/**
+ * @preserve jquery.layout 1.3.0 - Release Candidate 30.4
+ * $Date: 2012-03-10 08:00:00 (Sat, 10 Mar 2012) $
+ * $Rev: 303004 $
+ *
+ * Copyright (c) 2012 
+ *   Fabrizio Balliano (http://www.fabrizioballiano.net)
+ *   Kevin Dalman (http://allpro.net)
+ *
+ * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
+ * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
+ *
+ * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.2
+ *
+ * Docs: http://layout.jquery-dev.net/documentation.html
+ * Tips: http://layout.jquery-dev.net/tips.html
+ * Help: http://groups.google.com/group/jquery-ui-layout
+ */
+
+/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html
+ * {!Object}    non-nullable type (never NULL)
+ * {?string}    nullable type (sometimes NULL) - default for {Object}
+ * {number=}    optional parameter
+ * {*}          ALL types
+ */
+
+// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars
+
+;(function ($) {
+
+// alias Math methods - used a lot!
+var min     = Math.min
+,   max     = Math.max
+,   round   = Math.floor
+;
+function isStr (v) { return $.type(v) === "string"; }
+
+function runPluginCallbacks (Instance, a_fn) {
+    if ($.isArray(a_fn)) 
+        for (var i=0, c=a_fn.length; i<c; i++) {
+            var fn = a_fn[i];
+            try {
+                if (isStr(fn)) // 'name' of a function
+                    fn = eval(fn);
+                if ($.isFunction(fn))
+                    fn( Instance );
+            } catch (ex) {}
+        }
+};
+
+
+/*
+ *  GENERIC $.layout METHODS - used by all layouts
+ */
+$.layout = {
+
+    version:    "1.3.rc30.4"
+,   revision:   0.033004 // 1.3.0 final = 1.0300 - major(n+).minor(nn)+patch(nn+)
+
+    // LANGUAGE CUSTOMIZATION
+,   language: {
+    //  Tips and messages for resizers, togglers, custom buttons, etc.
+        Open:           "Open"  // eg: "Open Pane"
+    ,   Close:          "Close"
+    ,   Resize:         "Resize"
+    ,   Slide:          "Slide Open"
+    ,   Pin:            "Pin"
+    ,   Unpin:          "Un-Pin"
+    ,   noRoomToOpenTip: "Not enough room to show this pane."
+    ,   minSizeWarning: "Panel has reached its minimum size"
+    ,   maxSizeWarning: "Panel has reached its maximum size"
+    //  Developer error messages
+    ,   pane:                   "pane"      // description of "layout pane element"
+    ,   selector:               "selector"  // description of "jQuery-selector"
+    ,   errButton:              "Error Adding Button \n\nInvalid "
+    ,   errContainerMissing:    "UI Layout Initialization Error\n\nThe specified layout-container does not exist."
+    ,   errCenterPaneMissing:   "UI Layout Initialization Error\n\nThe center-pane element does not exist.\n\nThe center-pane is a required element."
+    ,   errContainerHeight:     "UI Layout Initialization Warning\n\nThe layout-container \"CONTAINER\" has no height.\n\nTherefore the layout is 0-height and hence 'invisible'!"
+    }
+
+    // can update code here if $.browser is phased out
+,   browser: {
+        mozilla:    !!$.browser.mozilla
+    ,   webkit:     !!$.browser.webkit || !!$.browser.safari // webkit = jQ 1.4
+    ,   msie:       !!$.browser.msie
+    ,   isIE6:      !!$.browser.msie && $.browser.version == 6
+    ,   version:    $.browser.version // not used in Layout core, but may be used by plugins
+    }
+
+    // *PREDEFINED* EFFECTS & DEFAULTS 
+    // MUST list effect here - OR MUST set an fxSettings option (can be an empty hash: {})
+,   effects: {
+
+    //  Pane Open/Close Animations
+        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"  }
+        }
+    //  these are not recommended, but can be used
+    ,   blind:      {}
+    ,   clip:       {}
+    ,   explode:    {}
+    ,   fade:       {}
+    ,   fold:       {}
+    ,   puff:       {}
+
+    //  Pane Resize Animations
+    ,   size: {
+            all:    { easing:   "swing" }
+        }
+    }
+
+    // INTERNAL CONFIG DATA - DO NOT CHANGE THIS!
+,   config: {
+        optionRootKeys: "effects,panes,north,south,west,east,center".split(",")
+    ,   allPanes:       "north,south,west,east,center".split(",")
+    ,   borderPanes:    "north,south,west,east".split(",")
+    ,   oppositeEdge: {
+            north:  "south"
+        ,   south:  "north"
+        ,   east:   "west"
+        ,   west:   "east"
+        }
+    //  CSS used in multiple places
+    ,   hidden:  { visibility: "hidden" }
+    ,   visible: { visibility: "visible" }
+    //  layout element settings
+    ,   resizers: {
+            cssReq: {
+                position:   "absolute"
+            ,   padding:    0
+            ,   margin:     0
+            ,   fontSize:   "1px"
+            ,   textAlign:  "left"  // to counter-act "center" alignment!
+            ,   overflow:   "hidden" // prevent toggler-button from overflowing
+            //  SEE $.layout.defaults.zIndexes.resizer_normal
+            }
+        ,   cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=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
+            }
+        ,   cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
+                background: "#AAA"
+            }
+        }
+    ,   content: {
+            cssReq: {
+                position:   "relative" /* contain floated or positioned elements */
+            }
+        ,   cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
+                overflow:   "auto"
+            ,   padding:    "10px"
+            }
+        ,   cssDemoPane: { // DEMO CSS - REMOVE scrolling from 'pane' when it has a content-div
+                overflow:   "hidden"
+            ,   padding:    0
+            }
+        }
+    ,   panes: { // defaults for ALL panes - overridden by 'per-pane settings' below
+            cssReq: {
+                position:   "absolute"
+            ,   margin:     0
+            //  $.layout.defaults.zIndexes.pane_normal
+            }
+        ,   cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
+                padding:    "10px"
+            ,   background: "#FFF"
+            ,   border:     "1px solid #BBB"
+            ,   overflow:   "auto"
+            }
+        }
+    ,   north: {
+            side:           "Top"
+        ,   sizeType:       "Height"
+        ,   dir:            "horz"
+        ,   cssReq: {
+                top:        0
+            ,   bottom:     "auto"
+            ,   left:       0
+            ,   right:      0
+            ,   width:      "auto"
+            //  height:     DYNAMIC
+            }
+        }
+    ,   south: {
+            side:           "Bottom"
+        ,   sizeType:       "Height"
+        ,   dir:            "horz"
+        ,   cssReq: {
+                top:        "auto"
+            ,   bottom:     0
+            ,   left:       0
+            ,   right:      0
+            ,   width:      "auto"
+            //  height:     DYNAMIC
+            }
+        }
+    ,   east: {
+            side:           "Right"
+        ,   sizeType:       "Width"
+        ,   dir:            "vert"
+        ,   cssReq: {
+                left:       "auto"
+            ,   right:      0
+            ,   top:        "auto" // DYNAMIC
+            ,   bottom:     "auto" // DYNAMIC
+            ,   height:     "auto"
+            //  width:      DYNAMIC
+            }
+        }
+    ,   west: {
+            side:           "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"
+            }
+        }
+    }
+
+    // CALLBACK FUNCTION NAMESPACE - used to store reusable callback functions
+,   callbacks: {}
+
+    // LAYOUT-PLUGIN REGISTRATION
+    // more plugins can added beyond this default list
+,   plugins: {
+        draggable:      !!$.fn.draggable // resizing
+    ,   effects: {
+            core:       !!$.effects     // animimations (specific effects tested by initOptions)
+        ,   slide:      $.effects && $.effects.slide // default effect
+        }
+    }
+
+//  arrays of plugin or other methods to be triggered for events in *each layout* - will be passed 'Instance'
+,   onCreate:   []  // runs when layout is just starting to be created - right after options are set
+,   onLoad:     []  // runs after layout container and global events init, but before initPanes is called
+,   onReady:    []  // runs after initialization *completes* - ie, after initPanes completes successfully
+,   onDestroy:  []  // runs after layout is destroyed
+,   onUnload:   []  // runs after layout is destroyed OR when page unloads
+,   afterOpen:  []  // runs after setAsOpen() completes
+,   afterClose: []  // runs after setAsClosed() completes
+
+    /*
+    *   GENERIC UTILITY METHODS
+    */
+
+    // calculate and return the scrollbar width, as an integer
+,   scrollbarWidth:     function () { return window.scrollbarWidth  || $.layout.getScrollbarSize('width'); }
+,   scrollbarHeight:    function () { return window.scrollbarHeight || $.layout.getScrollbarSize('height'); }
+,   getScrollbarSize:   function (dim) {
+        var $c  = $('<div style="position: absolute; top: -10000px; left: -10000px; width: 100px; height: 100px; overflow: scroll;"></div>').appendTo("body");
+        var d   = { width: $c.width() - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight };
+        $c.remove();
+        window.scrollbarWidth   = d.width;
+        window.scrollbarHeight  = d.height;
+        return dim.match(/^(width|height)$/) ? d[dim] : d;
+    }
+
+
+    /**
+    * Returns hash container 'display' and 'visibility'
+    *
+    * @see  $.swap() - swaps CSS, runs callback, resets CSS
+    */
+,   showInvisibly: function ($E, force) {
+        if (!$E) return {};
+        if (!$E.jquery) $E = $($E);
+        var CSS = {
+            display:    $E.css('display')
+        ,   visibility: $E.css('visibility')
+        };
+        if (force || CSS.display === "none") { // only if not *already hidden*
+            $E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so can be measured
+            return CSS;
+        }
+        else return {};
+    }
+
+    /**
+    * Returns data for setting size of an element (container or a pane).
+    *
+    * @see  _create(), onWindowResize() for container, plus others for pane
+    * @return JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
+    */
+,   getElementDimensions: function ($E) {
+        var
+            d   = {}            // dimensions hash
+        ,   x   = d.css = {}    // CSS hash
+        ,   i   = {}            // TEMP insets
+        ,   b, p                // TEMP border, padding
+        ,   N   = $.layout.cssNum
+        ,   off = $E.offset()
+        ;
+        d.offsetLeft = off.left;
+        d.offsetTop  = off.top;
+
+        $.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge
+            b = x["border" + e] = $.layout.borderWidth($E, e);
+            p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e);
+            i[e] = b + p; // total offset of content from outer side
+            d["inset"+ e] = p;
+        });
+
+        d.offsetWidth   = $E.innerWidth();  // offsetWidth is used in calc when doing manual resize
+        d.offsetHeight  = $E.innerHeight(); // ditto
+        d.outerWidth    = $E.outerWidth();
+        d.outerHeight   = $E.outerHeight();
+        d.innerWidth    = max(0, d.outerWidth  - i.Left - i.Right);
+        d.innerHeight   = max(0, d.outerHeight - i.Top  - i.Bottom);
+
+        x.width     = $E.width();
+        x.height    = $E.height();
+        x.top       = N($E,"top",true);
+        x.bottom    = N($E,"bottom",true);
+        x.left      = N($E,"left",true);
+        x.right     = N($E,"right",true);
+
+        //d.visible = $E.is(":visible");// && x.width > 0 && x.height > 0;
+
+        return d;
+    }
+
+,   getElementCSS: function ($E, list) {
+        var
+            CSS = {}
+        ,   style   = $E[0].style
+        ,   props   = list.split(",")
+        ,   sides   = "Top,Bottom,Left,Right".split(",")
+        ,   attrs   = "Color,Style,Width".split(",")
+        ,   p, s, a, i, j, k
+        ;
+        for (i=0; i < props.length; i++) {
+            p = props[i];
+            if (p.match(/(border|padding|margin)$/))
+                for (j=0; j < 4; j++) {
+                    s = sides[j];
+                    if (p === "border")
+                        for (k=0; k < 3; k++) {
+                            a = attrs[k];
+                            CSS[p+s+a] = style[p+s+a];
+                        }
+                    else
+                        CSS[p+s] = style[p+s];
+                }
+            else
+                CSS[p] = style[p];
+        };
+        return CSS
+    }
+
+    /**
+    * Return the innerWidth for the current browser/doctype
+    *
+    * @see  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
+    * @param  {Array.<Object>}  $E  Must pass a jQuery object - first element is processed
+    * @param  {number=}         outerWidth (optional) Can pass a width, allowing calculations BEFORE element is resized
+    * @return {number}          Returns the innerWidth of the elem by subtracting padding and borders
+    */
+,   cssWidth: function ($E, outerWidth) {
+        var
+            b = $.layout.borderWidth
+        ,   n = $.layout.cssNum
+        ;
+        // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
+        if (outerWidth <= 0) return 0;
+
+        if (!$.support.boxModel) return outerWidth;
+
+        // strip border and padding from outerWidth to get CSS Width
+        var W = outerWidth
+            - b($E, "Left")
+            - b($E, "Right")
+            - n($E, "paddingLeft")      
+            - n($E, "paddingRight")
+        ;
+
+        return max(0,W);
+    }
+
+    /**
+    * Return the innerHeight for the current browser/doctype
+    *
+    * @see  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
+    * @param  {Array.<Object>}  $E  Must pass a jQuery object - first element is processed
+    * @param  {number=}         outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
+    * @return {number}          Returns the innerHeight of the elem by subtracting padding and borders
+    */
+,   cssHeight: function ($E, outerHeight) {
+        var
+            b = $.layout.borderWidth
+        ,   n = $.layout.cssNum
+        ;
+        // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
+        if (outerHeight <= 0) return 0;
+
+        if (!$.support.boxModel) return outerHeight;
+
+        // strip border and padding from outerHeight to get CSS Height
+        var H = outerHeight
+            - b($E, "Top")
+            - b($E, "Bottom")
+            - n($E, "paddingTop")
+            - n($E, "paddingBottom")
+        ;
+
+        return max(0,H);
+    }
+
+    /**
+    * Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist
+    *
+    * @see  Called by many methods
+    * @param {Array.<Object>}   $E                  Must pass a jQuery object - first element is processed
+    * @param {string}           prop                The name of the CSS property, eg: top, width, etc.
+    * @param {boolean=}         [allowAuto=false]   true = return 'auto' if that is value; false = return 0
+    * @return {(string|number)}                     Usually used to get an integer value for position (top, left) or size (height, width)
+    */
+,   cssNum: function ($E, prop, allowAuto) {
+        if (!$E.jquery) $E = $($E);
+        var CSS = $.layout.showInvisibly($E)
+        ,   p   = $.curCSS($E[0], prop, true)
+        ,   v   = allowAuto && p=="auto" ? p : (parseInt(p, 10) || 0);
+        $E.css( CSS ); // RESET
+        return v;
+    }
+
+,   borderWidth: function (el, side) {
+        if (el.jquery) el = el[0];
+        var b = "border"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left
+        return $.curCSS(el, b+"Style", true) === "none" ? 0 : (parseInt($.curCSS(el, b+"Width", true), 10) || 0);
+    }
+
+    /**
+    * Mouse-tracking utility - FUTURE REFERENCE
+    *
+    * init: if (!window.mouse) {
+    *           window.mouse = { x: 0, y: 0 };
+    *           $(document).mousemove( $.layout.trackMouse );
+    *       }
+    *
+    * @param {Object}       evt
+    *
+,   trackMouse: function (evt) {
+        window.mouse = { x: evt.clientX, y: evt.clientY };
+    }
+    */
+
+    /**
+    * SUBROUTINE for preventPrematureSlideClose option
+    *
+    * @param {Object}       evt
+    * @param {Object=}      el
+    */
+,   isMouseOverElem: function (evt, el) {
+        var
+            $E  = $(el || this)
+        ,   d   = $E.offset()
+        ,   T   = d.top
+        ,   L   = d.left
+        ,   R   = L + $E.outerWidth()
+        ,   B   = T + $E.outerHeight()
+        ,   x   = evt.pageX // evt.clientX ?
+        ,   y   = evt.pageY // evt.clientY ?
+        ;
+        // if X & Y are < 0, probably means is over an open SELECT
+        return ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B));
+    }
+
+    /**
+    * Message/Logging Utility
+    *
+    * @example $.layout.msg("My message");              // log text
+    * @example $.layout.msg("My message", true);        // alert text
+    * @example $.layout.msg({ foo: "bar" }, "Title");   // log hash-data, with custom title
+    * @example $.layout.msg({ foo: "bar" }, true, "Title", { sort: false }); -OR-
+    * @example $.layout.msg({ foo: "bar" }, "Title", { sort: false, display: true }); // alert hash-data
+    *
+    * @param {(Object|string)}          info            String message OR Hash/Array
+    * @param {(Boolean|string|Object)=} [popup=false]   True means alert-box - can be skipped
+    * @param {(Object|string)=}         [debugTitle=""] Title for Hash data - can be skipped
+    * @param {Object=}                  [debutOpts={}]  Extra options for debug output
+    */
+,   msg: function (info, popup, debugTitle, debugOpts) {
+        if ($.isPlainObject(info) && window.debugData) {
+            if (typeof popup === "string") {
+                debugOpts   = debugTitle;
+                debugTitle  = popup;
+            }
+            else if (typeof debugTitle === "object") {
+                debugOpts   = debugTitle;
+                debugTitle  = null;
+            }
+            var t = debugTitle || "log( <object> )"
+            ,   o = $.extend({ sort: false, returnHTML: false, display: false }, debugOpts);
+            if (popup === true || o.display)
+                debugData( info, t, o );
+            else if (window.console)
+                console.log(debugData( info, t, o ));
+        }
+        else if (popup)
+            alert(info);
+        else if (window.console)
+            console.log(info);
+    }
+
+};
+
+var lang = $.layout.language; // alias used in defaults...
+
+// DEFAULT OPTIONS - CHANGE IF DESIRED
+$.layout.defaults = {
+/*
+ *  LAYOUT & LAYOUT-CONTAINER OPTIONS
+ *  - none of these options are applicable to individual panes
+ */
+    name:                       ""          // Not required, but useful for buttons and used for the state-cookie
+,   containerClass:             "ui-layout-container" // layout-container element
+,   scrollToBookmarkOnLoad:     true        // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
+,   resizeWithWindow:           true        // bind thisLayout.resizeAll() to the window.resize event
+,   resizeWithWindowDelay:      200         // delay calling resizeAll because makes window resizing very jerky
+,   resizeWithWindowMaxDelay:   0           // 0 = none - force resize every XX ms while window is being resized
+,   onresizeall_start:          null        // CALLBACK when resizeAll() STARTS - NOT pane-specific
+,   onresizeall_end:            null        // CALLBACK when resizeAll() ENDS   - NOT pane-specific
+,   onload_start:               null        // CALLBACK when Layout inits - after options initialized, but before elements
+,   onload_end:                 null        // CALLBACK when Layout inits - after EVERYTHING has been initialized
+,   onunload_start:             null        // CALLBACK when Layout is destroyed OR onWindowUnload
+,   onunload_end:               null        // CALLBACK when Layout is destroyed OR onWindowUnload
+,   autoBindCustomButtons:      false       // search for buttons with ui-layout-button class and auto-bind them
+,   initPanes:                  true        // false = DO NOT initialize the panes onLoad - will init later
+,   showErrorMessages:          true        // enables fatal error messages to warn developers of common errors
+,   showDebugMessages:          false       // display console-and-alert debug msgs - IF this Layout version _has_ debugging code!
+//  Changing this zIndex value will cause other zIndex values to automatically change
+,   zIndex:                     null        // the PANE zIndex - resizers and masks will be +1
+//  DO NOT CHANGE the zIndex values below unless you clearly understand their relationships
+,   zIndexes: {                             // set _default_ z-index values here...
+        pane_normal:            0           // normal z-index for panes
+    ,   content_mask:           1           // applied to overlays used to mask content INSIDE panes during resizing
+    ,   resizer_normal:         2           // normal z-index for resizer-bars
+    ,   pane_sliding:           100         // applied to *BOTH* the pane and its resizer when a pane is 'slid open'
+    ,   pane_animate:           1000        // applied to the pane when being animated - not applied to the resizer
+    ,   resizer_drag:           10000       // applied to the CLONED resizer-bar when being 'dragged'
+    }
+/*
+ *  PANE DEFAULT SETTINGS
+ *  - settings under the 'panes' key become the default settings for *all panes*
+ *  - ALL pane-options can also be set specifically for each panes, which will override these 'default values'
+ */
+,   panes: { // default options for 'all panes' - will be overridden by 'per-pane settings'
+        applyDemoStyles:        false       // NOTE: renamed from applyDefaultStyles for clarity
+    ,   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
+    ,   initClosed:             false       // true = init pane as 'closed'
+    ,   initHidden:             false       // true = init pane as 'hidden' - no resizer-bar/spacing
+    //  SELECTORS
+    //, paneSelector:           ""          // MUST be pane-specific - jQuery selector for pane
+    ,   contentSelector:        ".ui-layout-content" // INNER div/element to auto-size so only it scrolls, not the entire pane!
+    ,   contentIgnoreSelector:  ".ui-layout-ignore" // element(s) to 'ignore' when measuring 'content'
+    ,   findNestedContent:      false       // true = $P.find(contentSelector), false = $P.children(contentSelector)
+    //  GENERIC ROOT-CLASSES - for auto-generated classNames
+    ,   paneClass:              "ui-layout-pane"    // Layout Pane
+    ,   resizerClass:           "ui-layout-resizer" // Resizer Bar
+    ,   togglerClass:           "ui-layout-toggler" // Toggler Button
+    ,   buttonClass:            "ui-layout-button"  // CUSTOM Buttons   - eg: '[ui-layout-button]-toggle/-open/-close/-pin'
+    //  ELEMENT SIZE & SPACING
+    //, size:                   100         // MUST be pane-specific -initial size of 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 sides - HEIGHT on east/west sides
+    ,   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:        lang.Close  // Toggler tool-tip (title)
+    ,   togglerTip_closed:      lang.Open   // ditto
+    ,   togglerContent_open:    ""          // text or HTML to put INSIDE the toggler
+    ,   togglerContent_closed:  ""          // ditto
+    //  RESIZING OPTIONS
+    ,   resizerDblClickToggle:  true        // 
+    ,   autoResize:             true        // IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes
+    ,   autoReopen:             true        // IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed
+    ,   resizerDragOpacity:     1           // option for ui.draggable
+    //, resizerCursor:          ""          // MUST be pane-specific - cursor when over resizer-bar
+    ,   maskContents:           false       // true = add DIV-mask over-or-inside this pane so can 'drag' over IFRAMES
+    ,   maskObjects:            false       // true = add IFRAME-mask over-or-inside this pane to cover objects/applets - content-mask will overlay this mask
+    ,   maskZindex:             null        // will override zIndexes.content_mask if specified - not applicable to iframe-panes
+    ,   resizingGrid:           false       // grid size that the resizers will snap-to during resizing, eg: [20,20]
+    ,   livePaneResizing:       false       // true = LIVE Resizing as resizer is dragged
+    ,   liveContentResizing:    false       // true = re-measure header/footer heights as resizer is dragged
+    ,   liveResizingTolerance:  1           // how many px change before pane resizes, to control performance
+    //  TIPS & MESSAGES - also see lang object
+    ,   noRoomToOpenTip:        lang.noRoomToOpenTip
+    ,   resizerTip:             lang.Resize // Resizer tool-tip (title)
+    ,   sliderTip:              lang.Slide  // resizer-bar triggers 'sliding' when pane is closed
+    ,   sliderCursor:           "pointer"   // cursor when resizer-bar will trigger 'sliding'
+    ,   slideTrigger_open:      "click"     // click, dblclick, mouseenter
+    ,   slideTrigger_close:     "mouseleave"// click, mouseleave
+    ,   slideDelay_open:        300         // applies only for mouseenter event - 0 = instant open
+    ,   slideDelay_close:       300         // applies only for mouseleave event (300ms is the minimum!)
+    ,   hideTogglerOnSlide:     false       // when pane is slid-open, should the toggler show?
+    ,   preventQuickSlideClose: $.layout.browser.webkit // Chrome triggers slideClosed as it is opening
+    ,   preventPrematureSlideClose: false   // handle incorrect mouseleave trigger, like when over a SELECT-list in IE
+    //  HOT-KEYS & MISC
+    ,   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'
+    //  PANE ANIMATION
+    //  NOTE: fxSss_open, fxSss_close & fxSss_size options (eg: fxName_open) are auto-generated if not passed
+    ,   fxName:                 "slide"     // ('none' or blank), slide, drop, scale -- only relevant to 'open' & 'close', NOT 'size'
+    ,   fxSpeed:                null        // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
+    ,   fxSettings:             {}          // can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
+    ,   fxOpacityFix:           true        // tries to fix opacity in IE to restore anti-aliasing after animation
+    ,   animatePaneSizing:      false       // true = animate resizing after dragging resizer-bar OR sizePane() is called
+    /*  NOTE: Action-specific FX options are auto-generated from the options above if not specifically set:
+        fxName_open:            "slide"     // 'Open' pane animation
+        fnName_close:           "slide"     // 'Close' pane animation
+        fxName_size:            "slide"     // 'Size' pane animation - when animatePaneSizing = true
+        fxSpeed_open:           null
+        fxSpeed_close:          null
+        fxSpeed_size:           null
+        fxSettings_open:        {}
+        fxSettings_close:       {}
+        fxSettings_size:        {}
+    */
+    //  CHILD/NESTED LAYOUTS
+    ,   childOptions:           null        // Layout-options for nested/child layout - even {} is valid as options
+    ,   initChildLayout:        true        // true = child layout will be created as soon as _this_ layout completes initialization
+    ,   destroyChildLayout:     true        // true = destroy child-layout if this pane is destroyed
+    ,   resizeChildLayout:      true        // true = trigger child-layout.resizeAll() when this pane is resized
+    //  PANE CALLBACKS
+    ,   triggerEventsOnLoad:    false       // true = trigger onopen OR onclose callbacks when layout initializes
+    ,   triggerEventsDuringLiveResize: true // true = trigger onresize callback REPEATEDLY if livePaneResizing==true
+    ,   onshow_start:           null        // CALLBACK when pane STARTS to Show    - BEFORE onopen/onhide_start
+    ,   onshow_end:             null        // CALLBACK when pane ENDS being Shown  - AFTER  onopen/onhide_end
+    ,   onhide_start:           null        // CALLBACK when pane STARTS to Close   - BEFORE onclose_start
+    ,   onhide_end:             null        // CALLBACK when pane ENDS being Closed - AFTER  onclose_end
+    ,   onopen_start:           null        // CALLBACK when pane STARTS to Open
+    ,   onopen_end:             null        // CALLBACK when pane ENDS being Opened
+    ,   onclose_start:          null        // CALLBACK when pane STARTS to Close
+    ,   onclose_end:            null        // CALLBACK when pane ENDS being Closed
+    ,   onresize_start:         null        // CALLBACK when pane STARTS being Resized ***FOR ANY REASON***
+    ,   onresize_end:           null        // CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
+    ,   onsizecontent_start:    null        // CALLBACK when sizing of content-element STARTS
+    ,   onsizecontent_end:      null        // CALLBACK when sizing of content-element ENDS
+    ,   onswap_start:           null        // CALLBACK when pane STARTS to Swap
+    ,   onswap_end:             null        // CALLBACK when pane ENDS being Swapped
+    ,   ondrag_start:           null        // CALLBACK when pane STARTS being ***MANUALLY*** Resized
+    ,   ondrag_end:             null        // CALLBACK when pane ENDS being ***MANUALLY*** Resized
+    }
+/*
+ *  PANE-SPECIFIC SETTINGS
+ *  - options listed below MUST be specified per-pane - they CANNOT be set under 'panes'
+ *  - all options under the 'panes' key can also be set specifically for any pane
+ *  - most options under the 'panes' key apply only to 'border-panes' - NOT the the center-pane
+ */
+,   north: {
+        paneSelector:           ".ui-layout-north"
+    ,   size:                   "auto"      // eg: "auto", "30%", .30, 200
+    ,   resizerCursor:          "n-resize"  // custom = url(myCursor.cur)
+    ,   customHotkey:           ""          // EITHER a charCode (43) OR a character ("o")
+    }
+,   south: {
+        paneSelector:           ".ui-layout-south"
+    ,   size:                   "auto"
+    ,   resizerCursor:          "s-resize"
+    ,   customHotkey:           ""
+    }
+,   east: {
+        paneSelector:           ".ui-layout-east"
+    ,   size:                   200
+    ,   resizerCursor:          "e-resize"
+    ,   customHotkey:           ""
+    }
+,   west: {
+        paneSelector:           ".ui-layout-west"
+    ,   size:                   200
+    ,   resizerCursor:          "w-resize"
+    ,   customHotkey:           ""
+    }
+,   center: {
+        paneSelector:           ".ui-layout-center"
+    ,   minWidth:               0
+    ,   minHeight:              0
+    }
+};
+
+$.layout.optionsMap = {
+    // layout/global options - NOT pane-options
+    layout: ("stateManagement,effects,zIndexes,"
+    +   "name,zIndex,scrollToBookmarkOnLoad,showErrorMessages,"
+    +   "resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay,"
+    +   "onresizeall,onresizeall_start,onresizeall_end,onload,onunload,autoBindCustomButtons").split(",")
+//  borderPanes: [ ALL options that are NOT specified as 'layout' ]
+    // default.panes options that apply to the center-pane (most options apply _only_ to border-panes)
+,   center: ("paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad,"
+    +   "showOverflowOnHover,maskContents,maskObjects,liveContentResizing,"
+    +   "childOptions,initChildLayout,resizeChildLayout,destroyChildLayout,"
+    +   "onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end").split(",")
+    // options that MUST be specifically set 'per-pane' - CANNOT set in the panes (defaults) key
+,   noDefault: ("paneSelector,resizerCursor,customHotkey").split(",")
+};
+
+/**
+ * Processes options passed in converts flat-format data into subkey (JSON) format
+ * In flat-format, subkeys are _currently_ separated with 2 underscores, like north__optName
+ * Plugins may also call this method so they can transform their own data
+ *
+ * @param  {!Object}    hash    Data/options passed by user - may be a single level or nested levels
+ * @return {Object}             Returns hash of minWidth & minHeight
+ */
+$.layout.transformData = function (hash) {
+    var json = { panes: {}, center: {} } // init return object
+    ,   data, branch, optKey, keys, key, val, i, c;
+
+    if (typeof hash !== "object") return json; // no options passed
+
+    // convert all 'flat-keys' to 'sub-key' format
+    for (optKey in hash) {
+        branch  = json;
+        data    = $.layout.optionsMap.layout;
+        val     = hash[ optKey ];
+        keys    = optKey.split("__"); // eg: west__size or north__fxSettings__duration
+        c       = keys.length - 1;
+        // convert underscore-delimited to subkeys
+        for (i=0; i <= c; i++) {
+            key = keys[i];
+            if (i === c)
+                branch[key] = val;
+            else if (!branch[key])
+                branch[key] = {}; // create the subkey
+            // recurse to sub-key for next loop - if not done
+            branch = branch[key];
+        }
+    }
+
+    return json;
+}
+
+// INTERNAL CONFIG DATA - DO NOT CHANGE THIS!
+$.layout.backwardCompatibility = {
+    // data used by renameOldOptions()
+    map: {
+    //  OLD Option Name:            NEW Option Name
+        applyDefaultStyles:         "applyDemoStyles"
+    ,   resizeNestedLayout:         "resizeChildLayout"
+    ,   resizeWhileDragging:        "livePaneResizing"
+    ,   resizeContentWhileDragging: "liveContentResizing"
+    ,   triggerEventsWhileDragging: "triggerEventsDuringLiveResize"
+    ,   maskIframesOnResize:        "maskContents"
+    ,   useStateCookie:             "stateManagement.enabled"
+    ,   "cookie.autoLoad":          "stateManagement.autoLoad"
+    ,   "cookie.autoSave":          "stateManagement.autoSave"
+    ,   "cookie.keys":              "stateManagement.stateKeys"
+    ,   "cookie.name":              "stateManagement.cookie.name"
+    ,   "cookie.domain":            "stateManagement.cookie.domain"
+    ,   "cookie.path":              "stateManagement.cookie.path"
+    ,   "cookie.expires":           "stateManagement.cookie.expires"
+    ,   "cookie.secure":            "stateManagement.cookie.secure"
+    }
+    /**
+    * @param {Object}   opts
+    */
+,   renameOptions: function (opts) {
+        var map = $.layout.backwardCompatibility.map
+        ,   oldData, newData, value
+        ;
+        for (var itemPath in map) {
+            oldData = getBranch( itemPath );
+            value   = oldData.branch[ oldData.key ]
+            if (value !== undefined) {
+                newData = getBranch( map[itemPath], true )
+                newData.branch[ newData.key ] = value;
+                delete oldData.branch[ oldData.key ];
+            }
+        }
+
+        /**
+        * @param {string}   path
+        * @param {boolean=} [create=false]  Create path if does not exist
+        */
+        function getBranch (path, create) {
+            var a = path.split(".") // split keys into array
+            ,   c = a.length - 1
+            ,   D = { branch: opts, key: a[c] } // init branch at top & set key (last item)
+            ,   i = 0, k, undef;
+            for (; i<c; i++) { // skip the last key (data)
+                k = a[i];
+                if (D.branch[ k ] == undefined) { // child-key does not exist
+                    if (create) {
+                        D.branch = D.branch[ k ] = {}; // create child-branch
+                    }
+                    else // can't go any farther
+                        D.branch = {}; // branch is undefined
+                }
+                else
+                    D.branch = D.branch[ k ]; // get child-branch
+            }
+            return D;
+        };
+    }
+    /**
+    * @param {Object}   opts
+    */
+,   renameAllOptions: function (opts) {
+        var ren = $.layout.backwardCompatibility.renameOptions;
+        // rename root (layout) options
+        ren( opts );
+        // rename 'defaults' to 'panes'
+        if (opts.defaults) {
+            if (typeof opts.panes !== "object")
+                opts.panes = {};
+            $.extend(true, opts.panes, opts.defaults);
+            delete opts.defaults;
+        }
+        // rename options in the the options.panes key
+        if (opts.panes) ren( opts.panes );
+        // rename options inside *each pane key*, eg: options.west
+        $.each($.layout.config.allPanes, function (i, pane) {
+            if (opts[pane]) ren( opts[pane] );
+        }); 
+        return opts;
+    }
+};
+
+
+
+/*  ============================================================
+ *  BEGIN WIDGET: $( selector ).layout( {options} );
+ *  ============================================================
+ */
+$.fn.layout = function (opts) {
+    var
+
+    // local aliases to global data
+    browser = $.layout.browser
+,   lang    = $.layout.language // internal alias
+,   _c      = $.layout.config
+
+    // local aliases to utlity methods
+,   cssW    = $.layout.cssWidth
+,   cssH    = $.layout.cssHeight
+,   elDims  = $.layout.getElementDimensions
+,   elCSS   = $.layout.getElementCSS
+
+/**
+ * options - populated by initOptions()
+ */
+,   options = $.extend(true, {}, $.layout.defaults)
+,   effects = options.effects = $.extend(true, {}, $.layout.effects)
+
+/**
+ * layout-state object
+ */
+,   state = {
+        // generate unique ID to use for event.namespace so can unbind only events added by 'this layout'
+        id:         "layout"+ $.now()   // code uses alias: sID
+    ,   initialized: false
+    ,   container:  {} // init all keys
+    ,   north:      {}
+    ,   south:      {}
+    ,   east:       {}
+    ,   west:       {}
+    ,   center:     {}
+    }
+
+/**
+ * parent/child-layout pointers
+ */
+//, hasParentLayout = false - exists ONLY as Instance.hasParentLayout
+,   children = {
+        north:      null
+    ,   south:      null
+    ,   east:       null
+    ,   west:       null
+    ,   center:     null
+    }
+
+/*
+ * ###########################
+ *  INTERNAL HELPER FUNCTIONS
+ * ###########################
+ */
+
+    /**
+    * Manages all internal timers
+    */
+,   timer = {
+        data:   {}
+    ,   set:    function (s, fn, ms) { timer.clear(s); timer.data[s] = setTimeout(fn, ms); }
+    ,   clear:  function (s) { var t=timer.data; if (t[s]) {clearTimeout(t[s]); delete t[s];} }
+    }
+
+,   _log = function (msg, popup) {
+        $.layout.msg( msg, (popup && options.showErrorMessages) );
+    }
+
+    /**
+    * 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|function())}  v_fn    Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
+    */
+,   _execCallback = function (pane, v_fn) {
+        if (!v_fn) return;
+        var fn;
+        try {
+            if (typeof v_fn === "function")
+                fn = v_fn;  
+            else if (!isStr(v_fn))
+                return;
+            else if (v_fn.match(/,/)) {
+                // 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 ($.isFunction( fn )) {
+                if (pane && $Ps[pane])
+                    // pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
+                    return fn( pane, $Ps[pane], state[pane], options[pane], options.name );
+                else // must be a layout/container callback - pass suitable info
+                    return fn( Instance, state, options, options.name );
+            }
+        }
+        catch (ex) {}
+    }
+
+,   trigger = function (fnName, pane) {
+        var o   = options
+        ,   fn  = pane && o[pane] ? o[pane][fnName] : o[fnName];
+        if (fn) _execCallback(pane || null, fn);
+    }
+
+    /**
+    * cure iframe display issues in IE & other browsers
+    */
+,   _fixIframe = function (pane) {
+        if (browser.mozilla) return; // skip FireFox - it auto-refreshes iframes onShow
+        var $P = $Ps[pane];
+        // if the 'pane' is an iframe, do it
+        if (state[pane].tagName === "IFRAME")
+            $P.css(_c.hidden).css(_c.visible); 
+        else // ditto for any iframes INSIDE the pane
+            $P.find('IFRAME').css(_c.hidden).css(_c.visible);
+    }
+
+    /**
+    * @param  {string}      pane        Can accept ONLY a 'pane' (east, west, etc)
+    * @param  {number=}     outerSize   (optional) Can pass a width, allowing calculations BEFORE element is resized
+    * @return {number}      Returns the innerHeight/Width of el by subtracting padding and borders
+    */
+,   cssSize = function (pane, outerSize) {
+        var fn = _c[pane].dir=="horz" ? cssH : cssW;
+        return fn($Ps[pane], outerSize);
+    }
+
+    /**
+    * @param  {string}      pane        Can accept ONLY a 'pane' (east, west, etc)
+    * @return {Object}      Returns hash of minWidth & minHeight
+    */
+,   cssMinDims = function (pane) {
+        // minWidth/Height means CSS width/height = 1px
+        var
+            $P  = $Ps[pane]
+            dir = _c[pane].dir
+        ,   d   = {
+                minWidth:   1001 - cssW($P, 1000)
+            ,   minHeight:  1001 - cssH($P, 1000)
+            }
+        ;
+        if (dir === "horz") d.minSize = d.minHeight;
+        if (dir === "vert") d.minSize = d.minWidth;
+        return d;
+    }
+
+    // TODO: see if these methods can be made more useful...
+    // TODO: *maybe* return cssW/H from these so caller can use this info
+
+    /**
+    * @param {(string|!Object)}     el
+    * @param {number=}              outerWidth
+    * @param {boolean=}             [autoHide=false]
+    */
+,   setOuterWidth = function (el, outerWidth, autoHide) {
+        var $E = el, w;
+        if (isStr(el)) $E = $Ps[el]; // west
+        else if (!el.jquery) $E = $(el);
+        w = cssW($E, outerWidth);
+        $E.css({ width: w });
+        if (w > 0) {
+            if (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) {
+                $E.show().data('autoHidden', false);
+                if (!browser.mozilla) // FireFox refreshes iframes - IE does not
+                    // make hidden, then visible to 'refresh' display after animation
+                    $E.css(_c.hidden).css(_c.visible);
+            }
+        }
+        else if (autoHide && !$E.data('autoHidden'))
+            $E.hide().data('autoHidden', true);
+    }
+
+    /**
+    * @param {(string|!Object)}     el
+    * @param {number=}              outerHeight
+    * @param {boolean=}             [autoHide=false]
+    */
+,   setOuterHeight = function (el, outerHeight, autoHide) {
+        var $E = el, h;
+        if (isStr(el)) $E = $Ps[el]; // west
+        else if (!el.jquery) $E = $(el);
+        h = cssH($E, outerHeight);
+        $E.css({ height: h, visibility: "visible" }); // may have been 'hidden' by sizeContent
+        if (h > 0 && $E.innerWidth() > 0) {
+            if (autoHide && $E.data('autoHidden')) {
+                $E.show().data('autoHidden', false);
+                if (!browser.mozilla) // FireFox refreshes iframes - IE does not
+                    $E.css(_c.hidden).css(_c.visible);
+            }
+        }
+        else if (autoHide && !$E.data('autoHidden'))
+            $E.hide().data('autoHidden', true);
+    }
+
+    /**
+    * @param {(string|!Object)}     el
+    * @param {number=}              outerSize
+    * @param {boolean=}             [autoHide=false]
+    */
+,   setOuterSize = function (el, outerSize, autoHide) {
+        if (_c[pane].dir=="horz") // pane = north or south
+            setOuterHeight(el, outerSize, autoHide);
+        else // pane = east or west
+            setOuterWidth(el, outerSize, autoHide);
+    }
+
+
+    /**
+    * Converts any 'size' params to a pixel/integer size, if not already
+    * If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated
+    *
+    /**
+    * @param  {string}              pane
+    * @param  {(string|number)=}    size
+    * @param  {string=}             [dir]
+    * @return {number}
+    */
+,   _parseSize = function (pane, size, dir) {
+        if (!dir) dir = _c[pane].dir;
+
+        if (isStr(size) && size.match(/%/))
+            size = (size === '100%') ? -1 : parseInt(size, 10) / 100; // convert % to decimal
+
+        if (size === 0)
+            return 0;
+        else if (size >= 1)
+            return parseInt(size, 10);
+
+        var o = options, avail = 0;
+        if (dir=="horz") // north or south or center.minHeight
+            avail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0);
+        else if (dir=="vert") // east or west or center.minWidth
+            avail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0);
+
+        if (size === -1) // -1 == 100%
+            return avail;
+        else if (size > 0) // percentage, eg: .25
+            return round(avail * size);
+        else if (pane=="center")
+            return 0;
+        else { // size < 0 || size=='auto' || size==Missing || size==Invalid
+            // auto-size the pane
+            var
+                $P  = $Ps[pane]
+            ,   dim = (dir === "horz" ? "height" : "width")
+            ,   vis = $.layout.showInvisibly($P) // show pane invisibly if hidden
+            ,   s   = $P.css(dim); // SAVE current size
+            ;
+            $P.css(dim, "auto");
+            size = (dim === "height") ? $P.outerHeight() : $P.outerWidth(); // MEASURE
+            $P.css(dim, s).css(vis); // RESET size & visibility
+            return size;
+        }
+    }
+
+    /**
+    * Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added
+    *
+    * @param  {(string|!Object)}    pane
+    * @param  {boolean=}            [inclSpace=false]
+    * @return {number}              Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
+    */
+,   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;
+    }
+
+    /**
+    * Calculate min/max pane dimensions and limits for resizing
+    *
+    * @param  {string}      pane
+    * @param  {boolean=}    [slide=false]
+    */
+,   setSizeLimits = function (pane, slide) {
+        if (!isInitialized()) return;
+        var 
+            o               = options[pane]
+        ,   s               = state[pane]
+        ,   c               = _c[pane]
+        ,   dir             = c.dir
+        ,   side            = c.side.toLowerCase()
+        ,   type            = c.sizeType.toLowerCase()
+        ,   isSliding       = (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param
+        ,   $P              = $Ps[pane]
+        ,   paneSpacing     = o.spacing_open
+        //  measure the pane on the *opposite side* from this pane
+        ,   altPane         = _c.oppositeEdge[pane]
+        ,   altS            = state[altPane]
+        ,   $altP           = $Ps[altPane]
+        ,   altPaneSize     = (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir=="horz" ? $altP.outerHeight() : $altP.outerWidth()))
+        ,   altPaneSpacing  = ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? "spacing_closed" : "spacing_open" ]) || 0)
+        //  limitSize prevents this pane from 'overlapping' opposite pane
+        ,   containerSize   = (dir=="horz" ? sC.innerHeight : sC.innerWidth)
+        ,   minCenterDims   = cssMinDims("center")
+        ,   minCenterSize   = dir=="horz" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth)
+        //  if pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them
+        ,   limitSize       = (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize("center", minCenterSize, dir) + altPaneSize + altPaneSpacing)))
+        ,   minSize         = s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize )
+        ,   maxSize         = s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize )
+        ,   r               = s.resizerPosition = {} // used to set resizing limits
+        ,   top             = sC.insetTop
+        ,   left            = sC.insetLeft
+        ,   W               = sC.innerWidth
+        ,   H               = sC.innerHeight
+        ,   rW              = o.spacing_open // subtract resizer-width to get top/left position for south/east
+        ;
+        switch (pane) {
+            case "north":   r.min = top + minSize;
+                            r.max = top + maxSize;
+                            break;
+            case "west":    r.min = left + minSize;
+                            r.max = left + maxSize;
+                            break;
+            case "south":   r.min = top + H - maxSize - rW;
+                            r.max = top + H - minSize - rW;
+                            break;
+            case "east":    r.min = left + W - maxSize - rW;
+                            r.max = left + W - minSize - rW;
+                            break;
+        };
+    }
+
+    /**
+    * Returns data for setting the size/position of center pane. Also used to set Height for east/west panes
+    *
+    * @return JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
+    */
+,   calcNewCenterPaneDims = function () {
+        var d = {
+            top:    getPaneSize("north", true) // true = include 'spacing' value for pane
+        ,   bottom: getPaneSize("south", true)
+        ,   left:   getPaneSize("west", true)
+        ,   right:  getPaneSize("east", true)
+        ,   width:  0
+        ,   height: 0
+        };
+
+        // NOTE: sC = state.container
+        // calc center-pane outer dimensions
+        d.width     = sC.innerWidth - d.left - d.right;  // outerWidth
+        d.height    = sC.innerHeight - d.bottom - d.top; // outerHeight
+        // add the 'container border/padding' to get final positions relative to the container
+        d.top       += sC.insetTop;
+        d.bottom    += sC.insetBottom;
+        d.left      += sC.insetLeft;
+        d.right     += sC.insetRight;
+
+        return d;
+    }
+
+
+    /**
+    * @param {!Object}      el
+    * @param {boolean=}     [allStates=false]
+    */
+,   getHoverClasses = function (el, allStates) {
+        var
+            $El     = $(el)
+        ,   type    = $El.data("layoutRole")
+        ,   pane    = $El.data("layoutEdge")
+        ,   o       = options[pane]
+        ,   root    = o[type +"Class"]
+        ,   _pane   = "-"+ pane // eg: "-west"
+        ,   _open   = "-open"
+        ,   _closed = "-closed"
+        ,   _slide  = "-sliding"
+        ,   _hover  = "-hover " // NOTE the trailing space
+        ,   _state  = $El.hasClass(root+_closed) ? _closed : _open
+        ,   _alt    = _state === _closed ? _open : _closed
+        ,   classes = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover)
+        ;
+        if (allStates) // when 'removing' classes, also remove alternate-state classes
+            classes += (root+_alt+_hover) + (root+_pane+_alt+_hover);
+
+        if (type=="resizer" && $El.hasClass(root+_slide))
+            classes += (root+_slide+_hover) + (root+_pane+_slide+_hover);
+
+        return $.trim(classes);
+    }
+,   addHover    = function (evt, el) {
+        var $E = $(el || this);
+        if (evt && $E.data("layoutRole") === "toggler")
+            evt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar
+        $E.addClass( getHoverClasses($E) );
+    }
+,   removeHover = function (evt, el) {
+        var $E = $(el || this);
+        $E.removeClass( getHoverClasses($E, true) );
+    }
+
+,   onResizerEnter  = function (evt) { // ALSO called by toggler.mouseenter
+        if ($.fn.disableSelection)
+            $("body").disableSelection();
+    }
+,   onResizerLeave  = function (evt, el) {
+        var
+            e = el || this // el is only passed when called by the timer
+        ,   pane = $(e).data("layoutEdge")
+        ,   name = pane +"ResizerLeave"
+        ;
+        timer.clear(pane+"_openSlider"); // cancel slideOpen timer, if set
+        timer.clear(name); // cancel enableSelection timer - may re/set below
+        // this method calls itself on a timer because it needs to allow
+        // enough time for dragging to kick-in and set the isResizing flag
+        // dragging has a 100ms delay set, so this delay must be >100
+        if (!el) // 1st call - mouseleave event
+            timer.set(name, function(){ onResizerLeave(evt, e); }, 200);
+        // if user is resizing, then dragStop will enableSelection(), so can skip it here
+        else if (!state[pane].isResizing && $.fn.enableSelection) // 2nd call - by timer
+            $("body").enableSelection();
+    }
+
+/*
+ * ###########################
+ *   INITIALIZATION METHODS
+ * ###########################
+ */
+
+    /**
+    * Initialize the layout - called automatically whenever an instance of layout is created
+    *
+    * @see  none - triggered onInit
+    * @return  mixed    true = fully initialized | false = panes not initialized (yet) | 'cancel' = abort
+    */
+,   _create = function () {
+        // initialize config/options
+        initOptions();
+        var o = options;
+
+        // TEMP state so isInitialized returns true during init process
+        state.creatingLayout = true;
+
+        // init plugins for this layout, if there are any (eg: stateManagement)
+        runPluginCallbacks( Instance, $.layout.onCreate );
+
+        // options & state have been initialized, so now run beforeLoad callback
+        // onload will CANCEL layout creation if it returns false
+        if (false === _execCallback(null, o.onload_start))
+            return 'cancel';
+
+        // initialize the container element
+        _initContainer();
+
+        // bind hotkey function - keyDown - if required
+        initHotkeys();
+
+        // bind window.onunload
+        $(window).bind("unload."+ sID, unload);
+
+        // init plugins for this layout, if there are any (eg: customButtons)
+        runPluginCallbacks( Instance, $.layout.onLoad );
+
+        // if this layout's container is another layout's pane, then set child/parent pointers
+        var parent = $N.data("parentLayout");
+        if (parent) {
+            Instance.hasParentLayout = true;
+            var pane = $N.data("layoutEdge"); // container's pane-name in parent-layout
+            // set pointers to THIS child-layout in parent-layout
+            // NOTE: parent.PANE.child is an ALIAS to parent.children.PANE
+            parent[pane].child = parent.children[pane] = Instance;
+        }
+
+        // if layout elements are hidden, then layout WILL NOT complete initialization!
+        // initLayoutElements will set initialized=true and run the onload callback IF successful
+        if (o.initPanes) _initLayoutElements();
+
+        delete state.creatingLayout;
+
+        return state.initialized;
+    }
+
+    /**
+    * Initialize the layout IF not already
+    *
+    * @see  All methods in Instance run this test
+    * @return  boolean  true = layoutElements have been initialized | false = panes are not initialized (yet)
+    */
+,   isInitialized = function () {
+        if (state.initialized || state.creatingLayout) return true; // already initialized
+        else return _initLayoutElements();  // try to init panes NOW
+    }
+
+    /**
+    * Initialize the layout - called automatically whenever an instance of layout is created
+    *
+    * @see  _create() & isInitialized
+    * @return  An object pointer to the instance created
+    */
+,   _initLayoutElements = function (retry) {
+        // initialize config/options
+        var o = options;
+
+        // CANNOT init panes inside a hidden container!
+        if (!$N.is(":visible")) {
+            // handle Chrome bug where popup window 'has no height'
+            // if layout is BODY element, try again in 50ms
+            // SEE: http://layout.jquery-dev.net/samples/test_popup_window.html
+            if ( !retry && browser.webkit && $N[0].tagName === "BODY" )
+                setTimeout(function(){ _initLayoutElements(true); }, 50);
+            return false;
+        }
+
+        // a center pane is required, so make sure it exists
+        if (!getPane("center").length) {
+            _log( lang.errCenterPaneMissing, true );
+            return false;
+        }
+
+        // TEMP state so isInitialized returns true during init process
+        state.creatingLayout = true;
+
+        // update Container dims
+        $.extend(sC, elDims( $N ));
+
+        // check to see if this layout 'nested' inside a pane
+        if ($N.data("layoutRole") === "pane")
+            o.resizeWithWindow = false;
+
+        // initialize all layout elements
+        initPanes();    // size & position panes - calls initHandles() - which calls initResizable()
+
+        if (o.scrollToBookmarkOnLoad) {
+            var l = self.location;
+            if (l.hash) l.replace( l.hash ); // scrollTo Bookmark
+        }
+
+        // bind resizeAll() for 'this layout instance' to window.resize event
+        if (o.resizeWithWindow)
+            $(window).bind("resize."+ sID, windowResize);
+
+        delete state.creatingLayout;
+        state.initialized = true;
+
+        // init plugins for this layout, if there are any
+        runPluginCallbacks( Instance, $.layout.onReady );
+
+        // now run the onload callback, if exists
+        _execCallback(null, o.onload_end || o.onload);
+
+        return true; // elements initialized successfully
+    }
+
+    /**
+    * Initialize nested layouts - called when _initLayoutElements completes
+    *
+    * NOT CURRENTLY USED
+    *
+    * @see _initLayoutElements
+    * @return  An object pointer to the instance created
+    */
+,   _initChildLayouts = function () {
+        $.each(_c.allPanes, function (idx, pane) {
+            if (options[pane].initChildLayout)
+                createChildLayout( pane );
+        });
+    }
+
+    /**
+    * Initialize nested layouts for a specific pane - can optionally pass layout-options
+    *
+    * @see _initChildLayouts
+    * @param {string}   pane        The pane being opened, ie: north, south, east, or west
+    * @param {Object=}  [opts]      Layout-options - if passed, will OVERRRIDE options[pane].childOptions
+    * @return  An object pointer to the layout instance created - or null
+    */
+,   createChildLayout = function (pane, opts) {
+        var $P  = $Ps[pane]
+        ,   o   = opts || options[pane].childOptions
+        ,   C   = children
+        ,   d   = "layout"
+        //  see if a child-layout ALREADY exists on this element
+        ,   L   = $P ? (C[pane] = $P.data(d) || null) : false
+        ;
+        // if no layout exists, but childOptions are set, try to create the layout now
+        if (!L && $P && o)
+            L = C[pane] = $P.layout(o) || null;
+        if (L)
+            L.hasParentLayout = true;   // set parent-flag in child - DO NOT set pointer or else have infinite recursion!
+        Instance[pane].child = C[pane]; // set pane-object pointer, even if null
+    }
+
+,   windowResize = function () {
+        var delay = Number(options.resizeWithWindowDelay);
+        if (delay < 10) delay = 100; // MUST have a delay!
+        // resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway
+        timer.clear("winResize"); // if already running
+        timer.set("winResize", function(){
+            timer.clear("winResize");
+            timer.clear("winResizeRepeater");
+            var dims = elDims( $N );
+            // only trigger resizeAll() if container has changed size
+            if (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight)
+                resizeAll();
+        }, delay);
+        // ALSO set fixed-delay timer, if not already running
+        if (!timer.data["winResizeRepeater"]) setWindowResizeRepeater();
+    }
+
+,   setWindowResizeRepeater = function () {
+        var delay = Number(options.resizeWithWindowMaxDelay);
+        if (delay > 0)
+            timer.set("winResizeRepeater", function(){ setWindowResizeRepeater(); resizeAll(); }, delay);
+    }
+
+,   unload = function () {
+        var o = options;
+
+        _execCallback(null, o.onunload_start);
+
+        // trigger plugin callabacks for this layout (eg: stateManagement)
+        runPluginCallbacks( Instance, $.layout.onUnload );
+
+        _execCallback(null, o.onunload_end || o.onunload);
+    }
+
+    /**
+    * Validate and initialize container CSS and events
+    *
+    * @see  _create()
+    */
+,   _initContainer = function () {
+        var
+            N       = $N[0]
+        ,   tag     = sC.tagName = N.tagName
+        ,   id      = sC.id = N.id
+        ,   cls     = sC.className = N.className
+        ,   o       = options
+        ,   name    = o.name
+        ,   fullPage= (tag === "BODY")
+        ,   props   = "overflow,position,margin,padding,border"
+        ,   CSS     = {}
+        ,   hid     = "hidden" // used A LOT!
+        ;
+        // sC -> state.container
+        sC.selector = $N.selector.split(".slice")[0];
+        sC.ref      = (o.name ? o.name +' layout / ' : '') + tag + (id ? "#"+id : cls ? '.['+cls+']' : ''); // used in messages
+
+        $N  .data("layout", Instance)
+            .data("layoutContainer", sID)   // unique identifier for internal use
+            .addClass(o.containerClass)
+        ;
+
+        // SAVE original container CSS for use in destroy()
+        var css = "layoutCSS";
+        if (!$N.data(css)) {
+            // handle props like overflow different for BODY & HTML - has 'system default' values
+            if (fullPage) {
+                CSS = $.extend( elCSS($N, props), {
+                    height:     $N.css("height")
+                ,   overflow:   $N.css("overflow")
+                ,   overflowX:  $N.css("overflowX")
+                ,   overflowY:  $N.css("overflowY")
+                });
+                // ALSO SAVE <HTML> CSS
+                var $H = $("html");
+                $H.data(css, {
+                    height:     "auto" // FF would return a fixed px-size!
+                ,   overflow:   $H.css("overflow")
+                ,   overflowX:  $H.css("overflowX")
+                ,   overflowY:  $H.css("overflowY")
+                });
+            }
+            else // handle props normally for non-body elements
+                CSS = elCSS($N, props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY");
+
+            $N.data(css, CSS);
+        }
+
+        try { // format html/body if this is a full page layout
+            if (fullPage) {
+                $("html").css({
+                    height:     "100%"
+                ,   overflow:   hid
+                ,   overflowX:  hid
+                ,   overflowY:  hid
+                });
+                $("body").css({
+                    position:   "relative"
+                ,   height:     "100%"
+                ,   overflow:   hid
+                ,   overflowX:  hid
+                ,   overflowY:  hid
+                ,   margin:     0
+                ,   padding:    0       // TODO: test whether body-padding could be handled?
+                ,   border:     "none"  // a body-border creates problems because it cannot be measured!
+                });
+
+                // set current layout-container dimensions
+                $.extend(sC, elDims( $N ));
+            }
+            else { // set required CSS for overflow and position
+                // ENSURE container will not 'scroll'
+                CSS = { overflow: hid, overflowX: hid, overflowY: hid }
+                var
+                    p = $N.css("position")
+                ,   h = $N.css("height")
+                ;
+                // if this is a NESTED layout, then container/outer-pane ALREADY has position and height
+                if (!$N.data("layoutRole")) {
+                    if (!p || !p.match(/fixed|absolute|relative/))
+                        CSS.position = "relative"; // container MUST have a 'position'
+                    /*
+                    if (!h || h=="auto")
+                        CSS.height = "100%"; // container MUST have a 'height'
+                    */
+                }
+                $N.css( CSS );
+
+                // set current layout-container dimensions
+                if ( $N.is(":visible") ) {
+                    $.extend(sC, elDims( $N ));
+                    if (o.showErrorMessages && sC.innerHeight < 1)
+                        _log( lang.errContainerHeight.replace(/CONTAINER/, sC.ref), true );
+                }
+            }
+        } catch (ex) {}
+    }
+
+    /**
+    * Bind layout hotkeys - if options enabled
+    *
+    * @see  _create() and addPane()
+    * @param {string=}  [panes=""]  The edge(s) to process
+    */
+,   initHotkeys = function (panes) {
+        panes = panes ? panes.split(",") : _c.borderPanes;
+        // bind keyDown to capture hotkeys, if option enabled for ANY pane
+        $.each(panes, function (i, pane) {
+            var o = options[pane];
+            if (o.enableCursorHotkey || o.customHotkey) {
+                $(document).bind("keydown."+ sID, keyDown); // only need to bind this ONCE
+                return false; // BREAK - binding was done
+            }
+        });
+    }
+
+    /**
+    * Build final OPTIONS data
+    *
+    * @see  _create()
+    */
+,   initOptions = function () {
+        var data, d, pane, key, val, i, c, o;
+
+        // reprocess user's layout-options to have correct options sub-key structure
+        opts = $.layout.transformData( opts ); // panes = default subkey
+
+        // auto-rename old options for backward compatibility
+        opts = $.layout.backwardCompatibility.renameAllOptions( opts );
+
+        // if user-options has 'panes' key (pane-defaults), process it...
+        if (!$.isEmptyObject(opts.panes)) {
+            // REMOVE any pane-defaults that MUST be set per-pane
+            data = $.layout.optionsMap.noDefault;
+            for (i=0, c=data.length; i<c; i++) {
+                key = data[i];
+                delete opts.panes[key]; // OK if does not exist
+            }
+            // REMOVE any layout-options specified under opts.panes
+            data = $.layout.optionsMap.layout;
+            for (i=0, c=data.length; i<c; i++) {
+                key = data[i];
+                delete opts.panes[key]; // OK if does not exist
+            }
+        }
+
+        // MOVE any NON-layout-options to opts.panes
+        data = $.layout.optionsMap.layout;
+        var rootKeys = $.layout.config.optionRootKeys;
+        for (key in opts) {
+            val = opts[key];
+            if ($.inArray(key, rootKeys) < 0 && $.inArray(key, data) < 0) {
+                if (!opts.panes[key])
+                    opts.panes[key] = $.isPlainObject(val) ? $.extend(true, {}, val) : val;
+                delete opts[key]
+            }
+        }
+
+        // START by updating ALL options from opts
+        $.extend(true, options, opts);
+
+        // CREATE final options (and config) for EACH pane
+        $.each(_c.allPanes, function (i, pane) {
+
+            // apply 'pane-defaults' to CONFIG.[PANE]
+            _c[pane] = $.extend( true, {}, _c.panes, _c[pane] );
+
+            d = options.panes;
+            o = options[pane];
+
+            // center-pane uses SOME keys in defaults.panes branch
+            if (pane === 'center') {
+                // ONLY copy keys from opts.panes listed in: $.layout.optionsMap.center
+                data = $.layout.optionsMap.center;      // list of 'center-pane keys'
+                for (i=0, c=data.length; i<c; i++) {    // loop the list...
+                    key = data[i];
+                    // only need to use pane-default if pane-specific value not set
+                    if (!opts.center[key] && (opts.panes[key] || !o[key]))
+                        o[key] = d[key]; // pane-default
+                }
+            }
+            else {
+                // border-panes use ALL keys in defaults.panes branch
+                o = options[pane] = $.extend({}, d, o); // re-apply pane-specific opts AFTER pane-defaults
+                createFxOptions( pane );
+                // ensure all border-pane-specific base-classes exist
+                if (!o.resizerClass)    o.resizerClass  = "ui-layout-resizer";
+                if (!o.togglerClass)    o.togglerClass  = "ui-layout-toggler";
+            }
+            // ensure we have base pane-class (ALL panes)
+            if (!o.paneClass) o.paneClass = "ui-layout-pane";
+        });
+
+        // update options.zIndexes if a zIndex-option specified
+        var zo  = opts.zIndex
+        ,   z   = options.zIndexes;
+        if (zo > 0) {
+            z.pane_normal       = zo;
+            z.content_mask      = max(zo+1, z.content_mask);    // MIN = +1
+            z.resizer_normal    = max(zo+2, z.resizer_normal);  // MIN = +2
+        }
+
+        function createFxOptions ( pane ) {
+            var o = options[pane]
+            ,   d = options.panes;
+            // ensure fxSettings key to avoid errors
+            if (!o.fxSettings) o.fxSettings = {};
+            if (!d.fxSettings) d.fxSettings = {};
+
+            $.each(["_open","_close","_size"], function (i,n) { 
+                var
+                    sName       = "fxName"+ n
+                ,   sSpeed      = "fxSpeed"+ n
+                ,   sSettings   = "fxSettings"+ n
+                    // recalculate fxName according to specificity rules
+                ,   fxName = o[sName] =
+                        o[sName]    // options.west.fxName_open
+                    ||  d[sName]    // options.panes.fxName_open
+                    ||  o.fxName    // options.west.fxName
+                    ||  d.fxName    // options.panes.fxName
+                    ||  "none"      // MEANS $.layout.defaults.panes.fxName == "" || false || null || 0
+                ;
+                // validate fxName to ensure is valid effect - MUST have effect-config data in options.effects
+                if (fxName === "none" || !$.effects || !$.effects[fxName] || !options.effects[fxName])
+                    fxName = o[sName] = "none"; // effect not loaded OR unrecognized fxName
+
+                // set vars for effects subkeys to simplify logic
+                var fx      = options.effects[fxName] || {} // effects.slide
+                ,   fx_all  = fx.all    || null             // effects.slide.all
+                ,   fx_pane = fx[pane]  || null             // effects.slide.west
+                ;
+                // create fxSpeed[_open|_close|_size]
+                o[sSpeed] =
+                    o[sSpeed]               // options.west.fxSpeed_open
+                ||  d[sSpeed]               // options.west.fxSpeed_open
+                ||  o.fxSpeed               // options.west.fxSpeed
+                ||  d.fxSpeed               // options.panes.fxSpeed
+                ||  null                    // DEFAULT - let fxSetting.duration control speed
+                ;
+                // create fxSettings[_open|_close|_size]
+                o[sSettings] = $.extend(
+                    {}
+                ,   fx_all                  // effects.slide.all
+                ,   fx_pane                 // effects.slide.west
+                ,   d.fxSettings            // options.panes.fxSettings
+                ,   o.fxSettings            // options.west.fxSettings
+                ,   d[sSettings]            // options.panes.fxSettings_open
+                ,   o[sSettings]            // options.west.fxSettings_open
+                );
+            });
+
+            // DONE creating action-specific-settings for this pane,
+            // so DELETE generic options - are no longer meaningful
+            delete o.fxName;
+            delete o.fxSpeed;
+            delete o.fxSettings;
+        }
+
+        // DELETE 'panes' key now that we are done - values were copied to EACH pane
+        delete options.panes;
+    }
+
+    /**
+    * Initialize module objects, styling, size and position for all panes
+    *
+    * @see  _initElements()
+    * @param {string}   pane        The pane to process
+    */
+,   getPane = function (pane) {
+        var sel = options[pane].paneSelector
+        if (sel.substr(0,1)==="#") // ID selector
+            // NOTE: elements selected 'by ID' DO NOT have to be 'children'
+            return $N.find(sel).eq(0);
+        else { // class or other selector
+            var $P = $N.children(sel).eq(0);
+            // look for the pane nested inside a 'form' element
+            return $P.length ? $P : $N.children("form:first").children(sel).eq(0);
+        }
+    }
+
+,   initPanes = function () {
+        // NOTE: do north & south FIRST so we can measure their height - do center LAST
+        $.each(_c.allPanes, function (idx, pane) {
+            addPane( pane, true );
+        });
+
+        // init the pane-handles NOW in case we have to hide or close the pane below
+        initHandles();
+
+        // now that all panes have been initialized and initially-sized,
+        // make sure there is really enough space available for each pane
+        $.each(_c.borderPanes, function (i, pane) {
+            if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN
+                setSizeLimits(pane);
+                makePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit()
+            }
+        });
+        // size center-pane AGAIN in case we 'closed' a border-pane in loop above
+        sizeMidPanes("center");
+
+        //  Chrome/Webkit sometimes fires callbacks BEFORE it completes resizing!
+        //  Before RC30.3, there was a 10ms delay here, but that caused layout 
+        //  to load asynchrously, which is BAD, so try skipping delay for now
+
+        // process pane contents and callbacks, and init/resize child-layout if exists
+        $.each(_c.allPanes, function (i, pane) {
+            var o = options[pane];
+            if ($Ps[pane]) {
+                if (state[pane].isVisible) { // pane is OPEN
+                    sizeContent(pane);
+                    // trigger pane.onResize if triggerEventsOnLoad = true
+                    if (o.triggerEventsOnLoad)
+                        _execCallback(pane, o.onresize_end || o.onresize);
+                    // resize child - IF inner-layout already exists (created before this layout)
+                    resizeChildLayout(pane);
+                }
+                // init childLayout - even if pane is not visible
+                if (o.initChildLayout && o.childOptions)
+                    createChildLayout(pane);
+            }
+        });
+    }
+
+    /**
+    * Add a pane to the layout - subroutine of initPanes()
+    *
+    * @see  initPanes()
+    * @param {string}   pane            The pane to process
+    * @param {boolean=} [force=false]   Size content after init
+    */
+,   addPane = function (pane, force) {
+        if (!force && !isInitialized()) return;
+        var
+            o       = options[pane]
+        ,   s       = state[pane]
+        ,   c       = _c[pane]
+        ,   fx      = s.fx
+        ,   dir     = c.dir
+        ,   spacing = o.spacing_open || 0
+        ,   isCenter = (pane === "center")
+        ,   CSS     = {}
+        ,   $P      = $Ps[pane]
+        ,   size, minSize, maxSize
+        ;
+
+        // if pane-pointer already exists, remove the old one first
+        if ($P)
+            removePane( pane, false, true, false );
+        else
+            $Cs[pane] = false; // init
+
+        $P = $Ps[pane] = getPane(pane);
+        if (!$P.length) {
+            $Ps[pane] = false; // logic
+            return;
+        }
+
+        // SAVE original Pane CSS
+        if (!$P.data("layoutCSS")) {
+            var props = "position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border";
+            $P.data("layoutCSS", elCSS($P, props));
+        }
+
+        // add classes, attributes & events
+        $P  .data("parentLayout", Instance)
+            .data("layoutRole", "pane")
+            .data("layoutEdge", pane)
+            .css(c.cssReq).css("zIndex", options.zIndexes.pane_normal)
+            .css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles
+            .addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
+            .bind("mouseenter."+ sID, addHover )
+            .bind("mouseleave."+ sID, removeHover );
+
+        // create alias for pane data in Instance - initHandles will add more
+        Instance[pane] = { name: pane, pane: $Ps[pane], options: options[pane], state: state[pane], child: children[pane] };
+
+        // see if this pane has a 'scrolling-content element'
+        initContent(pane, false); // false = do NOT sizeContent() - called later
+
+        if (!isCenter) {
+            // call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden)
+            // if o.size is auto or not valid, then MEASURE the pane and use that as its 'size'
+            size    = s.size = _parseSize(pane, o.size);
+            minSize = _parseSize(pane,o.minSize) || 1;
+            maxSize = _parseSize(pane,o.maxSize) || 100000;
+            if (size > 0) size = max(min(size, maxSize), minSize);
+
+            // state for border-panes
+            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!
+
+            // array for 'pin buttons' whose classNames are auto-updated on pane-open/-close
+            if (!s.pins) s.pins = [];
+        }
+        //  states common to ALL panes
+        s.tagName   = $P[0].tagName;
+        s.edge      = pane;     // useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going)
+        s.noRoom    = false;    // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
+        s.isVisible = true;     // false = pane is invisible - closed OR hidden - simplify logic
+
+        // set css-position to account for container borders & padding
+        switch (pane) {
+            case "north":   CSS.top     = sC.insetTop;
+                            CSS.left    = sC.insetLeft;
+                            CSS.right   = sC.insetRight;
+                            break;
+            case "south":   CSS.bottom  = sC.insetBottom;
+                            CSS.left    = sC.insetLeft;
+                            CSS.right   = sC.insetRight;
+                            break;
+            case "west":    CSS.left    = sC.insetLeft; // top, bottom & height set by sizeMidPanes()
+                            break;
+            case "east":    CSS.right   = sC.insetRight; // ditto
+                            break;
+            case "center":  // top, left, width & height set by sizeMidPanes()
+        }
+
+        if (dir === "horz") // north or south pane
+            CSS.height = cssH($P, size);
+        else if (dir === "vert") // east or west pane
+            CSS.width = cssW($P, size);
+        //else if (isCenter) {}
+
+        $P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes
+        if (dir != "horz") sizeMidPanes(pane, true); // true = skipCallback
+
+        // close or hide the pane if specified in settings
+        if (o.initClosed && o.closable && !o.initHidden)
+            close(pane, true, true); // true, true = force, noAnimation
+        else if (o.initHidden || o.initClosed)
+            hide(pane); // will be completely invisible - no resizer or spacing
+        else if (!s.noRoom)
+            // make the pane visible - in case was initially hidden
+            $P.css("display","block");
+        // ELSE setAsOpen() - called later by initHandles()
+
+        // RESET visibility now - pane will appear IF display:block
+        $P.css("visibility","visible");
+
+        // check option for auto-handling of pop-ups & drop-downs
+        if (o.showOverflowOnHover)
+            $P.hover( allowOverflow, resetOverflow );
+
+        // if adding a pane AFTER initialization, then...
+        if (state.initialized) {
+            initHandles( pane );
+            initHotkeys( pane );
+            resizeAll(); // will sizeContent if pane is visible
+            if (s.isVisible) { // pane is OPEN
+                if (o.triggerEventsOnLoad)
+                    _execCallback(pane, o.onresize_end || o.onresize); 
+                resizeChildLayout(pane);
+            }
+            if (o.initChildLayout && o.childOptions)
+                createChildLayout(pane);
+        }
+    }
+
+    /**
+    * Initialize module objects, styling, size and position for all resize bars and toggler buttons
+    *
+    * @see  _create()
+    * @param {string=}  [panes=""]  The edge(s) to process
+    */
+,   initHandles = function (panes) {
+        panes = panes ? panes.split(",") : _c.borderPanes;
+
+        // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
+        $.each(panes, function (i, pane) {
+            var $P      = $Ps[pane];
+            $Rs[pane]   = false; // INIT
+            $Ts[pane]   = false;
+            if (!$P) return; // pane does not exist - skip
+
+            var 
+                o       = options[pane]
+            ,   s       = state[pane]
+            ,   c       = _c[pane]
+            ,   rClass  = o.resizerClass
+            ,   tClass  = o.togglerClass
+            ,   side    = c.side.toLowerCase()
+            ,   spacing = (s.isVisible ? o.spacing_open : o.spacing_closed)

[... 3189 lines stripped ...]