JSFiddle - React, Tailwind, and code Playground

by tonyleeper

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.3.0.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.js"></script>
<h1>Try entering some different values:</h1>
<!-- ko foreach: dataset -->
    <input type="text" data-bind="value: $data.value" />
<!-- /ko -->

<button data-bind="click: getData">Random</button>

<div class="line-graph" data-bind="lineGraph: dataset"></div>

CSS

* {
    padding: 0;
    margin: 0;
}

html, body {
    height: 100%;
    font-family: verdana;
    font-size: 12px;
    text-align: center;
}

h1 {
    padding: 10px;
}

input {
    width: 50px;
    padding: 5px;
    margin-left: 10px;
}

button {
    padding: 5px;
    margin-left: 10px;
}

svg {
    display: block;
    width: 100%;
    height: 100%;
}

svg .data-point {
    stroke: blue;
    stroke-width: 1.5px;
    fill: white;        
}

svg path {
    fill: none;
    stroke: blue;
    stroke-width: 1.5px;
}

svg .axis path, 
svg .axis line {
    fill: none;
    stroke: black;
}

svg .axis text {
    font-size: 10px;
    fill: black;
}

svg .y-axis-gridlines path,
svg .y-axis-gridlines line {
    opacity: 0.2;
}

JavaScript

/**
    D3 - LineGraph
*/

var format = {
    multipliers: [
        { value: 1e24, suffix: 'Y' },
        { value: 1e21, suffix: 'Z' },
        { value: 1e18, suffix: 'E' },
        { value: 1e15, suffix: 'P' },
        { value: 1e12, suffix: 'T' },
        { value: 1e9, suffix: 'G' },
        { value: 1e6, suffix: 'M' },
        { value: 1e3, suffix: 'k' },
        { value: 1e0, suffix: '' },
        { value: 1e-3, suffix: 'm' },
        { value: 1e-6, suffix: 'µ' },
        { value: 1e-9, suffix: 'n' },
        { value: 1e-12, suffix: 'p' },
        { value: 1e-15, suffix: 'f' },
        { value: 1e-18, suffix: 'a' },
        { value: 1e-21, suffix: 'z' },
        { value: 1e-24, suffix: 'y' }
    ],

    toShortForm: function(n) {
        if (n < 0) {
            return '-' + this.toShortForm(-n);
        }
        
        if (n === 0) {
            return n;
        }
        
        if (n > 1) {
            n = n.toPrecision(3);
        }

        if (n < 1e27 && n > 1e-27) {
            for (var i = 0; i < this.multipliers.length; i++) {
                if (n >= this.multipliers[i].value) {
                    return (n / this.multipliers[i].value).toFixed(1) + this.multipliers[i].suffix
                }
            }
        } 

        return n.toExponential();    
    }
};

ko.bindingHandlers.lineGraph = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // Define the resolution
        var width = 600;
        var height = 300;    
        
        // Create the SVG 'canvas'
        var svg = d3.select(element)
            .append("svg")
            .attr("viewBox", "0 0 " + width + " " + height)
    
        // get the data
        var dataset = ko.unwrap(valueAccessor());
        
        // Define the padding around the graph
        var padding = 50;
        
        // Set the scales
        var minDate = new Date(d3.min(dataset, function(d) { return d.date; }));
       ...