Mechanical rename of base::debug -> base::trace_event [final pass]
[chromium-blink-merge.git] / third_party / polymer / components-chromium / core-layout-grid / core-layout-grid-extracted.js
blob11fb5cbd4f6fde9fc4c9f3ab7d8ea5e0c9d2457d
2   (function() {
4     Polymer('core-layout-grid', {
6       nodes: null,
7       layout: null,
8       auto: false,
10       created: function() {
11         this.layout = [];
12       },
14       nodesChanged: function() {
15         this.invalidate();
16       },
18       layoutChanged: function() {
19         this.invalidate();
20       },
22       autoNodes: function() {
23         this.nodes = this.parentNode.children.array().filter(
24           function(node) {
25             switch(node.localName) {
26               case 'core-layout-grid':
27               case 'style':
28                 return false;
29             }
30             return true;
31           }
32         );
33       },
35       invalidate: function() {
36         if (this.layout && this.layout.length) {
37           // job debounces layout, only letting it occur every N ms
38           this.layoutJob = this.job(this.layoutJob, this.relayout);
39         }
40       },
42       relayout: function() {
43         if (!this.nodes || this.auto) {
44           this.autoNodes();
45         }
46         layout(this.layout, this.nodes);
47         this.asyncFire('core-layout');
48       }
50     });
52     //
54     var lineParent;
56     function line(axis, p, d) {
57       var l = document.createElement('line');
58       var extent = (axis === 'left' ? 'width' : 
59         (axis === 'top' ? 'height' : axis));
60       l.setAttribute('extent', extent);
61       if (d < 0) {
62         axis = (axis === 'left' ? 'right' : 
63           (axis === 'top' ? 'bottom' : axis));
64       }
65       p = Math.abs(p);
66       l.style[axis] = p + 'px';
67       l.style[extent] = '0px';
68       lineParent.appendChild(l);
69     }
71     var colCount, colOwners, rowCount, rowOwners;
73     function matrixillate(matrix) {
74       // mesaure the matrix, must be rectangular
75       rowCount = matrix.length;
76       colCount = rowCount && matrix[0].length || 0;
77       // transpose matrix
78       var transpose = [];
79       for (var i=0; i<colCount; i++) {
80         var c = [];
81         for (var j=0; j<rowCount; j++) {
82           c.push(matrix[j][i]);
83         }
84         transpose.push(c);
85       }
86       // assign sizing control
87       colOwners = findOwners(matrix);
88       rowOwners = findOwners(transpose);
89       //console.log('colOwners', colOwners);
90       //console.log('rowOwners', rowOwners);
91     }
93     function findOwners(matrix) {
94       var majCount = matrix.length;
95       var minCount = majCount && matrix[0].length || 0;
96       var owners = [];
97       // for each column (e.g.)
98       for (var i=0; i<minCount; i++) {
99         // array of contained areas
100         var contained = {};
101         // look at each row to find a containing area
102         for (var j=0; j<majCount; j++) {
103           // get the row vector
104           var vector = matrix[j]
105           // node index at [i,j]
106           var nodei = vector[i];
107           // if a node is there
108           if (nodei) {
109             // determine if it bounds this column
110             var owns = false;
111             if (i === 0) {
112               owns = (i === minCount-1) || (nodei !== vector[i+1]);
113             } else if (i === minCount - 1) {
114               owns = (i === 0) || (nodei !== vector[i-1]);
115             } else {
116               owns = nodei !== vector[i-1] && nodei !== vector[i+1];
117             }
118             if (owns) {
119               contained[nodei] = 1;
120             }
121           }
122           // store the owners for this column
123           owners[i] = contained;
124         }
125       }
126       return owners;
127     }
129     var nodes;
131     function colWidth(i) {
132       for (var col in colOwners[i]) {
133         col = Number(col);
134         if (col === 0) {
135           return 96;
136         }
137         var node = nodes[col - 1];
138         if (node.hasAttribute('h-flex') || node.hasAttribute('flex')) {
139           return -1;
140         }
141         var w = node.offsetWidth;
142         //console.log('colWidth(' + i + ') ==', w);
143         return w;
144       }
145       return -1;
146     }
148     function rowHeight(i) {
149       for (var row in rowOwners[i]) {
150         row = Number(row);
151         if (row === 0) {
152           return 96;
153         }
154         var node = nodes[row - 1];
155         if (node.hasAttribute('v-flex') || node.hasAttribute('flex')) {
156           return -1;
157         }
158         var h = node.offsetHeight;
159         //console.log('rowHeight(' + i + ') ==', h);
160         return h;
161       }
162       return -1;
163     }
165     var m = 0;
167     function railize(count, sizeFn) {
168       //
169       // create rails for `count` tracks using 
170       // sizing function `sizeFn(trackNo)`
171       //
172       // for n tracks there are (n+1) rails
173       //
174       //   |track|track|track|
175       //  0|->sz0|->sz1|<-sz2|0
176       //
177       //   |track|track|track|
178       //  0|->sz0|     |<-sz2|0
179       //
180       // there can be one elastic track per set
181       //
182       //   |track|track|track|track|
183       //  0|-->s0|-->s1|<--s1|<--s2|0
184       //
185       // sz1 spans multiple  tracks which makes
186       // it elastic (it's underconstrained)
187       //
188       var rails = [];
189       var a = 0;
190       for (var i=0, x; i<count; i++) {
191         rails[i] = {p: a, s: 1};
192         x = sizeFn(i) + m + m;
193         if (x == -1) {
194           break;
195         }
196         a += x;
197       }
198       if (i === count) {
199         rails[i] = {p: 0, s: -1};
200       }
201       var b = 0;
202       for (var ii=count, x; ii>i; ii--) {
203         rails[ii] = {p: b, s: -1};
204         x = sizeFn(ii - 1) + m + m;
205         if (x !== -1) {
206           b += x;
207         }
208       }
209       return rails;
210     }
212     // TODO(sjmiles): this code tries to preserve actual position,
213     // so 'unposition' is really 'naturalize' or something
214     function unposition(box) {
215       var style = box.style;
216       //style.right = style.bottom = style.width = style.height = '';
217       style.position = 'absolute';
218       style.display = 'inline-block';
219       style.boxSizing = style.mozBoxSizing = 'border-box';
220     }
222     function _position(style, maj, min, ext, a, b) {
223       style[maj] = style[min] = '';
224       style[ext] = 'auto';
225       if (a.s < 0 && b.s < 0) {
226         var siz = a.p - b.p - m - m;
227         style[ext] = siz + 'px';
228         var c = 'calc(100% - ' + (b.p + siz + m) + 'px' + ')';
229         style[maj] = '-webkit-' + c;
230         style[maj] = c;
231       } else if (b.s < 0) {
232         style[maj] = a.p + m + 'px';
233         style[min] = b.p + m + 'px';
234       } else {
235         style[maj] = a.p + m + 'px';
236         style[ext] = b.p - a.p - m - m + 'px';
237       }
238     }
240     function position(elt, left, right, top, bottom) {
241       _position(elt.style, 'top', 'bottom', 'height', rows[top], 
242           rows[bottom]);
243       _position(elt.style, 'left', 'right', 'width', columns[left], 
244           columns[right]);
245     }
247     function layout(matrix, anodes, alineParent) {
248       //console.group('layout');
250       lineParent = alineParent;
251       nodes = anodes;
252       matrixillate(matrix);
254       nodes.forEach(unposition);
256       columns = railize(colCount, colWidth);
257       rows = railize(rowCount, rowHeight);
259       if (alineParent) {
260         //console.group('column rails');
261         columns.forEach(function(c) {
262           //console.log(c.p, c.s);
263           line('left', c.p, c.s);
264         });
265         //console.groupEnd();
267         //console.group('row rails');
268         rows.forEach(function(r) {
269           //console.log(r.p, r.s);
270           line('top', r.p, r.s);
271         });
272         //console.groupEnd();
273       }
275       //console.group('rail boundaries');
276       nodes.forEach(function(node, i) {
277         // node indices are 1-based
278         var n = i + 1;
279         // boundary rails
280         var l, r, t = 1e10, b = -1e10;
281         matrix.forEach(function(vector, i) {
282           var f = vector.indexOf(n);
283           if (f > -1) {
284             l = f;
285             r = vector.lastIndexOf(n) + 1;
286             t = Math.min(t, i);
287             b = Math.max(b, i) + 1;
288           }
289         });
290         if (l == undefined) {
291           //console.log('unused');
292           node.style.position = 'absolute';
293           var offscreen = node.getAttribute('offscreen');
294           switch (offscreen) {
295             case 'basement':
296               node.style.zIndex = 0;
297               break;
298             case 'left':
299             case 'top':
300               node.style[offscreen] = node.offsetWidth * -2 + 'px';
301               break;
302             case 'right':
303               node.style.left = node.offsetParent.offsetWidth 
304                   + node.offsetWidth + 'px';
305               break;
306             case 'bottom':
307               node.style.top = node.parentNode.offsetHeight 
308                   + node.offsetHeight + 'px';
309               break;
310             default:
311               node.style[Math.random() >= 0.5 ? 'left' : 'top'] = '-110%';
312           }
313           //node.style.opacity = 0;
314           node.style.pointerEvents = 'none';
315         } else {
316           node.style.pointerEvents = '';
317           //node.style.opacity = '';
318           //console.log(l, r, t, b);
319           position(node, l, r, t, b);
320         }
321       });
322       //console.groupEnd();
323       //console.groupEnd();
324     }
326   })();