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 + + + + + + + + + + + + + + +
+
West
+
Center
+
East
+
+ + + \ 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 + + + +
+

Examples

+ +
+ + 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 + + + + + + + + + + + + + + + +
+
+
+ Toggle slide +
Outer layout west
+
+
+
+
Inner layout North
+
Inner layout Center
+
Inner layout South
+
+
+ + \ 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 + + + + + + + + + + + + + + +
+
North
+
Center
+
South
+
+ + \ 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