locked
Using D3.js in LightSwitch RRS feed

  • Question

  • D3.js was mentioned over here.  I checked it out and it looks amazing!  For those of you that are using it in LS:

    - Are you using it without the C1 bits?

    - Can you share an example of how to _render?

    Just to try, I went to http://bl.ocks.org/mbostock/3943967 and grabbed the script for the stacked bars.  I appended a div to the element just to see if I could get the control to render.  I didn't attempt to databind anything, just used the static data in the example.  When I F5 the control flashes on the screen for a second, then disappears.  Not sure how to get this to work.  I can tell, even by the quick flash of the control, that once it's working properly it will look outstanding! 

    This would be a fabulous blog post for one of the experts :O)

    Wednesday, July 2, 2014 4:38 PM

Answers

  • Here is a sample based on that block:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.D3test.ScreenContent_render = function (element, contentItem) {
    
        var n = 4, // number of layers
            m = 29; //58, // number of samples per layer
            stack = d3.layout.stack(),
            layers = stack(d3.range(n).map(function () { return bumpLayer(m, .1); })),
            yGroupMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y; }); }),
            yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 + d.y; }); });
    
        var margin = { top: 40, right: 10, bottom: 20, left: 10 },
            padding = 6,
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;
    
        var xAxisLength = width,
            yAxisLength = height;
    
        var x = d3.scale.ordinal()
            .domain(d3.range(m))
            .rangeRoundBands([0, width], .08);
    
        var y = d3.scale.linear()
            .domain([0, yStackMax])
            .range([height, 0]);
    
        var color = d3.scale.linear()
            .domain([0, n - 1])
            .range(["#ca4", "#055"]);
        //.range(["#aad", "#556"]);
    
        var xAxis = d3.svg.axis()
            .scale(x)
            .tickSubdivide(1)
            .tickSize(10)
            .tickPadding(6)
            .orient("bottom");
    
        var yAxis = d3.svg.axis()
            .orient("left")
            .scale(y)
            .tickSubdivide(1)
            .tickSize(10)
            .tickPadding(6);
    
        //var svg = d3.select("body").append("svg")
        $(element).append("<svg></svg>");
        var svg = d3.select("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
          .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
        var layer = svg.selectAll(".layer")
            .data(layers)
          .enter().append("g")
            .attr("class", "layer")
            .style("fill", function (d, i) { return color(i); });
    
        var rect = layer.selectAll("rect")
            .data(function (d) { return d; })
          .enter().append("rect")
            .attr("x", function (d) { return x(d.x); })
            .attr("y", height)
            .attr("width", x.rangeBand())
            .attr("height", 0);
    
        rect.transition()
            .delay(function (d, i) { return i * 10; })
            .attr("y", function (d) { return y(d.y0 + d.y); })
            .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); });
    
        svg.append("g")
            .attr("class", "x axis x-axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);
    
        svg.append("g")
            .attr("class", "y axis y-axis")
            .attr("transform", "translate(" + padding + ",0)")
            .call(yAxis);
    
        renderXGridlines();
        renderYGridlines();
    
        d3.selectAll("input").on("change", change);
    
        var timeout = setTimeout(function () {
            d3.select("input[value=\"grouped\"]").property("checked", true).each(change);
        }, 2000);
    
        var timeout = setTimeout(function () {
            groupIt();
        }, 8000);
    
        function groupIt() {
            transitionGrouped();
            var timeout = setTimeout(function () {
                stackIt();
            }, 8000);
        }
    
        function stackIt() {
            transitionStacked();
            var timeout = setTimeout(function () {
                groupIt();
            }, 8000);
        }
    
        function change() {
            clearTimeout(timeout);
            if (this.value === "grouped")
                transitionGrouped();
            else
                transitionStacked();
        }
    
        function transitionGrouped() {
            y.domain([0, yGroupMax]);
    
            rect.transition()
                .duration(500)
                .delay(function (d, i) { return i * 10; })
                .attr("x", function (d, i, j) { return x(d.x) + x.rangeBand() / n * j; })
                .attr("width", x.rangeBand() / n)
              .transition()
                .attr("y", function (d) { return y(d.y); })
                .attr("height", function (d) { return height - y(d.y); });
        }
    
        function transitionStacked() {
            y.domain([0, yStackMax]);
    
            rect.transition()
                .duration(500)
                .delay(function (d, i) { return i * 10; })
                .attr("y", function (d) { return y(d.y0 + d.y); })
                .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); })
              .transition()
                .attr("x", function (d) { return x(d.x); })
                .attr("width", x.rangeBand());
        }
    
        // Inspired by Lee Byron's test data generator.
        function bumpLayer(n, o) {
    
            function bump(a) {
                var x = 1 / (.1 + Math.random()),
                    y = 2 * Math.random() - .5,
                    z = 10 / (.1 + Math.random());
                for (var i = 0; i < n; i++) {
                    var w = (i / n - y) * z;
                    a[i] += x * Math.exp(-w * w);
                }
            }
    
            var a = [], i;
            for (i = 0; i < n; ++i) a[i] = o + o * Math.random();
            for (i = 0; i < 5; ++i) bump(a);
            return a.map(function (d, i) { return { x: i, y: Math.max(0, d) }; });
        }
    
        function renderXGridlines() {
            var lines = d3.selectAll("g.x-axis g.tick")
                    .select("line.grid-line")
                    .remove(); // <-D
    
            lines = d3.selectAll("g.x-axis g.tick")
                    .append("line")
                    .classed("grid-line", true)
    
            lines.attr("x1", 0)
                    .attr("y1", 0)
                    .attr("x2", 0)
                    .attr("y2", -yAxisLength);
        }
    
        function renderYGridlines() {
            var lines = d3.selectAll("g.y-axis g.tick")
                    .select("line.grid-line").remove();
    
            lines = d3.selectAll("g.y-axis g.tick")
                    .append("line")
                    .classed("grid-line", true)
    
            lines.attr("x1", 0)
                .attr("y1", 0)
                .attr("x2", xAxisLength)
                .attr("y2", 0);
        }
    
    };

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    • Marked as answer by Hessc Wednesday, July 2, 2014 5:25 PM
    Wednesday, July 2, 2014 4:46 PM

