mirror of
https://github.com/bckelley/cgm-remote-monitor.git
synced 2026-08-24 03:14:12 -05:00
stub out time in range tool
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
window._ = require('lodash');
|
||||
window.$ = window.jQuery = require('jquery');
|
||||
window.moment = require('moment-timezone');
|
||||
window.sugar = require('sugar');
|
||||
window.Nightscout = window.Nightscout || {};
|
||||
|
||||
window.Nightscout = {
|
||||
|
||||
+3
-1
@@ -64,19 +64,21 @@
|
||||
"jquery": "^2.1.4",
|
||||
"lodash": "^3.9.1",
|
||||
"long": "~2.2.3",
|
||||
"mfb": "^0.12.0",
|
||||
"minimed-connect-to-nightscout": "git://github.com/mddub/minimed-connect-to-nightscout#v0.2.4",
|
||||
"moment": "2.10.6",
|
||||
"moment-timezone": "^0.4.0",
|
||||
"parse-duration": "^0.1.1",
|
||||
"mongodb": "^2.0.42",
|
||||
"mqtt": "~0.3.11",
|
||||
"node-cache": "^3.0.0",
|
||||
"parse-duration": "^0.1.1",
|
||||
"pushover-notifications": "0.2.0",
|
||||
"request": "^2.58.0",
|
||||
"sgvdata": "git://github.com/ktind/sgvdata.git#wip/protobuf",
|
||||
"share2nightscout-bridge": "git://github.com/bewest/share2nightscout-bridge.git#wip/generalize",
|
||||
"simple-statistics": "~0.7.0",
|
||||
"socket.io": "^1.3.5",
|
||||
"sugar": "^1.4.1",
|
||||
"traverse": "^0.6.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Nightscout performance comparison</title>
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/images/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/images/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/images/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/images/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="/images/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/images/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="/images/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="/images/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="shortcut icon" href="/images/favicon.ico">
|
||||
<meta name="msapplication-TileColor" content="#00a300">
|
||||
<meta name="msapplication-TileImage" content="/images/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
||||
<meta name="theme-color" content="#333333">
|
||||
|
||||
<link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/report.css" />
|
||||
<link rel="stylesheet" type="text/css" href="css/compare.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/bower_components/jquery-ui/themes/ui-lightness/jquery-ui.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1><img src="/images/logo1.png"><span class="translate">Nightscout performance comparison</span></h1>
|
||||
<!--
|
||||
<div id="info"></div>
|
||||
<hr>
|
||||
<div id="pluginchartplaceholders"></div>
|
||||
<div id="chartContainer" ></div>
|
||||
-->
|
||||
<div id="toolbar">
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="menu_holder">
|
||||
|
||||
|
||||
<ul id="menu" class="mfb-component--tr mfb-zoomin" data-mfb-toggle="hover">
|
||||
<li class="mfb-component__wrap">
|
||||
<a href="#" class="mfb-component__button--main">
|
||||
<i class="mfb-component__main-icon--resting ion-plus-round"></i>
|
||||
<i class="mfb-component__main-icon--active ion-close-round"></i>
|
||||
</a>
|
||||
<ul class="mfb-component__list">
|
||||
<li>
|
||||
<a href="#Details" data-mfb-label="Details" class="mfb-component__button--child">
|
||||
<i class="mfb-component__child-icon ion-more"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#Add" data-mfb-label="Add" class="mfb-component__button--child">
|
||||
<i class="mfb-component__child-icon ion-plus"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
<div class="reticle">
|
||||
<div class="controls">
|
||||
<span class="begin"><input class="begin-input" value="two weeks ago"/></span>
|
||||
<span class="interstice">from</span>
|
||||
<span class="end"><input class="end-input" size=30 value="now"/></span>
|
||||
</div>
|
||||
<div class="timeline">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<div id="view">
|
||||
<div class="ranges">
|
||||
</div>
|
||||
<div class="observations">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="templates">
|
||||
<div class="reticle">
|
||||
<div class="controls">
|
||||
<span class="begin"><input class="begin-input" value="two weeks ago"/></span>
|
||||
<span class="interstice">from</span>
|
||||
<span class="end"><input class="end-input" size=30 value="now"/></span>
|
||||
</div>
|
||||
<div class="timeline">
|
||||
</div>
|
||||
</div>
|
||||
<div class="pool">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<b><span class="translate">Authentication status</span>: </b><span id="authentication_placeholder"></span>
|
||||
|
||||
<script src="/api/v1/status.js"></script>
|
||||
<script src="/public/js/bundle.js"></script>
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script src="/bower_components/jQuery-Storage-API/jquery.storageapi.min.js"></script>
|
||||
<script src="/bower_components/tipsy-jmalonzo/src/javascripts/jquery.tipsy.js"></script>
|
||||
<script src="/bower_components/jquery-flot/jquery.flot.js"></script>
|
||||
<script src="/bower_components/jquery-flot/jquery.flot.pie.js"></script>
|
||||
<script src="/bower_components/jquery-flot/jquery.flot.time.js"></script>
|
||||
<script src="/bower_components/jquery-flot/jquery.flot.fillbetween.js"></script>
|
||||
<script src="/bower_components/jquery-ui/jquery-ui.min.js"></script>
|
||||
|
||||
<script src="/report/js/flotcandle.js"></script>
|
||||
<script src="js/report.js"></script>
|
||||
<script src="js/compare.js"></script>
|
||||
<script src="../mfb/mfb.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function ( ) {
|
||||
var toolbar = $('#toolbar');
|
||||
var view = $('#view');
|
||||
var timeline = $('#toolbar .timeline');
|
||||
var templates = $('#templates');
|
||||
|
||||
var manage_opts = {
|
||||
templates: templates
|
||||
}
|
||||
var pools = manager(view, [ ], manage_opts);
|
||||
|
||||
var control = slippy(timeline,
|
||||
{ controls: toolbar.find('.controls')
|
||||
} );
|
||||
var compare = { toolbar: toolbar, timeline: timeline, control: control};
|
||||
Nightscout.compare = compare;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
@import url("../../mfb/mfb.min.css");
|
||||
#chartContainer, #toolbar, #view, #templates {
|
||||
margin: 0 5%;
|
||||
width: 80%;
|
||||
position: relative;
|
||||
min-height: 49%;
|
||||
}
|
||||
|
||||
#chartContainer svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.reticle .controls>span,
|
||||
.reticle .controls .begin,
|
||||
.reticle .controls .end {
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 0;
|
||||
|
||||
}
|
||||
.reticle .controls .interstice {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
line-height: 120%;
|
||||
font-size: 200%;
|
||||
}
|
||||
.reticle .controls .begin {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
.reticle .controls .end {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.reticle .controls INPUT {
|
||||
line-height: 120%;
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
#menu_holder {
|
||||
}
|
||||
|
||||
#menu {
|
||||
}
|
||||
|
||||
.reticle .timeline {
|
||||
min-height: 8em;
|
||||
border: 1px solid pink;
|
||||
}
|
||||
|
||||
.axis path,
|
||||
.axis line {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.pool {
|
||||
min-height: 500px;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
|
||||
#templates {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.debug #templates {
|
||||
display: block;
|
||||
}
|
||||
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,405 @@
|
||||
|
||||
|
||||
|
||||
function slippy (dom, opt) {
|
||||
|
||||
console.log(dom, opt);
|
||||
var svg = { };
|
||||
var chart;
|
||||
var container;
|
||||
var scales = { x: { }, y: { } };
|
||||
var dom_width, dom_height, width, height;
|
||||
var scaleExtent = [ 0, 200 ];
|
||||
var zoomer;
|
||||
|
||||
var margin = {top: 20, right: 50, bottom: 20, left: 50};
|
||||
get_dimensions( );
|
||||
|
||||
|
||||
function frame ( ) {
|
||||
get_dimensions( );
|
||||
var range = frame.getRange( );
|
||||
// var width = dom.width( );
|
||||
// var height = dom.height( );
|
||||
svg.attr('width', dom_width)
|
||||
// .attr('height', height)
|
||||
;
|
||||
var begin = scales.x.invert(0);
|
||||
var end = scales.x.invert(width);
|
||||
range = frame.setRange(begin, end);
|
||||
var delta = moment(begin).from(moment(end));
|
||||
// .replace(' ago', '');
|
||||
opt.controls.find('.begin-input').val(delta);
|
||||
opt.controls.find('.end-input').val(end.format(Date.ISO8601_DATETIME));
|
||||
opt.controls.data('range', {begin: begin, end: end});
|
||||
// console.log(width, height, delta)
|
||||
|
||||
// console.log(opt);
|
||||
chart.select(".x.axis").call(frame.xAxis);
|
||||
dom.trigger('refocus', [range, frame]);
|
||||
|
||||
}
|
||||
|
||||
frame.getRange = function _getRange ( ) {
|
||||
return [frame.begin, frame.end];
|
||||
}
|
||||
|
||||
frame.setRange = function _setRange (begin, end) {
|
||||
frame.begin = Date.create(begin);
|
||||
frame.end = Date.create(end);
|
||||
return frame.getRange( );
|
||||
}
|
||||
|
||||
function get_dimensions( ) {
|
||||
dom_width = dom.width( );
|
||||
dom_height = dom.height( );
|
||||
margin = {top: 20, right: 50, bottom: 20, left: 50},
|
||||
width = dom_width - margin.left - margin.right,
|
||||
height = dom_height - margin.top - margin.bottom;
|
||||
}
|
||||
|
||||
function init ( ) {
|
||||
var begin = opt.begin || opt.controls.find('INPUT.begin-input').val( );
|
||||
var end = opt.end || opt.controls.find('INPUT.end-input').val( );
|
||||
var range = frame.setRange(begin, end);
|
||||
var width = dom.width( );
|
||||
var height = dom.height( );
|
||||
svg = d3.select(dom.get(0)).append('svg')
|
||||
.attr('class', 'slippy-chart')
|
||||
;
|
||||
;
|
||||
chart = svg.append('g')
|
||||
.attr('class', 'widget')
|
||||
.attr("tranform", "translate(" + 0 + ", " + margin.top + ")")
|
||||
;
|
||||
scales.x = d3.time.scale( )
|
||||
.domain(range)
|
||||
.nice(d3.time.week)
|
||||
.rangeRound([0, dom.width( )])
|
||||
;
|
||||
scales.y = d3.scale.log( )
|
||||
.domain([ 40, 400 ])
|
||||
.rangeRound([1, dom.height( )])
|
||||
;
|
||||
frame.xAxis = d3.svg.axis( )
|
||||
.scale(scales.x)
|
||||
.ticks(7)
|
||||
.tickSize(12, 1, 1)
|
||||
;
|
||||
chart.append("g")
|
||||
.attr("transform", "translate(" + 0 + ", " + (height / 2) + ")")
|
||||
.attr("class", "x axis")
|
||||
.call(frame.xAxis)
|
||||
;
|
||||
|
||||
zoomer = d3.behavior.zoom( )
|
||||
.x(scales.x)
|
||||
.scaleExtent(scaleExtent)
|
||||
.on('zoom', frame);
|
||||
;
|
||||
svg.call(zoomer);
|
||||
|
||||
// frame.setRange(begin, end);
|
||||
opt.controls.on('change', 'INPUT', refocus);
|
||||
frame( );
|
||||
return frame;
|
||||
}
|
||||
|
||||
function refocus (ev) {
|
||||
var target = $(ev.target);
|
||||
if (target.is('INPUT')) {
|
||||
var begin = opt.controls.find('INPUT.begin-input').val( );
|
||||
var end = opt.controls.find('INPUT.end-input').val( );
|
||||
var range = frame.setRange(begin, end);
|
||||
}
|
||||
scales.x.domain(range)
|
||||
.nice(d3.time.week)
|
||||
;
|
||||
frame( );
|
||||
}
|
||||
|
||||
return init( );
|
||||
// return frame;
|
||||
}
|
||||
|
||||
function manager (view, data, opts) {
|
||||
|
||||
var templates = opts.templates;
|
||||
var item_opts = opts.item_opts || { };
|
||||
var pools = [ ];
|
||||
function manage ( ) {
|
||||
}
|
||||
|
||||
function init ( ) {
|
||||
rows = view.find('.reticle');
|
||||
if (rows.length > 0) {
|
||||
} else {
|
||||
var item = make({ });
|
||||
pools.push(item);
|
||||
}
|
||||
view.on('refocus', '.reticle', on_refocus);
|
||||
return manage;
|
||||
}
|
||||
|
||||
function make (data) {
|
||||
var item = templates.find('.reticle').clone(true);
|
||||
var pool = templates.find('.pool').clone(true);
|
||||
var end = data.end || Date.create('now').format(Date.ISO8601_DATETIME);
|
||||
var begin = data.begin || Date.create(end).rewind({weeks: 6}).format(Date.ISO8601_DATETIME);
|
||||
view.find('.ranges').append(item);
|
||||
view.find('.observations').append(pool);
|
||||
var control = slippy(item.find('.timeline'),
|
||||
{ controls: item.find('.controls')
|
||||
, begin: begin
|
||||
, end: end
|
||||
} );
|
||||
var reticle = {dom: item, control: control};
|
||||
var lense = ranger(pool, { });
|
||||
var display = { dom: pool, control: lense };
|
||||
return { reticle: reticle, display: display };
|
||||
}
|
||||
|
||||
function on_refocus (ev, range) {
|
||||
var target = $(ev.target);
|
||||
var pool = pools.filter(function (pool) {
|
||||
var timeline = pool.reticle.dom.find('.timeline');
|
||||
return timeline.is(target);
|
||||
}).pop( );
|
||||
if (pool) {
|
||||
pool.display.control.setRange(range[0], range[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return init( );
|
||||
}
|
||||
|
||||
function pager (opts) {
|
||||
var query = { };
|
||||
var url = opts.url || '/api/v1/entries.json?find[type]=sgv&find[sgv][$gt]=39&count=500000&';
|
||||
query.begin = opts.begin;
|
||||
query.end = opts.end;
|
||||
var payload;
|
||||
function page ( ) {
|
||||
}
|
||||
|
||||
function refresh (start, end) {
|
||||
// console.log("PAYLOAD?", payload);
|
||||
if (payload) {
|
||||
// TODO: soft update, only get deltas against the edges of the
|
||||
// cursor.
|
||||
// start.isBefore
|
||||
// start.isBetween
|
||||
// start.isAfter
|
||||
// end.isBefore
|
||||
// end.isBetween
|
||||
// end.isAfter
|
||||
do_query(start, end, first_page);
|
||||
} else {
|
||||
do_query(start, end, first_page);
|
||||
}
|
||||
query.begin = start;
|
||||
query.end = end;
|
||||
}
|
||||
|
||||
function param_string (begin, end) {
|
||||
return [
|
||||
"find[dateString][$gte]=" + Date.create(begin).format(Date.ISO8601_DATETIME)
|
||||
, "find[dateString][$lte]=" + Date.create(end).format(Date.ISO8601_DATETIME)
|
||||
].join('&')
|
||||
}
|
||||
|
||||
function do_query (begin, end, cb) {
|
||||
var fetch = url + param_string(begin, end);
|
||||
$.getJSON(fetch, cb);
|
||||
}
|
||||
|
||||
function first_page (resp) {
|
||||
// console.log('resp', resp);
|
||||
payload = resp;
|
||||
do_payload( );
|
||||
}
|
||||
|
||||
function do_payload ( ) {
|
||||
if (opts.callback && opts.callback.call) {
|
||||
opts.callback(payload);
|
||||
} else {
|
||||
console.log(payload);
|
||||
}
|
||||
}
|
||||
|
||||
function init ( ) {
|
||||
if (query.begin && query.end) {
|
||||
do_query(query.begin, query.end, first_page);
|
||||
}
|
||||
page( );
|
||||
return page;
|
||||
}
|
||||
|
||||
page.refresh = refresh;
|
||||
|
||||
return init( );
|
||||
}
|
||||
|
||||
function time_in_range (data, opts) {
|
||||
var range = {
|
||||
high: 180
|
||||
, low: 80
|
||||
};
|
||||
|
||||
function sgv (d) { return d.sgv; }
|
||||
function is_clean (d) { return sgv(d) > 39; }
|
||||
function is_in_range (d) { return sgv(d) >= range.low && sgv(d) <= range.high; }
|
||||
function is_high (d) { return sgv(d) > range.high; }
|
||||
function is_low (d) { return sgv(d) < range.low; }
|
||||
var results = [ ];
|
||||
var days = d3.nest( )
|
||||
.key(function (d) {
|
||||
return Date.create(d.dateString).format('{yyyy}-{MM}-{dd}')
|
||||
} )
|
||||
.rollup(function (leaves) {
|
||||
var clean = leaves.filter(is_clean);
|
||||
var nominal = clean.filter(is_in_range);
|
||||
var highs = clean.filter(is_high);
|
||||
var lows = clean.filter(is_low);
|
||||
return {
|
||||
length: clean.length
|
||||
, color: opts.color || '#eee'
|
||||
, target: nominal.length / clean.length * 100
|
||||
, highs: highs.length / clean.length * 100
|
||||
, lows: lows.length / clean.length * 100
|
||||
, mean: d3.mean(clean, sgv)
|
||||
, median: d3.median(clean, sgv)
|
||||
};
|
||||
} )
|
||||
.entries(data);
|
||||
;
|
||||
return days;
|
||||
}
|
||||
|
||||
function ranger (dom, opts) {
|
||||
var scales = { x: { }, y: { } };
|
||||
var dimensions = {height: null, width: null };
|
||||
var margin = {top: 20, right: 50, bottom: 20, left: 50};
|
||||
var xAxis, yAxis;
|
||||
var dom_width, dom_height;
|
||||
var width, height;
|
||||
var root = { };
|
||||
var dots = { };
|
||||
var chart = { };
|
||||
|
||||
function my ( ) {
|
||||
console.log('dots', dots);
|
||||
// dots = chart.selectAll('circle')
|
||||
// dots.enter( )
|
||||
// .append("circle")
|
||||
}
|
||||
|
||||
function render_circles (dots) {
|
||||
console.log('selection', dots);
|
||||
dots.append('circle')
|
||||
.attr("class", "dot")
|
||||
.attr("r", 5)
|
||||
.attr("title", function (d) { return d.key; })
|
||||
.attr("color", function (d) { return d.values.color; })
|
||||
.attr("cx", function (d) {console.log(d); return scales.x(d.values.target); })
|
||||
.attr("cy", function (d) { return scales.y(d.values.mean); })
|
||||
}
|
||||
|
||||
function render (selection) {
|
||||
console.log('selection');
|
||||
}
|
||||
|
||||
my.setRange = function _setRange (begin, end) {
|
||||
adjuster(begin, end);
|
||||
}
|
||||
|
||||
function adjust_range (begin, end) {
|
||||
my.page.refresh(begin, end);
|
||||
}
|
||||
|
||||
var adjuster = _.debounce(adjust_range, 1000);
|
||||
|
||||
function on_data (payload) {
|
||||
var days = time_in_range(payload, opts);
|
||||
dots.data(days).enter( ).call(render_circles).remove( );
|
||||
my( );
|
||||
console.log('got days', days);
|
||||
}
|
||||
|
||||
function init ( ) {
|
||||
my.page = pager({begin: opts.begin, end: opts.end, callback: on_data});
|
||||
get_dimensions( );
|
||||
|
||||
scales.x = d3.scale.linear( )
|
||||
.domain([0, 100])
|
||||
.range([0, width])
|
||||
;
|
||||
|
||||
scales.y = d3.scale.log( )
|
||||
.domain( [40, 400] )
|
||||
.rangeRound( [height - (margin.top + margin.bottom), 1] )
|
||||
.base(12)
|
||||
;
|
||||
|
||||
|
||||
// Axis
|
||||
xAxis = d3.svg.axis( )
|
||||
.ticks(10)
|
||||
.scale(scales.x)
|
||||
.tickFormat(function(d) { return parseInt(d, 10) + "%"; })
|
||||
.orient('top')
|
||||
// d3.svg.axis()
|
||||
// .scale(x)
|
||||
// .ticks(my.range.length)
|
||||
// .tickSize(12, 1, 1)
|
||||
;
|
||||
;
|
||||
// .tickFormat(d3.time.format('%m/%d/%y'))
|
||||
//.tickSize(25, 18);
|
||||
|
||||
|
||||
yAxis = d3.svg.axis()
|
||||
.scale(scales.y)
|
||||
.tickValues([40, 60, 70, 80, 120, 160, 180, 200, 220, 260, 300, 350, 400])
|
||||
.tickFormat(d3.format("d"))
|
||||
.tickSize(6, 3, 1)
|
||||
.orient('left')
|
||||
;
|
||||
|
||||
root = d3.select(dom.get(0)).append('svg')
|
||||
.attr('class', 'ranger')
|
||||
.attr('height', dom_height)
|
||||
.attr('width', dom_width)
|
||||
;
|
||||
|
||||
chart = root.append('g')
|
||||
.attr("transform", "translate(" + 0 + ", " + (margin.top) + ")")
|
||||
.attr('class', 'ranger-chart')
|
||||
;
|
||||
|
||||
chart.append("g")
|
||||
.attr("transform", "translate(" + margin.left + ", " + (margin.top) + ")")
|
||||
.attr("class", "x axis")
|
||||
.call(xAxis)
|
||||
;
|
||||
chart.append("g")
|
||||
.attr("transform", "translate(" + margin.left + ", " + (margin.top) + ")")
|
||||
// .attr("transform", "translate(" + dom_width + ", " + (0) + ")")
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis)
|
||||
;
|
||||
dots = chart.selectAll("circle");
|
||||
return my;
|
||||
}
|
||||
|
||||
function get_dimensions( ) {
|
||||
dom_width = dom.width( );
|
||||
dom_height = dom.height( );
|
||||
margin = {top: 20, right: 50, bottom: 20, left: 50},
|
||||
width = dom_width - margin.left - margin.right,
|
||||
height = dom_height - margin.top - margin.bottom;
|
||||
}
|
||||
|
||||
return init( );
|
||||
}
|
||||
@@ -77,7 +77,7 @@
|
||||
filter.subcategory = '';
|
||||
$('#rp_subcategory').empty().append('<option value="">' + translate('(none)') + '</option>');
|
||||
if (filter.category !== '') {
|
||||
Object.keys(food_categories[filter.category]).forEach(function eachSubCategory(s) {
|
||||
Object.keys(food_categories[filter.category] || {}).forEach(function eachSubCategory(s) {
|
||||
$('#rp_subcategory').append('<option value="' + s + '">' + s + '</option>');
|
||||
});
|
||||
}
|
||||
@@ -665,4 +665,4 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user