11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (function() {
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Polymer('core-layout-grid', {
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      nodes: null,
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      layout: null,
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      auto: false,
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      created: function() {
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this.layout = [];
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      },
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      nodesChanged: function() {
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this.invalidate();
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      },
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      layoutChanged: function() {
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this.invalidate();
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      },
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      autoNodes: function() {
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this.nodes = this.parentNode.children.array().filter(
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          function(node) {
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            switch(node.localName) {
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              case 'core-layout-grid':
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              case 'style':
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                return false;
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            }
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            return true;
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        );
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      },
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      invalidate: function() {
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (this.layout && this.layout.length) {
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // job debounces layout, only letting it occur every N ms
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this.layoutJob = this.job(this.layoutJob, this.relayout);
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      },
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      relayout: function() {
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!this.nodes || this.auto) {
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this.autoNodes();
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        layout(this.layout, this.nodes);
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this.asyncFire('core-layout');
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    });
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    var lineParent;
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function line(axis, p, d) {
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var l = document.createElement('line');
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var extent = (axis === 'left' ? 'width' :
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        (axis === 'top' ? 'height' : axis));
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      l.setAttribute('extent', extent);
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (d < 0) {
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        axis = (axis === 'left' ? 'right' :
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          (axis === 'top' ? 'bottom' : axis));
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      p = Math.abs(p);
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      l.style[axis] = p + 'px';
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      l.style[extent] = '0px';
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      lineParent.appendChild(l);
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    var colCount, colOwners, rowCount, rowOwners;
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function matrixillate(matrix) {
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // mesaure the matrix, must be rectangular
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      rowCount = matrix.length;
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      colCount = rowCount && matrix[0].length || 0;
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // transpose matrix
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var transpose = [];
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (var i=0; i<colCount; i++) {
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var c = [];
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        for (var j=0; j<rowCount; j++) {
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          c.push(matrix[j][i]);
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        transpose.push(c);
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // assign sizing control
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      colOwners = findOwners(matrix);
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      rowOwners = findOwners(transpose);
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //console.log('colOwners', colOwners);
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //console.log('rowOwners', rowOwners);
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function findOwners(matrix) {
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var majCount = matrix.length;
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var minCount = majCount && matrix[0].length || 0;
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var owners = [];
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // for each column (e.g.)
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (var i=0; i<minCount; i++) {
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // array of contained areas
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var contained = {};
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // look at each row to find a containing area
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        for (var j=0; j<majCount; j++) {
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // get the row vector
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          var vector = matrix[j]
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // node index at [i,j]
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          var nodei = vector[i];
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // if a node is there
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (nodei) {
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            // determine if it bounds this column
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            var owns = false;
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            if (i === 0) {
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              owns = (i === minCount-1) || (nodei !== vector[i+1]);
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            } else if (i === minCount - 1) {
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              owns = (i === 0) || (nodei !== vector[i-1]);
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            } else {
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              owns = nodei !== vector[i-1] && nodei !== vector[i+1];
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            }
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            if (owns) {
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              contained[nodei] = 1;
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            }
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // store the owners for this column
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          owners[i] = contained;
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return owners;
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    var nodes;
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function colWidth(i) {
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (var col in colOwners[i]) {
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        col = Number(col);
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (col === 0) {
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          return 96;
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var node = nodes[col - 1];
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (node.hasAttribute('h-flex') || node.hasAttribute('flex')) {
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          return -1;
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var w = node.offsetWidth;
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        //console.log('colWidth(' + i + ') ==', w);
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return w;
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return -1;
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function rowHeight(i) {
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (var row in rowOwners[i]) {
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        row = Number(row);
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (row === 0) {
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          return 96;
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var node = nodes[row - 1];
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (node.hasAttribute('v-flex') || node.hasAttribute('flex')) {
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          return -1;
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var h = node.offsetHeight;
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        //console.log('rowHeight(' + i + ') ==', h);
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return h;
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return -1;
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    var m = 0;
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function railize(count, sizeFn) {
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // create rails for `count` tracks using
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // sizing function `sizeFn(trackNo)`
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // for n tracks there are (n+1) rails
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //   |track|track|track|
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //  0|->sz0|->sz1|<-sz2|0
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //   |track|track|track|
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //  0|->sz0|     |<-sz2|0
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // there can be one elastic track per set
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //   |track|track|track|track|
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //  0|-->s0|-->s1|<--s1|<--s2|0
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // sz1 spans multiple  tracks which makes
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // it elastic (it's underconstrained)
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var rails = [];
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var a = 0;
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (var i=0, x; i<count; i++) {
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        rails[i] = {p: a, s: 1};
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        x = sizeFn(i) + m + m;
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (x == -1) {
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          break;
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        a += x;
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (i === count) {
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        rails[i] = {p: 0, s: -1};
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var b = 0;
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (var ii=count, x; ii>i; ii--) {
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        rails[ii] = {p: b, s: -1};
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        x = sizeFn(ii - 1) + m + m;
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (x !== -1) {
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          b += x;
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return rails;
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(sjmiles): this code tries to preserve actual position,
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // so 'unposition' is really 'naturalize' or something
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function unposition(box) {
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var style = box.style;
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //style.right = style.bottom = style.width = style.height = '';
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      style.position = 'absolute';
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      style.display = 'inline-block';
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      style.boxSizing = style.mozBoxSizing = 'border-box';
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function _position(style, maj, min, ext, a, b) {
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      style[maj] = style[min] = '';
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      style[ext] = 'auto';
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (a.s < 0 && b.s < 0) {
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var siz = a.p - b.p - m - m;
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        style[ext] = siz + 'px';
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var c = 'calc(100% - ' + (b.p + siz + m) + 'px' + ')';
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        style[maj] = '-webkit-' + c;
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        style[maj] = c;
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else if (b.s < 0) {
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        style[maj] = a.p + m + 'px';
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        style[min] = b.p + m + 'px';
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        style[maj] = a.p + m + 'px';
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        style[ext] = b.p - a.p - m - m + 'px';
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function position(elt, left, right, top, bottom) {
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      _position(elt.style, 'top', 'bottom', 'height', rows[top],
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          rows[bottom]);
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      _position(elt.style, 'left', 'right', 'width', columns[left],
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          columns[right]);
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function layout(matrix, anodes, alineParent) {
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //console.group('layout');
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      lineParent = alineParent;
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      nodes = anodes;
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      matrixillate(matrix);
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      nodes.forEach(unposition);
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      columns = railize(colCount, colWidth);
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      rows = railize(rowCount, rowHeight);
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (alineParent) {
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        //console.group('column rails');
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        columns.forEach(function(c) {
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          //console.log(c.p, c.s);
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          line('left', c.p, c.s);
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        });
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        //console.groupEnd();
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        //console.group('row rails');
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        rows.forEach(function(r) {
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          //console.log(r.p, r.s);
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          line('top', r.p, r.s);
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        });
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        //console.groupEnd();
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //console.group('rail boundaries');
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      nodes.forEach(function(node, i) {
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // node indices are 1-based
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var n = i + 1;
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // boundary rails
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        var l, r, t = 1e10, b = -1e10;
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        matrix.forEach(function(vector, i) {
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          var f = vector.indexOf(n);
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (f > -1) {
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            l = f;
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            r = vector.lastIndexOf(n) + 1;
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            t = Math.min(t, i);
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            b = Math.max(b, i) + 1;
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        });
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (l == undefined) {
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          //console.log('unused');
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          node.style.position = 'absolute';
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          var offscreen = node.getAttribute('offscreen');
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          switch (offscreen) {
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            case 'basement':
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              node.style.zIndex = 0;
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              break;
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            case 'left':
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            case 'top':
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              node.style[offscreen] = node.offsetWidth * -2 + 'px';
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              break;
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            case 'right':
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              node.style.left = node.offsetParent.offsetWidth
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  + node.offsetWidth + 'px';
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              break;
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            case 'bottom':
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              node.style.top = node.parentNode.offsetHeight
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  + node.offsetHeight + 'px';
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              break;
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            default:
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              node.style[Math.random() >= 0.5 ? 'left' : 'top'] = '-110%';
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          //node.style.opacity = 0;
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          node.style.pointerEvents = 'none';
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        } else {
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          node.style.pointerEvents = '';
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          //node.style.opacity = '';
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          //console.log(l, r, t, b);
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          position(node, l, r, t, b);
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      });
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //console.groupEnd();
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //console.groupEnd();
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  })();
327