Skip to content

Instantly share code, notes, and snippets.

@junkor-1011
Last active September 22, 2020 17:22
Show Gist options
  • Select an option

  • Save junkor-1011/be5ec83ffc8baff46003f8982713237e to your computer and use it in GitHub Desktop.

Select an option

Save junkor-1011/be5ec83ffc8baff46003f8982713237e to your computer and use it in GitHub Desktop.
D3 TimeSeries Graphs in jQuery-UI Dialog
{
"times": ["2020-09-21 16:40:00", "2020-09-22 17:45:00", "2020-09-23 18:50:00", "2020-09-24 19:55:00", "2020-09-25 21:00:00"],
"A": [3, 10, -3, 6, 2],
"B": [3.5, -10.3, -3.2, -5.6, 2.9],
"C": [13, 8.7, -13, -1.6, 12.9]
}
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<title>D3 time series graph with jQuery UI Dialog</title>
<!-- stylesheet -->
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
/>
<link
rel="stylesheet"
href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"
/>
<link rel="stylesheet" href="/resources/demos/style.css" />
<!-- javascript library -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
async
></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
async
></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://d3js.org/d3.v6.min.js" async></script>
</head>
<body>
<h1>Test: D3 Graph in Dialog</h1>
<div id="dialog" title="Basic dialog">
<!-- Initialize a select button -->
<select id="selectButton"></select>
<!-- Create a div where the graph will take place -->
<div id="d3_dataviz"></div>
</div>
<button id="opener" class="btn btn-primary btn-lg">Open Dialog</button>
<!-- read script -->
<script src="./main.js"></script>
</body>
</html>
// ***
// variables ------------------
let readData; // for DEBUG
let readDataFormated; // for DEBUG
const dataPath = './data.json';
const DialogSize = {
width: 800,
height: 600,
};
const margin = {
top: 10,
bottom: 30,
left: 30,
right: 50,
};
const graphSize = {
width: DialogSize.width - margin.left - margin.right,
height: DialogSize.height - margin.top - margin.bottom,
};
// functions
const plotGraphD3 = (json) => {
// parseDate
// CAUTION: this process will override original object.
const dataTimeFormated = Object.assign(json, {
times: json.times.map((x) => {
return d3.timeParse('%Y-%m-%d %H:%M:%S')(x);
}),
});
// make data
const dataKeys = Object.keys(dataTimeFormated);
const dataSize = dataTimeFormated[dataKeys[0]].length;
const data = [];
for (let i = 0; i < dataSize; i++) {
const record = {};
dataKeys.forEach((key) => {
record[key] = dataTimeFormated[key][i];
});
data.push(record);
}
console.log(data);
readDataFormated = data;
// append the svg
const svg = d3
.select('#d3_dataviz')
.append('svg')
.attr('width', DialogSize.width)
.attr('height', DialogSize.height)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
// button
const allGroup = ['A', 'B', 'C'];
d3.select('#selectButton')
.selectAll('myOptions')
.data(allGroup)
.enter()
.append('option')
.text((d) => {
return d;
})
.attr('value', (d) => {
return d;
});
// x-axis
console.log(
d3.extent(data, (d) => {
return d.times;
})
); // DEBUG
const x = d3
.scaleTime()
.domain(
d3.extent(data, (d) => {
return d.times;
})
)
.range([0, graphSize.width]);
svg
.append('g')
.attr('transform', `translate(0, ${graphSize.height})`)
.attr('id', 'axisX')
.call(d3.axisBottom(x));
// y-axis
const y = d3.scaleLinear().domain([-15, 15]).range([graphSize.height, 0]);
svg.append('g').attr('id', 'axisY').call(d3.axisLeft(y));
// draw line
const line = svg
.append('g')
.append('path')
.attr('class', 'high')
.datum(data)
.attr(
'd',
d3
.line()
.x(function (d) {
return x(d.times);
})
.y(function (d) {
return y(d.A);
})
)
.attr('stroke', 'black')
.attr('stroke-width', 4)
.attr('fill', 'none');
// draw dots
const dot = svg
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function (d) {
return x(d.times);
})
.attr('cy', function (d) {
return y(d.A);
})
.attr('r', 3)
.style('fill', '#0000ff');
// implement update
const update = (selectedGroup) => {
const dataFilter = data.map((d) => {
return { times: d.times, value: d[selectedGroup] };
});
console.log(dataFilter);
// update axis
d3.select('#axisX').remove();
d3.select('#axisY').remove();
x.domain(
d3.extent(dataFilter, (d) => {
return d.times;
})
);
y.domain([
d3.min(dataFilter, (d) => {
return d.value;
}),
d3.max(dataFilter, (d) => {
return d.value;
}),
]);
svg
.append('g')
.attr('id', 'axisX')
.attr('transform', `translate(0, ${graphSize.height})`)
.call(d3.axisBottom(x));
svg.append('g').attr('id', 'axisY').call(d3.axisLeft(y));
// Give these new data to update
line
.datum(dataFilter)
.transition()
.duration(1000)
.attr(
'd',
d3
.line()
.x((d) => {
return x(d.times);
})
.y((d) => {
return y(d.value);
})
);
dot
.data(dataFilter)
.transition()
.duration(1000)
.attr('cx', (d) => {
return x(d.times);
})
.attr('cy', (d) => {
return y(d.value);
});
};
// When the button is changed, run the updateChart function
d3.select('#selectButton').on('change', (event) => {
// recover the option that has been chosen
const selectedOption = d3.select(event.currentTarget).property('value');
// run the updateChart function with this selected option
console.log(selectedOption); // for DEBUG
update(selectedOption);
});
};
const loadAndSetData = () => {
const query = {};
fetch(dataPath + '?' + new URLSearchParams(query))
.then((a) => (a.ok ? a.json() : null))
.then((json) => {
readData = JSON.parse(JSON.stringify(json));
plotGraphD3(json);
})
.catch((error) => {
console.error('Error:', error);
});
return { message: 'Done.' };
};
// actions -------------------
// dialog
$('#dialog').dialog({
autoOpen: false,
modal: false,
title: 'D3 TimeSeries Graph Sample',
width: DialogSize.width,
height: DialogSize.height,
});
// button(opener)
$('#opener').on('click', () => {
// clear inner dialog
$('#dialog')
.empty()
.append('<select id="selectButton"></select>')
.append('<div id="d3_dataviz"></div>');
// load data & call d3
const result = loadAndSetData();
console.log(result);
// open dialog
$('#dialog').dialog('open');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment