Muze Programmatic trellis layout

by Adarsh Lilha

HTML

<link href="https://cdn.charts.com/lib/muze/core/latest/themes/muze.css" rel="stylesheet">
<script src="https://cdn.charts.com/lib/muze/core/latest/muze.js" type="text/javascript"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<div id="chart"></div>

CSS

body,
html {
  font-family: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif;
  width: 100%;
  height: 100%;
}

.chart {
  margin-left: 20px;
}

.muze-grid-lines path {
  opacity: 0.1;
}

.muze-grid .muze-text-cell {
  font-size: 12px !important;
}

.muze-layer-text text {
  alignment-baseline: central;
}

.chart-div {
  float: left;
  padding: 15px;
}

.muze-layer-point {
  fill-opacity: 1 !important;
}

#chart {
  overflow-y: auto !important;
  text-align: center;
  padding: 0px 10px 10px 10px;
  height: auto;
  min-height: 350px;
}

.twitter-link {
  text-decoration: none;
  color: #3182bd;
  font-weight: 700;
}

.twitter-link:hover {
  text-decoration: underline;
}

.chart-header {
  font-size: 24px !important;
  margin-bottom: 10px;
  color: #5f5f5f !important;
}

JavaScript

const env = muze();
const DataModel = muze.DataModel;
const html = muze.Operators.html;
const require = muze.utils.require;

const users = [
"aplusk","barackobama","c_nyakundih","d_copperfield","elonmusk","hilaryr","hillaryclinton","iamcardib","jack","jashkenas","johnleguizamo","kathyireland","katyperry","kyliejenner","lucaspeterson","marthalanefox","michaeldell","nickconfessore","nickywhelan","nytimes","paulhollywood","paulkagame","poppy","porszag","rambodonkeykong","realalexjones","realdonaldtrump","samiralrifai","seanhannity","senjohnmccain","taylorswift13","twitter"];

d3.json('https://raw.githubusercontent.com/chartshq/muze/master/examples/data/twitter-purge.json', (data) => {
    const jsonData = data;
    const schema = [{
        name: 'user',
        type: 'dimension'
    }, {
        name: 'followers',
        type: 'measure',
        defAggFn: 'avg'
    }, {
        name: 'time',
        type: 'dimension',
        subtype: 'temporal'
    }];

    const formatter = (val) => {
        if (val > 1000000) {
            return `${(val / 1000000).toFixed(2)} M`
        } else if (val > 1000) {
            return `${(val / 1000).toFixed(2)} K`
        } return val.toFixed(2);
    }

    const rootData = new DataModel(jsonData, schema);
    const canvases = [];

    const div = document.createElement('div')
    div.className = 'chart-header muze-header-cell';
    div.innerHTML = 'Charting the Great Twitter Bot Purge of 2018 (A Trellis Example)';
    document.getElementById('chart').appendChild(div);
    users.forEach((user, i) => {
        const newDomNode = document.createElement('div')
        newDomNode.className = 'chart-div';
        newDomNode.id =`chart${i + 1}`;
      	document.getElementById('chart').appendChild(newDomNode);
	
        const canvas = env.canvas()
            .rows([[], ['followers']])
            .columns(['time'])
            .data(rootData.select(f => f.user.value === user))
            .width(250)
            .height(200)
          ...