Skip to content

Instantly share code, notes, and snippets.

@markarios
Last active August 29, 2015 14:02
Show Gist options
  • Save markarios/058f85800d598fc9f2b6 to your computer and use it in GitHub Desktop.
Save markarios/058f85800d598fc9f2b6 to your computer and use it in GitHub Desktop.
[
{
"item":"Samsung Galaxy Tab Pro 8.4",
"manufacture":"Samsung",
"type":"tablet",
"di":8.4,
"hp":1600,
"wp":2560,
"dp":3019,
"PPI":359,
"brightness_nits":410,
"Model":"SM-T320NZWAXAR",
"data_source":"http://www.samsung.com/us/mobile/galaxy-tab/SM-T320NZWAXAR",
"collected_date":"06/10/14",
"data_source_brightness":"http://www.phonearena.com/reviews/Samsung-Galaxy-Tab-PRO-8.4-Review_id3588"
},
{
"item":"Apple Ipad Mini with Retina",
"manufacture":"Apple",
"type":"tablet",
"di":7.9,
"hp":2048,
"wp":1536,
"dp":2560,
"PPI":324,
"brightness_nits":450,
"Model":"ME279LL/A",
"data_source":"http://www.apple.com/ipad-mini/",
"collected_date":"06/10/14",
"data_source_brightness":"http://www.phonearena.com/reviews/LG-G-Pad-8.3-vs-Apple-iPad-mini-2-with-Retina-Display_id3527"
},
{
"item":"Dell Ultrasharp 27” Monitor",
"manufacture":"Dell",
"type":"desktop monitor",
"di":27,
"hp":2560,
"wp":1440,
"dp":2937,
"PPI":108,
"brightness_nits":350,
"Model":"U2713H",
"data_source":"http://accessories.us.dell.com/sna/productdetail.aspx?c=us&l=en&cs=19&sku=225-4148",
"collected_date":"06/10/14",
"data_source_brightness":"http://accessories.us.dell.com/sna/productdetail.aspx?c=us&l=en&cs=19&sku=225-4148"
},
{
"item":"Apple 27\" Thunderbolt Display",
"manufacture":"Apple",
"type":"desktop monitor",
"di":27,
"hp":2560,
"wp":1440,
"dp":2937,
"PPI":108,
"brightness_nits":375,
"Model":"MC007LL/A ",
"data_source":"http://www.apple.com/displays/specs.html",
"collected_date":"06/10/14",
"data_source_brightness":"http://www.apple.com/displays/specs.html"
},
{
"item":"HP 20” Flat Screen Monitor",
"manufacture":"HP",
"type":"desktop monitor",
"di":20,
"hp":1600,
"wp":900,
"dp":1836,
"PPI":91,
"brightness_nits":200,
"Model":"W2071D",
"data_source":"http://h20566.www2.hp.com/portal/site/hpsc/template.PAGE/public/kb/docDisplay?javax.portlet.begCacheTok=com.vignette.cachetoken&javax.portlet.endCacheTok=com.vignette.cachetoken&javax.portlet.prp_ba847bafb2a2d782fcbb0710b053ce01=wsrp-navigationalState%3DdocId%253Demr_na-c03361036-1%257CdocLocale%253D%257CcalledBy%253D&javax.portlet.tpst=ba847bafb2a2d782fcbb0710b053ce01&sp4ts.oid=3884696&ac.admitted=1402446358741.876444892.199480143",
"collected_date":"06/10/14",
"data_source_brightness":"http://h20566.www2.hp.com/portal/site/hpsc/template.PAGE/public/kb/docDisplay?javax.portlet.begCacheTok=com.vignette.cachetoken&javax.portlet.endCacheTok=com.vignette.cachetoken&javax.portlet.prp_ba847bafb2a2d782fcbb0710b053ce01=wsrp-navigationalState%3DdocId%253Demr_na-c03361036-1%257CdocLocale%253D%257CcalledBy%253D&javax.portlet.tpst=ba847bafb2a2d782fcbb0710b053ce01&sp4ts.oid=3884696&ac.admitted=1402446358741.876444892.199480143"
},
{
"item":"Apple Imac 27”",
"manufacture":"Apple",
"type":"desktop",
"di":27,
"hp":2560,
"wp":1440,
"dp":2937,
"PPI":108,
"brightness_nits":300,
"Model":"ME088LL/A",
"data_source":"http://www.apple.com/imac/specs/",
"collected_date":"06/10/14",
"data_source_brightness":"http://www.pcmag.com/article2/0,2817,2411377,00.asp"
},
{
"item":"Sharp 32” 4k Ultra HD Monitor",
"manufacture":"Sharp",
"type":"desktop monitor",
"di":32,
"hp":3840,
"wp":2160,
"dp":4406,
"PPI":137,
"brightness_nits":350,
"Model":"PNK321 ",
"data_source":"https://www.sharpusa.com/ForBusiness/PresentationProducts/ProfessionalLCDMonitors/PNK321.aspx",
"collected_date":"06/10/14",
"data_source_brightness":"https://www.sharpusa.com/ForBusiness/PresentationProducts/ProfessionalLCDMonitors/PNK321.aspx"
},
{
"item":"Macbook Air 13”",
"manufacture":"Apple",
"type":"laptop",
"di":13,
"hp":1440,
"wp":900,
"dp":1698,
"PPI":130,
"brightness_nits":288,
"Model":"MD760LL/B",
"data_source":"https://www.apple.com/macbook-air/",
"collected_date":"06/10/14",
"data_source_brightness":"http://www.laptopmag.com/reviews/laptops/apple-macbook-air-13-inch-2014.aspx"
},
{
"item":"Macbook Pro with Retina 13”",
"manufacture":"Apple",
"type":"laptop",
"di":13.3,
"hp":2560,
"wp":1440,
"dp":2937,
"PPI":220,
"brightness_nits":300,
"Model":"ME865LL/A",
"data_source":"http://www.apple.com/macbook-pro/specs-retina/",
"collected_date":"06/10/14",
"data_source_brightness":"http://appleinsider.com/articles/12/10/23/apple-unveils-13-inch-macbook-pro-with-retina-display"
},
{
"item":"Apple Iphone 5S",
"manufacture":"Apple",
"type":"smartphone",
"di":4,
"hp":1136,
"wp":640,
"dp":1304,
"PPI":325,
"brightness_nits":580,
"Model":"ME343LL/A",
"data_source":"http://www.apple.com/iphone-5s/specs/",
"collected_date":"06/10/14",
"data_source_brightness":"http://www.phonearena.com/reviews/Google-Nexus-5-vs-Apple-iPhone-5s_id3480"
},
{
"item":"Google Nexus 5",
"manufacture":"Google",
"type":"smartphone",
"di":4.95,
"hp":1920,
"wp":1080,
"dp":2203,
"PPI":445,
"brightness_nits":480,
"Model":"LGD82016KT",
"data_source":"http://www.google.com/nexus/5/",
"collected_date":"06/10/14",
"data_source_brightness":"http://www.phonearena.com/reviews/Google-Nexus-5-vs-Apple-iPhone-5s_id3480"
},
{
"item":"Kindle Fire HD 7“",
"manufacture":"Amazon",
"type":"tablet",
"di":7,
"hp":1280,
"wp":800,
"dp":1509,
"PPI":215,
"brightness_nits":486,
"Model":"B00C5W16B8",
"data_source":"http://www.amazon.com/Kindle-Fire-HD-Display-Wi-Fi/dp/B00C5W16B8/ref=sr_1_3?s=electronics&ie=UTF8&qid=1402512304&sr=1-3&keywords=amazon+tablets#tech",
"collected_date":"06/11/14",
"data_source_brightness":"http://www.notebookcheck.net/Review-Amazon-Kindle-Fire-HD-8-9-Tablet.85965.0.html"
},
{
"item":"Kindle Fire HDX 7”",
"manufacture":"Amazon",
"type":"tablet",
"di":7,
"hp":1920,
"wp":1200,
"dp":2264,
"PPI":323,
"brightness_nits":527,
"Model":"B00BWYQ9YE",
"data_source":"http://www.amazon.com/Kindle-Fire-HD-Display-Wi-Fi/dp/B00C5W16B8/ref=sr_1_3?s=electronics&ie=UTF8&qid=1402512304&sr=1-3&keywords=amazon+tablets#tech",
"collected_date":"06/11/14",
"data_source_brightness":"http://www.phonearena.com/news/Amazon-Kindle-Fire-HDX-8.9-beats-out-the-Apple-iPad-Air-and-Nexus-10-in-display-test_id49053"
},
{
"item":"Samsung Galaxy Note 10.1",
"manufacture":"Samsung",
"type":"tablet",
"di":10.1,
"hp":2560,
"wp":1600,
"dp":3019,
"PPI":298,
"brightness_nits":430,
"Model":"SM-P6000ZKYXAR",
"data_source":"http://www.samsung.com/global/microsite/2014galaxynote10.1/specification.html",
"collected_date":"06/11/14",
"data_source_brightness":"http://www.phonearena.com/reviews/Samsung-Galaxy-Note-10.1-2014-vs-Apple-iPad-4_id3445"
},
{
"item":"Google Nexus 7",
"manufacture":"Google",
"type":"tablet",
"di":7,
"hp":1280,
"wp":800,
"dp":1509,
"PPI":215,
"brightness_nits":583,
"Model":"NEXUS7 ASUS-2B16",
"data_source":"http://www.google.com/nexus/7/specs/",
"collected_date":"06/11/14",
"data_source_brightness":"http://www.anandtech.com/show/7176/nexus-7-2013-mini-review/2"
},
{
"item":"Apple Ipad Air",
"manufacture":"Apple",
"type":"tablet",
"di":9.7,
"hp":2048,
"wp":1536,
"dp":2560,
"PPI":263,
"brightness_nits":364,
"Model":"MD788LL/A",
"data_source":"https://www.apple.com/ipad-air/",
"collected_date":"06/11/14",
"data_source_brightness":"http://www.phonearena.com/reviews/Samsung-Galaxy-Note-10.1-2014-vs-Apple-iPad-4_id3445"
}
]
.dc-chart {
float: left;
}
.dc-chart rect.bar {
stroke: none;
cursor: pointer;
}
.dc-chart rect.bar:hover {
fill-opacity: .5;
}
.dc-chart rect.stack1 {
stroke: none;
fill: red;
}
.dc-chart rect.stack2 {
stroke: none;
fill: green;
}
.dc-chart rect.deselected {
stroke: none;
fill: #ccc;
}
.dc-chart .pie-slice {
fill: white;
font-size: 12px;
cursor: pointer;
}
.dc-chart .pie-slice :hover {
fill-opacity: .8;
}
.dc-chart .selected path {
stroke-width: 3;
stroke: #ccc;
fill-opacity: 1;
}
.dc-chart .deselected path {
strok: none;
fill-opacity: .5;
fill: #ccc;
}
.dc-chart .axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dc-chart .axis text {
font: 10px sans-serif;
}
.dc-chart .grid-line {
fill: none;
stroke: #ccc;
opacity: .5;
shape-rendering: crispEdges;
}
.dc-chart .grid-line line {
fill: none;
stroke: #ccc;
opacity: .5;
shape-rendering: crispEdges;
}
.dc-chart .brush rect.background {
z-index: -999;
}
.dc-chart .brush rect.extent {
fill: steelblue;
fill-opacity: .125;
}
.dc-chart .brush .resize path {
fill: #eee;
stroke: #666;
}
.dc-chart path.line {
fill: none;
stroke-width: 1.5px;
}
.dc-chart circle.dot {
stroke: none;
}
.dc-chart g.dc-tooltip path {
fill: none;
stroke: grey;
stroke-opacity: .8;
}
.dc-chart path.area {
fill-opacity: .3;
stroke: none;
}
.dc-chart .node {
font-size: 0.7em;
cursor: pointer;
}
.dc-chart .node :hover {
fill-opacity: .8;
}
.dc-chart .selected circle {
stroke-width: 3;
stroke: #ccc;
fill-opacity: 1;
}
.dc-chart .deselected circle {
strok: none;
fill-opacity: .5;
fill: #ccc;
}
.dc-chart .bubble {
stroke: none;
fill-opacity: 0.6;
}
.dc-data-count {
float: right;
margin-top: 15px;
margin-right: 15px;
}
.dc-data-count .filter-count {
color: #3182bd;
font-weight: bold;
}
.dc-data-count .total-count {
color: #3182bd;
font-weight: bold;
}
.dc-data-table {
}
.dc-chart g.state {
cursor: pointer;
}
.dc-chart g.state :hover {
fill-opacity: .8;
}
.dc-chart g.state path {
stroke: white;
}
.dc-chart g.selected path {
}
.dc-chart g.deselected path {
fill: grey;
}
.dc-chart g.selected text {
}
.dc-chart g.deselected text {
display: none;
}
.dc-chart g.county path {
stroke: white;
fill: none;
}
.dc-chart g.debug rect {
fill: blue;
fill-opacity: .2;
}
.dc-chart g.row rect {
fill-opacity: 0.8;
cursor: pointer;
}
.dc-chart g.row rect:hover {
fill-opacity: 0.6;
}
.dc-chart g.row text {
fill: white;
font-size: 12px;
cursor: pointer;
}
.dc-legend {
font-size: 11px;
}
.dc-legend-item {
cursor: pointer;
}
.dc-chart g.axis text {
/* Makes it so the user can't accidentally click and select text that is meant as a label only */
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10 */
-o-user-select: none;
user-select: none;
pointer-events: none;
}
.dc-chart path.highlight {
stroke-width: 3;
fill-opacity: 1;
stroke-opacity: 1;
}
.dc-chart .highlight {
fill-opacity: 1;
stroke-opacity: 1;
}
.dc-chart .fadeout {
fill-opacity: 0.2;
stroke-opacity: 0.2;
}
/*
* Copyright 2012 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
dc = {
version: "1.5.0",
constants : {
CHART_CLASS: "dc-chart",
DEBUG_GROUP_CLASS: "debug",
STACK_CLASS: "stack",
DESELECTED_CLASS: "deselected",
SELECTED_CLASS: "selected",
NODE_INDEX_NAME: "__index__",
GROUP_INDEX_NAME: "__group_index__",
DEFAULT_CHART_GROUP: "__default_chart_group__",
EVENT_DELAY: 40,
NEGLIGIBLE_NUMBER: 1e-10
},
_renderlet : null
};
dc.chartRegistry = function() {
// chartGroup:string => charts:array
var _chartMap = {};
this.has = function(chart) {
for (var e in _chartMap) {
if (_chartMap[e].indexOf(chart) >= 0)
return true;
}
return false;
};
function initializeChartGroup(group) {
if (!group)
group = dc.constants.DEFAULT_CHART_GROUP;
if (!_chartMap[group])
_chartMap[group] = [];
return group;
}
this.register = function(chart, group) {
group = initializeChartGroup(group);
_chartMap[group].push(chart);
};
this.clear = function() {
_chartMap = {};
};
this.list = function(group) {
group = initializeChartGroup(group);
return _chartMap[group];
};
return this;
}();
dc.registerChart = function(chart, group) {
dc.chartRegistry.register(chart, group);
};
dc.hasChart = function(chart) {
return dc.chartRegistry.has(chart);
};
dc.deregisterAllCharts = function() {
dc.chartRegistry.clear();
};
dc.filterAll = function(group) {
var charts = dc.chartRegistry.list(group);
for (var i = 0; i < charts.length; ++i) {
charts[i].filterAll();
}
};
dc.renderAll = function(group) {
var charts = dc.chartRegistry.list(group);
for (var i = 0; i < charts.length; ++i) {
charts[i].render();
}
if(dc._renderlet !== null)
dc._renderlet(group);
};
dc.redrawAll = function(group) {
var charts = dc.chartRegistry.list(group);
for (var i = 0; i < charts.length; ++i) {
charts[i].redraw();
}
if(dc._renderlet !== null)
dc._renderlet(group);
};
dc.transition = function(selections, duration, callback) {
if (duration <= 0 || duration === undefined)
return selections;
var s = selections
.transition()
.duration(duration);
if (callback instanceof Function) {
callback(s);
}
return s;
};
dc.units = {};
dc.units.integers = function(s, e) {
return Math.abs(e - s);
};
dc.units.ordinal = function(s, e, domain){
return domain;
};
dc.units.fp = {};
dc.units.fp.precision= function(precision){
var _f = function(s, e, domain){return Math.ceil(Math.abs((e-s)/_f.resolution));};
_f.resolution = precision;
return _f;
};
dc.round = {};
dc.round.floor = function(n) {
return Math.floor(n);
};
dc.round.ceil = function(n) {
return Math.ceil(n);
};
dc.round.round = function(n) {
return Math.round(n);
};
dc.override = function(obj, functionName, newFunction) {
var existingFunction = obj[functionName];
obj["_" + functionName] = existingFunction;
obj[functionName] = newFunction;
};
dc.renderlet = function(_){
if(!arguments.length) return dc._renderlet;
dc._renderlet = _;
return dc;
};
dc.instanceOfChart = function (o) {
return o instanceof Object && o.__dc_flag__;
};
dc.errors = {};
dc.errors.Exception = function(msg) {
var _msg = msg != null ? msg : "Unexpected internal error";
this.message = _msg;
this.toString = function(){
return _msg;
};
};
dc.errors.InvalidStateException = function() {
dc.errors.Exception.apply(this, arguments);
};dc.dateFormat = d3.time.format("%m/%d/%Y");
dc.printers = {};
dc.printers.filters = function (filters) {
var s = "";
for (var i = 0; i < filters.length; ++i) {
if (i > 0) s += ", ";
s += dc.printers.filter(filters[i]);
}
return s;
};
dc.printers.filter = function (filter) {
var s = "";
if (filter) {
if (filter instanceof Array) {
if (filter.length >= 2)
s = "[" + dc.utils.printSingleValue(filter[0]) + " -> " + dc.utils.printSingleValue(filter[1]) + "]";
else if (filter.length >= 1)
s = dc.utils.printSingleValue(filter[0]);
} else {
s = dc.utils.printSingleValue(filter)
}
}
return s;
};
dc.utils = {};
dc.utils.printSingleValue = function (filter) {
var s = "" + filter;
if (filter instanceof Date)
s = dc.dateFormat(filter);
else if (typeof(filter) == "string")
s = filter;
else if (typeof(filter) == "number")
s = Math.round(filter);
return s;
};
dc.utils.add = function (l, r) {
if (typeof r === "string")
r = r.replace("%", "")
if (l instanceof Date) {
if (typeof r === "string") r = +r
var d = new Date();
d.setTime(l.getTime());
d.setDate(l.getDate() + r);
return d;
} else if (typeof r === "string") {
var percentage = (+r / 100);
return l > 0 ? l * (1 + percentage) : l * (1 - percentage);
} else {
return l + r;
}
};
dc.utils.subtract = function (l, r) {
if (typeof r === "string")
r = r.replace("%", "")
if (l instanceof Date) {
if (typeof r === "string") r = +r
var d = new Date();
d.setTime(l.getTime());
d.setDate(l.getDate() - r);
return d;
} else if (typeof r === "string") {
var percentage = (+r / 100);
return l < 0 ? l * (1 + percentage) : l * (1 - percentage);
} else {
return l - r;
}
};
dc.utils.GroupStack = function () {
var _dataLayers = [];
var _groups = [];
var _defaultAccessor;
function initializeDataLayer(i) {
if (!_dataLayers[i])
_dataLayers[i] = [];
}
this.setDataPoint = function (layerIndex, pointIndex, data) {
initializeDataLayer(layerIndex);
_dataLayers[layerIndex][pointIndex] = data;
};
this.getDataPoint = function (x, y) {
initializeDataLayer(x);
var dataPoint = _dataLayers[x][y];
if (dataPoint == undefined)
dataPoint = 0;
return dataPoint;
};
this.addGroup = function (group, accessor) {
if (!accessor)
accessor = _defaultAccessor;
_groups.push([group, accessor]);
return _groups.length - 1;
};
this.getGroupByIndex = function (index) {
return _groups[index][0];
};
this.getAccessorByIndex = function (index) {
return _groups[index][1];
};
this.size = function () {
return _groups.length;
};
this.clear = function () {
_dataLayers = [];
_groups = [];
};
this.setDefaultAccessor = function (retriever) {
_defaultAccessor = retriever;
};
this.getDataLayers = function () {
return _dataLayers;
};
this.toLayers = function () {
var layers = [];
for (var i = 0; i < _dataLayers.length; ++i) {
var layer = {index: i, points: []};
var dataPoints = _dataLayers[i];
for (var j = 0; j < dataPoints.length; ++j)
layer.points.push(dataPoints[j]);
layers.push(layer);
}
return layers;
};
};
dc.utils.isNegligible = function (max) {
return max === undefined || (max < dc.constants.NEGLIGIBLE_NUMBER && max > -dc.constants.NEGLIGIBLE_NUMBER);
}
dc.utils.groupMax = function (group, accessor) {
var max = d3.max(group.all(), function (e) {
return accessor(e);
});
if (dc.utils.isNegligible(max)) max = 0;
return max;
};
dc.utils.groupMin = function (group, accessor) {
var min = d3.min(group.all(), function (e) {
return accessor(e);
});
if (dc.utils.isNegligible(min)) min = 0;
return min;
};
dc.utils.nameToId = function (name) {
return name.toLowerCase().replace(/[\s]/g, "_").replace(/[\.']/g, "");
};
dc.utils.appendOrSelect = function (parent, name) {
var element = parent.select(name);
if (element.empty()) element = parent.append(name);
return element;
};
dc.utils.createLegendable = function (chart, group, index) {
var legendable = {name: group.__name__, data: group};
if (typeof chart.colors === 'function') legendable.color = chart.colors()(index);
return legendable;
};
dc.events = {
current: null
};
dc.events.trigger = function(closure, delay) {
if (!delay){
closure();
return;
}
dc.events.current = closure;
setTimeout(function() {
if (closure == dc.events.current)
closure();
}, delay);
};
dc.cumulative = {};
dc.cumulative.Base = function() {
this._keyIndex = [];
this._map = {};
this.sanitizeKey = function(key) {
key = key + "";
return key;
};
this.clear = function() {
this._keyIndex = [];
this._map = {};
};
this.size = function() {
return this._keyIndex.length;
};
this.getValueByKey = function(key) {
key = this.sanitizeKey(key);
var value = this._map[key];
return value;
};
this.setValueByKey = function(key, value) {
key = this.sanitizeKey(key);
return this._map[key] = value;
};
this.indexOfKey = function(key) {
key = this.sanitizeKey(key);
return this._keyIndex.indexOf(key);
};
this.addToIndex = function(key) {
key = this.sanitizeKey(key);
this._keyIndex.push(key);
};
this.getKeyByIndex = function(index) {
return this._keyIndex[index];
};
};
dc.cumulative.Sum = function() {
dc.cumulative.Base.apply(this, arguments);
this.add = function(key, value) {
if (value == null)
value = 0;
if (this.getValueByKey(key) == null) {
this.addToIndex(key);
this.setValueByKey(key, value);
} else {
this.setValueByKey(key, this.getValueByKey(key) + value);
}
};
this.minus = function(key, value) {
this.setValueByKey(key, this.getValueByKey(key) - value);
};
this.cumulativeSum = function(key) {
var keyIndex = this.indexOfKey(key);
if (keyIndex < 0) return 0;
var cumulativeValue = 0;
for (var i = 0; i <= keyIndex; ++i) {
var k = this.getKeyByIndex(i);
cumulativeValue += this.getValueByKey(k);
}
return cumulativeValue;
};
};
dc.cumulative.Sum.prototype = new dc.cumulative.Base();
dc.cumulative.CountUnique = function() {
dc.cumulative.Base.apply(this, arguments);
function hashSize(hash) {
var size = 0, key;
for (key in hash) {
if (hash.hasOwnProperty(key)) size++;
}
return size;
}
this.add = function(key, e) {
if (this.getValueByKey(key) == null) {
this.setValueByKey(key, {});
this.addToIndex(key);
}
if (e != null) {
if (this.getValueByKey(key)[e] == null)
this.getValueByKey(key)[e] = 0;
this.getValueByKey(key)[e] += 1;
}
};
this.minus = function(key, e) {
this.getValueByKey(key)[e] -= 1;
if (this.getValueByKey(key)[e] <= 0)
delete this.getValueByKey(key)[e];
};
this.count = function(key) {
return hashSize(this.getValueByKey(key));
};
this.cumulativeCount = function(key) {
var keyIndex = this.indexOfKey(key);
if (keyIndex < 0) return 0;
var cumulativeCount = 0;
for (var i = 0; i <= keyIndex; ++i) {
var k = this.getKeyByIndex(i);
cumulativeCount += this.count(k);
}
return cumulativeCount;
};
};
dc.cumulative.CountUnique.prototype = new dc.cumulative.Base();
dc.baseChart = function (_chart) {
_chart.__dc_flag__ = true;
var _dimension;
var _group;
var _anchor;
var _root;
var _svg;
var _width = 200, _height = 200;
var _keyAccessor = function (d) {
return d.key;
};
var _valueAccessor = function (d) {
return d.value;
};
var _label = function (d) {
return d.key;
};
var _renderLabel = false;
var _title = function (d) {
return d.key + ": " + d.value;
};
var _renderTitle = false;
var _transitionDuration = 750;
var _filterPrinter = dc.printers.filters;
var _renderlets = [];
var _chartGroup = dc.constants.DEFAULT_CHART_GROUP;
var NULL_LISTENER = function (chart) {
};
var _listeners = {
preRender: NULL_LISTENER,
postRender: NULL_LISTENER,
preRedraw: NULL_LISTENER,
postRedraw: NULL_LISTENER,
filtered: NULL_LISTENER,
zoomed: NULL_LISTENER
};
var _legend;
var _filters = [];
var _filterHandler = function (dimension, filters) {
dimension.filter(null);
if (filters.length == 0)
dimension.filter(null);
else if (filters.length == 1)
dimension.filter(filters[0]);
else
dimension.filterFunction(function (d) {
return filters.indexOf(d) >= 0;
});
return filters;
};
_chart.width = function (w) {
if (!arguments.length) return _width;
_width = w;
return _chart;
};
_chart.height = function (h) {
if (!arguments.length) return _height;
_height = h;
return _chart;
};
_chart.dimension = function (d) {
if (!arguments.length) return _dimension;
_dimension = d;
_chart.expireCache();
return _chart;
};
_chart.group = function (g, name) {
if (!arguments.length) return _group;
_group = g;
_chart.expireCache();
if (typeof name === 'string') _group.__name__ = name;
return _chart;
};
_chart.orderedGroup = function () {
return _group.order(function (p) {
return p.key;
});
};
_chart.filterAll = function () {
return _chart.filter(null);
};
_chart.dataSet = function () {
return _dimension != undefined && _group != undefined;
};
_chart.select = function (s) {
return _root.select(s);
};
_chart.selectAll = function (s) {
return _root ? _root.selectAll(s) : null;
};
_chart.anchor = function (a, chartGroup) {
if (!arguments.length) return _anchor;
if (dc.instanceOfChart(a)) {
_anchor = a.anchor();
_root = a.root();
} else {
_anchor = a;
_root = d3.select(_anchor);
_root.classed(dc.constants.CHART_CLASS, true);
dc.registerChart(_chart, chartGroup);
}
_chartGroup = chartGroup;
return _chart;
};
_chart.root = function (r) {
if (!arguments.length) return _root;
_root = r;
return _chart;
};
_chart.svg = function (_) {
if (!arguments.length) return _svg;
_svg = _;
return _chart;
};
_chart.resetSvg = function () {
_chart.select("svg").remove();
return _chart.generateSvg();
};
_chart.generateSvg = function () {
_svg = _chart.root().append("svg")
.attr("width", _chart.width())
.attr("height", _chart.height());
return _svg;
};
_chart.filterPrinter = function (_) {
if (!arguments.length) return _filterPrinter;
_filterPrinter = _;
return _chart;
};
_chart.turnOnControls = function () {
if (_root) {
_chart.selectAll(".reset").style("display", null);
_chart.selectAll(".filter").text(_filterPrinter(_chart.filters())).style("display", null);
}
return _chart;
};
_chart.turnOffControls = function () {
if (_root) {
_chart.selectAll(".reset").style("display", "none");
_chart.selectAll(".filter").style("display", "none").text(_chart.filter());
}
return _chart;
};
_chart.transitionDuration = function (d) {
if (!arguments.length) return _transitionDuration;
_transitionDuration = d;
return _chart;
};
_chart.render = function () {
_listeners.preRender(_chart);
if (_dimension == null)
throw new dc.errors.InvalidStateException("Mandatory attribute chart.dimension is missing on chart["
+ _chart.anchor() + "]");
if (_group == null)
throw new dc.errors.InvalidStateException("Mandatory attribute chart.group is missing on chart["
+ _chart.anchor() + "]");
var result = _chart.doRender();
if (_legend) _legend.render();
_chart.activateRenderlets("postRender");
return result;
};
_chart.activateRenderlets = function (event) {
if (_chart.transitionDuration() > 0 && _svg) {
_svg.transition().duration(_chart.transitionDuration())
.each("end", function () {
runAllRenderlets();
if (event) _listeners[event](_chart);
});
} else {
runAllRenderlets();
if (event) _listeners[event](_chart);
}
}
_chart.redraw = function () {
_listeners.preRedraw(_chart);
var result = _chart.doRedraw();
_chart.activateRenderlets("postRedraw");
return result;
};
_chart.invokeFilteredListener = function (chart, f) {
if (f !== undefined) _listeners.filtered(_chart, f);
};
_chart.invokeZoomedListener = function (chart) {
_listeners.zoomed(_chart);
};
_chart.hasFilter = function (filter) {
if (!arguments.length) return _filters.length > 0;
return _filters.indexOf(filter) >= 0;
};
function removeFilter(_) {
_filters.splice(_filters.indexOf(_), 1);
applyFilters();
_chart.invokeFilteredListener(_chart, _);
}
function addFilter(_) {
_filters.push(_);
applyFilters();
_chart.invokeFilteredListener(_chart, _);
}
function resetFilters() {
_filters = [];
applyFilters();
_chart.invokeFilteredListener(_chart, null);
}
function applyFilters() {
if (_chart.dataSet() && _chart.dimension().filter != undefined) {
var fs = _filterHandler(_chart.dimension(), _filters);
_filters = fs ? fs : _filters;
}
}
_chart.filter = function (_) {
if (!arguments.length) return _filters.length > 0 ? _filters[0] : null;
if (_ == null) {
resetFilters();
} else {
if (_chart.hasFilter(_))
removeFilter(_);
else
addFilter(_);
}
if (_root != null && _chart.hasFilter()) {
_chart.turnOnControls();
} else {
_chart.turnOffControls();
}
return _chart;
};
_chart.filters = function () {
return _filters;
};
_chart.highlightSelected = function (e) {
d3.select(e).classed(dc.constants.SELECTED_CLASS, true);
d3.select(e).classed(dc.constants.DESELECTED_CLASS, false);
};
_chart.fadeDeselected = function (e) {
d3.select(e).classed(dc.constants.SELECTED_CLASS, false);
d3.select(e).classed(dc.constants.DESELECTED_CLASS, true);
};
_chart.resetHighlight = function (e) {
d3.select(e).classed(dc.constants.SELECTED_CLASS, false);
d3.select(e).classed(dc.constants.DESELECTED_CLASS, false);
};
_chart.onClick = function (d) {
var filter = _chart.keyAccessor()(d);
dc.events.trigger(function () {
_chart.filter(filter);
dc.redrawAll(_chart.chartGroup());
});
};
_chart.filterHandler = function (_) {
if (!arguments.length) return _filterHandler;
_filterHandler = _;
return _chart;
};
// abstract function stub
_chart.doRender = function () {
// do nothing in base, should be overridden by sub-function
return _chart;
};
_chart.doRedraw = function () {
// do nothing in base, should be overridden by sub-function
return _chart;
};
_chart.legendables = function () {
// do nothing in base, should be overridden by sub-function
return [];
};
_chart.legendHighlight = function (d) {
// do nothing in base, should be overridden by sub-function
};
_chart.legendReset = function (d) {
// do nothing in base, should be overridden by sub-function
};
_chart.keyAccessor = function (_) {
if (!arguments.length) return _keyAccessor;
_keyAccessor = _;
return _chart;
};
_chart.valueAccessor = function (_) {
if (!arguments.length) return _valueAccessor;
_valueAccessor = _;
return _chart;
};
_chart.label = function (_) {
if (!arguments.length) return _label;
_label = _;
_renderLabel = true;
return _chart;
};
_chart.renderLabel = function (_) {
if (!arguments.length) return _renderLabel;
_renderLabel = _;
return _chart;
};
_chart.title = function (_) {
if (!arguments.length) return _title;
_title = _;
_renderTitle = true;
return _chart;
};
_chart.renderTitle = function (_) {
if (!arguments.length) return _renderTitle;
_renderTitle = _;
return _chart;
};
_chart.renderlet = function (_) {
_renderlets.push(_);
return _chart;
};
function runAllRenderlets() {
for (var i = 0; i < _renderlets.length; ++i) {
_renderlets[i](_chart);
}
}
_chart.chartGroup = function (_) {
if (!arguments.length) return _chartGroup;
_chartGroup = _;
return _chart;
};
_chart.on = function (event, listener) {
_listeners[event] = listener;
return _chart;
};
_chart.expireCache = function () {
// do nothing in base, should be overridden by sub-function
return _chart;
};
_chart.legend = function (l) {
if (!arguments.length) return _legend;
_legend = l;
_legend.parent(_chart);
return _chart;
};
return _chart;
};
dc.marginable = function (_chart) {
var _margin = {top: 10, right: 50, bottom: 30, left: 30};
_chart.margins = function (m) {
if (!arguments.length) return _margin;
_margin = m;
return _chart;
};
_chart.effectiveWidth = function () {
return _chart.width() - _chart.margins().left - _chart.margins().right;
};
_chart.effectiveHeight = function () {
return _chart.height() - _chart.margins().top - _chart.margins().bottom;
};
return _chart;
};dc.coordinateGridChart = function (_chart) {
var DEFAULT_Y_AXIS_TICKS = 5;
var GRID_LINE_CLASS = "grid-line";
var HORIZONTAL_CLASS = "horizontal";
var VERTICAL_CLASS = "vertical";
_chart = dc.colorChart(dc.marginable(dc.baseChart(_chart)));
_chart.colors(d3.scale.category10());
var _parent;
var _g;
var _chartBodyG;
var _x;
var _xOriginalDomain;
var _xAxis = d3.svg.axis();
var _xUnits = dc.units.integers;
var _xAxisPadding = 0;
var _xElasticity = false;
var _y;
var _yAxis = d3.svg.axis();
var _yAxisPadding = 0;
var _yElasticity = false;
var _brush = d3.svg.brush();
var _brushOn = true;
var _round;
var _renderHorizontalGridLine = false;
var _renderVerticalGridLine = false;
var _refocused = false;
var _unitCount;
var _rangeChart;
var _focusChart;
var _mouseZoomable = false;
var _clipPadding = 0;
_chart.title(function (d) {
return d.data.key + ": " + d.data.value;
});
_chart.rescale = function () {
_unitCount = null;
_chart.xUnitCount();
}
_chart.rangeChart = function (_) {
if (!arguments.length) return _rangeChart;
_rangeChart = _;
_rangeChart.focusChart(_chart);
return _chart;
}
_chart.generateG = function (parent) {
if (parent == null)
_parent = _chart.svg();
else
_parent = parent;
_g = _parent.append("g");
_chartBodyG = _g.append("g").attr("class", "chart-body")
.attr("transform", "translate(" + _chart.margins().left + ", " + _chart.margins().top + ")")
.attr("clip-path", "url(#" + getClipPathId() + ")");
return _g;
};
_chart.g = function (_) {
if (!arguments.length) return _g;
_g = _;
return _chart;
};
_chart.mouseZoomable = function (z) {
if (!arguments.length) return _mouseZoomable;
_mouseZoomable = z;
return _chart;
};
_chart.chartBodyG = function (_) {
if (!arguments.length) return _chartBodyG;
_chartBodyG = _;
return _chart;
};
_chart.x = function (_) {
if (!arguments.length) return _x;
_x = _;
_xOriginalDomain = _x.domain();
return _chart;
};
_chart.xOriginalDomain = function () {
return _xOriginalDomain;
};
_chart.xUnits = function (_) {
if (!arguments.length) return _xUnits;
_xUnits = _;
return _chart;
};
_chart.xAxis = function (_) {
if (!arguments.length) return _xAxis;
_xAxis = _;
return _chart;
};
_chart.elasticX = function (_) {
if (!arguments.length) return _xElasticity;
_xElasticity = _;
return _chart;
};
_chart.xAxisPadding = function (_) {
if (!arguments.length) return _xAxisPadding;
_xAxisPadding = _;
return _chart;
};
_chart.xUnitCount = function () {
if (_unitCount == null) {
var units = _chart.xUnits()(_chart.x().domain()[0], _chart.x().domain()[1], _chart.x().domain());
if (units instanceof Array)
_unitCount = units.length;
else
_unitCount = units;
}
return _unitCount;
};
_chart.isOrdinal = function () {
return _chart.xUnits() === dc.units.ordinal;
};
_chart.prepareOrdinalXAxis = function (count) {
if (!count)
count = _chart.xUnitCount();
var range = [];
var currentPosition = 0;
var increment = _chart.xAxisLength() / count;
for (var i = 0; i < count; i++) {
range[i] = currentPosition;
currentPosition += increment;
}
_x.range(range);
};
function prepareXAxis(g) {
if (_chart.elasticX() && !_chart.isOrdinal()) {
_x.domain([_chart.xAxisMin(), _chart.xAxisMax()]);
}
if (_chart.isOrdinal()) {
_chart.prepareOrdinalXAxis();
} else {
_x.range([0, _chart.xAxisLength()]);
}
_xAxis = _xAxis.scale(_chart.x()).orient("bottom");
renderVerticalGridLines(g);
}
_chart.renderXAxis = function (g) {
var axisXG = g.selectAll("g.x");
if (axisXG.empty())
axisXG = g.append("g")
.attr("class", "axis x")
.attr("transform", "translate(" + _chart.margins().left + "," + _chart.xAxisY() + ")");
dc.transition(axisXG, _chart.transitionDuration())
.call(_xAxis);
};
function renderVerticalGridLines(g) {
var gridLineG = g.selectAll("g." + VERTICAL_CLASS);
if (_renderVerticalGridLine) {
if (gridLineG.empty())
gridLineG = g.insert("g", ":first-child")
.attr("class", GRID_LINE_CLASS + " " + VERTICAL_CLASS)
.attr("transform", "translate(" + _chart.yAxisX() + "," + _chart.margins().top + ")");
var ticks = _xAxis.tickValues() ? _xAxis.tickValues() : _x.ticks(_xAxis.ticks()[0]);
var lines = gridLineG.selectAll("line")
.data(ticks);
// enter
var linesGEnter = lines.enter()
.append("line")
.attr("x1", function (d) {
return _x(d);
})
.attr("y1", _chart.xAxisY() - _chart.margins().top)
.attr("x2", function (d) {
return _x(d);
})
.attr("y2", 0)
.attr("opacity", 0);
dc.transition(linesGEnter, _chart.transitionDuration())
.attr("opacity", 1);
// update
dc.transition(lines, _chart.transitionDuration())
.attr("x1", function (d) {
return _x(d);
})
.attr("y1", _chart.xAxisY() - _chart.margins().top)
.attr("x2", function (d) {
return _x(d);
})
.attr("y2", 0);
// exit
lines.exit().remove();
}
else {
gridLineG.selectAll("line").remove()
}
}
_chart.xAxisY = function () {
return (_chart.height() - _chart.margins().bottom);
};
_chart.xAxisLength = function () {
return _chart.effectiveWidth();
};
function prepareYAxis(g) {
if (_y == null || _chart.elasticY()) {
_y = d3.scale.linear();
_y.domain([_chart.yAxisMin(), _chart.yAxisMax()]).rangeRound([_chart.yAxisHeight(), 0]);
}
_y.range([_chart.yAxisHeight(), 0]);
_yAxis = _yAxis.scale(_y).orient("left").ticks(DEFAULT_Y_AXIS_TICKS);
renderHorizontalGridLines(g);
}
_chart.renderYAxis = function (g) {
var axisYG = g.selectAll("g.y");
if (axisYG.empty())
axisYG = g.append("g")
.attr("class", "axis y")
.attr("transform", "translate(" + _chart.yAxisX() + "," + _chart.margins().top + ")");
dc.transition(axisYG, _chart.transitionDuration())
.call(_yAxis);
};
function renderHorizontalGridLines(g) {
var gridLineG = g.selectAll("g." + HORIZONTAL_CLASS);
if (_renderHorizontalGridLine) {
var ticks = _yAxis.tickValues() ? _yAxis.tickValues() : _y.ticks(_yAxis.ticks()[0]);
if (gridLineG.empty())
gridLineG = g.insert("g", ":first-child")
.attr("class", GRID_LINE_CLASS + " " + HORIZONTAL_CLASS)
.attr("transform", "translate(" + _chart.yAxisX() + "," + _chart.margins().top + ")");
var lines = gridLineG.selectAll("line")
.data(ticks);
// enter
var linesGEnter = lines.enter()
.append("line")
.attr("x1", 1)
.attr("y1", function (d) {
return _y(d);
})
.attr("x2", _chart.xAxisLength())
.attr("y2", function (d) {
return _y(d);
})
.attr("opacity", 0);
dc.transition(linesGEnter, _chart.transitionDuration())
.attr("opacity", 1);
// update
dc.transition(lines, _chart.transitionDuration())
.attr("x1", 1)
.attr("y1", function (d) {
return _y(d);
})
.attr("x2", _chart.xAxisLength())
.attr("y2", function (d) {
return _y(d);
});
// exit
lines.exit().remove();
}
else {
gridLineG.selectAll("line").remove()
}
}
_chart.yAxisX = function () {
return _chart.margins().left;
};
_chart.y = function (_) {
if (!arguments.length) return _y;
_y = _;
return _chart;
};
_chart.yAxis = function (y) {
if (!arguments.length) return _yAxis;
_yAxis = y;
return _chart;
};
_chart.elasticY = function (_) {
if (!arguments.length) return _yElasticity;
_yElasticity = _;
return _chart;
};
_chart.renderHorizontalGridLines = function (_) {
if (!arguments.length) return _renderHorizontalGridLine;
_renderHorizontalGridLine = _;
return _chart;
};
_chart.renderVerticalGridLines = function (_) {
if (!arguments.length) return _renderVerticalGridLine;
_renderVerticalGridLine = _;
return _chart;
};
_chart.xAxisMin = function () {
var min = d3.min(_chart.group().all(), function (e) {
return _chart.keyAccessor()(e);
});
return dc.utils.subtract(min, _xAxisPadding);
};
_chart.xAxisMax = function () {
var max = d3.max(_chart.group().all(), function (e) {
return _chart.keyAccessor()(e);
});
return dc.utils.add(max, _xAxisPadding);
};
_chart.yAxisMin = function () {
var min = d3.min(_chart.group().all(), function (e) {
return _chart.valueAccessor()(e);
});
min = dc.utils.subtract(min, _yAxisPadding);
return min;
};
_chart.yAxisMax = function () {
var max = d3.max(_chart.group().all(), function (e) {
return _chart.valueAccessor()(e);
});
max = dc.utils.add(max, _yAxisPadding);
return max;
};
_chart.yAxisPadding = function (_) {
if (!arguments.length) return _yAxisPadding;
_yAxisPadding = _;
return _chart;
};
_chart.yAxisHeight = function () {
return _chart.effectiveHeight();
};
_chart.round = function (_) {
if (!arguments.length) return _round;
_round = _;
return _chart;
};
dc.override(_chart, "filter", function (_) {
if (!arguments.length) return _chart._filter();
_chart._filter(_);
if (_) {
_chart.brush().extent(_);
} else {
_chart.brush().clear();
}
return _chart;
});
_chart.brush = function (_) {
if (!arguments.length) return _brush;
_brush = _;
return _chart;
};
function brushHeight() {
return _chart.xAxisY() - _chart.margins().top;
}
_chart.renderBrush = function (g) {
if (_chart.isOrdinal())
_brushOn = false;
if (_brushOn) {
_brush.on("brushstart", brushStart)
.on("brush", brushing)
.on("brushend", brushEnd);
var gBrush = g.append("g")
.attr("class", "brush")
.attr("transform", "translate(" + _chart.margins().left + "," + _chart.margins().top + ")")
.call(_brush.x(_chart.x()));
gBrush.selectAll("rect").attr("height", brushHeight());
gBrush.selectAll(".resize").append("path").attr("d", _chart.resizeHandlePath);
if (_chart.hasFilter()) {
_chart.redrawBrush(g);
}
}
};
function brushStart(p) {
}
_chart.extendBrush = function () {
var extent = _brush.extent();
if (_chart.round()) {
extent[0] = extent.map(_chart.round())[0];
extent[1] = extent.map(_chart.round())[1];
_g.select(".brush")
.call(_brush.extent(extent));
}
return extent;
};
_chart.brushIsEmpty = function (extent) {
return _brush.empty() || !extent || extent[1] <= extent[0];
};
function brushing(p) {
var extent = _chart.extendBrush();
_chart.redrawBrush(_g);
if (_chart.brushIsEmpty(extent)) {
dc.events.trigger(function () {
_chart.filter(null);
dc.redrawAll(_chart.chartGroup());
});
} else {
dc.events.trigger(function () {
_chart.filter(null);
_chart.filter([extent[0], extent[1]]);
dc.redrawAll(_chart.chartGroup());
}, dc.constants.EVENT_DELAY);
}
}
function brushEnd(p) {
}
_chart.redrawBrush = function (g) {
if (_brushOn) {
if (_chart.filter() && _chart.brush().empty())
_chart.brush().extent(_chart.filter());
var gBrush = g.select("g.brush");
gBrush.call(_chart.brush().x(_chart.x()));
gBrush.selectAll("rect").attr("height", brushHeight());
}
_chart.fadeDeselectedArea();
};
_chart.fadeDeselectedArea = function () {
// do nothing, sub-chart should override this function
};
// borrowed from Crossfilter example
_chart.resizeHandlePath = function (d) {
var e = +(d == "e"), x = e ? 1 : -1, y = brushHeight() / 3;
return "M" + (.5 * x) + "," + y
+ "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
+ "V" + (2 * y - 6)
+ "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
+ "Z"
+ "M" + (2.5 * x) + "," + (y + 8)
+ "V" + (2 * y - 8)
+ "M" + (4.5 * x) + "," + (y + 8)
+ "V" + (2 * y - 8);
};
function getClipPathId() {
return _chart.anchor().replace('#', '') + "-clip";
}
_chart.clipPadding = function (p) {
if (!arguments.length) return _clipPadding;
_clipPadding = p;
return _chart;
};
function generateClipPath() {
var defs = dc.utils.appendOrSelect(_parent, "defs");
var chartBodyClip = dc.utils.appendOrSelect(defs, "clipPath").attr("id", getClipPathId());
var padding = _clipPadding * 2;
dc.utils.appendOrSelect(chartBodyClip, "rect")
.attr("width", _chart.xAxisLength() + padding)
.attr("height", _chart.yAxisHeight() + padding);
}
_chart.doRender = function () {
if (_x == null)
throw new dc.errors.InvalidStateException("Mandatory attribute chart.x is missing on chart["
+ _chart.anchor() + "]");
_chart.resetSvg();
if (_chart.dataSet()) {
_chart.generateG();
generateClipPath();
prepareXAxis(_chart.g());
prepareYAxis(_chart.g());
_chart.plotData();
_chart.renderXAxis(_chart.g());
_chart.renderYAxis(_chart.g());
_chart.renderBrush(_chart.g());
enableMouseZoom();
}
return _chart;
};
function enableMouseZoom() {
if (_mouseZoomable) {
_chart.root().call(d3.behavior.zoom()
.x(_chart.x())
.scaleExtent([1, 100])
.on("zoom", function () {
_chart.focus(_chart.x().domain());
_chart.invokeZoomedListener(_chart);
updateRangeSelChart();
}));
}
}
function updateRangeSelChart() {
if (_rangeChart) {
var refDom = _chart.x().domain();
var origDom = _rangeChart.xOriginalDomain();
var newDom = [
refDom[0] < origDom[0] ? refDom[0] : origDom[0],
refDom[1] > origDom[1] ? refDom[1] : origDom[1]];
_rangeChart.focus(newDom);
_rangeChart.filter(null);
_rangeChart.filter(refDom);
dc.events.trigger(function () {
dc.redrawAll(_chart.chartGroup());
});
}
}
_chart.doRedraw = function () {
prepareXAxis(_chart.g());
prepareYAxis(_chart.g());
_chart.plotData();
if (_chart.elasticY())
_chart.renderYAxis(_chart.g());
if (_chart.elasticX() || _refocused)
_chart.renderXAxis(_chart.g());
_chart.redrawBrush(_chart.g());
return _chart;
};
_chart.subRender = function () {
if (_chart.dataSet()) {
_chart.plotData();
}
return _chart;
};
_chart.brushOn = function (_) {
if (!arguments.length) return _brushOn;
_brushOn = _;
return _chart;
};
_chart.getDataWithinXDomain = function (group) {
var data = [];
if (_chart.isOrdinal()) {
data = group.all();
} else {
group.all().forEach(function (d) {
var key = _chart.keyAccessor()(d);
if (key >= _chart.x().domain()[0] && key <= _chart.x().domain()[1])
data.push(d);
});
}
return data;
};
function hasRangeSelected(range) {
return range instanceof Array && range.length > 1;
}
_chart.focus = function (range) {
_refocused = true;
if (hasRangeSelected(range)) {
_chart.x().domain(range);
} else {
_chart.x().domain(_chart.xOriginalDomain());
}
_chart.rescale();
_chart.redraw();
if (!hasRangeSelected(range))
_refocused = false;
};
_chart.refocused = function () {
return _refocused;
};
_chart.focusChart = function (c) {
if (!arguments.length) return _focusChart;
_focusChart = c;
_chart.on("filtered", function (chart) {
dc.events.trigger(function () {
_focusChart.focus(chart.filter());
_focusChart.filter(chart.filter());
dc.redrawAll(chart.chartGroup());
});
});
return _chart;
};
return _chart;
};
dc.colorChart = function(_chart) {
var _colors = d3.scale.category20c();
var _colorDomain = [0, _colors.range().length];
var _colorCalculator = function(value) {
var minValue = _colorDomain[0];
var maxValue = _colorDomain[1];
if (isNaN(value)) value = 0;
if(maxValue == null) return _colors(value);
var colorsLength = _chart.colors().range().length;
var denominator = (maxValue - minValue) / colorsLength;
var colorValue = Math.abs(Math.min(colorsLength - 1, Math.round((value - minValue) / denominator)));
return _chart.colors()(colorValue);
};
var _colorAccessor = function(d, i){return i;};
_chart.colors = function(_) {
if (!arguments.length) return _colors;
if (_ instanceof Array) {
_colors = d3.scale.ordinal().range(_);
var domain = [];
for(var i = 0; i < _.length; ++i){
domain.push(i);
}
_colors.domain(domain);
} else {
_colors = _;
}
_colorDomain = [0, _colors.range().length];
return _chart;
};
_chart.colorCalculator = function(_){
if(!arguments.length) return _colorCalculator;
_colorCalculator = _;
return _chart;
};
_chart.getColor = function(d, i){
return _colorCalculator(_colorAccessor(d, i));
};
_chart.colorAccessor = function(_){
if(!arguments.length) return _colorAccessor;
_colorAccessor = _;
return _chart;
};
_chart.colorDomain = function(_){
if(!arguments.length) return _colorDomain;
_colorDomain = _;
return _chart;
};
return _chart;
};
dc.stackableChart = function (_chart) {
var _groupStack = new dc.utils.GroupStack();
var _stackLayout = d3.layout.stack()
.offset("zero")
.order("default")
.values(function (d) {
return d.points;
});
var _allGroups;
var _allValueAccessors;
var _allKeyAccessors;
var _stackLayers;
_chart.stack = function (group, p2, retriever) {
if (typeof p2 === 'string')
group.__name__ = p2;
else if (typeof p2 === 'function')
retriever = p2;
_groupStack.setDefaultAccessor(_chart.valueAccessor());
_groupStack.addGroup(group, retriever);
_chart.expireCache();
return _chart;
};
_chart.expireCache = function () {
_allGroups = null;
_allValueAccessors = null;
_allKeyAccessors = null;
_stackLayers = null;
return _chart;
};
_chart.allGroups = function () {
if (_allGroups == null) {
_allGroups = [];
_allGroups.push(_chart.group());
for (var i = 0; i < _groupStack.size(); ++i)
_allGroups.push(_groupStack.getGroupByIndex(i));
}
return _allGroups;
};
_chart.allValueAccessors = function () {
if (_allValueAccessors == null) {
_allValueAccessors = [];
_allValueAccessors.push(_chart.valueAccessor());
for (var i = 0; i < _groupStack.size(); ++i)
_allValueAccessors.push(_groupStack.getAccessorByIndex(i));
}
return _allValueAccessors;
};
_chart.getValueAccessorByIndex = function (groupIndex) {
return _chart.allValueAccessors()[groupIndex];
};
_chart.yAxisMin = function () {
var min, all = flattenStack();
min = d3.min(all, function (p) {
return (p.y + p.y0 < p.y0) ? (p.y + p.y0) : p.y0;
});
min = dc.utils.subtract(min, _chart.yAxisPadding());
return min;
};
_chart.yAxisMax = function () {
var max, all = flattenStack();
max = d3.max(all, function (p) {
return p.y + p.y0;
});
max = dc.utils.add(max, _chart.yAxisPadding());
return max;
};
function flattenStack() {
var all = [];
if (_chart.x()) {
var xDomain = _chart.x().domain();
_chart.stackLayers().forEach(function (e) {
e.points.forEach(function (p) {
if (p.x >= xDomain[0] && p.x <= xDomain[1])
all.push(p);
});
});
} else {
_chart.stackLayers().forEach(function (e) {
all = all.concat(e.points);
});
}
return all;
}
_chart.allKeyAccessors = function () {
if (_allKeyAccessors == null) {
_allKeyAccessors = [];
_allKeyAccessors.push(_chart.keyAccessor());
for (var i = 0; i < _groupStack.size(); ++i)
_allKeyAccessors.push(_chart.keyAccessor());
}
return _allKeyAccessors;
};
_chart.getKeyAccessorByIndex = function (groupIndex) {
return _chart.allKeyAccessors()[groupIndex];
};
_chart.xAxisMin = function () {
var min = null;
var allGroups = _chart.allGroups();
for (var groupIndex = 0; groupIndex < allGroups.length; ++groupIndex) {
var group = allGroups[groupIndex];
var m = dc.utils.groupMin(group, _chart.getKeyAccessorByIndex(groupIndex));
if (min == null || min > m) min = m;
}
return dc.utils.subtract(min, _chart.xAxisPadding());
};
_chart.xAxisMax = function () {
var max = null;
var allGroups = _chart.allGroups();
for (var groupIndex = 0; groupIndex < allGroups.length; ++groupIndex) {
var group = allGroups[groupIndex];
var m = dc.utils.groupMax(group, _chart.getKeyAccessorByIndex(groupIndex));
if (max == null || max < m) max = m;
}
return dc.utils.add(max, _chart.xAxisPadding());
};
function getKeyFromData(groupIndex, d) {
return _chart.getKeyAccessorByIndex(groupIndex)(d);
}
function getValueFromData(groupIndex, d) {
return _chart.getValueAccessorByIndex(groupIndex)(d);
}
function calculateDataPointMatrix(data, groupIndex) {
for (var dataIndex = 0; dataIndex < data.length; ++dataIndex) {
var d = data[dataIndex];
var key = getKeyFromData(groupIndex, d);
var value = getValueFromData(groupIndex, d);
_groupStack.setDataPoint(groupIndex, dataIndex, {data: d, x: key, y: value});
}
}
_chart.calculateDataPointMatrixForAll = function () {
var groups = _chart.allGroups();
for (var groupIndex = 0; groupIndex < groups.length; ++groupIndex) {
var group = groups[groupIndex];
var data = group.all();
calculateDataPointMatrix(data, groupIndex);
}
};
_chart.getChartStack = function () {
return _groupStack;
};
dc.override(_chart, "valueAccessor", function (_) {
if (!arguments.length) return _chart._valueAccessor();
_chart.expireCache();
return _chart._valueAccessor(_);
});
dc.override(_chart, "keyAccessor", function (_) {
if (!arguments.length) return _chart._keyAccessor();
_chart.expireCache();
return _chart._keyAccessor(_);
});
_chart.stackLayout = function (stack) {
if (!arguments.length) return _stackLayout;
_stackLayout = stack;
return _chart;
};
_chart.stackLayers = function (_) {
if (!arguments.length) {
if (_stackLayers == null) {
_chart.calculateDataPointMatrixForAll();
_stackLayers = _chart.stackLayout()(_groupStack.toLayers());
}
return _stackLayers;
} else {
_stackLayers = _;
}
};
_chart.legendables = function () {
var items = [];
_allGroups.forEach(function (g, i) {
items.push(dc.utils.createLegendable(_chart, g, i));
});
return items;
};
return _chart;
};
dc.abstractBubbleChart = function (_chart) {
var _maxBubbleRelativeSize = 0.3;
var _minRadiusWithLabel = 10;
_chart.BUBBLE_NODE_CLASS = "node";
_chart.BUBBLE_CLASS = "bubble";
_chart.MIN_RADIUS = 10;
_chart = dc.colorChart(_chart);
_chart.renderLabel(true);
_chart.renderTitle(false);
var _r = d3.scale.linear().domain([0, 100]);
var _rValueAccessor = function (d) {
return d.r;
};
_chart.r = function (_) {
if (!arguments.length) return _r;
_r = _;
return _chart;
};
_chart.radiusValueAccessor = function (_) {
if (!arguments.length) return _rValueAccessor;
_rValueAccessor = _;
return _chart;
};
_chart.rMin = function () {
var min = d3.min(_chart.group().all(), function (e) {
return _chart.radiusValueAccessor()(e);
});
return min;
};
_chart.rMax = function () {
var max = d3.max(_chart.group().all(), function (e) {
return _chart.radiusValueAccessor()(e);
});
return max;
};
_chart.bubbleR = function (d) {
var value = _chart.radiusValueAccessor()(d);
var r = _chart.r()(value);
if (isNaN(r) || value <= 0)
r = 0;
return r;
};
var labelFunction = function (d) {
return _chart.label()(d);
};
var labelOpacity = function (d) {
return (_chart.bubbleR(d) > _minRadiusWithLabel) ? 1 : 0;
};
_chart.doRenderLabel = function (bubbleGEnter) {
if (_chart.renderLabel()) {
var label = bubbleGEnter.select("text");
if (label.empty()) {
label = bubbleGEnter.append("text")
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.on("click", _chart.onClick);
}
label
.attr("opacity", 0)
.text(labelFunction);
dc.transition(label, _chart.transitionDuration())
.attr("opacity", labelOpacity);
}
};
_chart.doUpdateLabels = function (bubbleGEnter) {
if (_chart.renderLabel()) {
var labels = bubbleGEnter.selectAll("text")
.text(labelFunction);
dc.transition(labels, _chart.transitionDuration())
.attr("opacity", labelOpacity);
}
};
var titleFunction = function (d) {
return _chart.title()(d);
};
_chart.doRenderTitles = function (g) {
if (_chart.renderTitle()) {
var title = g.select("title");
if (title.empty())
g.append("title").text(titleFunction);
}
};
_chart.doUpdateTitles = function (g) {
if (_chart.renderTitle()) {
g.selectAll("title").text(titleFunction);
}
};
_chart.minRadiusWithLabel = function (_) {
if (!arguments.length) return _minRadiusWithLabel;
_minRadiusWithLabel = _;
return _chart;
};
_chart.maxBubbleRelativeSize = function (_) {
if (!arguments.length) return _maxBubbleRelativeSize;
_maxBubbleRelativeSize = _;
return _chart;
};
_chart.initBubbleColor = function (d, i) {
this[dc.constants.NODE_INDEX_NAME] = i;
return _chart.getColor(d, i);
};
_chart.updateBubbleColor = function (d, i) {
// a work around to get correct node index since
return _chart.getColor(d, this[dc.constants.NODE_INDEX_NAME]);
};
_chart.fadeDeselectedArea = function () {
if (_chart.hasFilter()) {
_chart.selectAll("g." + _chart.BUBBLE_NODE_CLASS).each(function (d) {
if (_chart.isSelectedNode(d)) {
_chart.highlightSelected(this);
} else {
_chart.fadeDeselected(this);
}
});
} else {
_chart.selectAll("g." + _chart.BUBBLE_NODE_CLASS).each(function (d) {
_chart.resetHighlight(this);
});
}
};
_chart.isSelectedNode = function (d) {
return _chart.hasFilter(d.key);
};
_chart.onClick = function (d) {
var filter = d.key;
dc.events.trigger(function () {
_chart.filter(filter);
dc.redrawAll(_chart.chartGroup());
});
};
return _chart;
};
dc.pieChart = function (parent, chartGroup) {
var DEFAULT_MIN_ANGLE_FOR_LABEL = 0.5;
var _sliceCssClass = "pie-slice";
var _radius,
_innerRadius = 0;
var _g;
var _minAngleForLabel = DEFAULT_MIN_ANGLE_FOR_LABEL;
var _chart = dc.colorChart(dc.baseChart({}));
var _slicesCap = Infinity;
var _othersLabel = "Others";
var _othersGrouper = function (data, sum) {
data.push({"key": _othersLabel, "value": sum });
};
function assemblePieData() {
if (_slicesCap == Infinity) {
return _chart.orderedGroup().top(_slicesCap); // ordered by keys
} else {
var topRows = _chart.group().top(_slicesCap); // ordered by value
var topRowsSum = d3.sum(topRows, _chart.valueAccessor());
var allRows = _chart.group().all();
var allRowsSum = d3.sum(allRows, _chart.valueAccessor());
_othersGrouper(topRows, allRowsSum - topRowsSum);
return topRows;
}
}
_chart.label(function (d) {
return _chart.keyAccessor()(d.data);
});
_chart.renderLabel(true);
_chart.title(function (d) {
return _chart.keyAccessor()(d.data) + ": " + _chart.valueAccessor()(d.data);
});
_chart.transitionDuration(350);
_chart.doRender = function () {
_chart.resetSvg();
_g = _chart.svg()
.append("g")
.attr("transform", "translate(" + _chart.cx() + "," + _chart.cy() + ")");
drawChart();
return _chart;
};
function drawChart() {
if (_chart.dataSet()) {
var pie = calculateDataPie();
// set radius on basis of chart dimension if missing
_radius = _radius ? _radius : d3.min([_chart.width(), _chart.height()]) /2;
var arc = _chart.buildArcs();
var pieData = pie(assemblePieData());
if (_g) {
var slices = _g.selectAll("g." + _sliceCssClass)
.data(pieData);
createElements(slices, arc, pieData);
updateElements(pieData, arc);
removeElements(slices);
highlightFilter();
}
}
}
function createElements(slices, arc, pieData) {
var slicesEnter = createSliceNodes(slices);
createSlicePath(slicesEnter, arc);
createTitles(slicesEnter);
createLabels(pieData, arc);
}
function createSliceNodes(slices) {
var slicesEnter = slices
.enter()
.append("g")
.attr("class", function (d, i) {
return _sliceCssClass + " _" + i;
});
return slicesEnter;
}
function createSlicePath(slicesEnter, arc) {
var slicePath = slicesEnter.append("path")
.attr("fill", function (d, i) {
return _chart.getColor(d, i);
})
.on("click", onClick)
.attr("d", function (d, i) {
return safeArc(d, i, arc);
});
slicePath.transition()
.duration(_chart.transitionDuration())
.attrTween("d", tweenPie);
}
function createTitles(slicesEnter) {
if (_chart.renderTitle()) {
slicesEnter.append("title").text(function (d) {
return _chart.title()(d);
});
}
}
function createLabels(pieData, arc) {
if (_chart.renderLabel()) {
var labels = _g.selectAll("text." + _sliceCssClass)
.data(pieData);
var labelsEnter = labels
.enter()
.append("text")
.attr("class", function (d, i) {
return _sliceCssClass + " _" + i;
})
.on("click", onClick);
dc.transition(labelsEnter, _chart.transitionDuration())
.attr("transform", function (d) {
d.innerRadius = _chart.innerRadius();
d.outerRadius = _radius;
var centroid = arc.centroid(d);
if (isNaN(centroid[0]) || isNaN(centroid[1])) {
return "translate(0,0)";
} else {
return "translate(" + centroid + ")";
}
})
.attr("text-anchor", "middle")
.text(function (d) {
var data = d.data;
if (sliceHasNoData(data) || sliceTooSmall(d))
return "";
return _chart.label()(d);
});
}
}
function updateElements(pieData, arc) {
updateSlicePaths(pieData, arc);
updateLabels(pieData, arc);
updateTitles(pieData);
}
function updateSlicePaths(pieData, arc) {
var slicePaths = _g.selectAll("g." + _sliceCssClass)
.data(pieData)
.select("path")
.attr("d", function (d, i) {
return safeArc(d, i, arc);
});
dc.transition(slicePaths, _chart.transitionDuration(),
function (s) {
s.attrTween("d", tweenPie);
}).attr("fill", function (d, i) {
return _chart.getColor(d, i);
});
}
function updateLabels(pieData, arc) {
if (_chart.renderLabel()) {
var labels = _g.selectAll("text." + _sliceCssClass)
.data(pieData);
dc.transition(labels, _chart.transitionDuration())
.attr("transform", function (d) {
d.innerRadius = _chart.innerRadius();
d.outerRadius = _radius;
var centroid = arc.centroid(d);
if (isNaN(centroid[0]) || isNaN(centroid[1])) {
return "translate(0,0)";
} else {
return "translate(" + centroid + ")";
}
})
.attr("text-anchor", "middle")
.text(function (d) {
var data = d.data;
if (sliceHasNoData(data) || sliceTooSmall(d))
return "";
return _chart.label()(d);
});
}
}
function updateTitles(pieData) {
if (_chart.renderTitle()) {
_g.selectAll("g." + _sliceCssClass)
.data(pieData)
.select("title")
.text(function (d) {
return _chart.title()(d);
});
}
}
function removeElements(slices) {
slices.exit().remove();
}
function highlightFilter() {
if (_chart.hasFilter()) {
_chart.selectAll("g." + _sliceCssClass).each(function (d) {
if (_chart.isSelectedSlice(d)) {
_chart.highlightSelected(this);
} else {
_chart.fadeDeselected(this);
}
});
} else {
_chart.selectAll("g." + _sliceCssClass).each(function (d) {
_chart.resetHighlight(this);
});
}
}
_chart.innerRadius = function (r) {
if (!arguments.length) return _innerRadius;
_innerRadius = r;
return _chart;
};
_chart.radius = function (r) {
if (!arguments.length) return _radius;
_radius = r;
return _chart;
};
_chart.cx = function () {
return _chart.width() / 2;
};
_chart.cy = function () {
return _chart.height() / 2;
};
_chart.buildArcs = function () {
return d3.svg.arc().outerRadius(_radius).innerRadius(_innerRadius);
};
_chart.isSelectedSlice = function (d) {
return _chart.hasFilter(_chart.keyAccessor()(d.data));
};
_chart.doRedraw = function () {
drawChart();
return _chart;
};
_chart.minAngleForLabel = function (_) {
if (!arguments.length) return _minAngleForLabel;
_minAngleForLabel = _;
return _chart;
};
_chart.slicesCap = function (_) {
if (!arguments.length) return _slicesCap;
_slicesCap = _;
return _chart;
};
_chart.othersLabel = function (_) {
if (!arguments.length) return _othersLabel;
_othersLabel = _;
return _chart;
};
_chart.othersGrouper = function (_) {
if (!arguments.length) return _othersGrouper;
_othersGrouper = _;
return _chart;
};
function calculateDataPie() {
return d3.layout.pie().sort(null).value(function (d) {
return _chart.valueAccessor()(d);
});
}
function sliceTooSmall(d) {
var angle = (d.endAngle - d.startAngle);
return isNaN(angle) || angle < _minAngleForLabel;
}
function sliceHasNoData(data) {
return _chart.valueAccessor()(data) == 0;
}
function tweenPie(b) {
b.innerRadius = _chart.innerRadius();
var current = this._current;
if (isOffCanvas(current))
current = {startAngle: 0, endAngle: 0};
var i = d3.interpolate(current, b);
this._current = i(0);
return function (t) {
return safeArc(i(t), 0, _chart.buildArcs());
};
}
function isOffCanvas(current) {
return current == null || isNaN(current.startAngle) || isNaN(current.endAngle);
}
function onClick(d) {
_chart.onClick(d.data);
}
function safeArc(d, i, arc) {
var path = arc(d, i);
if (path.indexOf("NaN") >= 0)
path = "M0,0";
return path;
}
return _chart.anchor(parent, chartGroup);
};
dc.barChart = function (parent, chartGroup) {
var MIN_BAR_WIDTH = 1;
var DEFAULT_GAP_BETWEEN_BARS = 2;
var _chart = dc.stackableChart(dc.coordinateGridChart({}));
var _gap = DEFAULT_GAP_BETWEEN_BARS;
var _centerBar = false;
var _numberOfBars;
var _barWidth;
dc.override(_chart, 'rescale', function () {
_chart._rescale();
_numberOfBars = null;
_barWidth = null;
getNumberOfBars();
});
_chart.plotData = function () {
var layers = _chart.chartBodyG().selectAll("g.stack")
.data(_chart.stackLayers());
calculateBarWidth();
layers
.enter()
.append("g")
.attr("class", function (d, i) {
return "stack " + "_" + i;
});
layers.each(function (d, i) {
var layer = d3.select(this);
renderBars(layer, d, i);
});
_chart.stackLayers(null);
};
function barHeight(d) {
return Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0));
}
function renderBars(layer, d, i) {
var bars = layer.selectAll("rect.bar")
.data(d.points);
bars.enter()
.append("rect")
.attr("class", "bar")
.attr("fill", function (d) {
return _chart.colors()(i);
})
.append("title").text(_chart.title());
dc.transition(bars, _chart.transitionDuration())
.attr("x", function (d) {
var x = _chart.x()(d.x);
if (_centerBar) x -= _barWidth / 2;
return x;
})
.attr("y", function (d) {
var y = _chart.y()(d.y + d.y0);
if (d.y < 0)
y -= barHeight(d);
return y;
})
.attr("width", _barWidth)
.attr("height", function (d) {
return barHeight(d);
})
.select("title").text(_chart.title());
dc.transition(bars.exit(), _chart.transitionDuration())
.attr("height", 0)
.remove();
}
function calculateBarWidth() {
if (_barWidth == null) {
var numberOfBars = _chart.isOrdinal() ? getNumberOfBars() + 1 : getNumberOfBars();
var w = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars);
if (w == Infinity || isNaN(w) || w < MIN_BAR_WIDTH)
w = MIN_BAR_WIDTH;
_barWidth = w;
}
}
function getNumberOfBars() {
if (_numberOfBars == null) {
_numberOfBars = _chart.xUnitCount();
}
return _numberOfBars;
}
_chart.fadeDeselectedArea = function () {
var bars = _chart.chartBodyG().selectAll("rect.bar");
var extent = _chart.brush().extent();
if (_chart.isOrdinal()) {
if (_chart.hasFilter()) {
bars.classed(dc.constants.SELECTED_CLASS, function (d) {
return _chart.hasFilter(_chart.keyAccessor()(d.data));
});
bars.classed(dc.constants.DESELECTED_CLASS, function (d) {
return !_chart.hasFilter(_chart.keyAccessor()(d.data));
});
} else {
bars.classed(dc.constants.SELECTED_CLASS, false);
bars.classed(dc.constants.DESELECTED_CLASS, false);
}
} else {
if (!_chart.brushIsEmpty(extent)) {
var start = extent[0];
var end = extent[1];
bars.classed(dc.constants.DESELECTED_CLASS, function (d) {
var xValue = _chart.keyAccessor()(d.data);
return xValue < start || xValue >= end;
});
} else {
bars.classed(dc.constants.DESELECTED_CLASS, false);
}
}
};
_chart.centerBar = function (_) {
if (!arguments.length) return _centerBar;
_centerBar = _;
return _chart;
};
_chart.gap = function (_) {
if (!arguments.length) return _gap;
_gap = _;
return _chart;
};
_chart.extendBrush = function () {
var extent = _chart.brush().extent();
if (_chart.round() && !_centerBar) {
extent[0] = extent.map(_chart.round())[0];
extent[1] = extent.map(_chart.round())[1];
_chart.chartBodyG().select(".brush")
.call(_chart.brush().extent(extent));
}
return extent;
};
dc.override(_chart, "prepareOrdinalXAxis", function () {
return this._prepareOrdinalXAxis(_chart.xUnitCount() + 1);
});
_chart.legendHighlight = function (d) {
_chart.select('.chart-body').selectAll('rect.bar').filter(function () {
return d3.select(this).attr('fill') == d.color;
}).classed('highlight', true);
_chart.select('.chart-body').selectAll('rect.bar').filter(function () {
return d3.select(this).attr('fill') != d.color;
}).classed('fadeout', true);
};
_chart.legendReset = function (d) {
_chart.selectAll('.chart-body').selectAll('rect.bar').filter(function () {
return d3.select(this).attr('fill') == d.color;
}).classed('highlight', false);
_chart.selectAll('.chart-body').selectAll('rect.bar').filter(function () {
return d3.select(this).attr('fill') != d.color;
}).classed('fadeout', false);
};
return _chart.anchor(parent, chartGroup);
};
dc.lineChart = function (parent, chartGroup) {
var DEFAULT_DOT_RADIUS = 5;
var TOOLTIP_G_CLASS = "dc-tooltip";
var DOT_CIRCLE_CLASS = "dot";
var Y_AXIS_REF_LINE_CLASS = "yRef";
var X_AXIS_REF_LINE_CLASS = "xRef";
var _chart = dc.stackableChart(dc.coordinateGridChart({}));
var _renderArea = false;
var _dotRadius = DEFAULT_DOT_RADIUS;
_chart.transitionDuration(500);
_chart.plotData = function () {
var layers = _chart.chartBodyG().selectAll("g.stack")
.data(_chart.stackLayers());
var layersEnter = layers
.enter()
.append("g")
.attr("class", function (d, i) {
return "stack " + "_" + i;
});
drawLine(layersEnter, layers);
drawArea(layersEnter, layers);
drawDots(layers);
_chart.stackLayers(null);
};
_chart.renderArea = function (_) {
if (!arguments.length) return _renderArea;
_renderArea = _;
return _chart;
};
function drawLine(layersEnter, layers) {
var line = d3.svg.line()
.x(function (d) {
return _chart.x()(d.x);
})
.y(function (d) {
return _chart.y()(d.y + d.y0);
});
layersEnter.append("path")
.attr("class", "line")
.attr("stroke", function (d, i) {
return _chart.colors()(i);
})
.attr("fill", function (d, i) {
return _chart.colors()(i);
});
dc.transition(layers.select("path.line"), _chart.transitionDuration())
.attr("d", function (d) {
return line(d.points);
});
}
function drawArea(layersEnter, layers) {
if (_renderArea) {
var area = d3.svg.area()
.x(function (d) {
return _chart.x()(d.x);
})
.y(function (d) {
return _chart.y()(d.y + d.y0);
})
.y0(function (d) {
return _chart.y()(d.y0);
});
layersEnter.append("path")
.attr("class", "area")
.attr("fill", function (d, i) {
return _chart.colors()(i);
})
.attr("d", function (d) {
return area(d.points);
});
dc.transition(layers.select("path.area"), _chart.transitionDuration())
.attr("d", function (d) {
return area(d.points);
});
}
}
function drawDots(layersEnter) {
if (!_chart.brushOn()) {
layersEnter.each(function (d, i) {
var layer = d3.select(this);
var g = layer.select("g." + TOOLTIP_G_CLASS);
if (g.empty()) g = layer.append("g").attr("class", TOOLTIP_G_CLASS);
createRefLines(g);
var dots = g.selectAll("circle." + DOT_CIRCLE_CLASS)
.data(g.datum().points);
dots.enter()
.append("circle")
.attr("class", DOT_CIRCLE_CLASS)
.attr("r", _dotRadius)
.attr("fill", function (d) {
return _chart.colors()(i);
})
.style("fill-opacity", 1e-6)
.style("stroke-opacity", 1e-6)
.on("mousemove", function (d) {
var dot = d3.select(this);
showDot(dot);
showRefLines(dot, g);
})
.on("mouseout", function (d) {
var dot = d3.select(this);
hideDot(dot);
hideRefLines(g);
})
.append("title").text(_chart.title());
dots.attr("cx", function (d) {
return _chart.x()(d.x);
})
.attr("cy", function (d) {
return _chart.y()(d.y + d.y0);
})
.select("title").text(_chart.title());
dots.exit().remove();
});
}
}
function createRefLines(g) {
var yRefLine = g.select("path." + Y_AXIS_REF_LINE_CLASS).empty() ? g.append("path").attr("class", Y_AXIS_REF_LINE_CLASS) : g.select("path." + Y_AXIS_REF_LINE_CLASS);
yRefLine.style("display", "none").attr("stroke-dasharray", "5,5");
var xRefLine = g.select("path." + X_AXIS_REF_LINE_CLASS).empty() ? g.append("path").attr("class", X_AXIS_REF_LINE_CLASS) : g.select("path." + X_AXIS_REF_LINE_CLASS);
xRefLine.style("display", "none").attr("stroke-dasharray", "5,5");
}
function showDot(dot) {
dot.style("fill-opacity", .8);
dot.style("stroke-opacity", .8);
return dot;
}
function showRefLines(dot, g) {
var x = dot.attr("cx");
var y = dot.attr("cy");
g.select("path." + Y_AXIS_REF_LINE_CLASS).style("display", "").attr("d", "M0 " + y + "L" + (x) + " " + (y));
g.select("path." + X_AXIS_REF_LINE_CLASS).style("display", "").attr("d", "M" + x + " " + _chart.yAxisHeight() + "L" + x + " " + y);
}
function hideDot(dot) {
dot.style("fill-opacity", 1e-6).style("stroke-opacity", 1e-6);
}
function hideRefLines(g) {
g.select("path." + Y_AXIS_REF_LINE_CLASS).style("display", "none");
g.select("path." + X_AXIS_REF_LINE_CLASS).style("display", "none");
}
_chart.dotRadius = function (_) {
if (!arguments.length) return _dotRadius;
_dotRadius = _;
return _chart;
};
_chart.legendHighlight = function (d) {
_chart.selectAll('.chart-body').selectAll('path').filter(function () {
return d3.select(this).attr('fill') == d.color;
}).classed('highlight', true);
_chart.selectAll('.chart-body').selectAll('path').filter(function () {
return d3.select(this).attr('fill') != d.color;
}).classed('fadeout', true);
};
_chart.legendReset = function (d) {
_chart.selectAll('.chart-body').selectAll('path').filter(function () {
return d3.select(this).attr('fill') == d.color;
}).classed('highlight', false);
_chart.selectAll('.chart-body').selectAll('path').filter(function () {
return d3.select(this).attr('fill') != d.color;
}).classed('fadeout', false);
};
return _chart.anchor(parent, chartGroup);
};
dc.dataCount = function(parent, chartGroup) {
var _formatNumber = d3.format(",d");
var _chart = dc.baseChart({});
_chart.doRender = function() {
_chart.selectAll(".total-count").text(_formatNumber(_chart.dimension().size()));
_chart.selectAll(".filter-count").text(_formatNumber(_chart.group().value()));
return _chart;
};
_chart.doRedraw = function(){
return _chart.doRender();
};
return _chart.anchor(parent, chartGroup);
};
dc.dataTable = function(parent, chartGroup) {
var LABEL_CSS_CLASS = "dc-table-label";
var ROW_CSS_CLASS = "dc-table-row";
var COLUMN_CSS_CLASS = "dc-table-column";
var GROUP_CSS_CLASS = "dc-table-group";
var _chart = dc.baseChart({});
var _size = 25;
var _columns = [];
var _sortBy = function(d) {
return d;
};
var _order = d3.ascending;
var _sort;
_chart.doRender = function() {
_chart.selectAll("tbody").remove();
renderRows(renderGroups());
return _chart;
};
function renderGroups() {
var groups = _chart.root().selectAll("tbody")
.data(nestEntries(), function(d) {
return _chart.keyAccessor()(d);
});
var rowGroup = groups
.enter()
.append("tbody");
rowGroup
.append("tr")
.attr("class", GROUP_CSS_CLASS)
.append("td")
.attr("class", LABEL_CSS_CLASS)
.attr("colspan", _columns.length)
.html(function(d) {
return _chart.keyAccessor()(d);
});
groups.exit().remove();
return rowGroup;
}
function nestEntries() {
if (!_sort)
_sort = crossfilter.quicksort.by(_sortBy);
var entries = _chart.dimension().top(_size);
return d3.nest()
.key(_chart.group())
.sortKeys(_order)
.sortValues(_order)
.entries(_sort(entries, 0, entries.length));
}
function renderRows(groups) {
var rows = groups.order()
.selectAll("tr." + ROW_CSS_CLASS)
.data(function(d) {
return d.values;
});
var rowEnter = rows.enter()
.append("tr")
.attr("class", ROW_CSS_CLASS);
for (var i = 0; i < _columns.length; ++i) {
var f = _columns[i];
rowEnter.append("td")
.attr("class", COLUMN_CSS_CLASS + " _" + i)
.html(function(d) {
return f(d);
});
}
rows.exit().remove();
return rows;
}
_chart.doRedraw = function() {
return _chart.doRender();
};
_chart.size = function(s) {
if (!arguments.length) return _size;
_size = s;
return _chart;
};
_chart.columns = function(_) {
if (!arguments.length) return _columns;
_columns = _;
return _chart;
};
_chart.sortBy = function(_) {
if (!arguments.length) return _sortBy;
_sortBy = _;
return _chart;
};
_chart.order = function(_) {
if (!arguments.length) return _order;
_order = _;
return _chart;
};
return _chart.anchor(parent, chartGroup);
};
dc.bubbleChart = function(parent, chartGroup) {
var _chart = dc.abstractBubbleChart(dc.coordinateGridChart({}));
var _elasticRadius = false;
_chart.transitionDuration(750);
var bubbleLocator = function(d) {
return "translate(" + (bubbleX(d)) + "," + (bubbleY(d)) + ")";
};
_chart.elasticRadius = function(_) {
if (!arguments.length) return _elasticRadius;
_elasticRadius = _;
return _chart;
};
_chart.plotData = function() {
if (_elasticRadius)
_chart.r().domain([_chart.rMin(), _chart.rMax()]);
_chart.r().range([_chart.MIN_RADIUS, _chart.xAxisLength() * _chart.maxBubbleRelativeSize()]);
var bubbleG = _chart.chartBodyG().selectAll("g." + _chart.BUBBLE_NODE_CLASS)
.data(_chart.group().all());
renderNodes(bubbleG);
updateNodes(bubbleG);
removeNodes(bubbleG);
_chart.fadeDeselectedArea();
};
function renderNodes(bubbleG) {
var bubbleGEnter = bubbleG.enter().append("g");
bubbleGEnter
.attr("class", _chart.BUBBLE_NODE_CLASS)
.attr("transform", bubbleLocator)
.append("circle").attr("class", function(d, i) {
return _chart.BUBBLE_CLASS + " _" + i;
})
.on("click", _chart.onClick)
.attr("fill", _chart.initBubbleColor)
.attr("r", 0);
dc.transition(bubbleG, _chart.transitionDuration())
.attr("r", function(d) {
return _chart.bubbleR(d);
})
.attr("opacity", function(d) {
return (_chart.bubbleR(d) > 0) ? 1 : 0;
});
_chart.doRenderLabel(bubbleGEnter);
_chart.doRenderTitles(bubbleGEnter);
}
function updateNodes(bubbleG) {
dc.transition(bubbleG, _chart.transitionDuration())
.attr("transform", bubbleLocator)
.selectAll("circle." + _chart.BUBBLE_CLASS)
.attr("fill", _chart.updateBubbleColor)
.attr("r", function(d) {
return _chart.bubbleR(d);
})
.attr("opacity", function(d) {
return (_chart.bubbleR(d) > 0) ? 1 : 0;
});
_chart.doUpdateLabels(bubbleG);
_chart.doUpdateTitles(bubbleG);
}
function removeNodes(bubbleG) {
bubbleG.exit().remove();
}
function bubbleX(d) {
var x = _chart.x()(_chart.keyAccessor()(d)) + _chart.margins().left;
if (isNaN(x))
x = 0;
return x;
}
function bubbleY(d) {
var y = _chart.margins().top + _chart.y()(_chart.valueAccessor()(d));
if (isNaN(y))
y = 0;
return y;
}
_chart.renderBrush = function(g) {
// override default x axis brush from parent chart
};
_chart.redrawBrush = function(g) {
// override default x axis brush from parent chart
_chart.fadeDeselectedArea();
};
return _chart.anchor(parent, chartGroup);
};
dc.compositeChart = function (parent, chartGroup) {
var SUB_CHART_CLASS = "sub";
var _chart = dc.coordinateGridChart({});
var _children = [];
_chart.transitionDuration(500);
dc.override(_chart, "generateG", function () {
var g = this._generateG();
for (var i = 0; i < _children.length; ++i) {
var child = _children[i];
generateChildG(child, i);
if (child.dimension() == null) child.dimension(_chart.dimension());
if (child.group() == null) child.group(_chart.group());
child.chartGroup(_chart.chartGroup());
child.svg(_chart.svg());
child.xUnits(_chart.xUnits());
child.transitionDuration(_chart.transitionDuration());
child.brushOn(_chart.brushOn());
}
return g;
});
function generateChildG(child, i) {
child.generateG(_chart.g());
child.g().attr("class", SUB_CHART_CLASS + " _" + i);
}
_chart.plotData = function () {
for (var i = 0; i < _children.length; ++i) {
var child = _children[i];
if (child.g() == null) {
generateChildG(child, i);
}
child.x(_chart.x());
child.y(_chart.y());
child.xAxis(_chart.xAxis());
child.yAxis(_chart.yAxis());
child.plotData();
child.activateRenderlets();
}
};
_chart.fadeDeselectedArea = function () {
for (var i = 0; i < _children.length; ++i) {
var child = _children[i];
child.brush(_chart.brush());
child.fadeDeselectedArea();
}
};
_chart.compose = function (charts) {
_children = charts;
for (var i = 0; i < _children.length; ++i) {
var child = _children[i];
child.height(_chart.height());
child.width(_chart.width());
child.margins(_chart.margins());
}
return _chart;
};
_chart.children = function () {
return _children;
};
function getAllYAxisMinFromChildCharts() {
var allMins = [];
for (var i = 0; i < _children.length; ++i) {
allMins.push(_children[i].yAxisMin());
}
return allMins;
}
_chart.yAxisMin = function () {
return d3.min(getAllYAxisMinFromChildCharts());
};
function getAllYAxisMaxFromChildCharts() {
var allMaxes = [];
for (var i = 0; i < _children.length; ++i) {
allMaxes.push(_children[i].yAxisMax());
}
return allMaxes;
}
_chart.yAxisMax = function () {
return dc.utils.add(d3.max(getAllYAxisMaxFromChildCharts()), _chart.yAxisPadding());
};
function getAllXAxisMinFromChildCharts() {
var allMins = [];
for (var i = 0; i < _children.length; ++i) {
allMins.push(_children[i].xAxisMin());
}
return allMins;
}
_chart.xAxisMin = function () {
return dc.utils.subtract(d3.min(getAllXAxisMinFromChildCharts()), _chart.xAxisPadding());
};
function getAllXAxisMaxFromChildCharts() {
var allMaxes = [];
for (var i = 0; i < _children.length; ++i) {
allMaxes.push(_children[i].xAxisMax());
}
return allMaxes;
}
_chart.xAxisMax = function () {
return dc.utils.add(d3.max(getAllXAxisMaxFromChildCharts()), _chart.xAxisPadding());
};
_chart.legendables = function () {
var items = [];
for (var j = 0; j < _children.length; ++j) {
var childChart = _children[j];
childChart.allGroups().forEach(function (g, i) {
items.push(dc.utils.createLegendable(childChart, g, i));
});
}
return items;
};
_chart.legendHighlight = function (d) {
for (var j = 0; j < _children.length; ++j) {
var child = _children[j];
child.legendHighlight(d);
}
};
_chart.legendReset = function (d) {
for (var j = 0; j < _children.length; ++j) {
var child = _children[j];
child.legendReset(d);
}
};
return _chart.anchor(parent, chartGroup);
};
dc.geoChoroplethChart = function (parent, chartGroup) {
var _chart = dc.colorChart(dc.baseChart({}));
_chart.colorAccessor(function (d, i) {
return d;
});
var _geoPath = d3.geo.path();
var _projectionFlag;
var _geoJsons = [];
_chart.doRender = function () {
_chart.resetSvg();
for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) {
var states = _chart.svg().append("g")
.attr("class", "layer" + layerIndex);
var regionG = states.selectAll("g." + geoJson(layerIndex).name)
.data(geoJson(layerIndex).data)
.enter()
.append("g")
.attr("class", geoJson(layerIndex).name);
regionG
.append("path")
.attr("fill", "white")
.attr("d", _geoPath);
regionG.append("title");
plotData(layerIndex);
}
_projectionFlag = false;
};
function plotData(layerIndex) {
var maxValue = dc.utils.groupMax(_chart.group(), _chart.valueAccessor());
var data = generateLayeredData();
if (isDataLayer(layerIndex)) {
var regionG = renderRegionG(layerIndex);
renderPaths(regionG, layerIndex, data, maxValue);
renderTitle(regionG, layerIndex, data);
}
}
function generateLayeredData() {
var data = {};
var groupAll = _chart.group().all();
for (var i = 0; i < groupAll.length; ++i) {
data[_chart.keyAccessor()(groupAll[i])] = _chart.valueAccessor()(groupAll[i]);
}
return data;
}
function isDataLayer(layerIndex) {
return geoJson(layerIndex).keyAccessor;
}
function renderRegionG(layerIndex) {
var regionG = _chart.svg()
.selectAll(layerSelector(layerIndex))
.classed("selected", function (d) {
return isSelected(layerIndex, d);
})
.classed("deselected", function (d) {
return isDeselected(layerIndex, d);
})
.attr("class", function (d) {
var layerNameClass = geoJson(layerIndex).name;
var regionClass = dc.utils.nameToId(geoJson(layerIndex).keyAccessor(d));
var baseClasses = layerNameClass + " " + regionClass;
if (isSelected(layerIndex, d)) baseClasses += " selected";
if (isDeselected(layerIndex, d)) baseClasses += " deselected";
return baseClasses;
});
return regionG;
}
function layerSelector(layerIndex) {
return "g.layer" + layerIndex + " g." + geoJson(layerIndex).name;
}
function isSelected(layerIndex, d) {
return _chart.hasFilter() && _chart.hasFilter(getKey(layerIndex, d));
}
function isDeselected(layerIndex, d) {
return _chart.hasFilter() && !_chart.hasFilter(getKey(layerIndex, d));
}
function getKey(layerIndex, d) {
return geoJson(layerIndex).keyAccessor(d);
}
function geoJson(index) {
return _geoJsons[index];
}
function renderPaths(regionG, layerIndex, data, maxValue) {
var paths = regionG
.select("path")
.attr("fill", function (d) {
var currentFill = d3.select(this).attr("fill");
if (currentFill)
return currentFill;
return "none";
})
.on("click", function (d) {
return _chart.onClick(d, layerIndex);
});
dc.transition(paths, _chart.transitionDuration()).attr("fill", function (d, i) {
return _chart.getColor(data[geoJson(layerIndex).keyAccessor(d)], i);
});
}
_chart.onClick = function (d, layerIndex) {
var selectedRegion = geoJson(layerIndex).keyAccessor(d);
dc.events.trigger(function () {
_chart.filter(selectedRegion);
dc.redrawAll(_chart.chartGroup());
});
};
function renderTitle(regionG, layerIndex, data) {
if (_chart.renderTitle()) {
regionG.selectAll("title").text(function (d) {
var key = getKey(layerIndex, d);
var value = data[key];
return _chart.title()({key: key, value: value});
});
}
}
_chart.doRedraw = function () {
for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) {
plotData(layerIndex);
if(_projectionFlag) {
_chart.svg().selectAll("g." + geoJson(layerIndex).name + " path").attr("d", _geoPath)
};
}
_projectionFlag = false
};
_chart.overlayGeoJson = function (json, name, keyAccessor) {
for (var i = 0; i < _geoJsons.length; ++i) {
if (_geoJsons[i].name == name) {
_geoJsons[i].data = json;
_geoJsons[i].keyAccessor = keyAccessor;
return _chart
}
}
_geoJsons.push({name: name, data: json, keyAccessor: keyAccessor});
return _chart;
};
_chart.projection = function (projection) {
_geoPath.projection(projection);
_projectionFlag = true;
return _chart;
};
_chart.geoJsons = function () {
return _geoJsons;
};
_chart.removeGeoJson = function (name) {
var geoJsons = [];
for (var i = 0; i < _geoJsons.length; ++i) {
var layer = _geoJsons[i];
if (layer.name != name) {
geoJsons.push(layer);
}
}
_geoJsons = geoJsons;
return _chart;
};
return _chart.anchor(parent, chartGroup);
};
dc.bubbleOverlay = function(root, chartGroup) {
var BUBBLE_OVERLAY_CLASS = "bubble-overlay";
var BUBBLE_NODE_CLASS = "node";
var BUBBLE_CLASS = "bubble";
var _chart = dc.abstractBubbleChart(dc.baseChart({}));
var _g;
var _points = [];
_chart.transitionDuration(750);
_chart.radiusValueAccessor(function(d) {
return d.value;
});
_chart.point = function(name, x, y) {
_points.push({name: name, x: x, y: y});
return _chart;
};
_chart.doRender = function() {
_g = initOverlayG();
_chart.r().range([_chart.MIN_RADIUS, _chart.width() * _chart.maxBubbleRelativeSize()]);
initializeBubbles();
_chart.fadeDeselectedArea();
return _chart;
};
function initOverlayG() {
_g = _chart.select("g." + BUBBLE_OVERLAY_CLASS);
if (_g.empty())
_g = _chart.svg().append("g").attr("class", BUBBLE_OVERLAY_CLASS);
return _g;
}
function initializeBubbles() {
var data = mapData();
_points.forEach(function(point) {
var nodeG = getNodeG(point, data);
var circle = nodeG.select("circle." + BUBBLE_CLASS);
if (circle.empty())
circle = nodeG.append("circle")
.attr("class", BUBBLE_CLASS)
.attr("r", 0)
.attr("fill", _chart.initBubbleColor)
.on("click", _chart.onClick);
dc.transition(circle, _chart.transitionDuration())
.attr("r", function(d) {
return _chart.bubbleR(d);
});
_chart.doRenderLabel(nodeG);
_chart.doRenderTitles(nodeG);
});
}
function mapData() {
var data = {};
_chart.group().all().forEach(function(datum) {
data[_chart.keyAccessor()(datum)] = datum;
});
return data;
}
function getNodeG(point, data) {
var bubbleNodeClass = BUBBLE_NODE_CLASS + " " + dc.utils.nameToId(point.name);
var nodeG = _g.select("g." + dc.utils.nameToId(point.name));
if (nodeG.empty()) {
nodeG = _g.append("g")
.attr("class", bubbleNodeClass)
.attr("transform", "translate(" + point.x + "," + point.y + ")");
}
nodeG.datum(data[point.name]);
return nodeG;
}
_chart.doRedraw = function() {
updateBubbles();
_chart.fadeDeselectedArea();
return _chart;
};
function updateBubbles() {
var data = mapData();
_points.forEach(function(point) {
var nodeG = getNodeG(point, data);
var circle = nodeG.select("circle." + BUBBLE_CLASS);
dc.transition(circle, _chart.transitionDuration())
.attr("r", function(d) {
return _chart.bubbleR(d);
})
.attr("fill", _chart.updateBubbleColor);
_chart.doUpdateLabels(nodeG);
_chart.doUpdateTitles(nodeG);
});
}
_chart.debug = function(flag) {
if(flag){
var debugG = _chart.select("g." + dc.constants.DEBUG_GROUP_CLASS);
if(debugG.empty())
debugG = _chart.svg()
.append("g")
.attr("class", dc.constants.DEBUG_GROUP_CLASS);
var debugText = debugG.append("text")
.attr("x", 10)
.attr("y", 20);
debugG
.append("rect")
.attr("width", _chart.width())
.attr("height", _chart.height())
.on("mousemove", function() {
var position = d3.mouse(debugG.node());
var msg = position[0] + ", " + position[1];
debugText.text(msg);
});
}else{
_chart.selectAll(".debug").remove();
}
return _chart;
};
_chart.anchor(root, chartGroup);
return _chart;
};dc.rowChart = function (parent, chartGroup) {
var _g;
var _labelOffsetX = 10;
var _labelOffsetY = 15;
var _gap = 5;
var _rowCssClass = "row";
var _chart = dc.marginable(dc.colorChart(dc.baseChart({})));
var _xScale;
var _elasticX;
var _xAxis = d3.svg.axis().orient("bottom");
function calculateAxisScale() {
if (!_xScale || _elasticX) {
_xScale = d3.scale.linear().domain([0, d3.max(_chart.group().all(), _chart.valueAccessor())])
.range([0, _chart.effectiveWidth()]);
_xAxis.scale(_xScale);
}
}
function drawAxis() {
var axisG = _g.select("g.axis");
calculateAxisScale();
if (axisG.empty())
axisG = _g.append("g").attr("class", "axis")
.attr("transform", "translate(0, " + _chart.effectiveHeight() + ")");
dc.transition(axisG, _chart.transitionDuration())
.call(_xAxis);
}
_chart.doRender = function () {
_chart.resetSvg();
_g = _chart.svg()
.append("g")
.attr("transform", "translate(" + _chart.margins().left + "," + _chart.margins().top + ")");
drawAxis();
drawGridLines();
drawChart();
return _chart;
};
_chart.title(function (d) {
return _chart.keyAccessor()(d) + ": " + _chart.valueAccessor()(d);
});
_chart.label(function (d) {
return _chart.keyAccessor()(d);
});
function drawGridLines() {
_g.selectAll("g.tick")
.select("line.grid-line")
.remove();
_g.selectAll("g.tick")
.append("line")
.attr("class", "grid-line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", function (d) {
return -_chart.effectiveHeight();
});
}
function drawChart() {
drawAxis();
drawGridLines();
var rows = _g.selectAll("g." + _rowCssClass)
.data(_chart.group().all());
createElements(rows);
removeElements(rows);
updateElements(rows);
}
function createElements(rows) {
var rowEnter = rows.enter()
.append("g")
.attr("class", function (d, i) {
return _rowCssClass + " _" + i;
});
rowEnter.append("rect").attr("width", 0);
createLabels(rowEnter);
updateLabels(rows);
}
function removeElements(rows) {
rows.exit().remove();
}
function updateElements(rows) {
var height = rowHeight();
rows = rows.attr("transform",function (d, i) {
return "translate(0," + ((i + 1) * _gap + i * height) + ")";
}).select("rect")
.attr("height", height)
.attr("fill", _chart.getColor)
.on("click", onClick)
.classed("deselected", function (d) {
return (_chart.hasFilter()) ? !_chart.isSelectedRow(d) : false;
})
.classed("selected", function (d) {
return (_chart.hasFilter()) ? _chart.isSelectedRow(d) : false;
});
dc.transition(rows, _chart.transitionDuration())
.attr("width", function (d) {
return _xScale(_chart.valueAccessor()(d));
});
createTitles(rows);
}
function createTitles(rows) {
if (_chart.renderTitle()) {
rows.selectAll("title").remove();
rows.append("title").text(function (d) {
return _chart.title()(d);
});
}
}
function createLabels(rowEnter) {
if (_chart.renderLabel()) {
rowEnter.append("text")
.on("click", onClick);
}
}
function updateLabels(rows) {
if (_chart.renderLabel()) {
rows.select("text")
.attr("x", _labelOffsetX)
.attr("y", _labelOffsetY)
.attr("class", function (d, i) {
return _rowCssClass + " _" + i;
})
.text(function (d) {
return _chart.label()(d);
});
}
}
function numberOfRows() {
return _chart.group().all().length;
}
function rowHeight() {
var n = numberOfRows();
return (_chart.effectiveHeight() - (n + 1) * _gap) / n;
}
function onClick(d) {
_chart.onClick(d);
}
_chart.doRedraw = function () {
drawChart();
return _chart;
};
_chart.xAxis = function () {
return _xAxis;
};
_chart.gap = function (g) {
if (!arguments.length) return _gap;
_gap = g;
return _chart;
};
_chart.elasticX = function (_) {
if (!arguments.length) return _elasticX;
_elasticX = _;
return _chart;
};
_chart.labelOffsetX = function (o) {
if (!arguments.length) return _labelOffsetX;
_labelOffsetX = o;
return _chart;
};
_chart.labelOffsetY = function (o) {
if (!arguments.length) return _labelOffsetY;
_labelOffsetY = o;
return _chart;
};
_chart.isSelectedRow = function (d) {
return _chart.hasFilter(_chart.keyAccessor()(d));
};
return _chart.anchor(parent, chartGroup);
};
dc.legend = function () {
var LABEL_GAP = 2;
var _legend = {},
_parent,
_x = 0,
_y = 0,
_itemHeight = 12,
_gap = 5;
var _g;
_legend.parent = function (p) {
if (!arguments.length) return _parent;
_parent = p;
return _legend;
};
_legend.render = function () {
_g = _parent.svg().append("g")
.attr("class", "dc-legend")
.attr("transform", "translate(" + _x + "," + _y + ")");
var itemEnter = _g.selectAll('g.dc-legend-item')
.data(_parent.legendables())
.enter()
.append("g")
.attr("class", "dc-legend-item")
.attr("transform", function (d, i) {
return "translate(0," + i * legendItemHeight() + ")";
})
.on("mouseover", function(d){
_parent.legendHighlight(d);
})
.on("mouseout", function (d) {
_parent.legendReset(d);
});
itemEnter
.append("rect")
.attr("width", _itemHeight)
.attr("height", _itemHeight)
.attr("fill", function(d){return d.color;});
itemEnter.append("text")
.text(function(d){return d.name;})
.attr("x", _itemHeight + LABEL_GAP)
.attr("y", function(){return _itemHeight / 2 + (this.clientHeight?this.clientHeight:13) / 2 - 2});
};
function legendItemHeight() {
return _gap + _itemHeight;
}
_legend.x = function (x) {
if (!arguments.length) return _x;
_x = x;
return _legend;
};
_legend.y = function (y) {
if (!arguments.length) return _y;
_y = y;
return _legend;
};
_legend.gap = function (gap) {
if (!arguments.length) return _gap;
_gap = gap;
return _legend;
};
_legend.itemHeight = function (h) {
if (!arguments.length) return _itemHeight;
_itemHeight = h;
return _legend;
};
return _legend;
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Screen PPI and Brightness Cross Filter</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://square.github.io/crossfilter/crossfilter.v1.min.js"></script>
</head>
<body>
<script>
// A function for writing output to the html document
function write(temp) {
d3.select("body").append("text").text(temp).append("br");
}
d3.json("data.json", function(json){
var data = crossfilter(json);
// How many of each device are there?
var type = data.dimension(function(fact){return fact.type;});
var typeGroup = type.group();
var type_device_count = typeGroup.top(Infinity);
type_device_count.sort(function(a,b){
if(a.key > b.key)
return 1;
if(a.key < b.key)
return -1;
// a must be equal to be
return 0;
})
write("Device Types");
for (var i = 0; i < type_device_count.length; i++) {
write(type_device_count[i].key + "(s): " + type_device_count[i].value);
};
// What's the sum of ppi for each type of device?
var ppi = data.dimension(function(fact){return fact.type;})
var typePPIGroup = ppi.group().reduceSum(function(fact){return fact.PPI});
var ppi_device_sum = typePPIGroup.top(Infinity);
ppi_device_sum.sort(function(a,b){
if(a.key > b.key)
return 1;
if(a.key < b.key)
return -1;
// a must be equal to be
return 0;
})
write("");
write("Total PPI by Device Type");
for (var i = 0; i < ppi_device_sum.length; i++) {
write(ppi_device_sum[i].key + "(s): " + ppi_device_sum[i].value);
};
// What's the average PPI per device?
write("");
write("Average PPI by Device Type");
for (var i = 0; i < ppi_device_sum.length; i++) {
write(ppi_device_sum[i].key + "(s): " + ppi_device_sum[i].value/type_device_count[i].value);
};
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Screen PPI and Brightness Cross Filter</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://square.github.io/crossfilter/crossfilter.v1.min.js"></script>
</head>
<body>
<script>
// A function for writing output to the html document
function write(temp) {
d3.select("body").append("text").text(temp).append("br");
}
d3.json("data.json", function(json){
var data = crossfilter(json);
// How many of each device are there?
var type = data.dimension(function(fact){return fact.type;});
var typeGroup = type.group();
var type_device_count = typeGroup.top(Infinity);
type_device_count.sort(function(a,b){
if(a.key > b.key)
return 1;
if(a.key < b.key)
return -1;
// a must be equal to be
return 0;
})
write("Device Types");
for (var i = 0; i < type_device_count.length; i++) {
write(type_device_count[i].key + "(s): " + type_device_count[i].value);
};
// What's the sum of ppi for each type of device?
var ppi = data.dimension(function(fact){return fact.type;})
var typePPIGroup = ppi.group().reduceSum(function(fact){return fact.PPI});
var ppi_device_sum = typePPIGroup.top(Infinity);
ppi_device_sum.sort(function(a,b){
if(a.key > b.key)
return 1;
if(a.key < b.key)
return -1;
// a must be equal to be
return 0;
})
write("");
write("Total PPI by Device Type");
for (var i = 0; i < ppi_device_sum.length; i++) {
write(ppi_device_sum[i].key + "(s): " + ppi_device_sum[i].value);
};
// What's the average PPI per device?
write("");
write("Average PPI by Device Type");
for (var i = 0; i < ppi_device_sum.length; i++) {
write(ppi_device_sum[i].key + "(s): " + ppi_device_sum[i].value/type_device_count[i].value);
};
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment