block by timelyportfolio cf046330e9cf89990c0a

cf046330e9cf89990c0a

Full Screen

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.2/normalize.min.css" media="all" rel="stylesheet" type="text/css" />
    <title>css-layout foobar</title>
  </head>
  <body>
    <div layout='{"padding": 10, "flex": "row"}' id="wrapper">
      <!-- notice the layout attribute -->
      <div layout='{"alignSelf": "stretch"}'></div>
      <div layout='{"alignSelf": "stretch"}'></div>
      <div>no layout attribute !</div>
    </div>
    <script src="Layout.js"></script>
    <script src="app.js"></script>
  </body>
</html>

app.js

/* layout debug */
[].forEach.call(
    document.querySelectorAll("*"),
    function(a){
	a.style.outline="1px solid hsl(" + Math.random() * 360 +", 70%, 70%)";
    }
)


function elementToLayoutTree(element){
    var out = {element: element};
    var style = element.getAttribute("layout");

    if(style) {
	    out.style = JSON.parse(style);
    }

// uncomment to make it work
//    if(!styles) {
//	out.style = {};
//    }


    out.children = Array.prototype.slice.call(element.children).map(elementToLayoutTree)
    return out;
}


var wrapper = document.getElementById('wrapper')
var tree = elementToLayoutTree(wrapper);
console.log(tree);


/* css-layout magic is done here

   tree is modified in place */
computeLayout.computeLayout(tree);


function applyLayout(tree) {
    tree.element.style.position = "absolute";

    ['top', 'left', 'width', 'height'].forEach(function(property) {
	tree.element.style[property] = tree.layout[property] + 'px';
    });

    tree.children.forEach(applyLayout);
}



applyLayout(tree);

fc.js

/* globals window */

/**
 * A collection of components that make it easy to build interactive financial charts with D3
 *
 * @namespace fc
 */
window.fc = {
    version: '0.0.0',
    /**
     * Studies, trend-lines and other financial indicators that can be added to a chart
     *
     * @namespace fc.indicators
     */
    indicators: {},
    math: {},
    /**
     * Useful complex scales which add to the D3 scales in terms of render quality.
     * Also, complex financial scales that can be added to a chart
     *
     * @namespace fc.scale
     */
    scale: {
        discontinuity: {}
    },
    series: {},
    tools: {},
    /**
     * Utility components to shorted long winded implementations of common operations.
     * Also includes components for mock data generation and layout.
     *
     * @namespace fc.utilities
     */
    utilities: {}
};

fc_layout.js


        // parses the style attribute, converting it into a JavaScript object
        function parseStyle(style) {
            if (!style) {
                return {};
            }
            var properties = style.split(';');
            var json = {};
            properties.forEach(function(property) {
                var components = property.split(':');
                if (components.length === 2) {
                    var name = components[0].trim();
                    var value = components[1].trim();
                    json[name] = isNaN(value) ? value : Number(value);
                }
            });
            return json;
        }

        // creates the structure required by the layout engine
        function createNodes(el) {
            function getChildNodes() {
                var children = [];
                for (var i = 0; i < el.childNodes.length; i++) {
                    var child = el.childNodes[i];
                    if (child.nodeType === 1) {
                        if (child.getAttribute('layout-css')) {
                            children.push(createNodes(child));
                        }
                    }
                }
                return children;
            }
            return {
                style: parseStyle(el.getAttribute('layout-css')),
                children: getChildNodes(el),
                element: el,
                layout: {
                    width: undefined,
                    height: undefined,
                    top: 0,
                    left: 0
                }
            };
        }

        // takes the result of layout and applied it to the SVG elements
        function applyLayout(node) {
            node.element.setAttribute('layout-width', node.layout.width);
            node.element.setAttribute('layout-height', node.layout.height);
            node.element.setAttribute('transform', 'translate(' + node.layout.left + ', ' + node.layout.top + ')');
            node.children.forEach(applyLayout);
        }

        var layout = function(selection) {
            selection.each(function(data) {
                // compute the width and height of the SVG element
                var style = getComputedStyle(this);
                var width, height;


                if (layout.width.value !== -1) {
                    width = layout.width.value;
                } else {
                    width = parseFloat(style.width) - parseFloat(style.paddingLeft) - parseFloat(style.paddingRight);
                }
                if (layout.height.value !== -1) {
                    height = layout.height.value;
                } else {
                    height = parseFloat(style.height) - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);
                }

                // create the layout nodes
                var layoutNodes = createNodes(this);
                // set the width / height of the root
                layoutNodes.style.width = width;
                layoutNodes.style.height = height;

                // use the Facebook CSS goodness
                computeLayout.computeLayout(layoutNodes);

                // apply the resultant layout
                applyLayout(layoutNodes);
            });
        };


        layout.width = fc.utilities.property(-1);
        layout.height = fc.utilities.property(-1);

fc_property.js

(function(d3, fc) {
    'use strict';

    // a property that follows the D3 component convention for accessors
    // see: http://bost.ocks.org/mike/chart/
    fc.utilities.property = function(initialValue) {

        var accessor = function(newValue) {
            if (!arguments.length) {
                return accessor.value;
            }
            accessor.value = newValue;
            return this;
        };

        accessor.value = initialValue;

        return accessor;
    };

    // a property that follows the D3 component convention for accessors
    // see: http://bost.ocks.org/mike/chart/
    fc.utilities.functorProperty = function(initialValue) {

        var accessor = function(newValue) {
            if (!arguments.length) {
                return accessor.value;
            }
            accessor.value = d3.functor(newValue);
            return this;
        };

        accessor.value = d3.functor(initialValue);

        return accessor;
    };
}(d3, fc));

index_d3fin_comp.html

<!DOCTYPE html>
<html lang="en" meta-charset="utf-8">
<svg id="layout-test"
     style="width: 600px; height: 350px; margin: 10px; background: yellow"
     layout-css="paddingLeft: 10">
  <g layout-css="height: 30; justifyContent: center; flexDirection: row;">
  </g>
  <g layout-css="flex: 1; flexDirection: row;">
    <g layout-css="flex: 1; flexDirection: row; justifyContent: flex-end;">
      <g layout-css="width: 100; height: 100; margin: 10"></g>
    </g>
    <g layout-css="width: 50;"></g>
    <g layout-css="width: 30; justifyContent: center;"></g>
  </g>
  <g layout-css="height: 30; flexDirection: row">
    <g layout-css="flex: 1; marginRight: 80;"></g>
  </g>
  <g layout-css="height: 30; flexDirection: row">
  </g>
</svg>
<script src = "//d3js.org/d3.v3.min.js"></script>
<script src = "fc.js"></script>
<script src = "fc_property.js"></script>
<script src = "fc_layout.js"></script>
<script src="Layout.js"></script>
<script>

    d3.select('#layout-test').call(layout);

    var c10 = d3.scale.category10();

    d3.selectAll("g").filter(function(d) {
        return this.childElementCount === 0;
      })
      .append('rect').attr('fill', function(d, i) { return c10(i); })
      .attr('width', function() {
        return this.parentNode.getAttribute('layout-width')}
      )
      .attr('height', function() {
        return this.parentNode.getAttribute('layout-height')}
      );

</script>
</html>