All replies

  • Here is a sample based on that block:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.D3test.ScreenContent_render = function (element, contentItem) {
    
        var n = 4, // number of layers
            m = 29; //58, // number of samples per layer
            stack = d3.layout.stack(),
            layers = stack(d3.range(n).map(function () { return bumpLayer(m, .1); })),
            yGroupMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y; }); }),
            yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 + d.y; }); });
    
        var margin = { top: 40, right: 10, bottom: 20, left: 10 },
            padding = 6,
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;
    
        var xAxisLength = width,
            yAxisLength = height;
    
        var x = d3.scale.ordinal()
            .domain(d3.range(m))
            .rangeRoundBands([0, width], .08);
    
        var y = d3.scale.linear()
            .domain([0, yStackMax])
            .range([height, 0]);
    
        var color = d3.scale.linear()
            .domain([0, n - 1])
            .range(["#ca4", "#055"]);
        //.range(["#aad", "#556"]);
    
        var xAxis = d3.svg.axis()
            .scale(x)
            .tickSubdivide(1)
            .tickSize(10)
            .tickPadding(6)
            .orient("bottom");
    
        var yAxis = d3.svg.axis()
            .orient("left")
            .scale(y)
            .tickSubdivide(1)
            .tickSize(10)
            .tickPadding(6);
    
        //var svg = d3.select("body").append("svg")
        $(element).append("<svg></svg>");
        var svg = d3.select("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
          .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
        var layer = svg.selectAll(".layer")
            .data(layers)
          .enter().append("g")
            .attr("class", "layer")
            .style("fill", function (d, i) { return color(i); });
    
        var rect = layer.selectAll("rect")
            .data(function (d) { return d; })
          .enter().append("rect")
            .attr("x", function (d) { return x(d.x); })
            .attr("y", height)
            .attr("width", x.rangeBand())
            .attr("height", 0);
    
        rect.transition()
            .delay(function (d, i) { return i * 10; })
            .attr("y", function (d) { return y(d.y0 + d.y); })
            .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); });
    
        svg.append("g")
            .attr("class", "x axis x-axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);
    
        svg.append("g")
            .attr("class", "y axis y-axis")
            .attr("transform", "translate(" + padding + ",0)")
            .call(yAxis);
    
        renderXGridlines();
        renderYGridlines();
    
        d3.selectAll("input").on("change", change);
    
        var timeout = setTimeout(function () {
            d3.select("input[value=\"grouped\"]").property("checked", true).each(change);
        }, 2000);
    
        var timeout = setTimeout(function () {
            groupIt();
        }, 8000);
    
        function groupIt() {
            transitionGrouped();
            var timeout = setTimeout(function () {
                stackIt();
            }, 8000);
        }
    
        function stackIt() {
            transitionStacked();
            var timeout = setTimeout(function () {
                groupIt();
            }, 8000);
        }
    
        function change() {
            clearTimeout(timeout);
            if (this.value === "grouped")
                transitionGrouped();
            else
                transitionStacked();
        }
    
        function transitionGrouped() {
            y.domain([0, yGroupMax]);
    
            rect.transition()
                .duration(500)
                .delay(function (d, i) { return i * 10; })
                .attr("x", function (d, i, j) { return x(d.x) + x.rangeBand() / n * j; })
                .attr("width", x.rangeBand() / n)
              .transition()
                .attr("y", function (d) { return y(d.y); })
                .attr("height", function (d) { return height - y(d.y); });
        }
    
        function transitionStacked() {
            y.domain([0, yStackMax]);
    
            rect.transition()
                .duration(500)
                .delay(function (d, i) { return i * 10; })
                .attr("y", function (d) { return y(d.y0 + d.y); })
                .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); })
              .transition()
                .attr("x", function (d) { return x(d.x); })
                .attr("width", x.rangeBand());
        }
    
        // Inspired by Lee Byron's test data generator.
        function bumpLayer(n, o) {
    
            function bump(a) {
                var x = 1 / (.1 + Math.random()),
                    y = 2 * Math.random() - .5,
                    z = 10 / (.1 + Math.random());
                for (var i = 0; i < n; i++) {
                    var w = (i / n - y) * z;
                    a[i] += x * Math.exp(-w * w);
                }
            }
    
            var a = [], i;
            for (i = 0; i < n; ++i) a[i] = o + o * Math.random();
            for (i = 0; i < 5; ++i) bump(a);
            return a.map(function (d, i) { return { x: i, y: Math.max(0, d) }; });
        }
    
        function renderXGridlines() {
            var lines = d3.selectAll("g.x-axis g.tick")
                    .select("line.grid-line")
                    .remove(); // <-D
    
            lines = d3.selectAll("g.x-axis g.tick")
                    .append("line")
                    .classed("grid-line", true)
    
            lines.attr("x1", 0)
                    .attr("y1", 0)
                    .attr("x2", 0)
                    .attr("y2", -yAxisLength);
        }
    
        function renderYGridlines() {
            var lines = d3.selectAll("g.y-axis g.tick")
                    .select("line.grid-line").remove();
    
            lines = d3.selectAll("g.y-axis g.tick")
                    .append("line")
                    .classed("grid-line", true)
    
            lines.attr("x1", 0)
                .attr("y1", 0)
                .attr("x2", xAxisLength)
                .attr("y2", 0);
        }
    
    };

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    • Marked as answer by Hessc Wednesday, July 2, 2014 5:25 PM
    Wednesday, July 2, 2014 4:46 PM
  • A treemap taking data from a json file:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.D3TreeMap.ScreenContent_render = function (element, contentItem) {
        var margin = { top: 40, right: 10, bottom: 10, left: 10 },
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;
    
        //var color = d3.scale.category20c();
        var color = d3.scale.category10();
    
        var treemap = d3.layout.treemap()
            .size([width, height])
            .sticky(true)
            .value(function (d) { return d.size; });
    
        //var div = d3.select("body").append("div")
        var div = d3.select(element).append("div")
            .style("position", "relative")
            .style("width", (width + margin.left + margin.right) + "px")
            .style("height", (height + margin.top + margin.bottom) + "px")
            .style("left", margin.left + "px")
            .style("top", margin.top + "px");
    
        //d3.json("/HTMLClient/flare.json.js", function (error, root) {
        d3.json("/HTMLClient/globalsales.json.js", function (error, root) {
            var node = div.datum(root).selectAll(".node")
                .data(treemap.nodes)
              .enter().append("div")
                .attr("class", "node")
                .call(position)
                .style("background", function (d) { return d.children ? color(d.name) : null; })
                .style("color", "white")
                .append("div")
                .style("font-size", "10pt")
                .style("padding", "2px")
                .text(function (d) { return d.children ? null : d.name + " " + d.size; });
    
            d3.selectAll("input").on("change", function change() {
                var value = this.value === "count"
                    ? function () { return 1; }
                    : function (d) { return d.size; };
    
                node
                    .data(treemap.value(value).nodes)
                  .transition()
                    .duration(1500)
                    .call(position);
            });
        });
    
        function position() {
            this.style("left", function (d) { return d.x + "px"; })
                .style("top", function (d) { return d.y + "px"; })
                .style("width", function (d) { return Math.max(0, d.dx - 1) + "px"; })
                .style("height", function (d) { return Math.max(0, d.dy - 1) + "px"; });
        }
    };

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    Wednesday, July 2, 2014 4:48 PM
  • Zoomable circle packing:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.D3ZoomableCirclePacking.ScreenContent_render = function (element, contentItem) {
    
        var margin = 20,
            diameter = 660;
    
        var color = d3.scale.linear()
            .domain([-1, 5])
            .range(["hsl(122,70%,80%)", "hsl(254,30%,40%)"])
            .interpolate(d3.interpolateHcl);
    
        var pack = d3.layout.pack()
            .padding(2)
            .size([diameter - margin, diameter - margin])
            .value(function (d) { return d.size; })
    
        //var svg = d3.select("body").append("svg")
        $(element).append("<svg></svg>")
        var svg = d3.select("svg")
            .attr("width", diameter)
            .attr("height", diameter)
          .append("g")
            .attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
    
        //d3.json("/HTMLClient/flare.json.js", function (error, root) {
        d3.json("/HTMLClient/globalsales.json.js", function (error, root) {
            if (error) return console.error(error);
    
            var focus = root,
                nodes = pack.nodes(root),
                view;
    
            var circle = svg.selectAll("circle")
                .data(nodes)
              .enter().append("circle")
                .attr("class", function (d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
                .style("fill", function (d) { return d.children ? color(d.depth) : null; })
                .on("click", function (d) { if (focus !== d) zoom(d), d3.event.stopPropagation(); });
    
            var text = svg.selectAll("text")
                .data(nodes)
              .enter().append("text")
                .attr("class", "label")
                .style("fill-opacity", function (d) { return d.parent === root ? 1 : 0; })
                .style("display", function (d) { return d.parent === root ? null : "none"; })
                .text(function (d) { return d.name; });
    
            var node = svg.selectAll("circle,text");
    
            d3.select("body")
                .style("background", color(-1))
                .on("click", function () { zoom(root); });
    
            zoomTo([root.x, root.y, root.r * 2 + margin]);
    
            function zoom(d) {
                var focus0 = focus; focus = d;
    
                var transition = d3.transition()
                    .duration(d3.event.altKey ? 7500 : 750)
                    .tween("zoom", function (d) {
                        var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
                        return function (t) { zoomTo(i(t)); };
                    });
    
                transition.selectAll("text")
                  .filter(function (d) { return d.parent === focus || this.style.display === "inline"; })
                    .style("fill-opacity", function (d) { return d.parent === focus ? 1 : 0; })
                    .each("start", function (d) { if (d.parent === focus) this.style.display = "inline"; })
                    .each("end", function (d) { if (d.parent !== focus) this.style.display = "none"; });
            }
    
            function zoomTo(v) {
                var k = diameter / v[2]; view = v;
                node.attr("transform", function (d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
                circle.attr("r", function (d) { return d.r * k; });
            }
        });
    
        d3.select(self.frameElement).style("height", diameter + "px");
    };

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    Wednesday, July 2, 2014 4:50 PM
  • And a possible set of styles:

    /* logo */
    .msls-large-icon .ui-icon-msls-home {
        background-image: url(Images/user-logo.png) !important;
        background-position-x: 10px !important;
        border-width:0;
        border-style:none;
        width: 170px;
        height: 30px;
        margin-right:8px !important;
        border-radius: 0 !important;
        -webkit-border-radius: 0 !important;
    }
    
    /* D3 Zoomable Circle Packing */
    .node {
      cursor: pointer;
    }
    
    .node:hover {
      stroke: #000;
      stroke-width: 1.5px;
    }
    
    .node--leaf {
      fill: white;
    }
    
    .label {
      font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
      text-anchor: middle;
      text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
      fill: black;
    }
    
    .label,
    .node--root,
    .node--leaf {
      pointer-events: none;
    }
    
    /* D3 treemap */
    .node {
      border: solid 1px white;
      font: 10px sans-serif;
      line-height: 12px;
      overflow: hidden;
      ;
      text-indent: 2px;
    }
    
    /* D3 Choropleth */
    .counties {
      fill: none;
    }
    
    .states {
      fill: none;
      stroke: #fff;
      stroke-linejoin: round;
    }
    
    .q8-9 { fill:rgb(255,198,219); }
    .q7-9 { fill:rgb(247,222,235); }
    .q6-9 { fill:rgb(198,239,219); }
    .q5-9 { fill:rgb(158,225,202); }
    .q4-9 { fill:rgb(107,214,174); }
    .q3-9 { fill:rgb(66,198,146); }
    .q2-9 { fill:rgb(33,181,113); }
    .q1-9 { fill:rgb(8,81,156); }
    .q0-9 { fill:rgb(8,48,107); }
    
    /* D3 Force Diagram*/
    .link {
        stroke: #2E2E2E;
        stroke-width: 2px;
    }
    
    .node {
        stroke: #fff;
        stroke-width: 2px;
    }
    .textClass {
        stroke: #323232;
        font-family: "Lucida Grande", "Droid Sans", Arial, Helvetica, sans-serif;
        font-weight: normal;
        stroke-width: .5;
        font-size: 14px;
    }
    
    /* D3 hexagonal binning */
    .axis text {
      font: 10px sans-serif;
    }
    
    .axis path, .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
    }
    
    .axis text {
        font: 10px sans-serif;
    }
    
    .axis .grid-line{
        stroke: black;
        shape-rendering: crispEdges;
        stroke-opacity: .2;
    }
    
    .hexagon {
      fill: none;
      stroke: #000;
      stroke-width: .5px;
    }
    
    /* D3 calendar */
    /*body {
      font: 10px sans-serif;
      shape-rendering: crispEdges;
    }*/
    
    .day {
      fill: #fff;
      stroke: #ccc;
    }
    
    .month {
      fill: none;
      stroke: #000;
      stroke-width: 2px;
    }
    
    .RdYlGn .q0-11{fill:rgb(165,0,38)}
    .RdYlGn .q1-11{fill:rgb(215,48,39)}
    .RdYlGn .q2-11{fill:rgb(244,109,67)}
    .RdYlGn .q3-11{fill:rgb(253,174,97)}
    .RdYlGn .q4-11{fill:rgb(254,224,139)}
    .RdYlGn .q5-11{fill:rgb(255,255,191)}
    .RdYlGn .q6-11{fill:rgb(217,239,139)}
    .RdYlGn .q7-11{fill:rgb(166,217,106)}
    .RdYlGn .q8-11{fill:rgb(102,189,99)}
    .RdYlGn .q9-11{fill:rgb(26,152,80)}
    .RdYlGn .q10-11{fill:rgb(0,104,55)}
    
    /* Replace user-splash-screen.png with your own splash screen image */
    #msls-id-app-loading .msls-app-loading-img {
        background-image: url(Images/user-splash-screen.png);
    }
    
    /* Font families for screen and dialog headers.  Font families for content inside a screen 
        or dialog are determined by the theme's global font family setting. */
    .msls-header .ui-title {
        font-family: 'Segoe Light', 'Segoe UI Light', 'Segoe UI', 'Segoe WP Light', 'Roboto Light','Frutiger','Helvetica Neue', Helvetica, Arial, sans-serif;
        font-weight: 200;
    }
    
    /* Customizable font styles for screen controls */
    .msls-font-style-large {
    }
    
    .msls-font-style-normal {
    }
    
    .msls-font-style-small {
    }
    
    /* Uncomment the following lines if you want to use certain jQuery Mobile listview features such as 
        count bubbles and icons inside LightSwitch lists. jQuery Mobile relies on list items using 
         for these features.  However, this setting performs poorly on certain mobile 
        devices (webkit based in particular) when there are large numbers of items in the list. */
    /*
    .msls-ctl-list .ui-listview > .ui-li,
    .msls-ctl-list .ui-field-contain.ui-li {
        ;
    }
    */
    
    /* Phone media query (portrait and landscape) */
    @media 
    screen and (max-width: 400px) and (orientation: portrait), 
    screen and (max-width: 640px) and (max-height: 400px) and (orientation: landscape) {
    }
    

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    Wednesday, July 2, 2014 4:51 PM
  • Creating a simple html table dynamically using d3js from LightSwitch collection:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.D3Languages.Languages_render = function (element, contentItem) {
    
        contentItem.screen.getLanguages().done(function (mydata) {
    
            var tb = d3.select(element).append("table")
                .attr("class", "msls-table ui-responsive table-stripe msls-hstretch ui-table ui-table-reflow")
                .attr("role", "grid")
                .attr("date-role", "table");
            //<table class="msls-table ui-responsive table-stripe msls-hstretch ui-table ui-table-reflow" role="grid" data-role="table" data-inset="true"><thead role="rowgroup"><tr><th tabindex="-1" class="msls-table-header ui-btn ui-btn-up-a" style="width: 50%; min-width: 30px;" data-theme="a">Name<th tabindex="-1" class="msls-table-header ui-btn ui-btn-up-a" style="width: 50%; min-width: 30px;" data-theme="a">Description</tr></thead><tbody role="rowgroup"><tr tabindex="-1" class="msls-tr msls-style ui-shadow ui-tr msls-presenter msls-ctl-table-row-layout msls-vauto msls-hstretch msls-presenter-content msls-font-style-normal msls-hscroll msls-table-row" data-icon="false"><td class="msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll" role="gridcell" style="min-width: 30px;"><b class="ui-table-cell-label">Name</b><div class="msls-text"><span class="id-element">OfferStatus</span></div></td><td class="msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll" role="gridcell" style="min-width: 30px;"><b class="ui-table-cell-label">Description</b><div class="msls-text"><span class="id-element">Offer Status</span></div></td></tr><tr tabindex="-1" class="msls-tr msls-style ui-shadow ui-tr msls-presenter msls-ctl-table-row-layout msls-vauto msls-hstretch msls-presenter-content msls-font-style-normal msls-hscroll msls-table-row" data-icon="false"><td class="msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll" role="gridcell" style="min-width: 30px;"><b class="ui-table-cell-label">Name</b><div class="msls-text"><span class="id-element">OfferType</span></div></td><td class="msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll" role="gridcell" style="min-width: 30px;"><b class="ui-table-cell-label">Description</b><div class="msls-text"><span class="id-element">Offer Type</span></div></td></tr><tr tabindex="-1" class="msls-tr msls-style ui-shadow ui-tr msls-presenter msls-ctl-table-row-layout msls-vauto msls-hstretch msls-presenter-content msls-font-style-normal msls-hscroll msls-table-row" data-icon="false"><td class="msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll" role="gridcell" style="min-width: 30px;"><b class="ui-table-cell-label">Name</b><div class="msls-text"><span class="id-element">OfferNumber</span></div></td><td class="msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll" role="gridcell" style="min-width: 30px;"><b class="ui-table-cell-label">Description</b><div class="msls-text"><span class="id-element">Offer Number</span></div></td></tr></tbody></table>
    
            tb.append("th")
                .attr("class", "msls-table-header ui-btn ui-btn-up-a")
                .text("name");
            tb.append("th").attr("class", "msls-table-header ui-btn ui-btn-up-a").text("description");
            tb.append("th").attr("class", "msls-table-header ui-btn ui-btn-up-a").text("created");
            tb.append("th").attr("class", "msls-table-header ui-btn ui-btn-up-a").text("modified");
    
            var tr = tb.selectAll("tr")
            .data(mydata._data)
            .enter().append("tr");
            tr.append("td")
                .attr("class", "msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll")
                .text(function (d) { return d.details._.Name; });
            tr.append("td")
                .attr("class", "msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll")
                .text(function (d) { return d.details._.Description; });
            tr.append("td")
                .attr("class", "msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll")
                .text(function (d) { return d.details._.Created; });
            tr.append("td")
                .attr("class", "msls-column msls-presenter msls-ctl-text msls-vauto msls-hstretch msls-leaf msls-redraw msls-presenter-content msls-font-style-normal msls-hscroll")
                .text(function (d) { return d.details._.Modified; });
    
        })
    };
    

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    Wednesday, July 2, 2014 4:55 PM
  • - Are you using it without the C1 bits?

    I am using it with the C1 bits here:

    Using D3 Controls in ComponentOne Studio for LightSwitch HTML Client

    Basically the C1 extensions writes code for you. It is still using the same d3 library.


    Unleash the Power - Get the LightSwitch HTML Client book

    http://LightSwitchHelpWebsite.com

    Wednesday, July 2, 2014 4:56 PM
  • My sample default.htm contains:

        <script src="http://d3js.org/d3.v3.min.js"></script>
        <script src="http://d3js.org/d3.hexbin.v0.min.js?5c6e4f0"></script>
        <script src="http://d3js.org/queue.v1.min.js"></script>
        <script src="http://d3js.org/topojson.v1.min.js"></script>

    Really do need to clean-up the samples...

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    Wednesday, July 2, 2014 5:01 PM
  • A globalsales.json data sample from me:

    {
        "name": "world",
        "children": [
         {
             "name": "EUROPE",
             "children": [
              {
                  "name": "uk",
                  "children": [
                   {"name": "scotland", "size": 1983},
                   {"name": "england", "size": 7047},
                   {"name": "wales", "size": 1375},
                   {"name": "northern ireland", "size": 1746}
                  ]
              },
            {"name": "portugal", "size": 1041},
            {"name": "spain", "size": 5176},
            {"name": "switzerland", "size": 449},
            {"name": "sweden", "size": 5593},
            {"name": "belgium", "size": 5534},
            {"name": "netherlands", "size": 9201},
            {"name": "france", "size": 19975},
            {"name": "italy", "size": 1116},
            {"name": "germany", "size": 6006}
             ]
         },
         {
             "name": "AM NORTH",
             "children": [
              {
                  "name": "usa",
                  "children": [
                   {"name": "maine", "size": 721},
                   {"name": "washington", "size": 4294},
                   {"name": "california", "size": 9800},
                   {"name": "texas", "size": 3314},
                   {"name": "florida", "size": 2220}
                  ]
              },
              {
                  "name": "canada",
                  "children": [
                  {"name": "toronto", "size": 7121},
                  {"name": "calgary", "size": 4294}
                 ]
              },
              {"name": "mexico", "size": 3100}
             ]
         },
         {"name": "AM SOUTH",
          "children": [
                {"name": "venezuela", "size": 1176},
                {"name": "peru", "size": 1449},
                {"name": "colombia", "size": 2593},
                {"name": "uruguay", "size": 2534},
                {"name": "argentina", "size": 9201},
                {"name": "brazil", "size": 13975}
               ]
         },
         {"name": "ASIAPAC", "size": 8250},
         {"name": "AFRICA", "size": 3100}
       ]
    }

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    Wednesday, July 2, 2014 5:04 PM
  • And a simple USA map, Chloropleth:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.D3Choropleth.ScreenContent_render = function (element, contentItem) {
    
        var width = 960,
            height = 600;
    
        var rateById = d3.map();
    
        var quantize = d3.scale.quantize()
            .domain([0, .15])
            .range(d3.range(9).map(function (i) { return "q" + i + "-9"; }));
    
        var projection = d3.geo.albersUsa()
            .scale(1280)
            .translate([width / 2, height / 2]);
    
        var path = d3.geo.path()
            .projection(projection);
    
        //var svg = d3.select("body").append("svg")
        $(element).append("<svg></svg>")
        var svg = d3.select("svg")
            .attr("width", width)
            .attr("height", height);
    
        queue()
            .defer(d3.json, "/HTMLClient/us.json.js")
            .defer(d3.tsv, "/HTMLClient/unemployment.csv", function (d) { rateById.set(d.id, +d.rate); })
            .await(ready);
    
        function ready(error, us) {
            svg.append("g")
                .attr("class", "counties")
              .selectAll("path")
                .data(topojson.feature(us, us.objects.counties).features)
              .enter().append("path")
                .attr("class", function (d) { return quantize(rateById.get(d.id)); })
                .attr("d", path);
    
            svg.append("path")
                .datum(topojson.mesh(us, us.objects.states, function (a, b) { return a !== b; }))
                .attr("class", "states")
                .attr("d", path);
        }
    
        d3.select(self.frameElement).style("height", height + "px");
    
    };

    Go find some data: "/HTMLClient/us.json.js" and "/HTMLClient/unemployment.csv" :)

    Dave


    Dave Baker | AIDE for LightSwitch | Xpert360 blog | twitter : @xpert360 | Xpert360 website | Opinions are my own. For better forums, remember to mark posts as helpful/answer.

    Wednesday, July 2, 2014 5:10 PM
  • What a treasure trove!!  Thanks so much!

    Surprisingly I was close when I tried the stacked bars.  I tried to append "layer" and "rect" inside a div but not svg as a tag.  This is great!

    Wednesday, July 2, 2014 5:27 PM