-
Notifications
You must be signed in to change notification settings - Fork 7
/
dashboard.html
252 lines (228 loc) · 7.68 KB
/
dashboard.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<!-- pull in D3, Crossfilter, and dc.js libraries -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js' type='text/javascript'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js' type='text/javascript'></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0-beta.27/dc.min.js"></script>
<!-- Switched DC.js version since -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0-beta.27/dc.min.css"/>
<style type="text/css">
.pager.pager-prev {
margin-right: 1em;
}
</style>
</head>
<body>
<div class="container">
<!-- new! first pie chart -->
<div class="row">
<div id="gain-loss-chart">
<strong>Days by Gain/Loss</strong>
<a class="reset" href="javascript:gainOrLossChart.filterAll();dc.redrawAll();" style="display: none;">reset</a>
<div class="clearfix"></div>
</div>
</div>
<div class="row">
<!-- create navigation buttons with bootstrap styles -->
<nav>
<ul class="pager">
<li class="pager-prev nasdaqTableFirstButton">
<a href="#">
<< First
</a>
</li>
<li class="nasdaqTablePreviousButton">
<a href="#">
< Previous
</a>
</li>
<span>
<span class="nasdaqTableStartNumber">0</span>-<span class="nasdaqTableEndNumber">0</span>
of <span class="nasdaqTableTotalRowCount">0</span> records.
</span>
<li class="nasdaqTableNextButton">
<a href="#">
Next >
</a>
</li>
<li class="pager-next nasdaqTableLastButton">
<a href="#">
Last >>
</a>
</li>
</ul>
</nav>
<!-- create a table to host the dataTable -->
<table class="dc-data-table table table-hover"></table>
</div> <!-- end row containing datatable -->
</div> <!-- end container -->
<script type='text/javascript'>
var ndx; // this will be our CrossFilter variable
// this is the variable that holds the first pie chart (new!)
var gainOrLossChart = dc.pieChart('#gain-loss-chart');
var nasdaqTable = dc.dataTable('.dc-data-table');
// pagination controls for nasdaqTable
var nasdaqTableOffset = 0, nasdaqTableItemsPerPage = 10;
function nasdaqPaginationDisplay() {
// This function does the following:
// disable << First, Previous if already at 0
// disable >> Next, Last if already at last page
// display number of records shown
var totalRowCount = ndx.size();
// update numbers shown
d3.select(".nasdaqTableTotalRowCount").text(totalRowCount);
d3.select(".nasdaqTableStartNumber").text(nasdaqTableOffset + 1);
d3.select(".nasdaqTableEndNumber").text(
Math.min(nasdaqTableOffset + nasdaqTableItemsPerPage, totalRowCount)
);
// disable first/previous buttons if we're at the start of the list
d3.select(".nasdaqTableFirstButton").classed("disabled",
nasdaqTableOffset <= 0
);
d3.select(".nasdaqTablePreviousButton").classed("disabled",
nasdaqTableOffset <= 0
);
// similarly with next/last buttons if we're at end of list
d3.select(".nasdaqTableNextButton").classed("disabled",
nasdaqTableOffset >= ndx.size() - (ndx.size() % nasdaqTableItemsPerPage)
);
d3.select(".nasdaqTableLastButton").classed("disabled",
nasdaqTableOffset >= ndx.size() - (ndx.size() % nasdaqTableItemsPerPage)
);
// attach click handlers to the buttons and set them to fire only when enabled
d3.select(".nasdaqTableFirstButton").on("click", function() {
if (!d3.select(this).classed("disabled")) {
nasdaqTableFirst();
}
});
d3.select(".nasdaqTablePreviousButton").on("click", function() {
if (!d3.select(this).classed("disabled")) {
nasdaqTablePrevious();
}
});
d3.select(".nasdaqTableNextButton").on("click", function() {
if (!d3.select(this).classed("disabled")) {
nasdaqTableNext();
}
});
d3.select(".nasdaqTableLastButton").on("click", function() {
if (!d3.select(this).classed("disabled")) {
nasdaqTableLast();
}
});
}
function nasdaqTableUpdate() {
// Given the current offset, redraw the table and reset pagination controls
// as necessary
nasdaqTable.beginSlice(nasdaqTableOffset);
nasdaqTable.endSlice(nasdaqTableOffset + nasdaqTableItemsPerPage);
nasdaqTable.redraw();
nasdaqPaginationDisplay();
}
function nasdaqTableFirst() {
// if "<< First" button clicked
nasdaqTableOffset = 0;
nasdaqTableUpdate();
}
function nasdaqTablePrevious() {
// if "< Previous" button clicked
if (nasdaqTableOffset >= nasdaqTableItemsPerPage) {
nasdaqTableOffset -= nasdaqTableItemsPerPage;
nasdaqTableUpdate();
}
}
function nasdaqTableNext() {
// if "> Next" button clicked
nasdaqTableOffset += nasdaqTableItemsPerPage;
nasdaqTableUpdate();
}
function nasdaqTableLast() {
// if ">> Last" button clicked
nasdaqTableOffset = ndx.size() - (ndx.size() % nasdaqTableItemsPerPage);
// TODO: we'll have to change ndx.size() to the number of filtered items eventually
// take care of that later
nasdaqTableUpdate();
}
// end nasdaqTable navigation controls
// load the data in from the CSV with d3
d3.csv('ndx.csv', function (data) {
// coerce the data into the correct format (see Step 2)
var dateFormat = d3.time.format('%m/%d/%Y');
var numberFormat = d3.format('.2f');
data.forEach(function (d) {
d.dd = dateFormat.parse(d.date);
d.close = +d.close; // coerce to number
d.open = +d.open;
d.change = +d.change;
d.volume = +d.volume
});
// load the data into CrossFilter
ndx = crossfilter(data);
var all = ndx.groupAll();
// Create a data dimension
var dateDimension = ndx.dimension(function (d) {
return d.dd;
});
// Create a categorical data dimension for gain/loss
var gainOrLoss = ndx.dimension(function (d) {
return d.open > d.close ? 'Loss' : 'Gain';
});
var gainOrLossGroup = gainOrLoss.group();
// create the gainOrLoss pie chart
gainOrLossChart
.width(180)
.height(180)
.radius(80)
.dimension(gainOrLoss)
.group(gainOrLossGroup) // all below are optional
.label(function (d) {
if (gainOrLossChart.hasFilter() && !gainOrLossChart.hasFilter(d.key)) {
return d.key + '(0%)';
}
var label = d.key;
if (all.value()) { // add in the percentage
label += '(' + Math.floor(d.value / all.value() * 100) + '%)';
}
return label;
})
.transitionDuration(500) // changes transition duration (default: 350 ms)
// create the dataTable
nasdaqTable
.dimension(dateDimension) // obligatory
.group(function (d) {
// obligatory
return 'All';
})
.size(Infinity) // optional, default 25
.columns([ // obligatory
'date',
'open',
'close',
{
label: 'Change', // use this as the column label
format: function (d) {
return numberFormat(d.close - d.open);
}
},
'volume'
])
.sortBy(function (d) {
// optional
return d.dd;
})
.order(
// optional
d3.ascending
)
nasdaqTableUpdate(); // make sure pagination kicks in for the datatable
// before the charts are loaded so we only display
// the first $nasdaqTableItemsPerPage rows
// render all charts (in this case just the datatable)
dc.renderAll();
});
</script>
</body>
</html>