diff --git a/.gitignore b/.gitignore
index e39040f5b4a..0e42e62deba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ docs
*.diff
*.patch
.DS_Store
+.idea
diff --git a/demos/index.html b/demos/index.html
index e1f4eec9132..5755de3d8bb 100644
--- a/demos/index.html
+++ b/demos/index.html
@@ -29,6 +29,7 @@
+
@@ -283,6 +284,7 @@
Spinner
Tabs
Tooltip
+ Layout
Effects
Color Animation
Toggle Class
diff --git a/demos/layout/horizontal.html b/demos/layout/horizontal.html
new file mode 100755
index 00000000000..eccf11011e8
--- /dev/null
+++ b/demos/layout/horizontal.html
@@ -0,0 +1,40 @@
+
+
+
+ Horizontal layout
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/layout/index.html b/demos/layout/index.html
new file mode 100644
index 00000000000..ffea26c5659
--- /dev/null
+++ b/demos/layout/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+ jQuery UI Accordion Demos
+
+
+
+
+
+
diff --git a/demos/layout/nested.html b/demos/layout/nested.html
new file mode 100755
index 00000000000..70a7071e4ad
--- /dev/null
+++ b/demos/layout/nested.html
@@ -0,0 +1,82 @@
+
+
+ Nested layout Example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/layout/vertical.html b/demos/layout/vertical.html
new file mode 100755
index 00000000000..1d9e792b9fa
--- /dev/null
+++ b/demos/layout/vertical.html
@@ -0,0 +1,47 @@
+
+
+ Vertical layout Example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/themes/base/jquery.ui.base.css b/themes/base/jquery.ui.base.css
index 9a18856c16a..643353dd2fa 100644
--- a/themes/base/jquery.ui.base.css
+++ b/themes/base/jquery.ui.base.css
@@ -22,3 +22,4 @@
@import url("jquery.ui.spinner.css");
@import url("jquery.ui.tabs.css");
@import url("jquery.ui.tooltip.css");
+@import url("jquery.ui.layout.css");
diff --git a/themes/base/jquery.ui.layout.css b/themes/base/jquery.ui.layout.css
new file mode 100644
index 00000000000..6d4958d8740
--- /dev/null
+++ b/themes/base/jquery.ui.layout.css
@@ -0,0 +1,154 @@
+.ui-layout{
+ position: relative;
+ overflow: hidden;
+ border: none;
+}
+.ui-layout.ui-layout-pane{
+ border: none;
+}
+.ui-layout-pane{
+ position: absolute;
+}
+.ui-layout-pane-east{
+ margin-left:16px;
+ right: 0;
+ top:0;
+}
+.ui-layout-pane-west{
+ margin-right:16px;
+ left: 0;
+ top:0;
+}
+.ui-layout-pane-east.ui-layout-pane-sliding.ui-layout-pane-open{
+ padding-left: 16px;
+}
+
+.ui-layout-pane-west.ui-layout-pane-sliding.ui-layout-pane-open{
+ padding-right: 16px;
+}
+
+.ui-layout .ui-layout-pane.ui-layout-pane-close{
+ border: none;
+}
+
+
+.ui-layout-pane.ui-layout-pane-close.ui-layout-pane-hiding > .ui-resizable-handle .ui-icon{
+ background: none;
+ width: 0;
+ height:0;
+ left:0;
+}
+
+.ui-layout-pane-west.ui-layout-pane-close.ui-layout-pane-hiding > .ui-resizable-e {
+ right: -5px;
+ width: 5px;
+}
+.ui-layout-pane-east.ui-layout-pane-close.ui-layout-pane-hiding > .ui-resizable-w {
+ left: -5px;
+ width: 5px;
+}
+.ui-layout-pane-south.ui-layout-pane-close.ui-layout-pane-hiding > .ui-resizable-n {
+ top: -5px;
+ width: 5px;
+}
+.ui-layout-pane-north.ui-layout-pane-close.ui-layout-pane-hiding > .ui-resizable-s {
+ bottom: -5px;
+ width: 5px;
+}
+
+
+.ui-layout-pane-west.ui-layout-pane-sliding.ui-layout-pane-hiding,
+.ui-layout-pane-west.ui-layout-pane-close.ui-layout-pane-hiding{
+ margin-right: 0;
+}
+.ui-layout-pane-east.ui-layout-pane-sliding.ui-layout-pane-hiding,
+.ui-layout-pane-east.ui-layout-pane-close.ui-layout-pane-hiding{
+ margin-left: 0;
+}
+.ui-layout-pane-north.ui-layout-pane-sliding.ui-layout-pane-hiding,
+.ui-layout-pane-north.ui-layout-pane-close.ui-layout-pane-hiding{
+ margin-bottom: 0;
+}
+.ui-layout-pane-south.ui-layout-pane-sliding.ui-layout-pane-hiding,
+.ui-layout-pane-south.ui-layout-pane-close.ui-layout-pane-hiding{
+ margin-bottom: 0;
+}
+
+
+.ui-layout-pane-north{
+ margin-bottom:16px;
+ top: 0;
+ left: 0;
+}
+.ui-layout-pane-south{
+ margin-top:16px;
+ bottom: 0;
+ left: 0;
+}
+.ui-layout-pane-north.ui-layout-pane-sliding.ui-layout-pane-open{
+ padding-bottom: 16px;
+}
+.ui-layout-pane-south.ui-layout-pane-sliding.ui-layout-pane-open{
+ padding-top: 16px;
+}
+
+
+
+.ui-layout-pane .ui-resizable-handle{
+ position: absolute;
+ z-index: inherit;
+}
+.ui-resizable-w, .ui-resizable-e {
+ width: 16px;
+ height: 100%;
+ top: 0;
+}
+.ui-resizable-e{
+ right:-17px;
+}
+
+.ui-layout-pane-sliding.ui-layout-pane-open > .ui-resizable-e{
+ right:0;
+}
+
+.ui-layout-pane-sliding.ui-layout-pane-open > .ui-resizable-w{
+ left:0;
+}
+
+.ui-resizable-w{
+ left:-17px;
+}
+
+.ui-resizable-s, .ui-resizable-n {
+ height: 16px;
+ width: 100%;
+ left: 0;
+}
+.ui-resizable-n{
+ top:-17px;
+}
+
+.ui-resizable-s{
+ bottom:-17px;
+}
+
+.ui-layout-pane-sliding.ui-layout-pane-open > .ui-resizable-n{
+ top:0;
+}
+.ui-layout-pane-sliding.ui-layout-pane-open > .ui-resizable-s{
+ bottom:0;
+}
+
+
+.ui-resizable-handle .ui-icon{
+ position: absolute;
+}
+
+.ui-resizable-w .ui-icon, .ui-resizable-e .ui-icon{
+ top: 50%;
+ margin-top: -8px;
+}
+.ui-resizable-n .ui-icon, .ui-resizable-s .ui-icon{
+ left: 50%;
+ margin-left: -8px;
+}
\ No newline at end of file
diff --git a/ui/jquery.ui.layout.js b/ui/jquery.ui.layout.js
new file mode 100644
index 00000000000..561e8339f72
--- /dev/null
+++ b/ui/jquery.ui.layout.js
@@ -0,0 +1,449 @@
+;(function($){
+
+ var toCamelCase = function(string){
+ string = $.trim(string.toLowerCase()).replace(/\s\s/,' ')
+ var words = string.split(" ")
+ for(var i=1;i')
+ $mask
+ .css({
+ opacity: 0.0001,
+ background: 'white',
+ width: $pane.width(),
+ height: $pane.height(),
+ zIndex: $pane.zIndex() + 1,
+ position: 'absolute'
+ })
+ .appendTo($pane)
+ .position({at:'left top', my: 'left top', of: $pane})
+ }
+ });
+ $pane.bind('resize', function(e){
+ $('>div.iframe-mask', $pane)
+ .width($pane.width())
+ .height($pane.height())
+ .position({at:'left top', my: 'left top', of: $pane})
+ });
+ $pane.bind('resize resizestop', function(e){
+ // resize central pane if not sliding
+ if (!self.options[pane].sliding)
+ self.resize();
+ });
+
+ var preventToggling = false;
+
+ $pane.bind('resizestop', function(e,ui){
+
+ // remove conflicting attributes
+ self._removeInlineStyleAttr(pane);
+
+ // remove potential iframe mask
+ $pane.children('div.iframe-mask').remove();
+
+
+ // prevent the pane to toggle after a mouseup event, if the orginal size has significantly been changed
+ if (Math.abs(ui.size[self._sizeProp()] - ui.originalSize[self._sizeProp()]) > 3){
+ preventToggling = true;
+ setTimeout(function(){
+ preventToggling = false;
+ },100);
+ }
+ else{
+ return true;
+ }
+
+
+ // close the sidePane if not visible anymore, otherwise record its dimension
+ if (ui.size[self._sizeProp()] < self.options[pane][self._sizeProp('closing')]){
+ self.close(pane)
+ }
+ else {
+ self._opened(pane);
+ self.options[pane][self._sizeProp()] = ui.size[self._sizeProp()]
+ }
+
+ });
+
+ // toggle the pane if clicking on the handler
+ $pane.data('resizable')._handles
+ .append('')
+
+ $(self.options[pane].toggleSelector, $pane)
+ .bind(self.options[pane].toggleEvent, function(e){
+ if (!preventToggling)
+ self.toggle(pane);
+ })
+ }
+
+ self.panes[pane] = $pane ;
+
+
+ self._hiding(pane) ;
+
+ // set pane dimension
+ if(self.options[pane].sliding){
+ self._sliding(pane)
+ $pane[self._sizeProp()](0);
+ self._closed(pane);
+
+ }
+ else if (self.options[pane].opened){
+ self._open(pane, false);
+ $pane[self._sizeProp('outer')](self.options[pane][self._sizeProp()], true)
+ }
+
+ }
+ });
+
+ if (this.element.hasClass('ui-layout-pane')){
+ this.element.bind('resize',function(e){
+ if (e.target == self.element[0]){
+ self.resizeElement();
+ }
+ })
+ }
+ else {
+ $(window).bind('resize', function(e){
+ self.resizeElement();
+ })
+ }
+
+ this.resizeElement();
+
+ },
+
+ resizeElement: function(){
+ var self = this;
+
+ if (this.element[0].tagName == "BODY"){
+ self.element
+ .css({padding: '0', margin: '0'})
+ .outerWidth($(window).width(), true)
+ .outerHeight($(window).height(), true);
+ } else if(!self.element.hasClass('ui-layout-pane')) {
+ self.element
+ .outerHeight(self.element.parent().innerHeight(), true)
+ .outerWidth(self.element.parent().innerWidth(), true);
+ }
+
+ self._panes().each(function() {
+ if (self.options.type == 'horizontal')
+ $(this).outerHeight(self.element.innerHeight(), true)
+ else
+ $(this).outerWidth(self.element.innerWidth(), true)
+ });
+
+ // resize center pane
+ self.resize();
+
+ return this;
+ },
+ resize: function(){
+ var self = this,
+ $pane = this.panes['center'],
+ $prev = $pane.prev('.ui-layout-pane');
+
+ var sum = 0;
+ this.element.children(".ui-layout-pane").not('.ui-layout-pane-center').each(function(){
+ if ($(this).hasClass('ui-layout-pane-sliding')){
+ sum+= $(this)[self._sizeProp('outer')](true) - $(this)[self._sizeProp('inner')]()
+ }
+ else{
+ sum+= $(this)[self._sizeProp('outer')](true);
+ }
+ });
+
+ $pane[self._sizeProp('outer')](this.element[self._sizeProp('inner')]() - sum, true );
+
+ var offset = function(){
+ return self.options.type == 'horizontal' ? $prev.css('marginRight')+' 0' : '0 ' + $prev.css('marginBottom')
+ }
+
+ if ($prev.length && !$prev.hasClass('ui-layout-pane-sliding')){
+ $pane.position({
+ offset: offset(),
+ of: $prev,
+ my: 'left top',
+ at: this.options.type == 'horizontal' ? 'right top' : 'left bottom',
+ collision: "none"
+ })
+ }
+ else{
+ $pane.position({
+ offset: $prev.hasClass('ui-layout-pane-sliding') ? offset() : '0 0',
+ of: this.element,
+ my: 'left top',
+ at: 'left top',
+ collision: "none"
+ })
+ }
+
+ this._trigger('resize')
+ // emulate a resize event from the center pane
+ $pane.trigger('resize');
+
+ return this
+ },
+ _putForeground:function(pane){
+ var $pane = this.panes[pane],
+ depth = this.element.parents('.ui-layout').length
+ this.options[pane].zIndex = $pane.zIndex();
+ $pane.zIndex(this.element.zIndex() + 10 - depth)
+ },
+ _sliding: function(pane){
+ this.panes[pane][this.options[pane].sliding ? 'addClass' : 'removeClass']('ui-layout-pane-sliding');
+ if (this.options[pane].sliding)
+ this._putForeground(pane);
+ },
+ _hiding: function(pane){
+ this.panes[pane][this.options[pane].hiding ? 'addClass' : 'removeClass']('ui-layout-pane-hiding');
+ },
+ option: function( pane, key, value ) {
+ if ($.inArray(pane, ['center', 'north', 'south', 'east', 'west'])){
+ this.options[pane][key] = value;
+ switch(key){
+ case 'hiding':
+ this._hiding(pane);
+ this.resize();
+ break;
+ case 'sliding':
+ this._sliding(pane);
+ this.resize();
+ break;
+ }
+ }
+ else{
+ this._super('option', pane, key)
+ }
+ return this;
+ },
+
+ _ui:function(pane){
+ return {pane: this.panes[pane], paneName: pane, options: this.options}
+ },
+ _open: function(pane, trigg){
+ trigg = ("undefined" == typeof trigg ) ? true : trigg;
+ this.panes[pane].addClass('ui-layout-pane-open')
+ this.panes[pane].removeClass('ui-layout-pane-close')
+ this.options[pane].opened = true;
+ if (trigg)
+ this._trigger(pane+'open', null, this._ui(pane));
+ },
+ _opened: function(pane){
+ this._trigger(pane+'opened', null, this._ui(pane));
+ },
+ _close: function(pane){
+ this._trigger(pane+'close', null, this._ui(pane));
+ },
+ _closed: function(pane){
+ this.panes[pane].removeClass('ui-layout-pane-open')
+ this.panes[pane].addClass('ui-layout-pane-close')
+ this.options[pane].opened = false;
+ this._trigger(pane+'closed', null, this._ui(pane));
+ },
+
+
+ _panes: function(){
+ return this.element.children('.ui-layout-pane')
+ },
+
+ _maxSize:function(pane){
+ var options = this.options[pane],
+ $pane = this.panes[pane],
+ property = this._sizeProp()
+
+ return Math.min(options.resizable[this._sizeProp('max')], this.element[this._sizeProp('inner')]() - ( this.options['center'].minWidth + this._panes().not($pane).not(this.panes['center'])[this._sizeProp('outer')](true) ))
+ },
+
+ _removeInlineStyleAttr: function(pane){
+ var $pane = this.panes[pane],
+ style = this.panes[pane].attr('style'),
+ props ;
+
+ switch(pane){
+ case 'east': props = 'left'; break;
+ case 'south': props = 'top'; break;
+ }
+ if (props){
+ $.each(props.split(','), function(i,r){
+ style=style.replace(new RegExp(r+':\\s\\w*\;',''));
+ });
+ $pane.attr('style', style);
+ }
+ },
+
+ toggle: function(pane, callback){
+ if (this.options[pane].opened)
+ this.close(pane, callback);
+ else
+ this.open(pane, callback)
+
+ return this.element
+ },
+ close: function(pane, callback){
+ var self = this,
+ css = {},
+ callback = callback || null ;
+ if (this.options[pane].opened){
+ this._close(pane)
+ css[self._sizeProp()] = 0;
+ this._animate(pane, css, function(){
+ self._closed(pane);
+ if (callback)
+ callback.apply(self.panes[pane])
+ })
+ }
+ return this.element
+ },
+ open: function(pane, callback){
+ var self = this,
+ callback = callback || null,
+ css = {} ;
+ if (!this.options[pane].opened){
+ this._open(pane)
+ css[self._sizeProp()] = Math.min(this.options[pane][this._sizeProp()], this._maxSize(pane)) ;
+ this._animate(pane, css, function(){
+ self._opened(pane)
+ if (callback)
+ callback.apply(self.panes[pane])
+ })
+ }
+ return this.element
+ },
+ _animate: function(pane, css, callback){
+ var self = this,
+ callback = callback || null ;
+
+ //self._putForeground(pane);
+
+ this.panes[pane].animate(css, {
+ step: function(currentStep){
+ if (!self.options[pane].sliding)
+ self.resize();
+ },
+ complete: function(){
+ if (callback){
+ callback();
+ }
+ if (!self.options[pane].sliding){
+ //self._putBackground(pane)
+ self.resize();
+ }
+ }}
+ );
+ }
+
+ });
+})(jQuery)
\ No newline at end of file