Index: pkg/polymer/lib/elements/polymer-layout/polymer-layout.html |
diff --git a/pkg/polymer/lib/elements/polymer-layout/polymer-layout.html b/pkg/polymer/lib/elements/polymer-layout/polymer-layout.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..711edf4d59e1735776f549f78065fea83cff60b5 |
--- /dev/null |
+++ b/pkg/polymer/lib/elements/polymer-layout/polymer-layout.html |
@@ -0,0 +1,255 @@ |
+<!-- |
+Copyright 2013 The Polymer Authors. All rights reserved. |
+Use of this source code is governed by a BSD-style |
+license that can be found in the LICENSE file. |
+--> |
+<!-- |
+/** |
+ * @module Polymer Elements |
+ */ |
+/** |
+ * `<polymer-layout>` arranges nodes horizontally via absolution positioning. |
+ * Set the `vertical` attribute (boolean) to arrange vertically instead. |
+ * |
+ * `<polymer-layout>` arranges it's <b>sibling elements</b>, not |
+ * it's children. |
+ * |
+ * One arranged node may be marked as elastic by giving it a `flex` |
+ * attribute (boolean). |
+ * |
+ * You may remove a node from layout by giving it a `nolayout` |
+ * attribute (boolean). |
+ * |
+ * CSS Notes: |
+ * |
+ * * `padding` is ignored on the parent node. |
+ * * `margin` is ignored on arranged nodes. |
+ * * `min-width` is ignored on arranged nodes, use `min-width` on the parent node |
+ * instead. |
+ * |
+ * Example: |
+ * |
+ * Arrange three `div` into columns. `flex` attribute on Column Two makes that |
+ * column elastic. |
+ * |
+ * <polymer-layout></polymer-layout> |
+ * <div>Column One</div> |
+ * <div flex>Column Two</div> |
+ * <div>Column Three</div> |
+ * |
+ * Remember that `<polymer-layout>` arranges it's sibling elements, not it's children. |
+ * |
+ * If body has width 52 device pixels (in this case, ascii characters), call that 52px. |
+ * Column One has it's natural width of 12px (including border), Column Three has it's |
+ * natural width of 14px, body border uses 2px, and Column Two automatically uses the |
+ * remaining space: 24px. |
+ * |
+ * |- 52px -| |
+ * ---------------------------------------------------- |
+ * ||Column One|| Column Two ||Column Three|| |
+ * ---------------------------------------------------- |
+ * |- 12px -||- (24px) -|| 14px -| |
+ * |
+ * As the parent node resizes, the elastic column reacts via CSS to adjust it's size. |
+ * No javascript is used during parent resizing, for best performance. |
+ * |
+ * Changes in content or sibling size is not handled automatically. |
+ * |
+ * ---------------------------------------------------------------- |
+ * ||Column One| Column Two |Column Three|| |
+ * ---------------------------------------------------------------- |
+ * |
+ * -------------------------------------- |
+ * ||Column One|Column Two|Column Three|| |
+ * -------------------------------------- |
+ * |
+ * Arrange in rows by adding the `vertical` attribute. |
+ * |
+ * Example: |
+ * |
+ * <polymer-layout vertical></polymer-layout> |
+ * <div>Row One</div> |
+ * <div flex>Row Two</div> |
+ * <div>Row Three</div> |
+ * |
+ * This setup will cause Row Two to stretch to fill the container. |
+ * |
+ * ----------- ----------- |
+ * |---------| |---------| |
+ * | | | | |
+ * |Row One | |Row One | |
+ * | | | | |
+ * |---------| |---------| |
+ * | | | | |
+ * |Row Two | |Row Two | |
+ * | | | | |
+ * |---------| | | |
+ * | | | | |
+ * |Row Three| | | |
+ * | | |---------| |
+ * |---------| | | |
+ * ----------- |Row Three| |
+ * | | |
+ * |---------| |
+ * |---------| |
+ * |
+ * Layouts can be nested arbitrarily. |
+ * |
+ * <polymer-layout></polymer-layout> |
+ * <div>Menu</div> |
+ * <div flex> |
+ * <polymer-layout vertical></polymer-layout> |
+ * <div>Title</div> |
+ * <div>Toolbar</div> |
+ * <div flex>Main</div> |
+ * <div>Footer</div> |
+ * </div> |
+ * |
+ * Renders something like this |
+ * |
+ * -------------------------------- |
+ * ||Menu ||Title || |
+ * || ||-----------------|| |
+ * || ||Toolbar || |
+ * || ||-----------------|| |
+ * || ||Main || |
+ * || || || |
+ * || ||-----------------|| |
+ * || ||Footer || |
+ * -------------------------------- |
+ * |
+ * @class polymer-layout |
+ * |
+ */ |
+--> |
+<link rel="import" href="../polymer/polymer.html"> |
+ |
+<polymer-element name="polymer-layout" attributes="vertical"> |
+ <template> |
+ <style> |
+ :host { |
+ display: none; |
+ } |
+ </style> |
+ </template> |
+ <script> |
+ Polymer('polymer-layout', { |
+ vertical: false, |
+ ready: function() { |
+ this.setAttribute('nolayout', ''); |
+ }, |
+ enteredView: function() { |
+ this.asyncMethod(function() { |
+ this.prepare(); |
+ this.layout(); |
+ }); |
+ }, |
+ prepare: function() { |
+ var parent = this.parentNode.host || this.parentNode; |
+ // explicit position harmful on <body> |
+ if (parent.localName !== 'body') { |
+ // may recalc |
+ var cs = window.getComputedStyle(parent); |
+ if (cs.position === 'static') { |
+ parent.style.position = 'relative'; |
+ } |
+ //parent.style.overflow = 'hidden'; |
+ } |
+ // changes will cause another recalc at next validation step |
+ var vertical; |
+ this.parentNode.childNodes.array().forEach(function(c, i) { |
+ if (c.nodeType === Node.ELEMENT_NODE && !c.hasAttribute('nolayout')) { |
+ stylize(c, { |
+ position: 'absolute', |
+ boxSizing: 'border-box', |
+ MozBoxSizing: 'border-box', |
+ }); |
+ // test for auto-vertical |
+ if (vertical === undefined) { |
+ vertical = (c.offsetWidth == 0 && c.offsetHeight !== 0); |
+ } |
+ } |
+ }); |
+ this.vertical = this.vertical || vertical; |
+ }, |
+ /** |
+ * Arrange sibling nodes end-to-end in one dimension. |
+ * |
+ * Arrangement is horizontal unless the `vertical` |
+ * attribute is applied on this node. |
+ * |
+ * @method layout |
+ */ |
+ layout: function() { |
+ var parent = this.parentNode.host || this.parentNode; |
+ var vertical = this.vertical; |
+ var ww = 0, hh = 0, pre = [], fit, post = []; |
+ var list = pre; |
+ // gather element information (at most one recalc) |
+ this.parentNode.childNodes.array().forEach(function(c, i) { |
+ if (c.nodeType===Node.ELEMENT_NODE && !c.hasAttribute('nolayout')) { |
+ var info = { |
+ element: c, |
+ w: c.offsetWidth, |
+ h: c.offsetHeight |
+ }; |
+ if (!c.hasAttribute('fit') && !c.hasAttribute('flex')) { |
+ ww += c.offsetWidth; |
+ hh += c.offsetHeight; |
+ list.push(info); |
+ } else { |
+ fit = c; |
+ list = post; |
+ ww = hh = 0; |
+ } |
+ } |
+ }); |
+ // update layout styles (invalidate, no recalc) |
+ var v = 0; |
+ var mxp = 0, myp = 0; |
+ pre.forEach(function(info) { |
+ if (vertical) { |
+ stylize(info.element, { |
+ top: v + 'px', right: mxp, height: info.h + 'px', left: mxp |
+ }); |
+ } else { |
+ stylize(info.element, { |
+ top: myp, width: info.w + 'px', bottom: myp, left: v + 'px' |
+ }); |
+ } |
+ v += vertical ? info.h : info.w; |
+ }); |
+ if (fit) { |
+ if (vertical) { |
+ stylize(fit, { |
+ top: v + 'px', right: mxp, bottom: hh + 'px', left: mxp |
+ }); |
+ } else { |
+ stylize(fit, { |
+ top: myp, right: ww + 'px', bottom: myp, left: v + 'px' |
+ }); |
+ } |
+ v = vertical ? hh : ww; |
+ post.forEach(function(info) { |
+ v -= vertical ? info.h : info.w; |
+ if (vertical) { |
+ stylize(info.element, { |
+ height: info.h + 'px', right: mxp, bottom: v + 'px', left: mxp |
+ }); |
+ } else { |
+ stylize(info.element, { |
+ top: myp, right: v + 'px', bottom: myp, width: info.w + 'px' |
+ }); |
+ } |
+ }); |
+ } |
+ } |
+ }); |
+ function stylize(element, styles) { |
+ var style = element.style; |
+ Object.keys(styles).forEach(function(k){ |
+ style[k] = styles[k]; |
+ }); |
+ } |
+ </script> |
+</polymer-element> |