/ext-4.0.7/docs/source/Anchor.html
HTML | 317 lines | 289 code | 28 blank | 0 comment | 0 complexity | c46c32791aa7ede081806f09725fc405 MD5 | raw file
1<!DOCTYPE html>
2<html>
3<head>
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; }
10 </style>
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14 }
15 </script>
16</head>
17<body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-layout-container-Anchor'>/**
19</span> * @class Ext.layout.container.Anchor
20 * @extends Ext.layout.container.Container
21 *
22 * This is a layout that enables anchoring of contained elements relative to the container's dimensions.
23 * If the container is resized, all anchored items are automatically rerendered according to their
24 * `{@link #anchor}` rules.
25 *
26 * This class is intended to be extended or created via the {@link Ext.container.AbstractContainer#layout layout}: 'anchor'
27 * config, and should generally not need to be created directly via the new keyword.
28 *
29 * AnchorLayout does not have any direct config options (other than inherited ones). By default,
30 * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
31 * container using the AnchorLayout can supply an anchoring-specific config property of `anchorSize`.
32 *
33 * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
34 * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
35 * logic if necessary.
36 *
37 * @example
38 * Ext.create('Ext.Panel', {
39 * width: 500,
40 * height: 400,
41 * title: "AnchorLayout Panel",
42 * layout: 'anchor',
43 * renderTo: Ext.getBody(),
44 * items: [
45 * {
46 * xtype: 'panel',
47 * title: '75% Width and 20% Height',
48 * anchor: '75% 20%'
49 * },
50 * {
51 * xtype: 'panel',
52 * title: 'Offset -300 Width & -200 Height',
53 * anchor: '-300 -200'
54 * },
55 * {
56 * xtype: 'panel',
57 * title: 'Mixed Offset and Percent',
58 * anchor: '-250 20%'
59 * }
60 * ]
61 * });
62 */
63Ext.define('Ext.layout.container.Anchor', {
64
65 /* Begin Definitions */
66
67 alias: 'layout.anchor',
68 extend: 'Ext.layout.container.Container',
69 alternateClassName: 'Ext.layout.AnchorLayout',
70
71 /* End Definitions */
72
73<span id='Ext-layout-container-Anchor-cfg-anchor'> /**
74</span> * @cfg {String} anchor
75 *
76 * This configuation option is to be applied to **child `items`** of a container managed by
77 * this layout (ie. configured with `layout:'anchor'`).
78 *
79 * This value is what tells the layout how an item should be anchored to the container. `items`
80 * added to an AnchorLayout accept an anchoring-specific config property of **anchor** which is a string
81 * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
82 * The following types of anchor values are supported:
83 *
84 * - **Percentage** : Any value between 1 and 100, expressed as a percentage.
85 *
86 * The first anchor is the percentage width that the item should take up within the container, and the
87 * second is the percentage height. For example:
88 *
89 * // two values specified
90 * anchor: '100% 50%' // render item complete width of the container and
91 * // 1/2 height of the container
92 * // one value specified
93 * anchor: '100%' // the width value; the height will default to auto
94 *
95 * - **Offsets** : Any positive or negative integer value.
96 *
97 * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
98 * and the second is the offset from the bottom edge. For example:
99 *
100 * // two values specified
101 * anchor: '-50 -100' // render item the complete width of the container
102 * // minus 50 pixels and
103 * // the complete height minus 100 pixels.
104 * // one value specified
105 * anchor: '-50' // anchor value is assumed to be the right offset value
106 * // bottom offset will default to 0
107 *
108 * - **Sides** : Valid values are `right` (or `r`) and `bottom` (or `b`).
109 *
110 * Either the container must have a fixed size or an anchorSize config value defined at render time in
111 * order for these to have any effect.
112 *
113 * - **Mixed** :
114 *
115 * Anchor values can also be mixed as needed. For example, to render the width offset from the container
116 * right edge by 50 pixels and 75% of the container's height use:
117 *
118 * anchor: '-50 75%'
119 */
120 type: 'anchor',
121
122<span id='Ext-layout-container-Anchor-cfg-defaultAnchor'> /**
123</span> * @cfg {String} defaultAnchor
124 * Default anchor for all child <b>container</b> items applied if no anchor or specific width is set on the child item. Defaults to '100%'.
125 */
126 defaultAnchor: '100%',
127
128 parseAnchorRE: /^(r|right|b|bottom)$/i,
129
130 // private
131 onLayout: function() {
132 this.callParent(arguments);
133
134 var me = this,
135 size = me.getLayoutTargetSize(),
136 owner = me.owner,
137 target = me.getTarget(),
138 ownerWidth = size.width,
139 ownerHeight = size.height,
140 overflow = target.getStyle('overflow'),
141 components = me.getVisibleItems(owner),
142 len = components.length,
143 boxes = [],
144 box, newTargetSize, component, anchorSpec, calcWidth, calcHeight,
145 i, el, cleaner;
146
147 if (ownerWidth < 20 && ownerHeight < 20) {
148 return;
149 }
150
151 // Anchor layout uses natural HTML flow to arrange the child items.
152 // To ensure that all browsers (I'm looking at you IE!) add the bottom margin of the last child to the
153 // containing element height, we create a zero-sized element with style clear:both to force a "new line"
154 if (!me.clearEl) {
155 me.clearEl = target.createChild({
156 cls: Ext.baseCSSPrefix + 'clear',
157 role: 'presentation'
158 });
159 }
160
161 // Work around WebKit RightMargin bug. We're going to inline-block all the children only ONCE and remove it when we're done
162 if (!Ext.supports.RightMargin) {
163 cleaner = Ext.Element.getRightMarginFixCleaner(target);
164 target.addCls(Ext.baseCSSPrefix + 'inline-children');
165 }
166
167 for (i = 0; i < len; i++) {
168 component = components[i];
169 el = component.el;
170
171 anchorSpec = component.anchorSpec;
172 if (anchorSpec) {
173 if (anchorSpec.right) {
174 calcWidth = me.adjustWidthAnchor(anchorSpec.right(ownerWidth) - el.getMargin('lr'), component);
175 } else {
176 calcWidth = undefined;
177 }
178 if (anchorSpec.bottom) {
179 calcHeight = me.adjustHeightAnchor(anchorSpec.bottom(ownerHeight) - el.getMargin('tb'), component);
180 } else {
181 calcHeight = undefined;
182 }
183
184 boxes.push({
185 component: component,
186 anchor: true,
187 width: calcWidth || undefined,
188 height: calcHeight || undefined
189 });
190 } else {
191 boxes.push({
192 component: component,
193 anchor: false
194 });
195 }
196 }
197
198 // Work around WebKit RightMargin bug. We're going to inline-block all the children only ONCE and remove it when we're done
199 if (!Ext.supports.RightMargin) {
200 target.removeCls(Ext.baseCSSPrefix + 'inline-children');
201 cleaner();
202 }
203
204 for (i = 0; i < len; i++) {
205 box = boxes[i];
206 me.setItemSize(box.component, box.width, box.height);
207 }
208
209 if (overflow && overflow != 'hidden' && !me.adjustmentPass) {
210 newTargetSize = me.getLayoutTargetSize();
211 if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
212 me.adjustmentPass = true;
213 me.onLayout();
214 }
215 }
216
217 delete me.adjustmentPass;
218 },
219
220 // private
221 parseAnchor: function(a, start, cstart) {
222 if (a && a != 'none') {
223 var ratio;
224 // standard anchor
225 if (this.parseAnchorRE.test(a)) {
226 var diff = cstart - start;
227 return function(v) {
228 return v - diff;
229 };
230 }
231 // percentage
232 else if (a.indexOf('%') != -1) {
233 ratio = parseFloat(a.replace('%', '')) * 0.01;
234 return function(v) {
235 return Math.floor(v * ratio);
236 };
237 }
238 // simple offset adjustment
239 else {
240 a = parseInt(a, 10);
241 if (!isNaN(a)) {
242 return function(v) {
243 return v + a;
244 };
245 }
246 }
247 }
248 return null;
249 },
250
251 // private
252 adjustWidthAnchor: function(value, comp) {
253 return value;
254 },
255
256 // private
257 adjustHeightAnchor: function(value, comp) {
258 return value;
259 },
260
261 configureItem: function(item) {
262 var me = this,
263 owner = me.owner,
264 anchor= item.anchor,
265 anchorsArray,
266 anchorSpec,
267 anchorWidth,
268 anchorHeight;
269
270 if (!item.anchor && item.items && !Ext.isNumber(item.width) && !(Ext.isIE6 && Ext.isStrict)) {
271 item.anchor = anchor = me.defaultAnchor;
272 }
273
274 // find the container anchoring size
275 if (owner.anchorSize) {
276 if (typeof owner.anchorSize == 'number') {
277 anchorWidth = owner.anchorSize;
278 }
279 else {
280 anchorWidth = owner.anchorSize.width;
281 anchorHeight = owner.anchorSize.height;
282 }
283 }
284 else {
285 anchorWidth = owner.initialConfig.width;
286 anchorHeight = owner.initialConfig.height;
287 }
288
289 if (anchor) {
290 // cache all anchor values
291 anchorsArray = anchor.split(' ');
292 item.anchorSpec = anchorSpec = {
293 right: me.parseAnchor(anchorsArray[0], item.initialConfig.width, anchorWidth),
294 bottom: me.parseAnchor(anchorsArray[1], item.initialConfig.height, anchorHeight)
295 };
296
297 if (anchorSpec.right) {
298 item.layoutManagedWidth = 1;
299 } else {
300 item.layoutManagedWidth = 2;
301 }
302
303 if (anchorSpec.bottom) {
304 item.layoutManagedHeight = 1;
305 } else {
306 item.layoutManagedHeight = 2;
307 }
308 } else {
309 item.layoutManagedWidth = 2;
310 item.layoutManagedHeight = 2;
311 }
312 this.callParent(arguments);
313 }
314
315});</pre>
316</body>
317</html>