1
restaurant-search/static/scripts/grapher.js

577 lines
18 KiB
JavaScript
Raw Normal View History

2014-10-03 02:43:56 +00:00
/*
* Copyright (c) 2015 Alex Yatskov <alex@foosoft.net>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
2014-10-03 02:43:56 +00:00
2014-09-27 01:10:45 +00:00
(function(grapher) {
2014-09-28 07:58:56 +00:00
'use strict';
2014-09-27 01:10:45 +00:00
//
// Range
//
2014-09-27 01:05:48 +00:00
2014-11-08 02:48:10 +00:00
function Range(min, max) {
this.min = Math.min(min, max);
this.max = Math.max(min, max);
2014-09-27 01:05:48 +00:00
2014-11-05 07:47:20 +00:00
this.contains = function(value) {
2014-11-08 02:48:10 +00:00
return value >= this.min && value <= this.max;
2014-09-27 01:10:45 +00:00
};
2014-09-27 01:05:48 +00:00
this.length = function() {
2014-11-08 02:48:10 +00:00
return this.max - this.min;
2014-09-27 01:10:45 +00:00
};
2014-09-27 01:05:48 +00:00
2014-09-27 01:10:45 +00:00
this.clamp = function(value) {
2014-11-08 02:48:10 +00:00
if (value < this.min) {
return this.min;
2014-09-27 01:10:45 +00:00
}
2014-09-27 01:05:48 +00:00
2014-11-08 02:48:10 +00:00
if (value > this.max) {
return this.max;
2014-09-27 01:10:45 +00:00
}
2014-09-27 01:05:48 +00:00
2014-09-27 01:10:45 +00:00
return value;
2014-09-28 07:58:56 +00:00
};
2014-10-31 02:00:43 +00:00
this.include = function(range) {
2014-11-08 02:48:10 +00:00
this.min = Math.min(this.min, range.min);
this.max = Math.max(this.max, range.max);
2014-10-31 02:00:43 +00:00
};
2014-11-05 08:48:07 +00:00
this.offset = function(value) {
2014-11-08 02:48:10 +00:00
return (value - this.min) / this.length();
};
2014-11-05 08:48:07 +00:00
this.project = function(value) {
2014-11-08 02:48:10 +00:00
return this.min + this.length() * value;
2014-11-05 08:48:07 +00:00
};
2014-09-27 01:05:48 +00:00
}
2014-07-08 04:35:52 +00:00
2014-09-27 01:10:45 +00:00
//
// Column
//
2014-07-08 04:35:52 +00:00
2014-10-31 02:15:51 +00:00
function Column(params) {
2015-06-28 02:24:07 +00:00
var _borderColor = '#d3d7cf';
2015-06-28 02:41:42 +00:00
var _bracketColorBg = '#ffffff';
var _bracketColorFg = '#555753';
var _bracketColorPt = '#2e3436';
var _fillColorBg = '#eeeeec';
2015-03-21 11:46:20 +00:00
var _fillColorNeg = '#3465a4';
var _fillColorPos = '#cc0000';
2015-06-28 02:24:07 +00:00
var _panelColor = '#d3d7cf';
var _tickColor = '#d3d7cf';
2015-03-21 11:46:20 +00:00
2015-06-28 02:41:42 +00:00
var _anchorSize = 2;
var _bracketSize = 10;
2015-03-21 11:46:20 +00:00
var _densitySize = 10;
var _desatOffset = -0.3;
2015-06-28 02:41:42 +00:00
var _easeTime = 400;
2015-03-21 11:46:20 +00:00
var _height = 500;
2015-06-28 02:24:07 +00:00
var _padding = 10;
2015-03-21 11:46:20 +00:00
var _panelSize = 20;
2015-06-28 03:36:35 +00:00
var _tickSize = 5;
2015-06-27 04:06:05 +00:00
var _width = 120;
2014-10-31 08:00:12 +00:00
2015-06-28 03:59:45 +00:00
var _indicatorAnim = null;
var _bracketAnim = null;
var _canvas = params.canvas;
var _data = params.data;
2014-11-05 09:31:00 +00:00
var _index = params.index;
var _name = params.name;
2015-06-28 03:59:45 +00:00
var _valueTrans = params.data.value;
var _bracketTrans = params.data.bracket;
2015-06-28 04:30:22 +00:00
var _onStateChanged = params.onStateChanged;
var _range = params.range;
2014-11-05 09:31:00 +00:00
var _scale = params.scale;
2014-11-05 11:14:15 +00:00
var _elements = {};
2014-11-01 06:43:03 +00:00
function createShapes() {
2015-06-28 02:41:42 +00:00
// indicatorBg
_elements.indicatorBg = _canvas.rect(
2015-06-28 02:24:07 +00:00
_densitySize,
2015-06-27 04:06:05 +00:00
0,
2015-06-28 02:24:07 +00:00
_width - (_bracketSize + _densitySize),
2015-06-27 04:06:05 +00:00
_height - _panelSize
).attr({
cursor: 'crosshair',
stroke: _borderColor,
2015-06-28 02:41:42 +00:00
fill: _fillColorBg
2015-06-28 03:14:38 +00:00
}).click(indicatorClick);
2014-11-01 06:43:03 +00:00
2014-11-05 08:48:07 +00:00
// density
2014-11-05 07:48:54 +00:00
_elements.density = _canvas.rect(
2015-06-28 02:24:07 +00:00
0,
2015-06-27 04:06:05 +00:00
0,
_densitySize,
_height - _panelSize
).attr({
stroke: _borderColor
});
2014-11-05 08:48:07 +00:00
// panel
2015-06-27 04:06:05 +00:00
_elements.panel = _canvas.rect(
2015-06-28 02:24:07 +00:00
0,
2015-06-27 04:06:05 +00:00
_height - _panelSize,
2015-06-28 02:24:07 +00:00
_width - _bracketSize,
2015-06-27 04:06:05 +00:00
_panelSize
).attr({
fill: _panelColor
});
2014-11-05 07:48:54 +00:00
2014-11-05 08:48:07 +00:00
// label
2014-11-05 07:48:54 +00:00
_elements.label = _canvas.text(
2015-06-28 03:36:35 +00:00
(_width - _bracketSize) / 2,
2015-06-27 04:06:05 +00:00
_height - _panelSize / 2,
_name
).attr({
'dominant-baseline': 'middle',
2015-06-28 02:41:42 +00:00
'text-anchor': 'middle'
2015-06-27 04:06:05 +00:00
});
2014-11-05 07:48:54 +00:00
2015-06-28 03:14:38 +00:00
// bracketBg
_elements.bracketBg = _canvas.rect(
_width - _bracketSize,
0,
_bracketSize,
_height - _panelSize
).attr({
fill: _bracketColorBg,
cursor: 'ns-resize'
}).click(bracketClick);
2015-06-27 05:41:56 +00:00
// indiciator
updateIndicator(_data.value);
2015-06-27 04:53:26 +00:00
2015-06-27 05:41:56 +00:00
// bracket
2015-06-28 03:59:45 +00:00
updateBracket(_data.bracket);
2015-06-27 04:53:26 +00:00
2014-11-05 08:48:07 +00:00
// tick
2014-11-05 07:47:20 +00:00
if (_range.contains(0.0)) {
var origin = valueToIndicator(0.0);
2015-06-27 04:06:05 +00:00
_elements.tick = _canvas.line(
2015-06-28 02:24:07 +00:00
_densitySize,
2015-06-27 04:06:05 +00:00
origin,
2015-06-28 03:36:35 +00:00
_width - _bracketSize + _tickSize,
2015-06-27 04:06:05 +00:00
origin
).attr({
stroke: _tickColor
});
2014-11-05 07:47:20 +00:00
}
2014-11-01 06:43:03 +00:00
_elements.group = _canvas.group(
2015-06-28 02:41:42 +00:00
_elements.indicatorBg,
_elements.indicator,
2014-11-01 06:43:03 +00:00
_elements.density,
2015-06-28 02:41:42 +00:00
_elements.bracketBg,
2015-06-27 06:07:13 +00:00
_elements.bracketPath,
2015-06-27 04:53:26 +00:00
_elements.bracketMin,
_elements.bracketMax,
2014-11-01 06:43:03 +00:00
_elements.panel,
_elements.tick,
_elements.label
);
2014-11-05 11:14:15 +00:00
_elements.group.transform(
Snap.format('t{x},{y}', {x: _index * (_width + _padding), y: 0})
);
2014-11-08 11:10:51 +00:00
updateDensity();
2014-11-01 06:43:03 +00:00
}
2014-10-31 08:00:12 +00:00
2014-11-08 11:10:51 +00:00
function updateIndicator(value) {
var range = computeIndicatorRange(value);
2015-06-27 05:41:56 +00:00
var fill = computeIndicatorColor(value);
2014-11-09 02:10:12 +00:00
2015-06-27 05:41:56 +00:00
if (_.has(_elements, 'indicator')) {
_elements.indicator.attr({
y: range.min,
height: range.max - range.min,
fill: fill
});
2015-06-28 03:59:45 +00:00
_valueTrans = value;
2015-06-27 05:41:56 +00:00
}
else {
_elements.indicator = _canvas.rect(
2015-06-28 02:24:07 +00:00
_densitySize,
2015-06-27 05:41:56 +00:00
range.min,
2015-06-28 02:24:07 +00:00
_width - (_densitySize + _bracketSize),
2015-06-27 05:41:56 +00:00
(range.max - range.min)
).attr({
cursor: 'crosshair',
fill: fill
2015-06-28 03:14:38 +00:00
}).click(indicatorClick);
2015-06-27 05:41:56 +00:00
}
2014-10-31 08:00:12 +00:00
}
2014-07-08 04:35:52 +00:00
2015-06-28 03:59:45 +00:00
function updateBracket(bracket) {
var visibility = bracket.min <= bracket.max ? 'visible' : 'hidden';
2015-06-27 07:39:40 +00:00
2015-06-28 03:59:45 +00:00
var yMin = valueToBracket(bracket.min);
var yMax = valueToBracket(bracket.max);
2015-06-27 12:51:54 +00:00
var ySize = yMax - yMin;
2015-06-27 07:39:40 +00:00
2015-06-27 12:51:54 +00:00
var xMin = _width - _bracketSize;
var xMax = _width;
2015-06-27 06:07:13 +00:00
var path =
2015-06-27 12:51:54 +00:00
'M' + xMin + ',' + yMin +
'Q' + xMax + ' ' + yMin + ',' + xMax + ' ' + (yMin + ySize * 0.025) +
'v' + ySize * 0.95 +
'Q' + xMax + ' ' + yMax + ',' + xMin + ' ' + yMax;
2015-06-27 06:07:13 +00:00
if (_.has(_elements, 'bracketPath')) {
_elements.bracketPath.attr({
2015-06-27 12:51:54 +00:00
visibility: visibility,
2015-06-27 06:07:13 +00:00
path: path
});
2015-06-28 03:59:45 +00:00
_bracketTrans = bracket;
2015-06-27 06:07:13 +00:00
}
else {
_elements.bracketPath = _canvas.path(path).attr({
2015-06-28 02:24:07 +00:00
visibility: visibility,
2015-06-28 02:41:42 +00:00
fill: _bracketColorBg,
2015-06-28 02:24:07 +00:00
strokeWidth: 1,
2015-06-28 02:41:42 +00:00
stroke: _bracketColorFg,
cursor: 'ns-resize',
2015-06-28 02:24:07 +00:00
'stroke-dasharray': '5, 1'
2015-06-28 03:14:38 +00:00
}).click(bracketClick);
2015-06-27 06:07:13 +00:00
}
2015-06-27 05:41:56 +00:00
if (_.has(_elements, 'bracketMin')) {
_elements.bracketMin.attr({
2015-06-27 12:51:54 +00:00
visibility: visibility,
cy: yMin
2015-06-27 05:41:56 +00:00
});
}
else {
_elements.bracketMin = _canvas.circle(
2015-06-27 12:51:54 +00:00
_width - _bracketSize,
yMin,
_anchorSize
2015-06-27 05:41:56 +00:00
).attr({
2015-06-27 12:51:54 +00:00
visibility: visibility,
2015-06-28 02:41:42 +00:00
fill: _bracketColorPt
2015-06-27 05:41:56 +00:00
});
}
2015-06-27 04:53:26 +00:00
2015-06-27 05:41:56 +00:00
if (_.has(_elements, 'bracketMax')) {
_elements.bracketMax.attr({
2015-06-27 12:51:54 +00:00
visibility: visibility,
cy: yMax
2015-06-27 05:41:56 +00:00
});
}
else {
_elements.bracketMax = _canvas.circle(
2015-06-27 12:51:54 +00:00
_width - _bracketSize,
yMax,
_anchorSize
2015-06-27 05:41:56 +00:00
).attr({
2015-06-27 12:51:54 +00:00
visibility: visibility,
2015-06-28 02:41:42 +00:00
fill: _bracketColorPt
2015-06-27 05:41:56 +00:00
});
}
2015-06-27 04:53:26 +00:00
}
2014-11-08 11:10:51 +00:00
function updateDensity() {
2015-06-28 02:41:42 +00:00
var fill = _fillColorBg;
2015-03-21 11:46:20 +00:00
if (_data.hints.length > 0) {
2015-04-18 10:02:49 +00:00
fill = _canvas.gradient(blendHints());
2015-03-21 11:46:20 +00:00
}
_elements.density.attr({fill: fill});
2014-11-08 11:10:51 +00:00
}
2015-04-18 10:02:49 +00:00
function blendHints() {
2014-10-31 06:58:25 +00:00
var colorStops = 'l(0,0,0,1)';
2014-10-31 07:08:47 +00:00
2015-04-18 10:02:49 +00:00
for (var i = 0, count = _data.hints.length; i < count; ++i) {
2014-09-27 01:10:45 +00:00
var colorPercent = 0;
if (_scale.length() > 0) {
2015-04-18 10:02:49 +00:00
colorPercent = Math.max(0, _data.hints[i].rating - _scale.min) / _scale.length();
2014-09-27 01:10:45 +00:00
}
2014-07-08 04:35:52 +00:00
2014-09-27 01:10:45 +00:00
var colorByte = 0xff - Math.min(0xff, Math.round(0xff * colorPercent));
2015-04-18 10:02:49 +00:00
var colorObj = tinycolor({r: colorByte, g: colorByte, b: colorByte});
2014-09-27 01:10:45 +00:00
var colorStr = colorObj.toHexString();
2014-07-08 04:35:52 +00:00
2014-10-31 06:58:25 +00:00
colorStops += colorStr;
if (i + 1 < count) {
colorStops += '-';
}
2014-10-31 02:15:51 +00:00
}
2014-07-08 04:35:52 +00:00
2014-09-27 01:10:45 +00:00
return colorStops;
2014-10-31 08:00:12 +00:00
}
2014-07-08 04:35:52 +00:00
2015-06-28 04:30:22 +00:00
function updateState(value, bracket) {
var updateBracket = bracket !== null;
var updateValue = value !== null;
2015-06-28 03:36:35 +00:00
2015-06-28 04:30:22 +00:00
if (updateBracket) {
_data.bracket.max = _range.clamp(bracket.max);
_data.bracket.min = _range.clamp(bracket.min);
}
if (updateValue) {
_data.value = _range.clamp(value);
}
if (_onStateChanged) {
_onStateChanged(
_name,
updateValue ? _data.value : null,
updateBracket ? _data.bracket : null
);
2014-09-27 01:10:45 +00:00
}
2014-11-10 10:14:45 +00:00
2015-06-28 03:59:45 +00:00
animateIndicator(_valueTrans, _data.value);
2014-11-08 10:53:13 +00:00
}
2014-11-08 11:10:51 +00:00
function animateIndicator(valueOld, valueNew) {
2014-11-09 03:31:52 +00:00
if (valueOld === valueNew) {
return;
}
2015-06-28 03:59:45 +00:00
if (_indicatorAnim !== null) {
_indicatorAnim.stop();
2014-11-09 03:31:52 +00:00
}
2015-06-28 03:59:45 +00:00
_indicatorAnim = Snap.animate(
2014-11-08 11:10:51 +00:00
valueOld,
valueNew,
2014-11-08 10:53:13 +00:00
function(value) {
2014-11-08 11:10:51 +00:00
updateIndicator(value);
2014-11-08 10:53:13 +00:00
},
_easeTime,
2014-11-10 10:14:45 +00:00
mina.easeinout,
2014-11-08 10:53:13 +00:00
function() {
2015-06-28 03:59:45 +00:00
_indicatorAnim = null;
}
);
}
function animateBracket(bracketOld, bracketNew) {
if (bracketOld.min === bracketNew.min && bracketOld.max === bracketNew.max) {
return;
}
if (_bracketAnim !== null) {
_bracketAnim.stop();
}
_bracketAnim = Snap.animate(
[bracketOld.min, bracketOld.max],
[bracketNew.min, bracketNew.max],
function(bracket) {
updateBracket({min: bracket[0], max: bracket[1]});
},
_easeTime,
mina.easeinout,
function() {
_bracketAnim = null;
2014-11-08 10:53:13 +00:00
}
);
2014-10-31 08:00:12 +00:00
}
2014-07-08 04:35:52 +00:00
2014-11-08 11:10:51 +00:00
function valueColorAdjust(value, color, offset) {
2014-09-27 01:10:45 +00:00
var colorObj = tinycolor(color);
2014-11-08 11:10:51 +00:00
var rangeEnd = value >= 0.0 ? _range.max : _range.min;
2014-11-08 02:48:10 +00:00
var rangeMid = (_range.min + _range.max) / 2.0;
2014-11-08 11:10:51 +00:00
var rangeRat = (value - rangeMid) / (rangeEnd - rangeMid);
2014-09-27 01:10:45 +00:00
var desatVal = Math.max(0.0, 1.0 - rangeRat + offset) * 100.0;
return colorObj.desaturate(desatVal).toHexString();
2014-10-31 08:00:12 +00:00
}
2014-11-08 11:10:51 +00:00
function computeIndicatorColor(value) {
var color = value >= 0.0 ? _fillColorPos : _fillColorNeg;
return valueColorAdjust(value, color, _desatOffset);
2014-10-31 08:00:12 +00:00
}
2014-11-08 11:10:51 +00:00
function computeIndicatorRange(value) {
return new Range(valueToIndicator(0.0), valueToIndicator(value));
}
2015-06-28 03:14:38 +00:00
function valueToControl(control, scalar) {
var box = control.getBBox();
2014-11-05 08:48:07 +00:00
var offset = _range.offset(scalar);
return box.y + box.height * (1.0 - offset);
}
2015-06-28 03:14:38 +00:00
function controlToValue(control, scalar) {
var box = control.getBBox();
2014-11-05 08:48:07 +00:00
var range = new Range(box.y, box.y + box.height);
return -_range.project(range.offset(scalar));
}
2015-06-28 03:14:38 +00:00
function valueToIndicator(scalar) {
return valueToControl(_elements.indicatorBg, scalar);
}
function indicatorToValue(scalar) {
return controlToValue(_elements.indicatorBg, scalar);
}
function valueToBracket(scalar) {
return valueToControl(_elements.bracketBg, scalar);
}
function bracketToValue(scalar) {
return controlToValue(_elements.bracketBg, scalar);
}
function indicatorClick(event, x, y) {
var rect = _canvas.node.getBoundingClientRect();
2015-06-28 03:36:35 +00:00
2015-06-28 04:30:22 +00:00
updateState(indicatorToValue(y - rect.top), null);
2015-06-28 03:14:38 +00:00
}
function bracketClick(event, x, y) {
var mid = (_data.bracket.min + _data.bracket.max) / 2;
var rect = _canvas.node.getBoundingClientRect();
2015-06-28 03:14:38 +00:00
2015-06-28 03:36:35 +00:00
var dist = Math.abs(mid - bracketToValue(y - rect.top));
dist = Math.min(dist, Math.abs(_range.max - mid));
dist = Math.min(dist, Math.abs(_range.min - mid));
2015-06-28 04:30:22 +00:00
updateState(_data.value, {max: mid + dist, min: mid - dist});
2014-11-05 08:48:07 +00:00
}
2014-10-31 08:00:12 +00:00
this.update = function(data, scale) {
2014-11-08 11:10:51 +00:00
_scale = scale;
2014-11-08 10:53:13 +00:00
2014-11-10 10:14:45 +00:00
if (_.has(data, 'value')) {
_data.value = data.value;
2015-06-28 03:59:45 +00:00
animateIndicator(_valueTrans, _data.value);
2014-11-10 10:14:45 +00:00
}
if (_.has(data, 'hints')) {
_data.hints = data.hints;
updateDensity();
}
2015-06-27 04:53:26 +00:00
if (_.has(data, 'bracket')) {
_data.bracket = data.bracket;
2015-06-28 03:59:45 +00:00
animateBracket(_bracketTrans, _data.bracket);
2015-06-27 04:53:26 +00:00
}
2014-09-27 01:10:45 +00:00
};
2014-11-01 06:43:03 +00:00
createShapes();
2014-07-08 04:35:52 +00:00
}
2014-09-27 01:10:45 +00:00
//
// Grapher
//
2014-07-08 04:35:52 +00:00
2014-10-31 02:00:43 +00:00
grapher.Grapher = function(params) {
var _canvas = params.canvas;
var _columns = {};
var _data = {};
2015-03-25 11:25:27 +00:00
var _range = new Range(-1.0, 1.0);
var _useLocalScale = params.useLocalScale || false;
var _displayType = params.displayType || 'density';
2015-06-28 04:30:22 +00:00
var _onStateChanged = params.onStateChanged;
2014-10-31 07:32:10 +00:00
2015-03-21 11:46:20 +00:00
function processHintParameters(columns) {
var displayTypes = {compatibility: 'compatibility', density: 'count'};
var statKey = displayTypes[_displayType];
for (var name in columns) {
var column = columns[name];
for (var i = 0, count = column.hints.length; i < count; ++i) {
2015-03-25 11:25:27 +00:00
column.hints[i].rating = column.hints[i][statKey];
2015-03-21 11:46:20 +00:00
}
}
2014-10-31 07:32:10 +00:00
}
2015-03-21 11:52:47 +00:00
function computeLocalScale(columnData) {
var ratings = _.map(columnData.hints, function(hint) {
2015-03-21 11:46:20 +00:00
return hint.rating;
});
return new Range(0, _.max(ratings));
2015-03-21 11:46:20 +00:00
}
2015-03-21 11:52:47 +00:00
function computeGlobalScale(columnsData) {
2014-10-31 07:32:10 +00:00
var globalScale = null;
2015-03-22 02:19:09 +00:00
for (var name in columnsData) {
var localScale = computeLocalScale(columnsData[name]);
2014-10-31 07:32:10 +00:00
if (globalScale) {
globalScale.include(localScale);
}
else {
globalScale = localScale;
}
}
return globalScale;
}
2015-03-21 11:52:47 +00:00
this.setColumns = function(columnsData) {
processHintParameters(columnsData);
2015-03-21 11:46:20 +00:00
var scale = null;
2014-10-31 07:32:10 +00:00
if (!_useLocalScale) {
2015-03-21 11:52:47 +00:00
scale = computeGlobalScale(columnsData);
2014-09-27 01:10:45 +00:00
}
2014-07-08 04:35:52 +00:00
2014-10-31 06:25:59 +00:00
var index = 0;
2015-03-21 11:52:47 +00:00
for (var name in columnsData) {
var columnData = _data[name] = columnsData[name];
2014-10-31 07:32:10 +00:00
if (_useLocalScale) {
2015-03-21 11:52:47 +00:00
scale = computeLocalScale(columnData);
2014-09-27 01:10:45 +00:00
}
2014-07-08 04:35:52 +00:00
2014-10-31 07:32:10 +00:00
var column = _columns[name];
2014-10-31 02:00:43 +00:00
if (column) {
2015-03-21 11:52:47 +00:00
column.update(columnData, scale);
2014-09-27 01:10:45 +00:00
}
2014-10-31 02:00:43 +00:00
else {
2014-10-31 07:32:10 +00:00
_columns[name] = new Column({
2015-06-28 04:30:22 +00:00
onStateChanged: _onStateChanged,
2014-10-31 07:36:20 +00:00
range: _range,
canvas: _canvas,
2015-03-21 11:52:47 +00:00
data: columnData,
2014-10-31 07:36:20 +00:00
name: name,
scale: scale,
index: index++,
2014-10-31 02:51:11 +00:00
});
2014-10-31 02:00:43 +00:00
}
}
2014-09-28 07:58:56 +00:00
};
2014-07-08 04:35:52 +00:00
2014-09-27 01:10:45 +00:00
this.setUseLocalScale = function(useLocalScale) {
2014-10-31 07:32:10 +00:00
if (useLocalScale != _useLocalScale) {
_useLocalScale = useLocalScale;
this.setColumns(_data);
2014-09-27 01:10:45 +00:00
}
2014-09-28 07:58:56 +00:00
};
2014-07-08 04:35:52 +00:00
2015-03-21 11:46:20 +00:00
this.setDisplayType = function(displayType) {
if (displayType != _displayType) {
_displayType = displayType;
this.setColumns(_data);
}
};
2014-09-28 07:58:56 +00:00
};
2014-09-27 01:10:45 +00:00
}(window.grapher = window.grapher || {}));