4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-layout-component-AbstractDock'>/**
19 </span> * @class Ext.layout.component.AbstractDock
20 * @extends Ext.layout.component.Component
22 * This ComponentLayout handles docking for Panels. It takes care of panels that are
23 * part of a ContainerLayout that sets this Panel's size and Panels that are part of
24 * an AutoContainerLayout in which this panel get his height based of the CSS or
28 Ext.define('Ext.layout.component.AbstractDock', {
30 /* Begin Definitions */
32 extend: 'Ext.layout.component.Component',
38 <span id='Ext-layout-component-AbstractDock-property-autoSizing'> /**
40 * @property autoSizing
42 * This flag is set to indicate this layout may have an autoHeight/autoWidth.
46 beforeLayout: function() {
47 var returnValue = this.callParent(arguments);
48 if (returnValue !== false && (!this.initializedBorders || this.childrenChanged) && (!this.owner.border || this.owner.manageBodyBorders)) {
49 this.handleItemBorders();
50 this.initializedBorders = true;
55 handleItemBorders: function() {
56 var owner = this.owner,
58 docked = this.getLayoutItems(),
65 oldBorders = this.borders,
72 i, ln, item, dock, side;
74 for (i = 0, ln = docked.length; i < ln; i++) {
78 if (item.ignoreBorderManagement) {
82 if (!borders[dock].satisfied) {
83 borders[dock].push(item);
84 borders[dock].satisfied = true;
87 if (!borders.top.satisfied && opposites[dock] !== 'top') {
88 borders.top.push(item);
90 if (!borders.right.satisfied && opposites[dock] !== 'right') {
91 borders.right.push(item);
93 if (!borders.bottom.satisfied && opposites[dock] !== 'bottom') {
94 borders.bottom.push(item);
96 if (!borders.left.satisfied && opposites[dock] !== 'left') {
97 borders.left.push(item);
102 for (side in oldBorders) {
103 if (oldBorders.hasOwnProperty(side)) {
104 ln = oldBorders[side].length;
105 if (!owner.manageBodyBorders) {
106 for (i = 0; i < ln; i++) {
107 oldBorders[side][i].removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
109 if (!oldBorders[side].satisfied && !owner.bodyBorder) {
110 body.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
113 else if (oldBorders[side].satisfied) {
114 body.setStyle('border-' + side + '-width', '');
120 for (side in borders) {
121 if (borders.hasOwnProperty(side)) {
122 ln = borders[side].length;
123 if (!owner.manageBodyBorders) {
124 for (i = 0; i < ln; i++) {
125 borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
127 if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) {
128 body.addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
131 else if (borders[side].satisfied) {
132 body.setStyle('border-' + side + '-width', '1px');
137 this.borders = borders;
140 <span id='Ext-layout-component-AbstractDock-method-onLayout'> /**
142 * @param {Ext.Component} owner The Panel that owns this DockLayout
143 * @param {Ext.Element} target The target in which we are going to render the docked items
144 * @param {Array} args The arguments passed to the ComponentLayout.layout method
146 onLayout: function(width, height) {
147 if (this.onLayout_running) {
150 this.onLayout_running = true;
154 layout = owner.layout,
155 target = me.getTarget(),
158 padding, border, frameSize;
160 // We start of by resetting all the layouts info
161 var info = me.info = {
169 // Clear isAutoDock flag
170 delete layout.isAutoDock;
172 Ext.applyIf(info, me.getTargetInfo());
174 // We need to bind to the ownerCt whenever we do not have a user set height or width.
175 if (owner && owner.ownerCt && owner.ownerCt.layout && owner.ownerCt.layout.isLayout) {
176 if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
177 owner.ownerCt.layout.bindToOwnerCtComponent = true;
180 owner.ownerCt.layout.bindToOwnerCtComponent = false;
184 // Determine if we have an autoHeight or autoWidth.
185 if (height == null || width == null) {
186 padding = info.padding;
187 border = info.border;
188 frameSize = me.frameSize;
190 // Auto-everything, clear out any style height/width and read from css
191 if ((height == null) && (width == null)) {
194 me.setTargetSize(null);
195 me.setBodyBox({width: null, height: null});
198 else if (height == null) {
200 // Clear any sizing that we already set in a previous layout
201 me.setTargetSize(width);
202 me.setBodyBox({width: width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right, height: null});
207 // Clear any sizing that we already set in a previous layout
208 me.setTargetSize(null, height);
209 me.setBodyBox({width: null, height: height - padding.top - padding.bottom - border.top - border.bottom - frameSize.top - frameSize.bottom});
213 if (layout && layout.isLayout) {
214 // Auto-Sized so have the container layout notify the component layout.
215 layout.bindToOwnerCtComponent = true;
216 // Set flag so we don't do a redundant container layout
217 layout.isAutoDock = layout.autoSize !== true;
220 // If this is an autosized container layout, then we must compensate for a
221 // body that is being autosized. We do not want to adjust the body's size
222 // to accommodate the dock items, but rather we will want to adjust the
225 // This is necessary because, particularly in a Box layout, all child items
226 // are set with absolute dimensions that are not flexible to the size of its
227 // innerCt/target. So once they are laid out, they are sized for good. By
228 // shrinking the body box to accommodate dock items, we're merely cutting off
229 // parts of the body. Not good. Instead, the target's size should expand
230 // to fit the dock items in. This is valid because the target container is
231 // suppose to be autosized to fit everything accordingly.
232 info.autoSizedCtLayout = layout.autoSize === true;
233 info.autoHeight = autoHeight;
234 info.autoWidth = autoWidth;
237 // The dockItems method will add all the top and bottom docked items height
238 // to the info.panelSize height. That's why we have to call setSize after
239 // we dock all the items to actually set the panel's width and height.
240 // We have to do this because the panel body and docked items will be position
241 // absolute which doesn't stretch the panel.
243 me.setTargetSize(info.size.width, info.size.height);
246 me.setTargetSize(width, height);
249 me.callParent(arguments);
250 this.onLayout_running = false;
253 <span id='Ext-layout-component-AbstractDock-method-dockItems'> /**
255 * This method will first update all the information about the docked items,
256 * body dimensions and position, the panel's total size. It will then
257 * set all these values on the docked items and panel body.
258 * @param {Array} items Array containing all the docked items
259 * @param {Boolean} autoBoxes Set this to true if the Panel is part of an
260 * AutoContainerLayout
262 dockItems : function() {
263 this.calculateDockBoxes();
265 // Both calculateAutoBoxes and calculateSizedBoxes are changing the
266 // information about the body, panel size, and boxes for docked items
267 // inside a property called info.
268 var info = this.info,
269 autoWidth = info.autoWidth,
270 autoHeight = info.autoHeight,
275 // We are going to loop over all the boxes that were calculated
276 // and set the position of each item the box belongs to.
277 for (i = 0; i < ln; i++) {
280 item.setPosition(dock.x, dock.y);
281 if ((autoWidth || autoHeight) && item.layout && item.layout.isLayout) {
282 // Auto-Sized so have the container layout notify the component layout.
283 item.layout.bindToOwnerCtComponent = true;
287 // Don't adjust body width/height if the target is using an auto container layout.
288 // But, we do want to adjust the body size if the container layout is auto sized.
289 if (!info.autoSizedCtLayout) {
291 info.bodyBox.width = null;
294 info.bodyBox.height = null;
298 // If the bodyBox has been adjusted because of the docked items
299 // we will update the dimensions and position of the panel's body.
300 this.setBodyBox(info.bodyBox);
303 <span id='Ext-layout-component-AbstractDock-method-calculateDockBoxes'> /**
305 * This method will set up some initial information about the panel size and bodybox
306 * and then loop over all the items you pass it to take care of stretching, aligning,
307 * dock position and all calculations involved with adjusting the body box.
308 * @param {Array} items Array containing all the docked items we have to layout
310 calculateDockBoxes : function() {
311 if (this.calculateDockBoxes_running) {
312 // [AbstractDock#calculateDockBoxes] attempted to run again while it was already running
315 this.calculateDockBoxes_running = true;
316 // We want to use the Panel's el width, and the Panel's body height as the initial
317 // size we are going to use in calculateDockBoxes. We also want to account for
318 // the border of the panel.
320 target = me.getTarget(),
321 items = me.getLayoutItems(),
325 autoWidth = info.autoWidth,
326 autoHeight = info.autoHeight,
329 padding = info.padding,
330 border = info.border,
331 frameSize = me.frameSize,
334 // If this Panel is inside an AutoContainerLayout, we will base all the calculations
335 // around the height of the body and the width of the panel.
337 size.height = bodyEl.getHeight() + padding.top + border.top + padding.bottom + border.bottom + frameSize.top + frameSize.bottom;
340 size.height = target.getHeight();
343 size.width = bodyEl.getWidth() + padding.left + border.left + padding.right + border.right + frameSize.left + frameSize.right;
346 size.width = target.getWidth();
350 x: padding.left + frameSize.left,
351 y: padding.top + frameSize.top,
352 width: size.width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right,
353 height: size.height - border.top - padding.top - border.bottom - padding.bottom - frameSize.top - frameSize.bottom
356 // Loop over all the docked items
357 for (i = 0; i < ln; i++) {
359 // The initBox method will take care of stretching and alignment
360 // In some cases it will also layout the dock items to be able to
361 // get a width or height measurement
362 box = me.initBox(item);
364 if (autoHeight === true) {
365 box = me.adjustAutoBox(box, i);
368 box = me.adjustSizedBox(box, i);
371 // Save our box. This allows us to loop over all docked items and do all
372 // calculations first. Then in one loop we will actually size and position
373 // all the docked items that have changed.
374 info.boxes.push(box);
376 this.calculateDockBoxes_running = false;
379 <span id='Ext-layout-component-AbstractDock-method-adjustSizedBox'> /**
381 * This method will adjust the position of the docked item and adjust the body box
383 * @param {Object} box The box containing information about the width and height
384 * of this docked item
385 * @param {Number} index The index position of this docked item
386 * @return {Object} The adjusted box
388 adjustSizedBox : function(box, index) {
389 var bodyBox = this.info.bodyBox,
390 frameSize = this.frameSize,
392 padding = info.padding,
394 border = info.border;
406 box.y = (bodyBox.y + bodyBox.height) - box.height;
410 box.x = (bodyBox.x + bodyBox.width) - box.width;
414 if (box.ignoreFrame) {
415 if (pos == 'bottom') {
416 box.y += (frameSize.bottom + padding.bottom + border.bottom);
419 box.y -= (frameSize.top + padding.top + border.top);
421 if (pos == 'right') {
422 box.x += (frameSize.right + padding.right + border.right);
425 box.x -= (frameSize.left + padding.left + border.left);
429 // If this is not an overlaying docked item, we have to adjust the body box
433 bodyBox.y += box.height;
434 bodyBox.height -= box.height;
438 bodyBox.x += box.width;
439 bodyBox.width -= box.width;
443 bodyBox.height -= box.height;
447 bodyBox.width -= box.width;
454 <span id='Ext-layout-component-AbstractDock-method-adjustAutoBox'> /**
456 * This method will adjust the position of the docked item inside an AutoContainerLayout
457 * and adjust the body box accordingly.
458 * @param {Object} box The box containing information about the width and height
459 * of this docked item
460 * @param {Number} index The index position of this docked item
461 * @return {Object} The adjusted box
463 adjustAutoBox : function (box, index) {
464 var info = this.info,
466 bodyBox = info.bodyBox,
469 boxesLn = boxes.length,
471 frameSize = this.frameSize,
472 padding = info.padding,
473 border = info.border,
474 autoSizedCtLayout = info.autoSizedCtLayout,
475 ln = (boxesLn < index) ? boxesLn : index,
478 if (pos == 'top' || pos == 'bottom') {
479 // This can affect the previously set left and right and bottom docked items
480 for (i = 0; i < ln; i++) {
481 adjustBox = boxes[i];
482 if (adjustBox.stretched && adjustBox.type == 'left' || adjustBox.type == 'right') {
483 adjustBox.height += box.height;
485 else if (adjustBox.type == 'bottom') {
486 adjustBox.y += box.height;
495 bodyBox.y += box.height;
496 if (info.autoHeight) {
497 size.height += box.height;
499 bodyBox.height -= box.height;
506 if (info.autoHeight) {
507 size.height += box.height;
509 bodyBox.height -= box.height;
512 box.y = (bodyBox.y + bodyBox.height);
518 bodyBox.x += box.width;
519 if (info.autoWidth) {
520 size.width += box.width;
522 bodyBox.width -= box.width;
529 if (info.autoWidth) {
530 size.width += box.width;
532 bodyBox.width -= box.width;
535 box.x = (bodyBox.x + bodyBox.width);
539 if (box.ignoreFrame) {
540 if (pos == 'bottom') {
541 box.y += (frameSize.bottom + padding.bottom + border.bottom);
544 box.y -= (frameSize.top + padding.top + border.top);
546 if (pos == 'right') {
547 box.x += (frameSize.right + padding.right + border.right);
550 box.x -= (frameSize.left + padding.left + border.left);
556 <span id='Ext-layout-component-AbstractDock-method-initBox'> /**
558 * This method will create a box object, with a reference to the item, the type of dock
559 * (top, left, bottom, right). It will also take care of stretching and aligning of the
561 * @param {Ext.Component} item The docked item we want to initialize the box for
562 * @return {Object} The initial box containing width and height and other useful information
564 initBox : function(item) {
566 bodyBox = me.info.bodyBox,
567 horizontal = (item.dock == 'top' || item.dock == 'bottom'),
569 frameSize = me.frameSize,
571 padding = info.padding,
572 border = info.border,
575 overlay: item.overlay,
577 offsets: Ext.Element.parseBox(item.offsets || {}),
578 ignoreFrame: item.ignoreParentFrame
580 // First we are going to take care of stretch and align properties for all four dock scenarios.
581 if (item.stretch !== false) {
582 box.stretched = true;
584 box.x = bodyBox.x + box.offsets.left;
585 box.width = bodyBox.width - (box.offsets.left + box.offsets.right);
586 if (box.ignoreFrame) {
587 box.width += (frameSize.left + frameSize.right + border.left + border.right + padding.left + padding.right);
589 item.setCalculatedSize(box.width - item.el.getMargin('lr'), undefined, owner);
592 box.y = bodyBox.y + box.offsets.top;
593 box.height = bodyBox.height - (box.offsets.bottom + box.offsets.top);
594 if (box.ignoreFrame) {
595 box.height += (frameSize.top + frameSize.bottom + border.top + border.bottom + padding.top + padding.bottom);
597 item.setCalculatedSize(undefined, box.height - item.el.getMargin('tb'), owner);
599 // At this point IE will report the left/right-docked toolbar as having a width equal to the
600 // container's full width. Forcing a repaint kicks it into shape so it reports the correct width.
601 if (!Ext.supports.ComputedStyle) {
607 item.doComponentLayout();
608 box.width = item.getWidth() - (box.offsets.left + box.offsets.right);
609 box.height = item.getHeight() - (box.offsets.bottom + box.offsets.top);
610 box.y += box.offsets.top;
612 box.x = (item.align == 'right') ? bodyBox.width - box.width : bodyBox.x;
613 box.x += box.offsets.left;
617 // If we haven't calculated the width or height of the docked item yet
618 // do so, since we need this for our upcoming calculations
619 if (box.width === undefined) {
620 box.width = item.getWidth() + item.el.getMargin('lr');
622 if (box.height === undefined) {
623 box.height = item.getHeight() + item.el.getMargin('tb');
629 <span id='Ext-layout-component-AbstractDock-method-getLayoutItems'> /**
631 * Returns an array containing all the <b>visible</b> docked items inside this layout's owner Panel
632 * @return {Array} An array containing all the <b>visible</b> docked items of the Panel
634 getLayoutItems : function() {
635 var it = this.owner.getDockedItems(),
639 for (; i < ln; i++) {
640 if (it[i].isVisible(true)) {
647 <span id='Ext-layout-component-AbstractDock-method-renderItems'> /**
649 * Render the top and left docked items before any existing DOM nodes in our render target,
650 * and then render the right and bottom docked items after. This is important, for such things
651 * as tab stops and ARIA readers, that the DOM nodes are in a meaningful order.
652 * Our collection of docked items will already be ordered via Panel.getDockedItems().
654 renderItems: function(items, target) {
655 var cns = target.dom.childNodes,
661 // Calculate the number of DOM nodes in our target that are not our docked items
662 for (i = 0; i < cnsLn; i++) {
663 cn = Ext.get(cns[i]);
664 for (j = 0; j < ln; j++) {
666 if (item.rendered && (cn.id == item.el.id || cn.contains(item.el.id))) {
676 // Now we go through our docked items and render/move them
677 for (i = 0, j = 0; i < ln; i++, j++) {
680 // If we're now at the right/bottom docked item, we jump ahead in our
681 // DOM position, just past the existing DOM nodes.
683 // TODO: This is affected if users provide custom weight values to their
684 // docked items, which puts it out of (t,l,r,b) order. Avoiding a second
685 // sort operation here, for now, in the name of performance. getDockedItems()
686 // needs the sort operation not just for this layout-time rendering, but
687 // also for getRefItems() to return a logical ordering (FocusManager, CQ, et al).
688 if (i === j && (item.dock === 'right' || item.dock === 'bottom')) {
692 // Same logic as Layout.renderItems()
693 if (item && !item.rendered) {
694 this.renderItem(item, target, j);
696 else if (!this.isValidParent(item, target, j)) {
697 this.moveItem(item, target, j);
702 <span id='Ext-layout-component-AbstractDock-method-setBodyBox'> /**
704 * This function will be called by the dockItems method. Since the body is positioned absolute,
705 * we need to give it dimensions and a position so that it is in the middle surrounded by
707 * @param {Object} box An object containing new x, y, width and height values for the
710 setBodyBox : function(box) {
715 bodyMargin = info.bodyMargin,
716 padding = info.padding,
717 border = info.border,
718 frameSize = me.frameSize;
720 // Panel collapse effectively hides the Panel's body, so this is a no-op.
721 if (owner.collapsed) {
725 if (Ext.isNumber(box.width)) {
726 box.width -= bodyMargin.left + bodyMargin.right;
729 if (Ext.isNumber(box.height)) {
730 box.height -= bodyMargin.top + bodyMargin.bottom;
733 me.setElementSize(body, box.width, box.height);
734 if (Ext.isNumber(box.x)) {
735 body.setLeft(box.x - padding.left - frameSize.left);
737 if (Ext.isNumber(box.y)) {
738 body.setTop(box.y - padding.top - frameSize.top);
742 <span id='Ext-layout-component-AbstractDock-method-configureItem'> /**
744 * We are overriding the Ext.layout.Layout configureItem method to also add a class that
745 * indicates the position of the docked item. We use the itemCls (x-docked) as a prefix.
746 * An example of a class added to a dock: right item is x-docked-right
747 * @param {Ext.Component} item The item we are configuring
749 configureItem : function(item, pos) {
750 this.callParent(arguments);
751 if (item.dock == 'top' || item.dock == 'bottom') {
752 item.layoutManagedWidth = 1;
753 item.layoutManagedHeight = 2;
755 item.layoutManagedWidth = 2;
756 item.layoutManagedHeight = 1;
759 item.addCls(Ext.baseCSSPrefix + 'docked');
760 item.addClsWithUI('docked-' + item.dock);
763 afterRemove : function(item) {
764 this.callParent(arguments);
766 item.el.removeCls(this.itemCls + '-' + item.dock);
768 var dom = item.el.dom;
770 if (!item.destroying && dom) {
771 dom.parentNode.removeChild(dom);
773 this.childrenChanged = true;