add dynamic date range calculation for dates, and add color gradient component, add color gradient for language and chrono
import Ember from 'ember';
import d3 from 'd3';
import ENV from 'app-client/config/environment';
import _ from 'lodash/lodash';
import URI from 'urijs';
export default Ember.Component.extend({
constants: Ember.inject.service(),
filter: Ember.inject.service(),
colors: Ember.inject.service(),
scale: Ember.computed('maxCount', 'minCount', function() {
let maxCount = this.get('maxCount');
let minCount = this.get('minCount');
return this.get('colors').getScaleLinear(minCount, maxCount);
}),
maxCount: 0,
minCount: 0,
filterObserver: Ember.observer('filter.language', function() {
Ember.$('.node').removeClass("selected");
Ember.$('.node[data-id="' + this.get('filter').get('language') + '"]').addClass("selected");
}),
didInsertElement: function(){
var self = this;
var baseurl = (ENV.APP.backRootURL || ENV.rootURL).replace(/\/$/,"")+'/api/v1';
var url = URI(baseurl+"/stats/languages").search(this.get('filter').get('queryParamsValuesURI'));
d3.json(url.href(), function(data) {
var margin = { top: 30, right: 0, bottom: 0, left: 0 };
var width = Ember.$('#' + self.get('elementId')).width();
var height = Ember.$('#' + self.get('elementId')).height() - margin.top - margin.bottom;
var languages = data['languages'];
var array = Object.keys(languages).map(function (key) { return languages[key]; });
var oldMin = Math.min(...array),
oldMax = Math.max(...array);
var sum = array.reduce(function(a, b) { return a + b; });
var average = sum / array.length;
var newMin = Math.floor((average - oldMin)),
newMax = Math.floor((oldMax - average));
var x = d3.scale.linear()
.domain([0, width])
.range([0, width]),
y = d3.scale.linear()
.domain([0, height])
.range([0, height]);
var treemap = d3.layout.treemap()
.children(function(d, depth) { return depth ? null : d._children; })
.sort(function(a, b) { return a.value - b.value; })
.value(function(d){
return Math.floor((((d.value - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin);
})
.round(false);
var element = d3.select('#' + self.get('elementId'))
.style("width", width + margin.left + margin.right + 'px')
.style("height", height + margin.bottom + margin.top + 'px')
.style("margin-left", -margin.left + "px")
.style("margin-right", -margin.right + "px")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.style("shape-rendering", "crispEdges");
var breadcrumbs = element.insert("div", ":first-child")
.attr("class", "breadcrumbs")
.attr("y", -margin.top)
.style("width", width + 'px')
.style("height", margin.top + 'px');
var root = _.cloneDeep(self.constants.LANGUAGES_TREEMAP);
root.x = root.y = 0;
root.dx = width;
root.dy = height;
root.depth = 0;
var transitioning = false;
accumulate(root);
layout(root);
display(root);
function accumulate(d) {
d._children = d.children;
if(d.children) {
d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0);
} else if (d.values) {
d.value = d.values.reduce(function(p, v) { return p + (languages[v] ? languages[v] : 0); }, 0);
} else {
d.value = languages[d.id] ? languages[d.id] : 0;
}
return d.value;
}
function layout(d) {
if (d._children) {
treemap.nodes({_children: d._children});
d._children.forEach(function(c) {
function getCount(node, count = 0) {
var c = languages[node.id];
if(typeof c === 'undefined') {
if(node._children) {
node._children.forEach(function(child) {
count = getCount(child, count);
});
} else if(node.values) {
count = node.values.reduce(function(p, v) { return p + (languages[v] ? languages[v] : 0); }, count);
}
return count;
} else {
return count + c;
}
}
c.count = getCount(c);
c.x = d.x + c.x * d.dx;
c.y = d.y + c.y * d.dy;
c.dx *= d.dx;
c.dy *= d.dy;
c.parent = d;
layout(c);
});
}
}
function position() {
return this.style("width", function(d) { return x(d.x + d.dx) - x(d.x) + 'px'; })
.style("height", function(d) { return y(d.y + d.dy) - y(d.y) + 'px'; })
.style("left", function(d) { return x(d.x) + 'px'; })
.style("top", function(d) { return y(d.y) + 'px'; });
}
function display(d) {
breadcrumbs
.datum(d.parent)
.html(name(d))
.on("click", transition);
var nodes = element.append("div")
.attr("class", "nodes")
.datum(d);
var node = nodes.selectAll()
.data(d._children)
.enter()
.append("div")
.attr("data-id", function(d) { return d.id; });
var dMin = Math.min.apply(null, d._children.map(function(d){ return d.count; }));
var dMax = Math.max.apply(null, d._children.map(function(d){ return d.count; }));
self.setProperties({minCount: dMin, maxCount: dMax});
var scale = self.get('scale');
var backgroundColor = function(_d) { return scale(_d.count);};
var colorClass = function(_d) { return (self.get('colors').getPerceptiveLuminance(backgroundColor(_d)) >= 0.5)?'light-color':'dark-color'; };
node.attr("class", function(_d) { return "node " + colorClass(_d) + ( _d.id === self.get('filter').get('language') ? " selected" : "" ); })
.call(position)
.style("background-color", backgroundColor)
.on("click", selectHandler);
node.filter(function(d) { return d._children; })
.classed("children", true)
.on("click", transition)
.append("i")
.attr("class", "fa fa-folder-o");
node.append("span")
.html(function(d) { return d.name + ' <span class="count">(' + d.count + ')</span>'; });
function transition(d) {
if (transitioning || !d) {
return;
}
selectHandler(d);
transitioning = true;
var newNode = display(d),
transitionNodes = node.transition().duration(750),
transitionNewNodes = newNode.transition().duration(750);
x.domain([d.x, d.x + d.dx]);
y.domain([d.y, d.y + d.dy]);
element.style("shape-rendering", null);
element.selectAll(".node").sort(function(a, b) { return a.depth - b.depth; });
newNode.selectAll().style("fill-opacity", 0);
transitionNodes.style("opacity", 0)
.call(position);
transitionNewNodes.style("opacity", 1)
.call(position);
transitionNodes.remove().each("end", function() {
element.style("shape-rendering", "crispEdges");
transitioning = false;
});
}
function selectHandler (d){
if (d.id){
self.get('filter').setFilter('language', d.id);
}
}
return node;
}
function name(d) {
return d.parent ? name(d.parent) + '<span class="level">' + d.name + '</span>' : '<span class="root">' + d.name + '</span>';
}
});
}
});