|
|
- /**
- _enyo.FittableLayout_ provides the base positioning and boundary logic for
- the fittable layout strategy. The fittable layout strategy is based on
- laying out items in either a set of rows or a set of columns, with most of
- the items having natural size, but one item expanding to fill the remaining
- space. The item that expands is labeled with the attribute _fit: true_.
-
- For example, in the following kind, the second component fills the available
- space in the container between the first and third components.
-
- enyo.kind({
- kind: "FittableRows",
- components: [
- {content: "1"},
- {content: "2", fit:true},
- {content: "3"}
- ]
- });
-
- <a href="#enyo.FittableColumnsLayout">enyo.FittableColumnsLayout</a> and
- <a href="#enyo.FittableRowsLayout">enyo.FittableRowsLayout</a> (or their
- subkinds) are used for layout rather than _enyo.FittableLayout_ because they
- specify properties that _enyo.FittableLayout_ expects to be available when
- laying items out.
- */
- enyo.kind({
- name: "enyo.FittableLayout",
- kind: "Layout",
- //* @protected
- calcFitIndex: function() {
- for (var i=0, c$=this.container.children, c; c=c$[i]; i++) {
- if (c.fit && c.showing) {
- return i;
- }
- }
- },
- getFitControl: function() {
- var c$=this.container.children;
- var f = c$[this.fitIndex];
- if (!(f && f.fit && f.showing)) {
- this.fitIndex = this.calcFitIndex();
- f = c$[this.fitIndex];
- }
- return f;
- },
- getLastControl: function() {
- var c$=this.container.children;
- var i = c$.length-1;
- var c = c$[i];
- while ((c=c$[i]) && !c.showing) {
- i--;
- }
- return c;
- },
- _reflow: function(measure, cMeasure, mAttr, nAttr) {
- this.container.addRemoveClass("enyo-stretch", !this.container.noStretch);
- var f = this.getFitControl();
- // no sizing if nothing is fit.
- if (!f) {
- return;
- }
- //
- // determine container size, available space
- var s=0, a=0, b=0, p;
- var n = this.container.hasNode();
- // calculate available space
- if (n) {
- // measure 1
- p = enyo.FittableLayout.calcPaddingExtents(n);
- // measure 2
- s = n[cMeasure] - (p[mAttr] + p[nAttr]);
- //console.log("overall size", s);
- }
- //
- // calculate space above fitting control
- // measure 3
- var fb = f.getBounds();
- // offset - container padding.
- a = fb[mAttr] - ((p && p[mAttr]) || 0);
- //console.log("above", a);
- //
- // calculate space below fitting control
- var l = this.getLastControl();
- if (l) {
- // measure 4
- var mb = enyo.FittableLayout.getComputedStyleValue(l.hasNode(), "margin", nAttr) || 0;
- if (l != f) {
- // measure 5
- var lb = l.getBounds();
- // fit offset + size
- var bf = fb[mAttr] + fb[measure];
- // last offset + size + ending margin
- var bl = lb[mAttr] + lb[measure] + mb;
- // space below is bottom of last item - bottom of fit item.
- b = bl - bf;
- } else {
- b = mb;
- }
- }
-
- // calculate appropriate size for fit control
- var fs = s - (a + b);
- //console.log(f.id, fs);
- // note: must be border-box;
- f.applyStyle(measure, fs + "px");
- },
- //* @public
- /**
- Updates the layout to reflect any changes to contained components or the
- layout container.
- */
- reflow: function() {
- if (this.orient == "h") {
- this._reflow("width", "clientWidth", "left", "right");
- } else {
- this._reflow("height", "clientHeight", "top", "bottom");
- }
- },
- statics: {
- //* @protected
- _ieCssToPixelValue: function(inNode, inValue) {
- var v = inValue;
- // From the awesome hack by Dean Edwards
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
- var s = inNode.style;
- // store style and runtime style values
- var l = s.left;
- var rl = inNode.runtimeStyle && inNode.runtimeStyle.left;
- // then put current style in runtime style.
- if (rl) {
- inNode.runtimeStyle.left = inNode.currentStyle.left;
- }
- // apply given value and measure its pixel value
- s.left = v;
- v = s.pixelLeft;
- // finally restore previous state
- s.left = l;
- if (rl) {
- s.runtimeStyle.left = rl;
- }
- return v;
- },
- _pxMatch: /px/i,
- getComputedStyleValue: function(inNode, inProp, inBoundary, inComputedStyle) {
- var s = inComputedStyle || enyo.dom.getComputedStyle(inNode);
- if (s) {
- return parseInt(s.getPropertyValue(inProp + "-" + inBoundary));
- } else if (inNode && inNode.currentStyle) {
- var v = inNode.currentStyle[inProp + enyo.cap(inBoundary)];
- if (!v.match(this._pxMatch)) {
- v = this._ieCssToPixelValue(inNode, v);
- }
- return parseInt(v);
- }
- return 0;
- },
- //* Gets the boundaries of a node's margin or padding box.
- calcBoxExtents: function(inNode, inBox) {
- var s = enyo.dom.getComputedStyle(inNode);
- return {
- top: this.getComputedStyleValue(inNode, inBox, "top", s),
- right: this.getComputedStyleValue(inNode, inBox, "right", s),
- bottom: this.getComputedStyleValue(inNode, inBox, "bottom", s),
- left: this.getComputedStyleValue(inNode, inBox, "left", s)
- };
- },
- //* Gets the calculated padding of a node.
- calcPaddingExtents: function(inNode) {
- return this.calcBoxExtents(inNode, "padding");
- },
- //* Gets the calculated margin of a node.
- calcMarginExtents: function(inNode) {
- return this.calcBoxExtents(inNode, "margin");
- }
- }
- });
-
- /**
- _enyo.FittableColumnsLayout_ provides a container in which items are laid
- out in a set of vertical columns, with most of the items having natural
- size, but one expanding to fill the remaining space. The one that expands is
- labeled with the attribute _fit: true_.
-
- _enyo.FittableColumnsLayout_ is meant to be used as a value for the
- _layoutKind_ property of other kinds. _layoutKind_ provides a way to add
- layout behavior in a pluggable fashion while retaining the ability to use a
- specific base kind.
-
- For example, the following code will align three components as columns, with
- the second filling the available container space between the first and third.
-
- enyo.kind({
- kind: enyo.Control,
- layoutKind: "FittableColumnsLayout",
- components: [
- {content: "1"},
- {content: "2", fit:true},
- {content: "3"}
- ]
- });
-
- Alternatively, if a specific base kind is not needed, then instead of
- setting the _layoutKind_ attribute, you can set the base kind to
- <a href="#enyo.FittableColumns">enyo.FittableColumns</a>:
-
- enyo.kind({
- kind: "FittableColumns",
- components: [
- {content: "1"},
- {content: "2", fit:true},
- {content: "3"}
- ]
- });
- */
- enyo.kind({
- name: "enyo.FittableColumnsLayout",
- kind: "FittableLayout",
- orient: "h",
- layoutClass: "enyo-fittable-columns-layout"
- });
-
-
- /**
- _enyo.FittableRowsLayout_ provides a container in which items are laid out
- in a set of horizontal rows, with most of the items having natural size, but
- one expanding to fill the remaining space. The one that expands is labeled
- with the attribute _fit: true_.
-
- _enyo.FittableRowsLayout_ is meant to be used as a value for the
- _layoutKind_ property of other kinds. _layoutKind_ provides a way to add
- layout behavior in a pluggable fashion while retaining the ability to use a
- specific base kind.
-
- For example, the following code will align three components as rows, with
- the second filling the available container space between the first and third.
-
- enyo.kind({
- kind: enyo.Control,
- layoutKind: "FittableRowsLayout",
- components: [
- {content: "1"},
- {content: "2", fit:true},
- {content: "3"}
- ]
- });
-
- Alternatively, if a specific base kind is not needed, then instead of
- setting the _layoutKind_ attribute, you can set the base kind to
- <a href="#enyo.FittableRows">enyo.FittableRows</a>:
-
- enyo.kind({
- kind: "FittableRows",
- components: [
- {content: "1"},
- {content: "2", fit:true},
- {content: "3"}
- ]
- });
- */
- enyo.kind({
- name: "enyo.FittableRowsLayout",
- kind: "FittableLayout",
- layoutClass: "enyo-fittable-rows-layout",
- orient: "v"
- });
|