2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
5 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
6 Code distributed by Google as part of the polymer project is also
7 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
12 @group Polymer Core Elements
14 @element core-layout-grid
20 <link rel=
"import" href=
"../polymer/polymer.html">
22 <polymer-element name=
"core-layout-grid" attributes=
"nodes layout auto">
26 Polymer('core-layout-grid', {
36 nodesChanged: function() {
40 layoutChanged: function() {
44 autoNodes: function() {
45 this.nodes
= this.parentNode
.children
.array().filter(
47 switch(node
.localName
) {
48 case 'core-layout-grid':
57 invalidate: function() {
58 if (this.layout
&& this.layout
.length
) {
59 // job debounces layout, only letting it occur every N ms
60 this.layoutJob
= this.job(this.layoutJob
, this.relayout
);
64 relayout: function() {
65 if (!this.nodes
|| this.auto
) {
68 layout(this.layout
, this.nodes
);
69 this.asyncFire('core-layout');
78 function line(axis
, p
, d
) {
79 var l
= document
.createElement('line');
80 var extent
= (axis
=== 'left' ? 'width' :
81 (axis
=== 'top' ? 'height' : axis
));
82 l
.setAttribute('extent', extent
);
84 axis
= (axis
=== 'left' ? 'right' :
85 (axis
=== 'top' ? 'bottom' : axis
));
88 l
.style
[axis
] = p
+ 'px';
89 l
.style
[extent
] = '0px';
90 lineParent
.appendChild(l
);
93 var colCount
, colOwners
, rowCount
, rowOwners
;
95 function matrixillate(matrix
) {
96 // mesaure the matrix, must be rectangular
97 rowCount
= matrix
.length
;
98 colCount
= rowCount
&& matrix
[0].length
|| 0;
101 for (var i
=0; i
<colCount
; i
++) {
103 for (var j
=0; j
<rowCount
; j
++) {
104 c
.push(matrix
[j
][i
]);
108 // assign sizing control
109 colOwners
= findOwners(matrix
);
110 rowOwners
= findOwners(transpose
);
111 //console.log('colOwners', colOwners);
112 //console.log('rowOwners', rowOwners);
115 function findOwners(matrix
) {
116 var majCount
= matrix
.length
;
117 var minCount
= majCount
&& matrix
[0].length
|| 0;
119 // for each column (e.g.)
120 for (var i
=0; i
<minCount
; i
++) {
121 // array of contained areas
123 // look at each row to find a containing area
124 for (var j
=0; j
<majCount
; j
++) {
125 // get the row vector
126 var vector
= matrix
[j
]
127 // node index at [i,j]
128 var nodei
= vector
[i
];
129 // if a node is there
131 // determine if it bounds this column
134 owns
= (i
=== minCount
-1) || (nodei
!== vector
[i
+1]);
135 } else if (i
=== minCount
- 1) {
136 owns
= (i
=== 0) || (nodei
!== vector
[i
-1]);
138 owns
= nodei
!== vector
[i
-1] && nodei
!== vector
[i
+1];
141 contained
[nodei
] = 1;
144 // store the owners for this column
145 owners
[i
] = contained
;
153 function colWidth(i
) {
154 for (var col
in colOwners
[i
]) {
159 var node
= nodes
[col
- 1];
160 if (node
.hasAttribute('h-flex') || node
.hasAttribute('flex')) {
163 var w
= node
.offsetWidth
;
164 //console.log('colWidth(' + i + ') ==', w);
170 function rowHeight(i
) {
171 for (var row
in rowOwners
[i
]) {
176 var node
= nodes
[row
- 1];
177 if (node
.hasAttribute('v-flex') || node
.hasAttribute('flex')) {
180 var h
= node
.offsetHeight
;
181 //console.log('rowHeight(' + i + ') ==', h);
189 function railize(count
, sizeFn
) {
191 // create rails for `count` tracks using
192 // sizing function `sizeFn(trackNo)`
194 // for n tracks there are (n+1) rails
196 // |track|track|track|
197 // 0|->sz0|->sz1|<-sz2|0
199 // |track|track|track|
202 // there can be one elastic track per set
204 // |track|track|track|track|
205 // 0|-->s0|-->s1|<--s1|<--s2|0
207 // sz1 spans multiple tracks which makes
208 // it elastic (it's underconstrained)
212 for (var i
=0, x
; i
<count
; i
++) {
213 rails
[i
] = {p
: a
, s
: 1};
214 x
= sizeFn(i
) + m
+ m
;
221 rails
[i
] = {p
: 0, s
: -1};
224 for (var ii
=count
, x
; ii
>i
; ii
--) {
225 rails
[ii
] = {p
: b
, s
: -1};
226 x
= sizeFn(ii
- 1) + m
+ m
;
234 // TODO(sjmiles): this code tries to preserve actual position,
235 // so 'unposition' is really 'naturalize' or something
236 function unposition(box
) {
237 var style
= box
.style
;
238 //style.right = style.bottom = style.width = style.height = '';
239 style
.position
= 'absolute';
240 style
.display
= 'inline-block';
241 style
.boxSizing
= style
.mozBoxSizing
= 'border-box';
244 function _position(style
, maj
, min
, ext
, a
, b
) {
245 style
[maj
] = style
[min
] = '';
247 if (a
.s
< 0 && b
.s
< 0) {
248 var siz
= a
.p
- b
.p
- m
- m
;
249 style
[ext
] = siz
+ 'px';
250 var c
= 'calc(100% - ' + (b
.p
+ siz
+ m
) + 'px' + ')';
251 style
[maj
] = '-webkit-' + c
;
253 } else if (b
.s
< 0) {
254 style
[maj
] = a
.p
+ m
+ 'px';
255 style
[min
] = b
.p
+ m
+ 'px';
257 style
[maj
] = a
.p
+ m
+ 'px';
258 style
[ext
] = b
.p
- a
.p
- m
- m
+ 'px';
262 function position(elt
, left
, right
, top
, bottom
) {
263 _position(elt
.style
, 'top', 'bottom', 'height', rows
[top
],
265 _position(elt
.style
, 'left', 'right', 'width', columns
[left
],
269 function layout(matrix
, anodes
, alineParent
) {
270 //console.group('layout');
272 lineParent
= alineParent
;
274 matrixillate(matrix
);
276 nodes
.forEach(unposition
);
278 columns
= railize(colCount
, colWidth
);
279 rows
= railize(rowCount
, rowHeight
);
282 //console.group('column rails');
283 columns
.forEach(function(c
) {
284 //console.log(c.p, c.s);
285 line('left', c
.p
, c
.s
);
287 //console.groupEnd();
289 //console.group('row rails');
290 rows
.forEach(function(r
) {
291 //console.log(r.p, r.s);
292 line('top', r
.p
, r
.s
);
294 //console.groupEnd();
297 //console.group('rail boundaries');
298 nodes
.forEach(function(node
, i
) {
299 // node indices are 1-based
302 var l
, r
, t
= 1e10
, b
= -1e10
;
303 matrix
.forEach(function(vector
, i
) {
304 var f
= vector
.indexOf(n
);
307 r
= vector
.lastIndexOf(n
) + 1;
309 b
= Math
.max(b
, i
) + 1;
312 if (l
== undefined) {
313 //console.log('unused');
314 node
.style
.position
= 'absolute';
315 var offscreen
= node
.getAttribute('offscreen');
318 node
.style
.zIndex
= 0;
322 node
.style
[offscreen
] = node
.offsetWidth
* -2 + 'px';
325 node
.style
.left
= node
.offsetParent
.offsetWidth
326 + node
.offsetWidth
+ 'px';
329 node
.style
.top
= node
.parentNode
.offsetHeight
330 + node
.offsetHeight
+ 'px';
333 node
.style
[Math
.random() >= 0.5 ? 'left' : 'top'] = '-110%';
335 //node.style.opacity = 0;
336 node
.style
.pointerEvents
= 'none';
338 node
.style
.pointerEvents
= '';
339 //node.style.opacity = '';
340 //console.log(l, r, t, b);
341 position(node
, l
, r
, t
, b
);
344 //console.groupEnd();
345 //console.groupEnd();