mirror of
https://github.com/apache/superset.git
synced 2024-09-12 08:39:45 -04:00
commit
2872c6262d
@ -12,51 +12,79 @@ require('select2');
|
||||
require('../node_modules/gridster/dist/jquery.gridster.min.js');
|
||||
|
||||
|
||||
var Dashboard = function (dashboardData) {
|
||||
var Dashboard = function(dashboardData) {
|
||||
var dashboard = $.extend(dashboardData, {
|
||||
filters: {},
|
||||
init: function () {
|
||||
init: function() {
|
||||
this.initDashboardView();
|
||||
var sliceObjects = [],
|
||||
dash = this;
|
||||
dashboard.slices.forEach(function (data) {
|
||||
var slice = px.Slice(data, dash);
|
||||
$("#slice_" + data.slice_id).find('a.refresh').click(function () {
|
||||
slice.render();
|
||||
});
|
||||
sliceObjects.push(slice);
|
||||
dashboard.slices.forEach(function(data) {
|
||||
var slice = px.Slice(data, dash);
|
||||
$("#slice_" + data.slice_id).find('a.refresh').click(function() {
|
||||
slice.render();
|
||||
});
|
||||
this.slices = sliceObjects;
|
||||
sliceObjects.push(slice);
|
||||
slice.render();
|
||||
});
|
||||
this.slices = sliceObjects;
|
||||
},
|
||||
addFilter: function (slice_id, filters) {
|
||||
this.filters[slice_id] = filters;
|
||||
setFilter: function(slice_id, col, vals) {
|
||||
console.log([slice_id, col, vals]);
|
||||
this.addFilter(slice_id, col, vals, false);
|
||||
},
|
||||
addFilter: function(slice_id, col, vals, merge) {
|
||||
if (merge === undefined) {
|
||||
merge = true;
|
||||
}
|
||||
if (!(slice_id in this.filters)) {
|
||||
this.filters[slice_id] = {};
|
||||
}
|
||||
if (!(col in this.filters[slice_id]) || !merge) {
|
||||
this.filters[slice_id][col] = vals;
|
||||
} else {
|
||||
this.filters[slice_id][col] = d3.merge([this.filters[slice_id][col], vals]);
|
||||
}
|
||||
this.refreshExcept(slice_id);
|
||||
},
|
||||
readFilters: function () {
|
||||
readFilters: function() {
|
||||
// Returns a list of human readable active filters
|
||||
return JSON.stringify(this.filters, null, 4);
|
||||
},
|
||||
refreshExcept: function (slice_id) {
|
||||
refreshExcept: function(slice_id) {
|
||||
var immune = this.metadata.filter_immune_slices;
|
||||
this.slices.forEach(function (slice) {
|
||||
if(slice.data.slice_id !== slice_id && immune.indexOf(slice.data.slice_id) === -1) {
|
||||
this.slices.forEach(function(slice) {
|
||||
if (slice.data.slice_id !== slice_id && immune.indexOf(slice.data.slice_id) === -1) {
|
||||
slice.render();
|
||||
}
|
||||
});
|
||||
},
|
||||
clearFilter: function (slice_id) {
|
||||
clearFilters: function(slice_id) {
|
||||
delete this.filters[slice_id];
|
||||
this.refreshExcept(slice_id);
|
||||
},
|
||||
getSlice: function (slice_id) {
|
||||
this.slices.forEach(function (slice, i) {
|
||||
removeFilter: function(slice_id, col, vals) {
|
||||
if (slice_id in this.filters) {
|
||||
if (col in this.filters[slice_id]) {
|
||||
var a = [];
|
||||
this.filters[slice_id][col].forEach(function(v) {
|
||||
if (vals.indexOf(v) < 0) {
|
||||
a.push(v);
|
||||
}
|
||||
});
|
||||
this.filters[slice_id][col] = a;
|
||||
}
|
||||
}
|
||||
this.refreshExcept(slice_id);
|
||||
},
|
||||
getSlice: function(slice_id) {
|
||||
this.slices.forEach(function(slice, i) {
|
||||
if (slice.slice_id === slice_id) {
|
||||
return slice;
|
||||
}
|
||||
});
|
||||
},
|
||||
initDashboardView: function () {
|
||||
initDashboardView: function() {
|
||||
dashboard = this;
|
||||
var gridster = $(".gridster ul").gridster({
|
||||
widget_margins: [5, 5],
|
||||
@ -66,12 +94,12 @@ var Dashboard = function (dashboardData) {
|
||||
},
|
||||
resize: {
|
||||
enabled: true,
|
||||
stop: function (e, ui, element) {
|
||||
stop: function(e, ui, element) {
|
||||
var slice_data = $(element).data('slice');
|
||||
dashboard.getSlice(slice_data.slice_id).resize();
|
||||
}
|
||||
},
|
||||
serialize_params: function (_w, wgd) {
|
||||
serialize_params: function(_w, wgd) {
|
||||
return {
|
||||
slice_id: $(_w).attr('slice_id'),
|
||||
col: wgd.col,
|
||||
@ -82,12 +110,12 @@ var Dashboard = function (dashboardData) {
|
||||
},
|
||||
}).data('gridster');
|
||||
$("div.gridster").css('visibility', 'visible');
|
||||
$("#savedash").click(function () {
|
||||
$("#savedash").click(function() {
|
||||
var expanded_slices = {};
|
||||
$.each($(".slice_info"), function (i, d) {
|
||||
$.each($(".slice_info"), function(i, d) {
|
||||
var widget = $(this).parents('.widget');
|
||||
var slice_description = widget.find('.slice_description');
|
||||
if(slice_description.is(":visible"))
|
||||
if (slice_description.is(":visible"))
|
||||
expanded_slices[$(d).attr('slice_id')] = true;
|
||||
});
|
||||
var data = {
|
||||
@ -98,9 +126,15 @@ var Dashboard = function (dashboardData) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: '/panoramix/save_dash/' + dashboard.id + '/',
|
||||
data: {'data': JSON.stringify(data)},
|
||||
success: function () {alert("Saved!");},
|
||||
error: function () {alert("Error :(");},
|
||||
data: {
|
||||
'data': JSON.stringify(data)
|
||||
},
|
||||
success: function() {
|
||||
alert("Saved!");
|
||||
},
|
||||
error: function() {
|
||||
alert("Error :(");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -114,34 +148,36 @@ var Dashboard = function (dashboardData) {
|
||||
});
|
||||
editor.getSession().setMode("ace/mode/css");
|
||||
|
||||
$(".select2").select2({dropdownAutoWidth : true});
|
||||
$("#css_template").on("change", function () {
|
||||
$(".select2").select2({
|
||||
dropdownAutoWidth: true
|
||||
});
|
||||
$("#css_template").on("change", function() {
|
||||
var css = $(this).find('option:selected').data('css');
|
||||
editor.setValue(css);
|
||||
$('#dash_css').val(css);
|
||||
$("#user_style").html(css);
|
||||
});
|
||||
$('#filters').click( function () {
|
||||
$('#filters').click(function() {
|
||||
alert(dashboard.readFilters());
|
||||
});
|
||||
$("a.closeslice").click(function () {
|
||||
$("a.closeslice").click(function() {
|
||||
var li = $(this).parents("li");
|
||||
gridster.remove_widget(li);
|
||||
});
|
||||
$(".slice_info").click(function () {
|
||||
$(".slice_info").click(function() {
|
||||
var widget = $(this).parents('.widget');
|
||||
var slice_description = widget.find('.slice_description');
|
||||
slice_description.slideToggle(500, function () {
|
||||
slice_description.slideToggle(500, function() {
|
||||
widget.find('.refresh').click();
|
||||
});
|
||||
});
|
||||
$("table.slice_header").mouseover(function () {
|
||||
$("table.slice_header").mouseover(function() {
|
||||
$(this).find("td.icons nobr").show();
|
||||
});
|
||||
$("table.slice_header").mouseout(function () {
|
||||
$("table.slice_header").mouseout(function() {
|
||||
$(this).find("td.icons nobr").hide();
|
||||
});
|
||||
editor.on("change", function () {
|
||||
editor.on("change", function() {
|
||||
var css = editor.getValue();
|
||||
$('#dash_css').val(css);
|
||||
$("#user_style").html(css);
|
||||
@ -152,6 +188,6 @@ var Dashboard = function (dashboardData) {
|
||||
return dashboard;
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
$(document).ready(function() {
|
||||
var dashboard = Dashboard($('.dashboard').data('dashboard'));
|
||||
});
|
||||
|
@ -21,44 +21,58 @@ require('../vendor/pygments.css');
|
||||
require('../node_modules/bootstrap-toggle/css/bootstrap-toggle.min.css');
|
||||
|
||||
var slice;
|
||||
function prepForm(){
|
||||
|
||||
function prepForm() {
|
||||
var i = 1;
|
||||
// Assigning the right id to form elements in filters
|
||||
$("#filters > div").each(function() {
|
||||
$(this).attr("id", function() {return "flt_" + i;})
|
||||
$(this).attr("id", function() {
|
||||
return "flt_" + i;
|
||||
})
|
||||
$(this).find("#flt_col_0")
|
||||
.attr("id", function() {return "flt_col_" + i;})
|
||||
.attr("name", function() {return "flt_col_" + i;});
|
||||
.attr("id", function() {
|
||||
return "flt_col_" + i;
|
||||
})
|
||||
.attr("name", function() {
|
||||
return "flt_col_" + i;
|
||||
});
|
||||
$(this).find("#flt_op_0")
|
||||
.attr("id", function() {return "flt_op_" + i;})
|
||||
.attr("name", function() {return "flt_op_" + i;});
|
||||
.attr("id", function() {
|
||||
return "flt_op_" + i;
|
||||
})
|
||||
.attr("name", function() {
|
||||
return "flt_op_" + i;
|
||||
});
|
||||
$(this).find("#flt_eq_0")
|
||||
.attr("id", function() {return "flt_eq_" + i;})
|
||||
.attr("name", function() {return "flt_eq_" + i;});
|
||||
.attr("id", function() {
|
||||
return "flt_eq_" + i;
|
||||
})
|
||||
.attr("name", function() {
|
||||
return "flt_eq_" + i;
|
||||
});
|
||||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
function renderSlice(){
|
||||
function renderSlice() {
|
||||
prepForm();
|
||||
slice.render();
|
||||
}
|
||||
|
||||
function initExploreView() {
|
||||
|
||||
function druidify(){
|
||||
function druidify() {
|
||||
$('div.alert').remove();
|
||||
history.pushState({}, document.title, slice.querystring());
|
||||
renderSlice();
|
||||
}
|
||||
|
||||
function get_collapsed_fieldsets(){
|
||||
function get_collapsed_fieldsets() {
|
||||
var collapsed_fieldsets = $("#collapsed_fieldsets").val();
|
||||
|
||||
if (collapsed_fieldsets != undefined && collapsed_fieldsets != "") {
|
||||
if (collapsed_fieldsets !== undefined && collapsed_fieldsets !== "") {
|
||||
collapsed_fieldsets = collapsed_fieldsets.split('||');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
collapsed_fieldsets = [];
|
||||
}
|
||||
return collapsed_fieldsets;
|
||||
@ -68,33 +82,31 @@ function initExploreView() {
|
||||
var parent = legend.parent();
|
||||
var fieldset = parent.find(".legend_label").text();
|
||||
var collapsed_fieldsets = get_collapsed_fieldsets();
|
||||
|
||||
if (!parent.hasClass("collapsed")){
|
||||
var index;
|
||||
if (!parent.hasClass("collapsed")) {
|
||||
if (animation) {
|
||||
parent.find(".fieldset_content").slideUp();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
parent.find(".fieldset_content").hide();
|
||||
}
|
||||
|
||||
parent.addClass("collapsed");
|
||||
parent.find("span.collapser").text("[+]");
|
||||
var index = collapsed_fieldsets.indexOf(fieldset);
|
||||
index = collapsed_fieldsets.indexOf(fieldset);
|
||||
if (index === -1 && fieldset !== "" && fieldset !== undefined) {
|
||||
collapsed_fieldsets.push(fieldset);
|
||||
}
|
||||
} else {
|
||||
if (animation) {
|
||||
parent.find(".fieldset_content").slideDown();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
parent.find(".fieldset_content").show();
|
||||
}
|
||||
parent.removeClass("collapsed");
|
||||
parent.find("span.collapser").text("[-]");
|
||||
|
||||
// removing from array, js is overcomplicated
|
||||
var index = collapsed_fieldsets.indexOf(fieldset);
|
||||
index = collapsed_fieldsets.indexOf(fieldset);
|
||||
if (index !== -1) {
|
||||
collapsed_fieldsets.splice(index, 1);
|
||||
}
|
||||
@ -102,11 +114,11 @@ function initExploreView() {
|
||||
$("#collapsed_fieldsets").val(collapsed_fieldsets.join("||"));
|
||||
}
|
||||
|
||||
$('legend').click(function () {
|
||||
$('legend').click(function() {
|
||||
toggle_fieldset($(this), true);
|
||||
});
|
||||
|
||||
function copyURLToClipboard (url) {
|
||||
function copyURLToClipboard(url) {
|
||||
var textArea = document.createElement("textarea");
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.left = '-1000px';
|
||||
@ -127,19 +139,26 @@ function initExploreView() {
|
||||
return successful;
|
||||
}
|
||||
|
||||
$('#shortner').click(function () {
|
||||
$('#shortner').click(function() {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: '/r/shortner/',
|
||||
data: {'data': '/' + window.location.pathname + slice.querystring()},
|
||||
data: {
|
||||
'data': '/' + window.location.pathname + slice.querystring()
|
||||
},
|
||||
success: function(data) {
|
||||
var close = '<a style="cursor: pointer;"><i class="fa fa-close" id="close_shortner"></i></a>';
|
||||
var copy = '<a style="cursor: pointer;"><i class="fa fa-clipboard" title="Copy to clipboard" id="copy_url"></i></a>';
|
||||
var spaces = ' '
|
||||
var close = '<a style="cursor: pointer;"><i class="fa fa-close" id="close_shortner"></i></a>';
|
||||
var copy = '<a style="cursor: pointer;"><i class="fa fa-clipboard" title="Copy to clipboard" id="copy_url"></i></a>';
|
||||
var spaces = ' '
|
||||
var popover = data + spaces + copy + spaces + close;
|
||||
|
||||
var $shortner = $('#shortner')
|
||||
.popover({content: popover, placement: 'left', html: true, trigger: 'manual'})
|
||||
.popover({
|
||||
content: popover,
|
||||
placement: 'left',
|
||||
html: true,
|
||||
trigger: 'manual'
|
||||
})
|
||||
.popover('show');
|
||||
|
||||
$('#copy_url').tooltip().click(function() {
|
||||
@ -152,31 +171,43 @@ function initExploreView() {
|
||||
}, 1200);
|
||||
}
|
||||
});
|
||||
$('#close_shortner').click(function(){
|
||||
$('#close_shortner').click(function() {
|
||||
$shortner.popover('destroy');
|
||||
});
|
||||
},
|
||||
error: function() {alert("Error :(");},
|
||||
error: function() {
|
||||
alert("Error :(");
|
||||
},
|
||||
});
|
||||
});
|
||||
$("#viz_type").change(function() {$("#query").submit();});
|
||||
$("#viz_type").change(function() {
|
||||
$("#query").submit();
|
||||
});
|
||||
|
||||
var collapsed_fieldsets = get_collapsed_fieldsets();
|
||||
for(var i=0; i < collapsed_fieldsets.length; i++){
|
||||
for (var i = 0; i < collapsed_fieldsets.length; i++) {
|
||||
toggle_fieldset($('legend:contains("' + collapsed_fieldsets[i] + '")'), false);
|
||||
}
|
||||
|
||||
$(".select2").select2({dropdownAutoWidth : true});
|
||||
$(".select2Sortable").select2({dropdownAutoWidth : true});
|
||||
$(".select2Sortable").select2Sortable({bindOrder: 'sortableStop'});
|
||||
$(".select2").select2({
|
||||
dropdownAutoWidth: true
|
||||
});
|
||||
$(".select2Sortable").select2({
|
||||
dropdownAutoWidth: true
|
||||
});
|
||||
$(".select2Sortable").select2Sortable({
|
||||
bindOrder: 'sortableStop'
|
||||
});
|
||||
$("form").show();
|
||||
$('[data-toggle="tooltip"]').tooltip({container: 'body'});
|
||||
$('[data-toggle="tooltip"]').tooltip({
|
||||
container: 'body'
|
||||
});
|
||||
$(".ui-helper-hidden-accessible").remove(); // jQuery-ui 1.11+ creates a div for every tooltip
|
||||
|
||||
function set_filters(){
|
||||
for (var i = 1; i < 10; i++){
|
||||
function set_filters() {
|
||||
for (var i = 1; i < 10; i++) {
|
||||
var eq = px.getParam("flt_eq_" + i);
|
||||
if (eq != ''){
|
||||
if (eq !== '') {
|
||||
add_filter(i);
|
||||
}
|
||||
}
|
||||
@ -187,7 +218,7 @@ function initExploreView() {
|
||||
var cp = $("#flt0").clone();
|
||||
$(cp).appendTo("#filters");
|
||||
$(cp).show();
|
||||
if (i != undefined){
|
||||
if (i !== undefined) {
|
||||
$(cp).find("#flt_eq_0").val(px.getParam("flt_eq_" + i));
|
||||
$(cp).find("#flt_op_0").val(px.getParam("flt_op_" + i));
|
||||
$(cp).find("#flt_col_0").val(px.getParam("flt_col_" + i));
|
||||
@ -208,16 +239,16 @@ function initExploreView() {
|
||||
|
||||
|
||||
$("#plus").click(add_filter);
|
||||
$("#btn_save").click(function () {
|
||||
$("#btn_save").click(function() {
|
||||
var slice_name = prompt("Name your slice!");
|
||||
if (slice_name != "" && slice_name != null) {
|
||||
if (slice_name !== "" && slice_name !== null) {
|
||||
$("#slice_name").val(slice_name);
|
||||
prepForm();
|
||||
$("#action").val("save");
|
||||
$("#query").submit();
|
||||
}
|
||||
});
|
||||
$("#btn_overwrite").click(function () {
|
||||
$("#btn_overwrite").click(function() {
|
||||
var flag = confirm("Overwrite slice [" + $("#slice_name").val() + "] !?");
|
||||
if (flag) {
|
||||
$("#action").val("overwrite");
|
||||
@ -233,37 +264,51 @@ function initExploreView() {
|
||||
return this.text.localeCompare(term) === 0;
|
||||
});
|
||||
if (filtered.length === 0) {
|
||||
return {id: term, text: term};
|
||||
return {
|
||||
id: term,
|
||||
text: term
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function initSelectionToValue(element, callback) {
|
||||
callback({id: element.val(), text: element.val()});
|
||||
callback({
|
||||
id: element.val(),
|
||||
text: element.val()
|
||||
});
|
||||
}
|
||||
|
||||
function list_data(arr) {
|
||||
var obj = [];
|
||||
for (var i=0; i<arr.length; i++){
|
||||
obj.push({id: arr[i], text: arr[i]});
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
obj.push({
|
||||
id: arr[i],
|
||||
text: arr[i]
|
||||
});
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
$(".select2_freeform").each(function(){
|
||||
$(".select2_freeform").each(function() {
|
||||
var parent = $(this).parent();
|
||||
var name = $(this).attr('name');
|
||||
var l = [];
|
||||
var selected = '';
|
||||
for(var i=0; i<this.options.length; i++) {
|
||||
l.push({id: this.options[i].value, text: this.options[i].text});
|
||||
if(this.options[i].selected){
|
||||
for (var i = 0; i < this.options.length; i++) {
|
||||
l.push({
|
||||
id: this.options[i].value,
|
||||
text: this.options[i].text
|
||||
});
|
||||
if (this.options[i].selected) {
|
||||
selected = this.options[i].value;
|
||||
}
|
||||
}
|
||||
var obj = parent.append(
|
||||
'<input class="' + $(this).attr('class') + '" name="'+ name +'" type="text" value="' + selected + '">'
|
||||
'<input class="' + $(this).attr('class') + '" name="' + name + '" type="text" value="' + selected + '">'
|
||||
);
|
||||
$("input[name='" + name +"']").select2({
|
||||
$("input[name='" + name + "']").select2({
|
||||
createSearchChoice: create_choices,
|
||||
initSelection: initSelectionToValue,
|
||||
dropdownAutoWidth : true,
|
||||
dropdownAutoWidth: true,
|
||||
multiple: false,
|
||||
data: l,
|
||||
});
|
||||
@ -279,7 +324,7 @@ $(document).ready(function() {
|
||||
px.registerViz(visType);
|
||||
|
||||
|
||||
var data = $('.slice').data('slice');
|
||||
var data = $('.slice').data('slice');
|
||||
slice = px.Slice(data);
|
||||
|
||||
//
|
||||
@ -290,9 +335,11 @@ $(document).ready(function() {
|
||||
|
||||
// make checkbox inputs display as toggles
|
||||
$(':checkbox')
|
||||
.addClass('pull-right')
|
||||
.attr("data-onstyle", "default")
|
||||
.bootstrapToggle({size: 'mini'});
|
||||
.addClass('pull-right')
|
||||
.attr("data-onstyle", "default")
|
||||
.bootstrapToggle({
|
||||
size: 'mini'
|
||||
});
|
||||
|
||||
$('div.toggle').addClass('pull-right');
|
||||
});
|
||||
|
@ -5,10 +5,12 @@ require('datatables-bootstrap3-plugin');
|
||||
require('bootstrap');
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#dataset-table').DataTable({
|
||||
"bPaginate": false,
|
||||
"order": [[ 1, "asc" ]]
|
||||
});
|
||||
$('#dataset-table_info').remove();
|
||||
$('#dataset-table').show();
|
||||
} );
|
||||
$('#dataset-table').DataTable({
|
||||
"bPaginate": false,
|
||||
"order": [
|
||||
[1, "asc"]
|
||||
]
|
||||
});
|
||||
$('#dataset-table_info').remove();
|
||||
$('#dataset-table').show();
|
||||
});
|
||||
|
@ -1,31 +1,32 @@
|
||||
var $ = require('jquery'), jQuery = $;
|
||||
var $ = require('jquery'),
|
||||
jQuery = $;
|
||||
var d3 = require('d3');
|
||||
|
||||
// vis sources
|
||||
var sourceMap = {
|
||||
area: 'nvd3_vis.js',
|
||||
bar: 'nvd3_vis.js',
|
||||
bubble: 'nvd3_vis.js',
|
||||
big_number: 'big_number.js',
|
||||
compare: 'nvd3_vis.js',
|
||||
dist_bar: 'nvd3_vis.js',
|
||||
area: 'nvd3_vis.js',
|
||||
bar: 'nvd3_vis.js',
|
||||
bubble: 'nvd3_vis.js',
|
||||
big_number: 'big_number.js',
|
||||
compare: 'nvd3_vis.js',
|
||||
dist_bar: 'nvd3_vis.js',
|
||||
directed_force: 'directed_force.js',
|
||||
filter_box: 'filter_box.js',
|
||||
heatmap: 'heatmap.js',
|
||||
iframe: 'iframe.js',
|
||||
line: 'nvd3_vis.js',
|
||||
markup: 'markup.js',
|
||||
para: 'parallel_coordinates.js',
|
||||
pie: 'nvd3_vis.js',
|
||||
pivot_table: 'pivot_table.js',
|
||||
sankey: 'sankey.js',
|
||||
sunburst: 'sunburst.js',
|
||||
table: 'table.js',
|
||||
word_cloud: 'word_cloud.js',
|
||||
world_map: 'world_map.js',
|
||||
filter_box: 'filter_box.js',
|
||||
heatmap: 'heatmap.js',
|
||||
iframe: 'iframe.js',
|
||||
line: 'nvd3_vis.js',
|
||||
markup: 'markup.js',
|
||||
para: 'parallel_coordinates.js',
|
||||
pie: 'nvd3_vis.js',
|
||||
pivot_table: 'pivot_table.js',
|
||||
sankey: 'sankey.js',
|
||||
sunburst: 'sunburst.js',
|
||||
table: 'table.js',
|
||||
word_cloud: 'word_cloud.js',
|
||||
world_map: 'world_map.js',
|
||||
};
|
||||
|
||||
var color = function(){
|
||||
var color = function() {
|
||||
// Color related utility functions go in this object
|
||||
var bnbColors = [
|
||||
//rausch hackb kazan babu lima beach barol
|
||||
@ -38,116 +39,131 @@ var color = function(){
|
||||
'fire': ['white', 'yellow', 'red', 'black'],
|
||||
'white_black': ['white', 'black'],
|
||||
'black_white': ['black', 'white'],
|
||||
}
|
||||
};
|
||||
var colorBnb = function() {
|
||||
// Color factory
|
||||
var seen = {};
|
||||
return function(s) {
|
||||
// next line is for dashed series that should have the same color
|
||||
s = s.replace('---', '');
|
||||
if(seen[s] === undefined)
|
||||
if (seen[s] === undefined)
|
||||
seen[s] = Object.keys(seen).length;
|
||||
return this.bnbColors[seen[s] % this.bnbColors.length];
|
||||
};
|
||||
};
|
||||
var colorScalerFactory = function (colors, data, accessor){
|
||||
var colorScalerFactory = function(colors, data, accessor) {
|
||||
// Returns a linear scaler our of an array of color
|
||||
if(!Array.isArray(colors))
|
||||
if (!Array.isArray(colors)) {
|
||||
colors = spectrums[colors];
|
||||
if(data !== undefined)
|
||||
var ext = d3.extent(data, accessor);
|
||||
else
|
||||
var ext = [0,1];
|
||||
}
|
||||
|
||||
var ext = [0, 1];
|
||||
if (data !== undefined) {
|
||||
ext = d3.extent(data, accessor);
|
||||
}
|
||||
|
||||
var points = [];
|
||||
var chunkSize = (ext[1] - ext[0]) / colors.length;
|
||||
$.each(colors, function(i, c){
|
||||
points.push(i * chunkSize)
|
||||
$.each(colors, function(i, c) {
|
||||
points.push(i * chunkSize);
|
||||
});
|
||||
return d3.scale.linear().domain(points).range(colors);
|
||||
}
|
||||
};
|
||||
return {
|
||||
bnbColors: bnbColors,
|
||||
category21: colorBnb(),
|
||||
colorScalerFactory: colorScalerFactory,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var px = (function() {
|
||||
|
||||
var visualizations = {};
|
||||
var dashboard = undefined;
|
||||
var slice = undefined;
|
||||
var dashboard;
|
||||
var slice;
|
||||
|
||||
function getParam(name) {
|
||||
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
||||
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
||||
results = regex.exec(location.search);
|
||||
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||
}
|
||||
|
||||
function UTC(dttm){
|
||||
return new Date(dttm.getUTCFullYear(), dttm.getUTCMonth(), dttm.getUTCDate(), dttm.getUTCHours(), dttm.getUTCMinutes(), dttm.getUTCSeconds());
|
||||
function UTC(dttm) {
|
||||
return new Date(dttm.getUTCFullYear(), dttm.getUTCMonth(), dttm.getUTCDate(), dttm.getUTCHours(), dttm.getUTCMinutes(), dttm.getUTCSeconds());
|
||||
}
|
||||
var tickMultiFormat = d3.time.format.multi([
|
||||
[".%L", function(d) { return d.getMilliseconds(); }], // If there are millisections, show only them
|
||||
[":%S", function(d) { return d.getSeconds(); }], // If there are seconds, show only them
|
||||
["%a %b %d, %I:%M %p", function(d) { return d.getMinutes()!=0; }], // If there are non-zero minutes, show Date, Hour:Minute [AM/PM]
|
||||
["%a %b %d, %I %p", function(d) { return d.getHours() != 0; }], // If there are hours that are multiples of 3, show date and AM/PM
|
||||
["%a %b %d, %Y", function(d) { return d.getDate() != 1; }], // If not the first of the month, do "month day, year."
|
||||
["%B %Y", function(d) { return d.getMonth() != 0 && d.getDate() == 1; }], // If the first of the month, do "month day, year."
|
||||
["%Y", function(d) { return true; }] // fall back on month, year
|
||||
[".%L", function(d) {
|
||||
return d.getMilliseconds();
|
||||
}], // If there are millisections, show only them
|
||||
[":%S", function(d) {
|
||||
return d.getSeconds();
|
||||
}], // If there are seconds, show only them
|
||||
["%a %b %d, %I:%M %p", function(d) {
|
||||
return d.getMinutes() !== 0;
|
||||
}], // If there are non-zero minutes, show Date, Hour:Minute [AM/PM]
|
||||
["%a %b %d, %I %p", function(d) {
|
||||
return d.getHours() !== 0;
|
||||
}], // If there are hours that are multiples of 3, show date and AM/PM
|
||||
["%a %b %d, %Y", function(d) {
|
||||
return d.getDate() !== 1;
|
||||
}], // If not the first of the month, do "month day, year."
|
||||
["%B %Y", function(d) {
|
||||
return d.getMonth() !== 0 && d.getDate() === 1;
|
||||
}], // If the first of the month, do "month day, year."
|
||||
["%Y", function(d) {
|
||||
return true;
|
||||
}] // fall back on month, year
|
||||
]);
|
||||
|
||||
function formatDate(dttm) {
|
||||
var d = UTC(new Date(dttm));
|
||||
//d = new Date(d.getTime() - 1 * 60 * 60 * 1000);
|
||||
return tickMultiFormat(d);
|
||||
}
|
||||
|
||||
function timeFormatFactory(d3timeFormat) {
|
||||
var f = d3.time.format(d3timeFormat)
|
||||
return function(dttm){
|
||||
var f = d3.time.format(d3timeFormat);
|
||||
return function(dttm) {
|
||||
var d = UTC(new Date(dttm));
|
||||
return f(d);
|
||||
};
|
||||
}
|
||||
|
||||
var Slice = function(data, dashboard){
|
||||
var Slice = function(data, dashboard) {
|
||||
var timer;
|
||||
var token = $('#' + data.token);
|
||||
var container_id = data.token + '_con';
|
||||
var selector = '#' + container_id;
|
||||
var container = $(selector);
|
||||
var slice_id = data.slice_id;
|
||||
var name = data['viz_name'];
|
||||
var name = data.viz_name;
|
||||
var dttm = 0;
|
||||
var timer;
|
||||
var stopwatch = function () {
|
||||
var stopwatch = function() {
|
||||
dttm += 10;
|
||||
var num = dttm / 1000;
|
||||
$('#timer').text(num.toFixed(2) + " sec");
|
||||
}
|
||||
};
|
||||
var qrystr = '';
|
||||
var always = function(data) {
|
||||
//Private f, runs after done and error
|
||||
clearInterval(timer);
|
||||
$('#timer').removeClass('btn-warning');
|
||||
}
|
||||
};
|
||||
slice = {
|
||||
data: data,
|
||||
container: container,
|
||||
container_id: container_id,
|
||||
selector: selector,
|
||||
querystring: function(){
|
||||
querystring: function() {
|
||||
var parser = document.createElement('a');
|
||||
parser.href = data.json_endpoint;
|
||||
if (dashboard !== undefined){
|
||||
if (dashboard !== undefined) {
|
||||
var flts = encodeURIComponent(JSON.stringify(dashboard.filters));
|
||||
qrystr = parser.search + "&extra_filters=" + flts;
|
||||
}
|
||||
else if ($('#query').length == 0){
|
||||
} else if ($('#query').length === 0) {
|
||||
qrystr = parser.search;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qrystr = '?' + $('#query').serialize();
|
||||
}
|
||||
return qrystr;
|
||||
@ -158,34 +174,41 @@ var px = (function() {
|
||||
var endpoint = parser.pathname + this.querystring() + "&json=true";
|
||||
return endpoint;
|
||||
},
|
||||
done: function (data) {
|
||||
done: function(data) {
|
||||
clearInterval(timer);
|
||||
token.find("img.loading").hide()
|
||||
token.find("img.loading").hide();
|
||||
container.show();
|
||||
if(data !== undefined)
|
||||
if (data !== undefined) {
|
||||
$("#query_container").html(data.query);
|
||||
}
|
||||
$('#timer').removeClass('btn-warning');
|
||||
$('#timer').addClass('btn-success');
|
||||
$('span.query').removeClass('disabled');
|
||||
$('#json').click(function(){window.location=data.json_endpoint});
|
||||
$('#standalone').click(function(){window.location=data.standalone_endpoint});
|
||||
$('#csv').click(function(){window.location=data.csv_endpoint});
|
||||
$('#json').click(function() {
|
||||
window.location = data.json_endpoint;
|
||||
});
|
||||
$('#standalone').click(function() {
|
||||
window.location = data.standalone_endpoint;
|
||||
});
|
||||
$('#csv').click(function() {
|
||||
window.location = data.csv_endpoint;
|
||||
});
|
||||
$('.btn-group.results span').removeAttr('disabled');
|
||||
always(data);
|
||||
},
|
||||
error: function (msg) {
|
||||
error: function(msg) {
|
||||
token.find("img.loading").hide();
|
||||
var err = '<div class="alert alert-danger">' + msg + '</div>';
|
||||
var err = '<div class="alert alert-danger">' + msg + '</div>';
|
||||
container.html(err);
|
||||
container.show();
|
||||
$('span.query').removeClass('disabled');
|
||||
$('#timer').addClass('btn-danger');
|
||||
always(data);
|
||||
},
|
||||
width: function(){
|
||||
width: function() {
|
||||
return token.width();
|
||||
},
|
||||
height: function(){
|
||||
height: function() {
|
||||
var others = 0;
|
||||
var widget = container.parents('.widget');
|
||||
var slice_description = widget.find('.slice_description');
|
||||
@ -195,7 +218,7 @@ var px = (function() {
|
||||
return widget.height() - others;
|
||||
},
|
||||
render: function() {
|
||||
$('.btn-group.results span').attr('disabled','disabled');
|
||||
$('.btn-group.results span').attr('disabled', 'disabled');
|
||||
token.find("img.loading").show();
|
||||
container.hide();
|
||||
container.html('');
|
||||
@ -213,19 +236,27 @@ var px = (function() {
|
||||
this.viz.resize();
|
||||
},
|
||||
addFilter: function(col, vals) {
|
||||
if(dashboard !== undefined)
|
||||
if (dashboard !== undefined)
|
||||
dashboard.addFilter(slice_id, col, vals);
|
||||
},
|
||||
setFilter: function(col, vals) {
|
||||
if (dashboard !== undefined)
|
||||
dashboard.setFilter(slice_id, col, vals);
|
||||
},
|
||||
clearFilter: function() {
|
||||
if(dashboard !== undefined)
|
||||
if (dashboard !== undefined)
|
||||
delete dashboard.clearFilter(slice_id);
|
||||
},
|
||||
removeFilter: function(col, vals) {
|
||||
if (dashboard !== undefined)
|
||||
delete dashboard.removeFilter(slice_id, col, vals);
|
||||
},
|
||||
};
|
||||
var visType = data.form_data.viz_type;
|
||||
px.registerViz(visType);
|
||||
slice['viz'] = visualizations[data.form_data.viz_type](slice);
|
||||
slice.viz = visualizations[data.form_data.viz_type](slice);
|
||||
return slice;
|
||||
}
|
||||
};
|
||||
|
||||
function registerViz(name) {
|
||||
var visSource = sourceMap[name];
|
||||
@ -235,12 +266,48 @@ var px = (function() {
|
||||
if (typeof visFactory === 'function') {
|
||||
visualizations[name] = visFactory;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
console.error("require(", visType, ") failed.");
|
||||
}
|
||||
}
|
||||
|
||||
function prepForm() {
|
||||
var i = 1;
|
||||
// Assigning the right id to form elements in filters
|
||||
$("#filters > div").each(function() {
|
||||
$(this).attr("id", function() {
|
||||
return "flt_" + i;
|
||||
});
|
||||
$(this).find("#flt_col_0")
|
||||
.attr("id", function() {
|
||||
return "flt_col_" + i;
|
||||
})
|
||||
.attr("name", function() {
|
||||
return "flt_col_" + i;
|
||||
});
|
||||
$(this).find("#flt_op_0")
|
||||
.attr("id", function() {
|
||||
return "flt_op_" + i;
|
||||
})
|
||||
.attr("name", function() {
|
||||
return "flt_op_" + i;
|
||||
});
|
||||
$(this).find("#flt_eq_0")
|
||||
.attr("id", function() {
|
||||
return "flt_eq_" + i;
|
||||
})
|
||||
.attr("name", function() {
|
||||
return "flt_eq_" + i;
|
||||
});
|
||||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
function renderSlice() {
|
||||
prepForm();
|
||||
slice.render();
|
||||
}
|
||||
|
||||
// Export public functions
|
||||
return {
|
||||
registerViz: registerViz,
|
||||
@ -249,7 +316,7 @@ var px = (function() {
|
||||
timeFormatFactory: timeFormatFactory,
|
||||
color: color(),
|
||||
getParam: getParam,
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
module.exports = px;
|
||||
|
@ -12,35 +12,41 @@ $(document).ready(function() {
|
||||
function getParam(name) {
|
||||
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
||||
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
||||
results = regex.exec(location.search);
|
||||
results = regex.exec(location.search);
|
||||
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||
}
|
||||
|
||||
function initSqlEditorView() {
|
||||
var database_id = $('#database_id').val();
|
||||
var editor = ace.edit("sql");
|
||||
editor.$blockScrolling = Infinity
|
||||
editor.$blockScrolling = Infinity;
|
||||
editor.getSession().setUseWrapMode(true);
|
||||
|
||||
var textarea = $('#sql').hide();
|
||||
editor.setTheme("ace/theme/crimson_editor");
|
||||
editor.setOptions({
|
||||
minLines: 16,
|
||||
maxLines: Infinity,
|
||||
minLines: 16,
|
||||
maxLines: Infinity,
|
||||
});
|
||||
editor.getSession().setMode("ace/mode/sql");
|
||||
editor.focus();
|
||||
$("select").select2({dropdownAutoWidth : true});
|
||||
$("select").select2({
|
||||
dropdownAutoWidth: true
|
||||
});
|
||||
|
||||
function showTableMetadata() {
|
||||
$(".metadata").load(
|
||||
'/panoramix/table/' + database_id + '/' + $("#dbtable").val() + '/');
|
||||
'/panoramix/table/' + database_id + '/' + $("#dbtable").val() + '/');
|
||||
}
|
||||
$("#dbtable").on("change", showTableMetadata);
|
||||
showTableMetadata();
|
||||
$("#create_view").click(function(){alert("Not implemented");});
|
||||
$("#create_view").click(function() {
|
||||
alert("Not implemented");
|
||||
});
|
||||
$(".sqlcontent").show();
|
||||
$("#select_star").click(function(){
|
||||
$.ajax('/panoramix/select_star/' + database_id + '/' + $("#dbtable").val() + '/')
|
||||
.done(function(msg){
|
||||
$("#select_star").click(function() {
|
||||
$.ajax('/panoramix/select_star/' + database_id + '/' + $("#dbtable").val() + '/')
|
||||
.done(function(msg) {
|
||||
editor.setValue(msg);
|
||||
});
|
||||
});
|
||||
@ -62,9 +68,10 @@ $(document).ready(function() {
|
||||
url: '/panoramix/runsql/',
|
||||
data: {
|
||||
'data': JSON.stringify({
|
||||
'database_id': $('#database_id').val(),
|
||||
'sql': editor.getSession().getValue(),
|
||||
})},
|
||||
'database_id': $('#database_id').val(),
|
||||
'sql': editor.getSession().getValue(),
|
||||
})
|
||||
},
|
||||
success: function(data) {
|
||||
$('#loading').hide(0);
|
||||
$('#results').show(0);
|
||||
|
@ -11,16 +11,16 @@ function bigNumberVis(slice) {
|
||||
var div = d3.select(slice.selector);
|
||||
|
||||
function render() {
|
||||
d3.json(slice.jsonEndpoint(), function(error, payload){
|
||||
d3.json(slice.jsonEndpoint(), function(error, payload) {
|
||||
//Define the percentage bounds that define color from red to green
|
||||
if (error != null){
|
||||
if (error !== null) {
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
var fd = payload.form_data;
|
||||
var json = payload.data;
|
||||
var color_range = [-1, 1];
|
||||
var compare_pos = -23
|
||||
var compare_pos = -23;
|
||||
var target_url = 'd3js.org';
|
||||
|
||||
var f = d3.format(fd.y_axis_format);
|
||||
@ -34,44 +34,54 @@ function bigNumberVis(slice) {
|
||||
var compare_suffix = ' ' + json.compare_suffix;
|
||||
var v_compare = null;
|
||||
var v = data[data.length - 1][1];
|
||||
if (json.compare_lag > 0){
|
||||
if (json.compare_lag > 0) {
|
||||
var pos = data.length - (json.compare_lag + 1);
|
||||
if (pos >= 0){
|
||||
if (pos >= 0) {
|
||||
v_compare = (v / data[pos][1]) - 1;
|
||||
}
|
||||
}
|
||||
var date_ext = d3.extent(data, function(d) { return d[0]; });
|
||||
var value_ext = d3.extent(data, function(d) { return d[1]; });
|
||||
var date_ext = d3.extent(data, function(d) {
|
||||
return d[0];
|
||||
});
|
||||
var value_ext = d3.extent(data, function(d) {
|
||||
return d[1];
|
||||
});
|
||||
|
||||
var margin = 20;
|
||||
var scale_x = d3.time.scale.utc().domain(date_ext).range([margin, width - margin]);
|
||||
var scale_y = d3.scale.linear().domain(value_ext).range([height - (margin), margin]);
|
||||
var colorRange = [d3.hsl(0, 1, 0.3), d3.hsl(120, 1, 0.3)];
|
||||
var scale_color = d3.scale
|
||||
.linear().domain(color_range)
|
||||
.interpolate(d3.interpolateHsl)
|
||||
.range(colorRange).clamp(true);
|
||||
.linear().domain(color_range)
|
||||
.interpolate(d3.interpolateHsl)
|
||||
.range(colorRange).clamp(true);
|
||||
var line = d3.svg.line()
|
||||
.x(function(d) { return scale_x(d[0]); })
|
||||
.y(function(d) { return scale_y(d[1]); })
|
||||
.interpolate("basis");
|
||||
.x(function(d) {
|
||||
return scale_x(d[0]);
|
||||
})
|
||||
.y(function(d) {
|
||||
return scale_y(d[1]);
|
||||
})
|
||||
.interpolate("basis");
|
||||
|
||||
//Drawing trend line
|
||||
var g = svg.append('g');
|
||||
var path = g.append('path')
|
||||
.attr('d', function(d) { return line(data); })
|
||||
.attr('stroke-width', 5)
|
||||
.attr('opacity', 0.5)
|
||||
.attr('fill', "none")
|
||||
.attr('stroke-linecap',"round")
|
||||
.attr('stroke', "grey");
|
||||
.attr('d', function(d) {
|
||||
return line(data);
|
||||
})
|
||||
.attr('stroke-width', 5)
|
||||
.attr('opacity', 0.5)
|
||||
.attr('fill', "none")
|
||||
.attr('stroke-linecap', "round")
|
||||
.attr('stroke', "grey");
|
||||
|
||||
var g = svg.append('g')
|
||||
.attr('class', 'digits')
|
||||
.attr('opacity', 1);
|
||||
g = svg.append('g')
|
||||
.attr('class', 'digits')
|
||||
.attr('opacity', 1);
|
||||
|
||||
var y = height / 2;
|
||||
if (v_compare != null) {
|
||||
if (v_compare !== null) {
|
||||
y = (height / 8) * 3;
|
||||
}
|
||||
|
||||
@ -86,15 +96,15 @@ function bigNumberVis(slice) {
|
||||
.style('cursor', 'pointer')
|
||||
.text(f(v))
|
||||
.style('font-size', d3.min([height, width]) / 3.5)
|
||||
.attr('fill','white');
|
||||
.attr('fill', 'white');
|
||||
|
||||
var c = scale_color(v_compare);
|
||||
|
||||
//Printing compare %
|
||||
if (v_compare != null) {
|
||||
if (v_compare !== null) {
|
||||
g.append('text')
|
||||
.attr('x', width / 2)
|
||||
.attr('y', (height / 16) *12)
|
||||
.attr('y', (height / 16) * 12)
|
||||
.text(fp(v_compare) + compare_suffix)
|
||||
.style('font-size', d3.min([height, width]) / 8)
|
||||
.style('text-anchor', 'middle')
|
||||
@ -103,7 +113,7 @@ function bigNumberVis(slice) {
|
||||
}
|
||||
|
||||
var g_axis = svg.append('g').attr('class', 'axis').attr('opacity', 0);
|
||||
var g = g_axis.append('g');
|
||||
g = g_axis.append('g');
|
||||
var x_axis = d3.svg.axis()
|
||||
.scale(scale_x)
|
||||
.orient('bottom')
|
||||
@ -112,7 +122,7 @@ function bigNumberVis(slice) {
|
||||
g.call(x_axis);
|
||||
g.attr('transform', 'translate(0,' + (height - margin) + ')');
|
||||
|
||||
var g = g_axis.append('g').attr('transform', 'translate(' + (width - margin) + ',0)');
|
||||
g = g_axis.append('g').attr('transform', 'translate(' + (width - margin) + ',0)');
|
||||
var y_axis = d3.svg.axis()
|
||||
.scale(scale_y)
|
||||
.orient('left')
|
||||
@ -121,34 +131,34 @@ function bigNumberVis(slice) {
|
||||
g.call(y_axis);
|
||||
g.selectAll('text')
|
||||
.style('text-anchor', 'end')
|
||||
.attr('y','-7')
|
||||
.attr('x','-4');
|
||||
.attr('y', '-7')
|
||||
.attr('x', '-4');
|
||||
|
||||
g.selectAll("text")
|
||||
.style('font-size', '10px');
|
||||
|
||||
div.on('mouseover', function(d) {
|
||||
var div = d3.select(this);
|
||||
div.select('path').transition().duration(500).attr('opacity', 1)
|
||||
.style('stroke-width', '2px');
|
||||
div.select('g.digits').transition().duration(500).attr('opacity', 0.1);
|
||||
div.select('g.axis').transition().duration(500).attr('opacity', 1);
|
||||
})
|
||||
.on('mouseout', function(d) {
|
||||
var div = d3.select(this);
|
||||
div.select('path').transition().duration(500).attr('opacity', 0.5)
|
||||
.style('stroke-width', '5px');
|
||||
div.select('g.digits').transition().duration(500).attr('opacity', 1);
|
||||
div.select('g.axis').transition().duration(500).attr('opacity', 0);
|
||||
});
|
||||
var div = d3.select(this);
|
||||
div.select('path').transition().duration(500).attr('opacity', 1)
|
||||
.style('stroke-width', '2px');
|
||||
div.select('g.digits').transition().duration(500).attr('opacity', 0.1);
|
||||
div.select('g.axis').transition().duration(500).attr('opacity', 1);
|
||||
})
|
||||
.on('mouseout', function(d) {
|
||||
var div = d3.select(this);
|
||||
div.select('path').transition().duration(500).attr('opacity', 0.5)
|
||||
.style('stroke-width', '5px');
|
||||
div.select('g.digits').transition().duration(500).attr('opacity', 1);
|
||||
div.select('g.axis').transition().duration(500).attr('opacity', 0);
|
||||
});
|
||||
slice.done(payload);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
render: render,
|
||||
resize: render,
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = bigNumberVis;
|
||||
|
@ -7,15 +7,15 @@ require('./directed_force.css');
|
||||
/* Modified from http://bl.ocks.org/d3noob/5141278 */
|
||||
function directedForceVis(slice) {
|
||||
var div = d3.select(slice.selector);
|
||||
var link_length = slice.data.form_data['link_length'] || 200;
|
||||
var charge = slice.data.form_data['charge'] || -500;
|
||||
var link_length = slice.data.form_data.link_length || 200;
|
||||
var charge = slice.data.form_data.charge || -500;
|
||||
|
||||
var render = function() {
|
||||
var width = slice.width();
|
||||
var height = slice.height() - 25;
|
||||
d3.json(slice.jsonEndpoint(), function(error, json) {
|
||||
|
||||
if (error != null){
|
||||
if (error !== null) {
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
@ -23,134 +23,144 @@ function directedForceVis(slice) {
|
||||
var nodes = {};
|
||||
// Compute the distinct nodes from the links.
|
||||
links.forEach(function(link) {
|
||||
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
|
||||
link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
|
||||
link.value = +link.value;
|
||||
link.source = nodes[link.source] || (nodes[link.source] = {
|
||||
name: link.source
|
||||
});
|
||||
link.target = nodes[link.target] || (nodes[link.target] = {
|
||||
name: link.target
|
||||
});
|
||||
link.value = +link.value;
|
||||
|
||||
var target_name = link.target.name;
|
||||
var source_name = link.source.name;
|
||||
var target_name = link.target.name;
|
||||
var source_name = link.source.name;
|
||||
|
||||
if (nodes[target_name]['total'] === undefined) {
|
||||
nodes[target_name]['total'] = link.value;
|
||||
}
|
||||
if (nodes[source_name]['total'] === undefined) {
|
||||
nodes[source_name]['total'] = 0;
|
||||
}
|
||||
if (nodes[target_name]['max'] === undefined) {
|
||||
nodes[target_name]['max'] = 0;
|
||||
}
|
||||
if (link.value > nodes[target_name]['max']) {
|
||||
nodes[target_name]['max'] = link.value;
|
||||
}
|
||||
if (nodes[target_name]['min'] === undefined) {
|
||||
nodes[target_name]['min'] = 0;
|
||||
}
|
||||
if (link.value > nodes[target_name]['min']) {
|
||||
nodes[target_name]['min'] = link.value;
|
||||
}
|
||||
if (nodes[target_name].total === undefined) {
|
||||
nodes[target_name].total = link.value;
|
||||
}
|
||||
if (nodes[source_name].total === undefined) {
|
||||
nodes[source_name].total = 0;
|
||||
}
|
||||
if (nodes[target_name].max === undefined) {
|
||||
nodes[target_name].max = 0;
|
||||
}
|
||||
if (link.value > nodes[target_name].max) {
|
||||
nodes[target_name].max = link.value;
|
||||
}
|
||||
if (nodes[target_name].min === undefined) {
|
||||
nodes[target_name].min = 0;
|
||||
}
|
||||
if (link.value > nodes[target_name].min) {
|
||||
nodes[target_name].min = link.value;
|
||||
}
|
||||
|
||||
nodes[target_name]['total'] += link.value;
|
||||
nodes[target_name].total += link.value;
|
||||
});
|
||||
|
||||
var force = d3.layout.force()
|
||||
.nodes(d3.values(nodes))
|
||||
.links(links)
|
||||
.size([width, height])
|
||||
.linkDistance(link_length)
|
||||
.charge(charge)
|
||||
.on("tick", tick)
|
||||
.start();
|
||||
.nodes(d3.values(nodes))
|
||||
.links(links)
|
||||
.size([width, height])
|
||||
.linkDistance(link_length)
|
||||
.charge(charge)
|
||||
.on("tick", tick)
|
||||
.start();
|
||||
|
||||
var svg = div.append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
|
||||
// build the arrow.
|
||||
svg.append("svg:defs").selectAll("marker")
|
||||
.data(["end"]) // Different link/path types can be defined here
|
||||
.enter().append("svg:marker") // This section adds in the arrows
|
||||
.attr("id", String)
|
||||
.attr("viewBox", "0 -5 10 10")
|
||||
.attr("refX", 15)
|
||||
.attr("refY", -1.5)
|
||||
.attr("markerWidth", 6)
|
||||
.attr("markerHeight", 6)
|
||||
.attr("orient", "auto")
|
||||
.data(["end"]) // Different link/path types can be defined here
|
||||
.enter().append("svg:marker") // This section adds in the arrows
|
||||
.attr("id", String)
|
||||
.attr("viewBox", "0 -5 10 10")
|
||||
.attr("refX", 15)
|
||||
.attr("refY", -1.5)
|
||||
.attr("markerWidth", 6)
|
||||
.attr("markerHeight", 6)
|
||||
.attr("orient", "auto")
|
||||
.append("svg:path")
|
||||
.attr("d", "M0,-5L10,0L0,5");
|
||||
.attr("d", "M0,-5L10,0L0,5");
|
||||
|
||||
var edgeScale = d3.scale.linear()
|
||||
.range([0.1, 0.5]);
|
||||
.range([0.1, 0.5]);
|
||||
// add the links and the arrows
|
||||
var path = svg.append("svg:g").selectAll("path")
|
||||
.data(force.links())
|
||||
.data(force.links())
|
||||
.enter().append("svg:path")
|
||||
.attr("class", "link")
|
||||
.style("opacity", function(d){
|
||||
return edgeScale(d.value/d.target.max);
|
||||
})
|
||||
.attr("marker-end", "url(#end)");
|
||||
.attr("class", "link")
|
||||
.style("opacity", function(d) {
|
||||
return edgeScale(d.value / d.target.max);
|
||||
})
|
||||
.attr("marker-end", "url(#end)");
|
||||
|
||||
// define the nodes
|
||||
var node = svg.selectAll(".node")
|
||||
.data(force.nodes())
|
||||
.data(force.nodes())
|
||||
.enter().append("g")
|
||||
.attr("class", "node")
|
||||
.on("mouseenter", function(d){
|
||||
d3.select(this)
|
||||
.select("circle")
|
||||
.transition()
|
||||
.style('stroke-width', 5);
|
||||
.attr("class", "node")
|
||||
.on("mouseenter", function(d) {
|
||||
d3.select(this)
|
||||
.select("circle")
|
||||
.transition()
|
||||
.style('stroke-width', 5);
|
||||
|
||||
d3.select(this)
|
||||
.select("text")
|
||||
.transition()
|
||||
.style('font-size', 25);
|
||||
})
|
||||
.on("mouseleave", function(d){
|
||||
d3.select(this)
|
||||
.select("circle")
|
||||
.transition()
|
||||
.style('stroke-width', 1.5);
|
||||
d3.select(this)
|
||||
.select("text")
|
||||
.transition()
|
||||
.style('font-size', 12);
|
||||
})
|
||||
.call(force.drag);
|
||||
d3.select(this)
|
||||
.select("text")
|
||||
.transition()
|
||||
.style('font-size', 25);
|
||||
})
|
||||
.on("mouseleave", function(d) {
|
||||
d3.select(this)
|
||||
.select("circle")
|
||||
.transition()
|
||||
.style('stroke-width', 1.5);
|
||||
d3.select(this)
|
||||
.select("text")
|
||||
.transition()
|
||||
.style('font-size', 12);
|
||||
})
|
||||
.call(force.drag);
|
||||
|
||||
// add the nodes
|
||||
var ext = d3.extent(d3.values(nodes), function(d) { return Math.sqrt(d.total); });
|
||||
var ext = d3.extent(d3.values(nodes), function(d) {
|
||||
return Math.sqrt(d.total);
|
||||
});
|
||||
var circleScale = d3.scale.linear()
|
||||
.domain(ext)
|
||||
.range([3, 30]);
|
||||
.domain(ext)
|
||||
.range([3, 30]);
|
||||
|
||||
node.append("circle")
|
||||
.attr("r", function(d){return circleScale(Math.sqrt(d.total));});
|
||||
.attr("r", function(d) {
|
||||
return circleScale(Math.sqrt(d.total));
|
||||
});
|
||||
|
||||
// add the text
|
||||
node.append("text")
|
||||
.attr("x", 6)
|
||||
.attr("dy", ".35em")
|
||||
.text(function(d) { return d.name; });
|
||||
.attr("x", 6)
|
||||
.attr("dy", ".35em")
|
||||
.text(function(d) {
|
||||
return d.name;
|
||||
});
|
||||
|
||||
// add the curvy lines
|
||||
function tick() {
|
||||
path.attr("d", function(d) {
|
||||
var dx = d.target.x - d.source.x,
|
||||
dy = d.target.y - d.source.y,
|
||||
dr = Math.sqrt(dx * dx + dy * dy);
|
||||
return "M" +
|
||||
d.source.x + "," +
|
||||
d.source.y + "A" +
|
||||
dr + "," + dr + " 0 0,1 " +
|
||||
d.target.x + "," +
|
||||
d.target.y;
|
||||
});
|
||||
path.attr("d", function(d) {
|
||||
var dx = d.target.x - d.source.x,
|
||||
dy = d.target.y - d.source.y,
|
||||
dr = Math.sqrt(dx * dx + dy * dy);
|
||||
return "M" +
|
||||
d.source.x + "," +
|
||||
d.source.y + "A" +
|
||||
dr + "," + dr + " 0 0,1 " +
|
||||
d.target.x + "," +
|
||||
d.target.y;
|
||||
});
|
||||
|
||||
node.attr("transform", function(d) {
|
||||
return "translate(" + d.x + "," + d.y + ")";
|
||||
});
|
||||
node.attr("transform", function(d) {
|
||||
return "translate(" + d.x + "," + d.y + ")";
|
||||
});
|
||||
}
|
||||
|
||||
slice.done(json);
|
||||
|
@ -5,33 +5,34 @@ var d3 = window.d3 || require('d3');
|
||||
require('./filter_box.css');
|
||||
|
||||
function filterBox(slice) {
|
||||
var slice = slice;
|
||||
var filtersObj = {};
|
||||
var d3token = d3.select(slice.selector);
|
||||
|
||||
var fltChanged = function() {
|
||||
var filters = []
|
||||
for (var filter in filtersObj) {
|
||||
var obj = filtersObj[filter];
|
||||
var val = obj.val();
|
||||
var vals = [];
|
||||
if (val !== '') {
|
||||
filters.push([filter, val.split(',')]);
|
||||
vals = val.split(',');
|
||||
}
|
||||
slice.setFilter(filter, vals);
|
||||
}
|
||||
slice.addFilter(filters);
|
||||
}
|
||||
};
|
||||
|
||||
var refresh = function() {
|
||||
d3token.selectAll("*").remove();
|
||||
var container = d3token
|
||||
.append('div')
|
||||
.classed('padded', true);
|
||||
d3token.selectAll("*").remove();
|
||||
var container = d3token
|
||||
.append('div')
|
||||
.classed('padded', true);
|
||||
|
||||
$.getJSON(slice.jsonEndpoint(), function(payload) {
|
||||
$.getJSON(slice.jsonEndpoint(), function(payload) {
|
||||
var maxes = {};
|
||||
for (var filter in payload.data) {
|
||||
var data = payload.data[filter];
|
||||
maxes[filter] = d3.max(data, function(d){return d.metric});
|
||||
maxes[filter] = d3.max(data, function(d) {
|
||||
return d.metric;
|
||||
});
|
||||
var id = 'fltbox__' + filter;
|
||||
|
||||
var div = container.append('div');
|
||||
@ -44,12 +45,12 @@ function filterBox(slice) {
|
||||
.attr('id', id);
|
||||
|
||||
filtersObj[filter] = $('#' + id).select2({
|
||||
placeholder: "Select [" + filter + ']',
|
||||
containment: 'parent',
|
||||
dropdownAutoWidth : true,
|
||||
data:data,
|
||||
multiple: true,
|
||||
formatResult: function(result, container, query, escapeMarkup) {
|
||||
placeholder: "Select [" + filter + ']',
|
||||
containment: 'parent',
|
||||
dropdownAutoWidth: true,
|
||||
data: data,
|
||||
multiple: true,
|
||||
formatResult: function(result, container, query, escapeMarkup) {
|
||||
var perc = Math.round((result.metric / maxes[result.filter]) * 100);
|
||||
var style = 'padding: 2px 5px;';
|
||||
style += "background-image: ";
|
||||
@ -58,16 +59,16 @@ function filterBox(slice) {
|
||||
$(container).attr('style', 'padding: 0px; background: white;');
|
||||
$(container).addClass('filter_box');
|
||||
return '<div style="' + style + '"><span>' + result.text + '</span></div>';
|
||||
},
|
||||
})
|
||||
.on('change', fltChanged);
|
||||
},
|
||||
})
|
||||
.on('change', fltChanged);
|
||||
}
|
||||
slice.done();
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
};
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
};
|
||||
return {
|
||||
render: refresh,
|
||||
resize: refresh,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// JS
|
||||
var $ = window.$ || require('jquery');
|
||||
var $ = window.$ || require('jquery');
|
||||
var px = window.px || require('../javascripts/modules/panoramix.js');
|
||||
var d3 = require('d3');
|
||||
|
||||
@ -11,27 +11,34 @@ require('./heatmap.css');
|
||||
// Inspired from http://bl.ocks.org/mbostock/3074470
|
||||
// https://jsfiddle.net/cyril123/h0reyumq/
|
||||
function heatmapVis(slice) {
|
||||
var margins = {t:10, r:10, b:50, l:60};
|
||||
var margins = {
|
||||
t: 10,
|
||||
r: 10,
|
||||
b: 50,
|
||||
l: 60
|
||||
};
|
||||
|
||||
function refresh() {
|
||||
var width = slice.width();
|
||||
var height = slice.height();
|
||||
var hmWidth = width - (margins.l + margins.r)
|
||||
var hmHeight = height - (margins.b + margins.t)
|
||||
var hmWidth = width - (margins.l + margins.r);
|
||||
var hmHeight = height - (margins.b + margins.t);
|
||||
var fp = d3.format('.3p');
|
||||
d3.json(slice.jsonEndpoint(), function(error, payload) {
|
||||
var matrix = {};
|
||||
if (error){
|
||||
if (error) {
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
var fd = payload.form_data;
|
||||
var data = payload.data;
|
||||
|
||||
function ordScale(k, rangeBands, reverse) {
|
||||
if (reverse === undefined) {
|
||||
reverse = false;
|
||||
}
|
||||
var domain = {};
|
||||
$.each(data, function(i, d){
|
||||
$.each(data, function(i, d) {
|
||||
domain[d[k]] = true;
|
||||
});
|
||||
domain = Object.keys(domain).sort(function(a, b) {
|
||||
@ -42,8 +49,7 @@ function heatmapVis(slice) {
|
||||
}
|
||||
if (rangeBands === undefined) {
|
||||
return d3.scale.ordinal().domain(domain).range(d3.range(domain.length));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return d3.scale.ordinal().domain(domain).rangeBands(rangeBands);
|
||||
}
|
||||
}
|
||||
@ -51,71 +57,72 @@ function heatmapVis(slice) {
|
||||
var yScale = ordScale('y', undefined, true);
|
||||
var xRbScale = ordScale('x', [0, hmWidth]);
|
||||
var yRbScale = ordScale('y', [hmHeight, 0]);
|
||||
var X = 0, Y = 1;
|
||||
var X = 0,
|
||||
Y = 1;
|
||||
var heatmapDim = [xRbScale.domain().length, yRbScale.domain().length];
|
||||
|
||||
var color = px.color.colorScalerFactory(fd.linear_color_scheme);
|
||||
|
||||
var scale = [
|
||||
d3.scale.linear()
|
||||
.domain([0, heatmapDim[X]])
|
||||
.range([0, hmWidth]),
|
||||
.domain([0, heatmapDim[X]])
|
||||
.range([0, hmWidth]),
|
||||
d3.scale.linear()
|
||||
.domain([0, heatmapDim[Y]])
|
||||
.range([0, hmHeight])
|
||||
.domain([0, heatmapDim[Y]])
|
||||
.range([0, hmHeight])
|
||||
];
|
||||
|
||||
var container = d3.select(slice.selector)
|
||||
.style("left", "0px")
|
||||
.style("position", "relative")
|
||||
.style("top", "0px");
|
||||
.style("left", "0px")
|
||||
.style("position", "relative")
|
||||
.style("top", "0px");
|
||||
|
||||
var canvas = container.append("canvas")
|
||||
.attr("width", heatmapDim[X])
|
||||
.attr("height", heatmapDim[Y])
|
||||
.style("width", hmWidth + "px")
|
||||
.style("height", hmHeight + "px")
|
||||
.style("image-rendering", fd.canvas_image_rendering)
|
||||
.style("left", margins.l + "px")
|
||||
.style("top", margins.t + "px")
|
||||
.style("position", "absolute");
|
||||
.attr("width", heatmapDim[X])
|
||||
.attr("height", heatmapDim[Y])
|
||||
.style("width", hmWidth + "px")
|
||||
.style("height", hmHeight + "px")
|
||||
.style("image-rendering", fd.canvas_image_rendering)
|
||||
.style("left", margins.l + "px")
|
||||
.style("top", margins.t + "px")
|
||||
.style("position", "absolute");
|
||||
|
||||
var svg = container.append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.style("left", "0px")
|
||||
.style("top", "0px")
|
||||
.style("position", "absolute");
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.style("left", "0px")
|
||||
.style("top", "0px")
|
||||
.style("position", "absolute");
|
||||
|
||||
var rect = svg.append('g')
|
||||
.attr("transform", "translate(" + margins.l + "," + margins.t + ")")
|
||||
.attr("transform", "translate(" + margins.l + "," + margins.t + ")")
|
||||
.append('rect')
|
||||
.style('fill-opacity', 0)
|
||||
.attr('stroke', 'black')
|
||||
.attr("width", hmWidth)
|
||||
.attr("height", hmHeight);
|
||||
.style('fill-opacity', 0)
|
||||
.attr('stroke', 'black')
|
||||
.attr("width", hmWidth)
|
||||
.attr("height", hmHeight);
|
||||
|
||||
var tip = d3.tip()
|
||||
.attr('class', 'd3-tip')
|
||||
.offset(function(){
|
||||
var k = d3.mouse(this);
|
||||
var x = k[0] - (hmWidth/ 2);
|
||||
return [k[1] - 20, x];
|
||||
})
|
||||
.html(function (d) {
|
||||
var k = d3.mouse(this);
|
||||
var m = Math.floor(scale[0].invert(k[0]));
|
||||
var n = Math.floor(scale[1].invert(k[1]));
|
||||
if(m in matrix && n in matrix[m]) {
|
||||
var obj = matrix[m][n];
|
||||
var s = "";
|
||||
s += "<div><b>" + fd.all_columns_x + ": </b>" + obj.x + "<div>"
|
||||
s += "<div><b>" + fd.all_columns_y +": </b>" + obj.y + "<div>"
|
||||
s += "<div><b>" + fd.metric + ": </b>" + obj.v + "<div>"
|
||||
s += "<div><b>%: </b>" + fp(obj.perc) + "<div>"
|
||||
return s;
|
||||
}
|
||||
});
|
||||
.attr('class', 'd3-tip')
|
||||
.offset(function() {
|
||||
var k = d3.mouse(this);
|
||||
var x = k[0] - (hmWidth / 2);
|
||||
return [k[1] - 20, x];
|
||||
})
|
||||
.html(function(d) {
|
||||
var k = d3.mouse(this);
|
||||
var m = Math.floor(scale[0].invert(k[0]));
|
||||
var n = Math.floor(scale[1].invert(k[1]));
|
||||
if (m in matrix && n in matrix[m]) {
|
||||
var obj = matrix[m][n];
|
||||
var s = "";
|
||||
s += "<div><b>" + fd.all_columns_x + ": </b>" + obj.x + "<div>";
|
||||
s += "<div><b>" + fd.all_columns_y + ": </b>" + obj.y + "<div>";
|
||||
s += "<div><b>" + fd.metric + ": </b>" + obj.v + "<div>";
|
||||
s += "<div><b>%: </b>" + fp(obj.perc) + "<div>";
|
||||
return s;
|
||||
}
|
||||
});
|
||||
|
||||
rect.call(tip);
|
||||
|
||||
@ -123,32 +130,36 @@ function heatmapVis(slice) {
|
||||
var yscale_skip = 2;
|
||||
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(xRbScale)
|
||||
.tickValues(xRbScale.domain().filter(
|
||||
function(d, i) { return !(i % (parseInt(fd.xscale_interval))); }))
|
||||
.orient("bottom");
|
||||
.scale(xRbScale)
|
||||
.tickValues(xRbScale.domain().filter(
|
||||
function(d, i) {
|
||||
return !(i % (parseInt(fd.xscale_interval)));
|
||||
}))
|
||||
.orient("bottom");
|
||||
var yAxis = d3.svg.axis()
|
||||
.scale(yRbScale)
|
||||
.tickValues(yRbScale.domain().filter(
|
||||
function(d, i) { return !(i % (parseInt(fd.yscale_interval))); }))
|
||||
.orient("left");
|
||||
.scale(yRbScale)
|
||||
.tickValues(yRbScale.domain().filter(
|
||||
function(d, i) {
|
||||
return !(i % (parseInt(fd.yscale_interval)));
|
||||
}))
|
||||
.orient("left");
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(" + margins.l + "," + (margins.t + hmHeight) + ")")
|
||||
.call(xAxis)
|
||||
.selectAll("text")
|
||||
.style("text-anchor", "end")
|
||||
.attr("transform", "rotate(-45)")
|
||||
.style("font-weight", "bold");
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(" + margins.l + "," + (margins.t + hmHeight) + ")")
|
||||
.call(xAxis)
|
||||
.selectAll("text")
|
||||
.style("text-anchor", "end")
|
||||
.attr("transform", "rotate(-45)")
|
||||
.style("font-weight", "bold");
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y axis")
|
||||
.attr("transform", "translate(" + margins.l + ", 0)")
|
||||
.call(yAxis);
|
||||
.attr("class", "y axis")
|
||||
.attr("transform", "translate(" + margins.l + ", 0)")
|
||||
.call(yAxis);
|
||||
|
||||
rect.on('mousemove', tip.show);
|
||||
rect.on('mouseout', tip.hide);
|
||||
rect.on('mousemove', tip.show);
|
||||
rect.on('mouseout', tip.hide);
|
||||
|
||||
var context = canvas.node().getContext("2d");
|
||||
context.imageSmoothingEnabled = false;
|
||||
@ -163,28 +174,28 @@ function heatmapVis(slice) {
|
||||
var image = context.createImageData(heatmapDim[0], heatmapDim[1]);
|
||||
var pixs = {};
|
||||
$.each(data, function(i, d) {
|
||||
var c = d3.rgb(color(d.perc));
|
||||
var x = xScale(d.x);
|
||||
var y = yScale(d.y);
|
||||
pixs[x + (y*xScale.domain().length)] = c;
|
||||
if (matrix[x] === undefined)
|
||||
matrix[x] = {}
|
||||
if (matrix[x][y] === undefined)
|
||||
matrix[x][y] = d;
|
||||
var c = d3.rgb(color(d.perc));
|
||||
var x = xScale(d.x);
|
||||
var y = yScale(d.y);
|
||||
pixs[x + (y * xScale.domain().length)] = c;
|
||||
if (matrix[x] === undefined)
|
||||
matrix[x] = {};
|
||||
if (matrix[x][y] === undefined)
|
||||
matrix[x][y] = d;
|
||||
});
|
||||
|
||||
var p = -1;
|
||||
for(var i = 0; i < heatmapDim[0] * heatmapDim[1]; i++){
|
||||
var c = pixs[i];
|
||||
var alpha = 255;
|
||||
if (c === undefined){
|
||||
c = d3.rgb('#F00');
|
||||
alpha = 0;
|
||||
}
|
||||
image.data[++p] = c.r;
|
||||
image.data[++p] = c.g;
|
||||
image.data[++p] = c.b;
|
||||
image.data[++p] = alpha;
|
||||
for (var i = 0; i < heatmapDim[0] * heatmapDim[1]; i++) {
|
||||
var c = pixs[i];
|
||||
var alpha = 255;
|
||||
if (c === undefined) {
|
||||
c = d3.rgb('#F00');
|
||||
alpha = 0;
|
||||
}
|
||||
image.data[++p] = c.r;
|
||||
image.data[++p] = c.g;
|
||||
image.data[++p] = c.b;
|
||||
image.data[++p] = alpha;
|
||||
}
|
||||
context.putImageData(image, 0, 0);
|
||||
imageObj.src = canvas.node().toDataURL();
|
||||
|
@ -3,7 +3,7 @@ var $ = window.$ || require('jquery');
|
||||
function iframeWidget(slice) {
|
||||
|
||||
function refresh() {
|
||||
$('#code').attr('rows', '15')
|
||||
$('#code').attr('rows', '15');
|
||||
$.getJSON(slice.jsonEndpoint(), function(payload) {
|
||||
slice.container.html('<iframe style="width:100%;"></iframe>');
|
||||
var iframe = slice.container.find('iframe');
|
||||
@ -14,7 +14,7 @@ function iframeWidget(slice) {
|
||||
.fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
render: refresh,
|
||||
@ -22,4 +22,4 @@ function iframeWidget(slice) {
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = iframeWidget
|
||||
module.exports = iframeWidget;
|
||||
|
@ -12,7 +12,7 @@ function markupWidget(slice) {
|
||||
.fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
render: refresh,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// JS
|
||||
var $ = window.$ || require('jquery');
|
||||
var $ = window.$ || require('jquery');
|
||||
var px = window.px || require('../javascripts/modules/panoramix.js');
|
||||
require('nvd3');
|
||||
|
||||
@ -7,198 +7,189 @@ require('nvd3');
|
||||
require('../node_modules/nvd3/build/nv.d3.min.css');
|
||||
|
||||
function nvd3Vis(slice) {
|
||||
var chart = undefined;
|
||||
var chart;
|
||||
var data = {};
|
||||
|
||||
var render = function() {
|
||||
$.getJSON(slice.jsonEndpoint(), function(payload) {
|
||||
var fd = payload.form_data;
|
||||
var viz_type = fd.viz_type;
|
||||
var fd = payload.form_data;
|
||||
var viz_type = fd.viz_type;
|
||||
|
||||
var f = d3.format('.3s');
|
||||
var colorKey = 'key';
|
||||
var f = d3.format('.3s');
|
||||
var colorKey = 'key';
|
||||
|
||||
nv.addGraph(function() {
|
||||
switch (viz_type) {
|
||||
nv.addGraph(function() {
|
||||
switch (viz_type) {
|
||||
|
||||
case 'line':
|
||||
if (fd.show_brush) {
|
||||
chart = nv.models.lineWithFocusChart();
|
||||
chart.lines2.xScale(d3.time.scale.utc());
|
||||
chart.x2Axis
|
||||
case 'line':
|
||||
if (fd.show_brush) {
|
||||
chart = nv.models.lineWithFocusChart();
|
||||
chart.lines2.xScale(d3.time.scale.utc());
|
||||
chart.x2Axis
|
||||
.showMaxMin(fd.x_axis_showminmax)
|
||||
.staggerLabels(true);
|
||||
} else {
|
||||
chart = nv.models.lineChart();
|
||||
}
|
||||
// To alter the tooltip header
|
||||
// chart.interactiveLayer.tooltip.headerFormatter(function(){return '';});
|
||||
chart.xScale(d3.time.scale.utc());
|
||||
chart.interpolate(fd.line_interpolation);
|
||||
chart.xAxis
|
||||
.showMaxMin(fd.x_axis_showminmax)
|
||||
.staggerLabels(false);
|
||||
} else {
|
||||
chart = nv.models.lineChart()
|
||||
}
|
||||
// To alter the tooltip header
|
||||
// chart.interactiveLayer.tooltip.headerFormatter(function(){return '';});
|
||||
chart.xScale(d3.time.scale.utc());
|
||||
chart.interpolate(fd.line_interpolation);
|
||||
chart.xAxis
|
||||
.showMaxMin(fd.x_axis_showminmax)
|
||||
.staggerLabels(true);
|
||||
break;
|
||||
.staggerLabels(true);
|
||||
break;
|
||||
|
||||
case 'bar':
|
||||
chart = nv.models.multiBarChart()
|
||||
.showControls(true)
|
||||
.groupSpacing(0.1);
|
||||
case 'bar':
|
||||
chart = nv.models.multiBarChart()
|
||||
.showControls(true)
|
||||
.groupSpacing(0.1);
|
||||
|
||||
chart.xAxis
|
||||
.showMaxMin(false)
|
||||
.staggerLabels(true);
|
||||
chart.xAxis
|
||||
.showMaxMin(false)
|
||||
.staggerLabels(true);
|
||||
|
||||
chart.stacked(fd.bar_stacked);
|
||||
break;
|
||||
chart.stacked(fd.bar_stacked);
|
||||
break;
|
||||
|
||||
case 'dist_bar':
|
||||
chart = nv.models.multiBarChart()
|
||||
.showControls(true) //Allow user to switch between 'Grouped' and 'Stacked' mode.
|
||||
.reduceXTicks(false)
|
||||
.rotateLabels(45)
|
||||
.groupSpacing(0.1); //Distance between each group of bars.
|
||||
case 'dist_bar':
|
||||
chart = nv.models.multiBarChart()
|
||||
.showControls(true) //Allow user to switch between 'Grouped' and 'Stacked' mode.
|
||||
.reduceXTicks(false)
|
||||
.rotateLabels(45)
|
||||
.groupSpacing(0.1); //Distance between each group of bars.
|
||||
|
||||
chart.xAxis
|
||||
.showMaxMin(false);
|
||||
chart.xAxis
|
||||
.showMaxMin(false);
|
||||
|
||||
chart.stacked(fd.bar_stacked);
|
||||
break;
|
||||
chart.stacked(fd.bar_stacked);
|
||||
break;
|
||||
|
||||
case 'pie':
|
||||
chart = nv.models.pieChart()
|
||||
colorKey = 'x';
|
||||
chart.valueFormat(f);
|
||||
if (fd.donut) {
|
||||
chart.donut(true);
|
||||
case 'pie':
|
||||
chart = nv.models.pieChart();
|
||||
colorKey = 'x';
|
||||
chart.valueFormat(f);
|
||||
if (fd.donut) {
|
||||
chart.donut(true);
|
||||
chart.labelsOutside(true);
|
||||
}
|
||||
chart.labelsOutside(true);
|
||||
}
|
||||
chart.labelsOutside(true);
|
||||
chart.cornerRadius(true);
|
||||
break;
|
||||
chart.cornerRadius(true);
|
||||
break;
|
||||
|
||||
case 'column':
|
||||
chart = nv.models.multiBarChart()
|
||||
.reduceXTicks(false)
|
||||
.rotateLabels(45);
|
||||
break;
|
||||
case 'column':
|
||||
chart = nv.models.multiBarChart()
|
||||
.reduceXTicks(false)
|
||||
.rotateLabels(45);
|
||||
break;
|
||||
|
||||
case 'compare':
|
||||
chart = nv.models.cumulativeLineChart();
|
||||
chart.xScale(d3.time.scale.utc());
|
||||
chart.xAxis
|
||||
.showMaxMin(false)
|
||||
.staggerLabels(true);
|
||||
break;
|
||||
case 'compare':
|
||||
chart = nv.models.cumulativeLineChart();
|
||||
chart.xScale(d3.time.scale.utc());
|
||||
chart.xAxis
|
||||
.showMaxMin(false)
|
||||
.staggerLabels(true);
|
||||
break;
|
||||
|
||||
case 'bubble':
|
||||
var row = function(col1, col2) {
|
||||
return "<tr><td>" + col1 + "</td><td>" + col2 + "</td></tr>";
|
||||
};
|
||||
chart = nv.models.scatterChart();
|
||||
chart.showDistX(true);
|
||||
chart.showDistY(true);
|
||||
chart.tooltip.contentGenerator(function (obj) {
|
||||
var p = obj.point;
|
||||
var s = "<table>";
|
||||
s += '<tr><td style="color:' + p.color + ';"><strong>' + p[fd.entity] + '</strong> (' + p.group + ')</td></tr>';
|
||||
s += row(fd.x, f(p.x));
|
||||
s += row(fd.y, f(p.y));
|
||||
s += row(fd.size, f(p.size));
|
||||
s += "</table>";
|
||||
return s;
|
||||
});
|
||||
chart.pointRange([5, fd.max_bubble_size * fd.max_bubble_size]);
|
||||
break;
|
||||
case 'bubble':
|
||||
var row = function(col1, col2) {
|
||||
return "<tr><td>" + col1 + "</td><td>" + col2 + "</td></tr>";
|
||||
};
|
||||
chart = nv.models.scatterChart();
|
||||
chart.showDistX(true);
|
||||
chart.showDistY(true);
|
||||
chart.tooltip.contentGenerator(function(obj) {
|
||||
var p = obj.point;
|
||||
var s = "<table>";
|
||||
s += '<tr><td style="color:' + p.color + ';"><strong>' + p[fd.entity] + '</strong> (' + p.group + ')</td></tr>';
|
||||
s += row(fd.x, f(p.x));
|
||||
s += row(fd.y, f(p.y));
|
||||
s += row(fd.size, f(p.size));
|
||||
s += "</table>";
|
||||
return s;
|
||||
});
|
||||
chart.pointRange([5, fd.max_bubble_size * fd.max_bubble_size]);
|
||||
break;
|
||||
|
||||
case 'area':
|
||||
chart = nv.models.stackedAreaChart();
|
||||
chart.style(fd.stacked_style);
|
||||
chart.xScale(d3.time.scale.utc());
|
||||
chart.xAxis
|
||||
.showMaxMin(false)
|
||||
.staggerLabels(true);
|
||||
break;
|
||||
case 'area':
|
||||
chart = nv.models.stackedAreaChart();
|
||||
chart.style(fd.stacked_style);
|
||||
chart.xScale(d3.time.scale.utc());
|
||||
chart.xAxis
|
||||
.showMaxMin(false)
|
||||
.staggerLabels(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error("unrecognized visualization for nvd3", viz_type);
|
||||
}
|
||||
|
||||
if ("showLegend" in chart && typeof fd.show_legend !== 'undefined') {
|
||||
chart.showLegend(fd.show_legend);
|
||||
}
|
||||
|
||||
var height = slice.height();
|
||||
|
||||
if(chart.hasOwnProperty("x2Axis")) {
|
||||
height += 30;
|
||||
}
|
||||
chart.height(height);
|
||||
slice.container.css('height', height + 'px');
|
||||
|
||||
if ((viz_type === "line" || viz_type === "area") && fd.rich_tooltip) {
|
||||
chart.useInteractiveGuideline(true);
|
||||
}
|
||||
if (fd.y_axis_zero) {
|
||||
chart.forceY([0, 1]);
|
||||
}
|
||||
else if (fd.y_log_scale) {
|
||||
chart.yScale(d3.scale.log());
|
||||
}
|
||||
if (fd.x_log_scale) {
|
||||
chart.xScale(d3.scale.log());
|
||||
}
|
||||
if (viz_type === 'bubble') {
|
||||
chart.xAxis.tickFormat(d3.format('.3s'));
|
||||
}
|
||||
else if (fd.x_axis_format == 'smart_date') {
|
||||
chart.xAxis.tickFormat(px.formatDate);
|
||||
if(chart.hasOwnProperty("x2Axis")) {
|
||||
chart.x2Axis.tickFormat(px.formatDate);
|
||||
default:
|
||||
console.error("unrecognized visualization for nvd3", viz_type);
|
||||
}
|
||||
}
|
||||
else if (fd.x_axis_format !== undefined) {
|
||||
var tf = px.timeFormatFactory(fd.x_axis_format);
|
||||
chart.xAxis.tickFormat(tf);
|
||||
if(chart.hasOwnProperty("x2Axis")) {
|
||||
chart.x2Axis.tickFormat(tf);
|
||||
}
|
||||
}
|
||||
if (chart.yAxis !== undefined) {
|
||||
chart.yAxis.tickFormat(d3.format('.3s'));
|
||||
}
|
||||
|
||||
if (fd.contribution || fd.num_period_compare || viz_type == 'compare') {
|
||||
chart.yAxis.tickFormat(d3.format('.3p'));
|
||||
if (chart.y2Axis != undefined) {
|
||||
if ("showLegend" in chart && typeof fd.show_legend !== 'undefined') {
|
||||
chart.showLegend(fd.show_legend);
|
||||
}
|
||||
|
||||
var height = slice.height();
|
||||
|
||||
if (chart.hasOwnProperty("x2Axis")) {
|
||||
height += 30;
|
||||
}
|
||||
chart.height(height);
|
||||
slice.container.css('height', height + 'px');
|
||||
|
||||
if ((viz_type === "line" || viz_type === "area") && fd.rich_tooltip) {
|
||||
chart.useInteractiveGuideline(true);
|
||||
}
|
||||
if (fd.y_axis_zero) {
|
||||
chart.forceY([0, 1]);
|
||||
} else if (fd.y_log_scale) {
|
||||
chart.yScale(d3.scale.log());
|
||||
}
|
||||
if (fd.x_log_scale) {
|
||||
chart.xScale(d3.scale.log());
|
||||
}
|
||||
if (viz_type === 'bubble') {
|
||||
chart.xAxis.tickFormat(d3.format('.3s'));
|
||||
} else if (fd.x_axis_format == 'smart_date') {
|
||||
chart.xAxis.tickFormat(px.formatDate);
|
||||
} else if (fd.x_axis_format !== undefined) {
|
||||
chart.xAxis.tickFormat(px.timeFormatFactory(fd.x_axis_format));
|
||||
}
|
||||
if (chart.yAxis !== undefined) {
|
||||
chart.yAxis.tickFormat(d3.format('.3s'));
|
||||
}
|
||||
|
||||
if (fd.contribution || fd.num_period_compare || viz_type == 'compare') {
|
||||
chart.yAxis.tickFormat(d3.format('.3p'));
|
||||
if (chart.y2Axis !== undefined) {
|
||||
chart.y2Axis.tickFormat(d3.format('.3p'));
|
||||
}
|
||||
} else if (fd.y_axis_format) {
|
||||
chart.yAxis.tickFormat(d3.format(fd.y_axis_format));
|
||||
}
|
||||
} else if (fd.y_axis_format) {
|
||||
chart.yAxis.tickFormat(d3.format(fd.y_axis_format));
|
||||
|
||||
if (chart.y2Axis != undefined) {
|
||||
chart.y2Axis.tickFormat(d3.format(fd.y_axis_format));
|
||||
if (chart.y2Axis !== undefined) {
|
||||
chart.y2Axis.tickFormat(d3.format(fd.y_axis_format));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chart.color(function(d, i){
|
||||
return px.color.category21(d[colorKey]);
|
||||
chart.color(function(d, i) {
|
||||
return px.color.category21(d[colorKey]);
|
||||
});
|
||||
|
||||
d3.select(slice.selector).html('');
|
||||
d3.select(slice.selector).append("svg")
|
||||
.datum(payload.data)
|
||||
.transition().duration(500)
|
||||
.attr('height', height)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
d3.select(slice.selector).append("svg")
|
||||
.datum(payload.data)
|
||||
.transition().duration(500)
|
||||
.attr('height', height)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
slice.done(payload);
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
|
||||
slice.done(payload);
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
};
|
||||
|
||||
var update = function() {
|
||||
@ -211,6 +202,6 @@ function nvd3Vis(slice) {
|
||||
render: render,
|
||||
resize: update,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = nvd3Vis;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// JS
|
||||
var d3 = window.d3 || require('d3');
|
||||
d3.parcoords = require('../vendor/parallel_coordinates/d3.parcoords.js');
|
||||
d3.divgrid = require('../vendor/parallel_coordinates/divgrid.js');
|
||||
d3.divgrid = require('../vendor/parallel_coordinates/divgrid.js');
|
||||
|
||||
// CSS
|
||||
require('../vendor/parallel_coordinates/d3.parcoords.css');
|
||||
@ -9,20 +9,22 @@ require('../vendor/parallel_coordinates/d3.parcoords.css');
|
||||
function parallelCoordVis(slice) {
|
||||
|
||||
function refresh() {
|
||||
$('#code').attr('rows', '15')
|
||||
$.getJSON(slice.jsonEndpoint(), function(payload) {
|
||||
$('#code').attr('rows', '15');
|
||||
$.getJSON(slice.jsonEndpoint(), function(payload) {
|
||||
var data = payload.data;
|
||||
var fd = payload.form_data;
|
||||
var ext = d3.extent(data, function(d){
|
||||
var ext = d3.extent(data, function(d) {
|
||||
return d[fd.secondary_metric];
|
||||
});
|
||||
ext = [ext[0], (ext[1]-ext[0])/2,ext[1]];
|
||||
ext = [ext[0], (ext[1] - ext[0]) / 2, ext[1]];
|
||||
var cScale = d3.scale.linear()
|
||||
.domain(ext)
|
||||
.range(['red', 'grey', 'blue'])
|
||||
.interpolate(d3.interpolateLab);
|
||||
|
||||
var color = function(d){return cScale(d[fd.secondary_metric])};
|
||||
var color = function(d) {
|
||||
return cScale(d[fd.secondary_metric]);
|
||||
};
|
||||
var container = d3.select(slice.selector);
|
||||
var eff_height = fd.show_datatable ? (slice.height() / 2) : slice.height();
|
||||
|
||||
@ -48,23 +50,27 @@ function parallelCoordVis(slice) {
|
||||
// create data table, row hover highlighting
|
||||
var grid = d3.divgrid();
|
||||
container.append("div")
|
||||
.datum(data.slice(0,10))
|
||||
.datum(data.slice(0, 10))
|
||||
.attr('id', "grid")
|
||||
.call(grid)
|
||||
.classed("parcoords", true)
|
||||
.selectAll(".row")
|
||||
.on({
|
||||
"mouseover": function(d) { parcoords.highlight([d]) },
|
||||
"mouseover": function(d) {
|
||||
parcoords.highlight([d]);
|
||||
},
|
||||
"mouseout": parcoords.unhighlight
|
||||
});
|
||||
// update data table on brush event
|
||||
parcoords.on("brush", function(d) {
|
||||
d3.select("#grid")
|
||||
.datum(d.slice(0,10))
|
||||
.datum(d.slice(0, 10))
|
||||
.call(grid)
|
||||
.selectAll(".row")
|
||||
.on({
|
||||
"mouseover": function(d) { parcoords.highlight([d]) },
|
||||
"mouseover": function(d) {
|
||||
parcoords.highlight([d]);
|
||||
},
|
||||
"mouseout": parcoords.unhighlight
|
||||
});
|
||||
});
|
||||
@ -72,14 +78,14 @@ function parallelCoordVis(slice) {
|
||||
slice.done();
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
};
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
render: refresh,
|
||||
resize: refresh,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = parallelCoordVis;
|
||||
|
@ -1,28 +1,27 @@
|
||||
|
||||
var $ = window.$ = require('jquery');
|
||||
var jQuery = window.jQuery = $;
|
||||
|
||||
require('datatables');
|
||||
require('./pivot_table.css');
|
||||
require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css')
|
||||
require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css');
|
||||
|
||||
module.exports = function(slice) {
|
||||
var container = slice.container;
|
||||
var form_data = slice.data.form_data;
|
||||
|
||||
function refresh() {
|
||||
$.getJSON(slice.jsonEndpoint(), function(json){
|
||||
$.getJSON(slice.jsonEndpoint(), function(json) {
|
||||
container.html(json.data);
|
||||
if (form_data.groupby.length == 1){
|
||||
if (form_data.groupby.length == 1) {
|
||||
var table = container.find('table').DataTable({
|
||||
paging: false,
|
||||
searching: false,
|
||||
});
|
||||
table.column('-1').order( 'desc' ).draw();
|
||||
table.column('-1').order('desc').draw();
|
||||
}
|
||||
slice.done(json);
|
||||
}).fail(function(xhr){
|
||||
slice.error(xhr.responseText);
|
||||
}).fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
}
|
||||
return {
|
||||
|
@ -9,96 +9,133 @@ function sankeyVis(slice) {
|
||||
var div = d3.select(slice.selector);
|
||||
|
||||
var render = function() {
|
||||
var margin = {top: 5, right: 5, bottom: 5, left: 5};
|
||||
var width = slice.width() - margin.left - margin.right;
|
||||
var height = slice.height() - margin.top - margin.bottom;
|
||||
var margin = {
|
||||
top: 5,
|
||||
right: 5,
|
||||
bottom: 5,
|
||||
left: 5
|
||||
};
|
||||
var width = slice.width() - margin.left - margin.right;
|
||||
var height = slice.height() - margin.top - margin.bottom;
|
||||
|
||||
var formatNumber = d3.format(",.0f"),
|
||||
format = function(d) { return formatNumber(d) + " TWh"; };
|
||||
var formatNumber = d3.format(",.0f"),
|
||||
format = function(d) {
|
||||
return formatNumber(d) + " TWh";
|
||||
};
|
||||
|
||||
var svg = div.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
var svg = div.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
var sankey = d3.sankey()
|
||||
.nodeWidth(15)
|
||||
.nodePadding(10)
|
||||
.size([width, height]);
|
||||
var sankey = d3.sankey()
|
||||
.nodeWidth(15)
|
||||
.nodePadding(10)
|
||||
.size([width, height]);
|
||||
|
||||
var path = sankey.link();
|
||||
var path = sankey.link();
|
||||
|
||||
d3.json(slice.jsonEndpoint(), function(error, json) {
|
||||
if (error != null){
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
var links = json.data;
|
||||
var nodes = {};
|
||||
// Compute the distinct nodes from the links.
|
||||
links.forEach(function(link) {
|
||||
link.source = nodes[link.source] ||
|
||||
(nodes[link.source] = {name: link.source});
|
||||
link.target = nodes[link.target] ||
|
||||
(nodes[link.target] = {name: link.target});
|
||||
link.value = +link.value;
|
||||
});
|
||||
nodes = d3.values(nodes);
|
||||
|
||||
sankey
|
||||
.nodes(nodes)
|
||||
.links(links)
|
||||
.layout(32);
|
||||
|
||||
var link = svg.append("g").selectAll(".link")
|
||||
.data(links)
|
||||
.enter().append("path")
|
||||
.attr("class", "link")
|
||||
.attr("d", path)
|
||||
.style("stroke-width", function(d) { return Math.max(1, d.dy); })
|
||||
.sort(function(a, b) { return b.dy - a.dy; });
|
||||
|
||||
link.append("title")
|
||||
.text(function(d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); });
|
||||
|
||||
var node = svg.append("g").selectAll(".node")
|
||||
.data(nodes)
|
||||
.enter().append("g")
|
||||
.attr("class", "node")
|
||||
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
|
||||
.call(d3.behavior.drag()
|
||||
.origin(function(d) { return d; })
|
||||
.on("dragstart", function() { this.parentNode.appendChild(this); })
|
||||
.on("drag", dragmove));
|
||||
|
||||
node.append("rect")
|
||||
.attr("height", function(d) { return d.dy; })
|
||||
.attr("width", sankey.nodeWidth())
|
||||
.style("fill", function(d) { return d.color = px.color.category21(d.name.replace(/ .*/, "")); })
|
||||
.style("stroke", function(d) { return d3.rgb(d.color).darker(2); })
|
||||
.append("title")
|
||||
.text(function(d) { return d.name + "\n" + format(d.value); });
|
||||
|
||||
node.append("text")
|
||||
.attr("x", -6)
|
||||
.attr("y", function(d) { return d.dy / 2; })
|
||||
.attr("dy", ".35em")
|
||||
.attr("text-anchor", "end")
|
||||
.attr("transform", null)
|
||||
.text(function(d) { return d.name; })
|
||||
.filter(function(d) { return d.x < width / 2; })
|
||||
.attr("x", 6 + sankey.nodeWidth())
|
||||
.attr("text-anchor", "start");
|
||||
|
||||
function dragmove(d) {
|
||||
d3.select(this).attr("transform", "translate(" + d.x + "," + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")");
|
||||
sankey.relayout();
|
||||
link.attr("d", path);
|
||||
}
|
||||
slice.done(json);
|
||||
d3.json(slice.jsonEndpoint(), function(error, json) {
|
||||
if (error !== null) {
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
var links = json.data;
|
||||
var nodes = {};
|
||||
// Compute the distinct nodes from the links.
|
||||
links.forEach(function(link) {
|
||||
link.source = nodes[link.source] ||
|
||||
(nodes[link.source] = {
|
||||
name: link.source
|
||||
});
|
||||
link.target = nodes[link.target] ||
|
||||
(nodes[link.target] = {
|
||||
name: link.target
|
||||
});
|
||||
link.value = +link.value;
|
||||
});
|
||||
}
|
||||
nodes = d3.values(nodes);
|
||||
|
||||
sankey
|
||||
.nodes(nodes)
|
||||
.links(links)
|
||||
.layout(32);
|
||||
|
||||
var link = svg.append("g").selectAll(".link")
|
||||
.data(links)
|
||||
.enter().append("path")
|
||||
.attr("class", "link")
|
||||
.attr("d", path)
|
||||
.style("stroke-width", function(d) {
|
||||
return Math.max(1, d.dy);
|
||||
})
|
||||
.sort(function(a, b) {
|
||||
return b.dy - a.dy;
|
||||
});
|
||||
|
||||
link.append("title")
|
||||
.text(function(d) {
|
||||
return d.source.name + " → " + d.target.name + "\n" + format(d.value);
|
||||
});
|
||||
|
||||
var node = svg.append("g").selectAll(".node")
|
||||
.data(nodes)
|
||||
.enter().append("g")
|
||||
.attr("class", "node")
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + d.x + "," + d.y + ")";
|
||||
})
|
||||
.call(d3.behavior.drag()
|
||||
.origin(function(d) {
|
||||
return d;
|
||||
})
|
||||
.on("dragstart", function() {
|
||||
this.parentNode.appendChild(this);
|
||||
})
|
||||
.on("drag", dragmove));
|
||||
|
||||
node.append("rect")
|
||||
.attr("height", function(d) {
|
||||
return d.dy;
|
||||
})
|
||||
.attr("width", sankey.nodeWidth())
|
||||
.style("fill", function(d) {
|
||||
return d.color = px.color.category21(d.name.replace(/ .*/, ""));
|
||||
})
|
||||
.style("stroke", function(d) {
|
||||
return d3.rgb(d.color).darker(2);
|
||||
})
|
||||
.append("title")
|
||||
.text(function(d) {
|
||||
return d.name + "\n" + format(d.value);
|
||||
});
|
||||
|
||||
node.append("text")
|
||||
.attr("x", -6)
|
||||
.attr("y", function(d) {
|
||||
return d.dy / 2;
|
||||
})
|
||||
.attr("dy", ".35em")
|
||||
.attr("text-anchor", "end")
|
||||
.attr("transform", null)
|
||||
.text(function(d) {
|
||||
return d.name;
|
||||
})
|
||||
.filter(function(d) {
|
||||
return d.x < width / 2;
|
||||
})
|
||||
.attr("x", 6 + sankey.nodeWidth())
|
||||
.attr("text-anchor", "start");
|
||||
|
||||
function dragmove(d) {
|
||||
d3.select(this).attr("transform", "translate(" + d.x + "," + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")");
|
||||
sankey.relayout();
|
||||
link.attr("d", path);
|
||||
}
|
||||
slice.done(json);
|
||||
});
|
||||
};
|
||||
return {
|
||||
render: render,
|
||||
resize: render,
|
||||
|
@ -1,8 +1,7 @@
|
||||
require('./sunburst.css');
|
||||
|
||||
/*
|
||||
Modified from http://bl.ocks.org/kerryrodden/7090426
|
||||
*/
|
||||
// Modified from http://bl.ocks.org/kerryrodden/7090426
|
||||
|
||||
function sunburstVis(slice) {
|
||||
var container = d3.select(slice.selector);
|
||||
var render = function() {
|
||||
@ -27,18 +26,28 @@ function sunburstVis(slice) {
|
||||
|
||||
var partition = d3.layout.partition()
|
||||
.size([2 * Math.PI, radius * radius])
|
||||
.value(function(d) { return d.m1; });
|
||||
.value(function(d) {
|
||||
return d.m1;
|
||||
});
|
||||
|
||||
var arc = d3.svg.arc()
|
||||
.startAngle(function(d) { return d.x; })
|
||||
.endAngle(function(d) { return d.x + d.dx; })
|
||||
.innerRadius(function(d) { return Math.sqrt(d.y); })
|
||||
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
|
||||
.startAngle(function(d) {
|
||||
return d.x;
|
||||
})
|
||||
.endAngle(function(d) {
|
||||
return d.x + d.dx;
|
||||
})
|
||||
.innerRadius(function(d) {
|
||||
return Math.sqrt(d.y);
|
||||
})
|
||||
.outerRadius(function(d) {
|
||||
return Math.sqrt(d.y + d.dy);
|
||||
});
|
||||
|
||||
var ext;
|
||||
d3.json(slice.jsonEndpoint(), function(error, json){
|
||||
d3.json(slice.jsonEndpoint(), function(error, json) {
|
||||
|
||||
if (error != null){
|
||||
if (error !== null) {
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
@ -62,23 +71,29 @@ function sunburstVis(slice) {
|
||||
.filter(function(d) {
|
||||
return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
|
||||
});
|
||||
ext = d3.extent(nodes, function(d){return d.m2 / d.m1;});
|
||||
ext = d3.extent(nodes, function(d) {
|
||||
return d.m2 / d.m1;
|
||||
});
|
||||
|
||||
var colorScale = d3.scale.linear()
|
||||
.domain([ext[0], ext[0] + ((ext[1] - ext[0]) / 2), ext[1]])
|
||||
.range(["#00D1C1", "white","#FFB400"]);
|
||||
.domain([ext[0], ext[0] + ((ext[1] - ext[0]) / 2), ext[1]])
|
||||
.range(["#00D1C1", "white", "#FFB400"]);
|
||||
|
||||
var path = arcs.data([json]).selectAll("path")
|
||||
.data(nodes)
|
||||
.data(nodes)
|
||||
.enter().append("svg:path")
|
||||
.attr("display", function(d) { return d.depth ? null : "none"; })
|
||||
.attr("d", arc)
|
||||
.attr("fill-rule", "evenodd")
|
||||
.style("stroke", "grey")
|
||||
.style("stroke-width", "1px")
|
||||
.style("fill", function(d) { return colorScale(d.m2/d.m1); })
|
||||
.style("opacity", 1)
|
||||
.on("mouseenter", mouseenter);
|
||||
.attr("display", function(d) {
|
||||
return d.depth ? null : "none";
|
||||
})
|
||||
.attr("d", arc)
|
||||
.attr("fill-rule", "evenodd")
|
||||
.style("stroke", "grey")
|
||||
.style("stroke-width", "1px")
|
||||
.style("fill", function(d) {
|
||||
return colorScale(d.m2 / d.m1);
|
||||
})
|
||||
.style("opacity", 1)
|
||||
.on("mouseenter", mouseenter);
|
||||
|
||||
|
||||
// Add the mouseleave handler to the bounding circle.
|
||||
@ -86,7 +101,7 @@ function sunburstVis(slice) {
|
||||
|
||||
// Get total size of the tree = value of root node from partition.
|
||||
totalSize = path.node().__data__.value;
|
||||
};
|
||||
}
|
||||
var f = d3.format(".3s");
|
||||
var fp = d3.format(".3p");
|
||||
|
||||
@ -110,9 +125,10 @@ function sunburstVis(slice) {
|
||||
.classed("middle", true)
|
||||
.style("font-size", "15px")
|
||||
.attr("y", "50")
|
||||
.text("m2/m1: " + fp(d.m2/d.m1));
|
||||
.text("m2/m1: " + fp(d.m2 / d.m1));
|
||||
|
||||
var sequenceArray = getAncestors(d);
|
||||
|
||||
function breadcrumbPoints(d, i) {
|
||||
var points = [];
|
||||
points.push("0,0");
|
||||
@ -129,10 +145,10 @@ function sunburstVis(slice) {
|
||||
// Update the breadcrumb trail to show the current sequence and percentage.
|
||||
function updateBreadcrumbs(nodeArray, percentageString) {
|
||||
var l = [];
|
||||
for(var i=0; i<nodeArray.length; i++){
|
||||
l.push(nodeArray[i].name)
|
||||
for (var i = 0; i < nodeArray.length; i++) {
|
||||
l.push(nodeArray[i].name);
|
||||
}
|
||||
var s = l.join(' > ')
|
||||
var s = l.join(' > ');
|
||||
gMiddleText.append("text")
|
||||
.text(s)
|
||||
.classed("middle", true)
|
||||
@ -142,8 +158,8 @@ function sunburstVis(slice) {
|
||||
|
||||
// Fade all the segments.
|
||||
arcs.selectAll("path")
|
||||
.style("stroke-width", "1px")
|
||||
.style("opacity", 0.3);
|
||||
.style("stroke-width", "1px")
|
||||
.style("opacity", 0.3);
|
||||
|
||||
// Then highlight only those that are an ancestor of the current segment.
|
||||
arcs.selectAll("path")
|
||||
@ -193,25 +209,28 @@ function sunburstVis(slice) {
|
||||
}
|
||||
|
||||
function buildHierarchy(rows) {
|
||||
var root = {"name": "root", "children": []};
|
||||
var root = {
|
||||
"name": "root",
|
||||
"children": []
|
||||
};
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
var m1 = +row[row.length-2];
|
||||
var m2 = +row[row.length-1];
|
||||
var parts = row.slice(0, row.length-2);
|
||||
var m1 = +row[row.length - 2];
|
||||
var m2 = +row[row.length - 1];
|
||||
var parts = row.slice(0, row.length - 2);
|
||||
if (isNaN(m1)) { // e.g. if this is a header row
|
||||
continue;
|
||||
}
|
||||
var currentNode = root;
|
||||
for (var j = 0; j < parts.length; j++) {
|
||||
var children = currentNode["children"];
|
||||
var children = currentNode.children;
|
||||
var nodeName = parts[j];
|
||||
var childNode;
|
||||
if (j + 1 < parts.length) {
|
||||
// Not yet at the end of the sequence; move down the tree.
|
||||
var foundChild = false;
|
||||
for (var k = 0; k < children.length; k++) {
|
||||
if (children[k]["name"] == nodeName) {
|
||||
if (children[k].name == nodeName) {
|
||||
childNode = children[k];
|
||||
foundChild = true;
|
||||
break;
|
||||
@ -219,40 +238,48 @@ function sunburstVis(slice) {
|
||||
}
|
||||
// If we don't already have a child node for this branch, create it.
|
||||
if (!foundChild) {
|
||||
childNode = {"name": nodeName, "children": []};
|
||||
childNode = {
|
||||
"name": nodeName,
|
||||
"children": []
|
||||
};
|
||||
children.push(childNode);
|
||||
}
|
||||
currentNode = childNode;
|
||||
} else {
|
||||
// Reached the end of the sequence; create a leaf node.
|
||||
childNode = {"name": nodeName, "m1": m1, 'm2': m2};
|
||||
childNode = {
|
||||
"name": nodeName,
|
||||
"m1": m1,
|
||||
'm2': m2
|
||||
};
|
||||
children.push(childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
function recurse(node){
|
||||
if (node.children){
|
||||
|
||||
function recurse(node) {
|
||||
if (node.children) {
|
||||
var sums;
|
||||
var m1 = 0;
|
||||
var m2 = 0;
|
||||
for (var i=0; i<node.children.length; i++){
|
||||
for (var i = 0; i < node.children.length; i++) {
|
||||
sums = recurse(node.children[i]);
|
||||
m1 += sums[0];
|
||||
m2 += sums[1];
|
||||
}
|
||||
node['m1'] = m1;
|
||||
node['m2'] = m2;
|
||||
node.m1 = m1;
|
||||
node.m2 = m2;
|
||||
}
|
||||
return [node['m1'], node['m2']]
|
||||
return [node.m1, node.m2];
|
||||
}
|
||||
recurse(root);
|
||||
return root;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
return {
|
||||
render: render,
|
||||
resize: render,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = sunburstVis;
|
||||
|
@ -4,7 +4,7 @@ var jQuery = window.jQuery = $;
|
||||
require('datatables');
|
||||
// CSS
|
||||
require('./table.css');
|
||||
require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css')
|
||||
require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css');
|
||||
|
||||
function tableVis(slice) {
|
||||
var data = slice.data;
|
||||
@ -13,18 +13,19 @@ function tableVis(slice) {
|
||||
var fC = d3.format('0,000');
|
||||
|
||||
function refresh() {
|
||||
$.getJSON(slice.jsonEndpoint(), function(json){
|
||||
$.getJSON(slice.jsonEndpoint(), function(json) {
|
||||
var data = json.data;
|
||||
var metrics = json.form_data.metrics;
|
||||
function col(c){
|
||||
|
||||
function col(c) {
|
||||
var arr = [];
|
||||
for (var i=0; i<data.records.length; i++){
|
||||
for (var i = 0; i < data.records.length; i++) {
|
||||
arr.push(json.data.records[i][c]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
var maxes = {};
|
||||
for (var i=0; i<metrics.length; i++){
|
||||
for (var i = 0; i < metrics.length; i++) {
|
||||
maxes[metrics[i]] = d3.max(col(metrics[i]));
|
||||
}
|
||||
|
||||
@ -32,60 +33,65 @@ function tableVis(slice) {
|
||||
.classed('dataframe dataframe table table-striped table-bordered table-condensed table-hover dataTable no-footer', true);
|
||||
|
||||
table.append('thead').append('tr')
|
||||
.selectAll('th')
|
||||
.data(data.columns).enter()
|
||||
.append('th')
|
||||
.text(function(d){return d});
|
||||
.selectAll('th')
|
||||
.data(data.columns).enter()
|
||||
.append('th')
|
||||
.text(function(d) {
|
||||
return d;
|
||||
});
|
||||
|
||||
table.append('tbody')
|
||||
.selectAll('tr')
|
||||
.data(data.records).enter()
|
||||
.append('tr')
|
||||
.selectAll('td')
|
||||
.data(function(row, i) {
|
||||
.selectAll('tr')
|
||||
.data(data.records).enter()
|
||||
.append('tr')
|
||||
.selectAll('td')
|
||||
.data(function(row, i) {
|
||||
return data.columns.map(function(c) {
|
||||
return {col: c, val: row[c], isMetric: metrics.indexOf(c) >=0};
|
||||
return {
|
||||
col: c,
|
||||
val: row[c],
|
||||
isMetric: metrics.indexOf(c) >= 0
|
||||
};
|
||||
});
|
||||
}).enter()
|
||||
.append('td')
|
||||
.style('background-image', function(d){
|
||||
if (d.isMetric){
|
||||
}).enter()
|
||||
.append('td')
|
||||
.style('background-image', function(d) {
|
||||
if (d.isMetric) {
|
||||
var perc = Math.round((d.val / maxes[d.col]) * 100);
|
||||
return "linear-gradient(to right, lightgrey, lightgrey " + perc + "%, rgba(0,0,0,0) " + perc + "%";
|
||||
}
|
||||
})
|
||||
.attr('title', function(d){
|
||||
if (!isNaN(d.val))
|
||||
return fC(d.val);
|
||||
})
|
||||
.attr('data-sort', function(d){
|
||||
})
|
||||
.attr('title', function(d) {
|
||||
if (!isNaN(d.val))
|
||||
return fC(d.val);
|
||||
})
|
||||
.attr('data-sort', function(d) {
|
||||
if (d.isMetric)
|
||||
return d.val;
|
||||
})
|
||||
.on("click", function(d){
|
||||
if(!d.isMetric){
|
||||
})
|
||||
.on("click", function(d) {
|
||||
if (!d.isMetric) {
|
||||
var td = d3.select(this);
|
||||
if (td.classed('filtered')){
|
||||
slice.clearFilter(d.col, [d.val]);
|
||||
table.selectAll('.filtered').classed('filtered', false);
|
||||
if (td.classed('filtered')) {
|
||||
slice.removeFilter(d.col, [d.val]);
|
||||
d3.select(this).classed('filtered', false);
|
||||
} else {
|
||||
table.selectAll('.filtered').classed('filtered', false);
|
||||
d3.select(this).classed('filtered', true);
|
||||
slice.addFilter([[d.col, [d.val]]]);
|
||||
slice.addFilter(d.col, [d.val]);
|
||||
}
|
||||
}
|
||||
})
|
||||
.style("cursor", function(d){
|
||||
if(!d.isMetric){
|
||||
return 'pointer';
|
||||
}
|
||||
})
|
||||
.html(function(d){
|
||||
})
|
||||
.style("cursor", function(d) {
|
||||
if (!d.isMetric) {
|
||||
return 'pointer';
|
||||
}
|
||||
})
|
||||
.html(function(d) {
|
||||
if (d.isMetric)
|
||||
return f(d.val);
|
||||
else
|
||||
return d.val;
|
||||
});
|
||||
});
|
||||
var datatable = slice.container.find('.dataTable').DataTable({
|
||||
paging: false,
|
||||
searching: form_data.include_search,
|
||||
@ -93,19 +99,19 @@ function tableVis(slice) {
|
||||
// Sorting table by main column
|
||||
if (form_data.metrics.length > 0) {
|
||||
var main_metric = form_data.metrics[0];
|
||||
datatable.column(data.columns.indexOf(main_metric)).order( 'desc' ).draw();
|
||||
datatable.column(data.columns.indexOf(main_metric)).order('desc').draw();
|
||||
}
|
||||
slice.done(json);
|
||||
slice.container.parents('.widget').find('.tooltip').remove();
|
||||
}).fail(function(xhr){
|
||||
}).fail(function(xhr) {
|
||||
slice.error(xhr.responseText);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
render: refresh,
|
||||
resize: function(){},
|
||||
resize: function() {},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = tableVis;
|
||||
|
@ -3,11 +3,11 @@ var d3 = window.d3 || require('d3');
|
||||
var cloudLayout = require('d3-cloud');
|
||||
|
||||
function wordCloudChart(slice) {
|
||||
var slice = slice;
|
||||
var chart = d3.select(slice.selector);
|
||||
|
||||
function refresh() {
|
||||
d3.json(slice.jsonEndpoint(), function(error, json) {
|
||||
if (error != null){
|
||||
if (error !== null) {
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
@ -17,20 +17,27 @@ function wordCloudChart(slice) {
|
||||
json.form_data.size_to,
|
||||
];
|
||||
var rotation = json.form_data.rotation;
|
||||
var f_rotation;
|
||||
if (rotation == "square") {
|
||||
var f_rotation = function() { return ~~(Math.random() * 2) * 90; };
|
||||
}
|
||||
else if (rotation == "flat") {
|
||||
var f_rotation = function() { return 0 };
|
||||
}
|
||||
else {
|
||||
var f_rotation = function() { return (~~(Math.random() * 6) - 3) * 30; };
|
||||
f_rotation = function() {
|
||||
return ~~(Math.random() * 2) * 90;
|
||||
};
|
||||
} else if (rotation == "flat") {
|
||||
f_rotation = function() {
|
||||
return 0;
|
||||
};
|
||||
} else {
|
||||
f_rotation = function() {
|
||||
return (~~(Math.random() * 6) - 3) * 30;
|
||||
};
|
||||
}
|
||||
var size = [slice.width(), slice.height()];
|
||||
|
||||
var scale = d3.scale.linear()
|
||||
.range(range)
|
||||
.domain(d3.extent(data, function(d) { return d.size; }));
|
||||
.domain(d3.extent(data, function(d) {
|
||||
return d.size;
|
||||
}));
|
||||
|
||||
var layout = cloudLayout()
|
||||
.size(size)
|
||||
@ -38,7 +45,9 @@ function wordCloudChart(slice) {
|
||||
.padding(5)
|
||||
.rotate(f_rotation)
|
||||
.font("serif")
|
||||
.fontSize(function(d) { return scale(d.size); })
|
||||
.fontSize(function(d) {
|
||||
return scale(d.size);
|
||||
})
|
||||
.on("end", draw);
|
||||
|
||||
layout.start();
|
||||
@ -47,21 +56,27 @@ function wordCloudChart(slice) {
|
||||
chart.selectAll("*").remove();
|
||||
|
||||
chart.append("svg")
|
||||
.attr("width", layout.size()[0])
|
||||
.attr("height", layout.size()[1])
|
||||
.attr("width", layout.size()[0])
|
||||
.attr("height", layout.size()[1])
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + layout.size()[0] / 2 + "," + layout.size()[1] / 2 + ")")
|
||||
.attr("transform", "translate(" + layout.size()[0] / 2 + "," + layout.size()[1] / 2 + ")")
|
||||
.selectAll("text")
|
||||
.data(words)
|
||||
.enter().append("text")
|
||||
.style("font-size", function(d) { return d.size + "px"; })
|
||||
.style("font-family", "Impact")
|
||||
.style("fill", function(d, i) {return px.color.category21(d.text); })
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + [d.x, d.y] + ") rotate(" + d.rotate + ")";
|
||||
})
|
||||
.text(function(d) { return d.text; });
|
||||
.data(words)
|
||||
.enter().append("text")
|
||||
.style("font-size", function(d) {
|
||||
return d.size + "px";
|
||||
})
|
||||
.style("font-family", "Impact")
|
||||
.style("fill", function(d, i) {
|
||||
return px.color.category21(d.text);
|
||||
})
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + [d.x, d.y] + ") rotate(" + d.rotate + ")";
|
||||
})
|
||||
.text(function(d) {
|
||||
return d.text;
|
||||
});
|
||||
}
|
||||
slice.done(data);
|
||||
});
|
||||
|
@ -13,31 +13,35 @@ function worldMapChart(slice) {
|
||||
|
||||
container.css('height', slice.height());
|
||||
|
||||
d3.json(slice.jsonEndpoint(), function(error, json){
|
||||
d3.json(slice.jsonEndpoint(), function(error, json) {
|
||||
var fd = json.form_data;
|
||||
|
||||
if (error != null){
|
||||
if (error !== null) {
|
||||
slice.error(error.responseText);
|
||||
return '';
|
||||
}
|
||||
var ext = d3.extent(json.data, function(d){return d.m1});
|
||||
var extRadius = d3.extent(json.data, function(d){return d.m2});
|
||||
var ext = d3.extent(json.data, function(d) {
|
||||
return d.m1;
|
||||
});
|
||||
var extRadius = d3.extent(json.data, function(d) {
|
||||
return d.m2;
|
||||
});
|
||||
var radiusScale = d3.scale.linear()
|
||||
.domain([extRadius[0], extRadius[1]])
|
||||
.range([1, fd.max_bubble_size]);
|
||||
|
||||
json.data.forEach(function(d){
|
||||
d.radius = radiusScale(d.m2);
|
||||
});
|
||||
json.data.forEach(function(d) {
|
||||
d.radius = radiusScale(d.m2);
|
||||
});
|
||||
|
||||
var colorScale = d3.scale.linear()
|
||||
.domain([ext[0], ext[1]])
|
||||
.range(["#FFF", "black"]);
|
||||
|
||||
var d = {};
|
||||
for (var i=0; i<json.data.length; i++){
|
||||
for (var i = 0; i < json.data.length; i++) {
|
||||
var country = json.data[i];
|
||||
country['fillColor'] = colorScale(country.m1);
|
||||
country.fillColor = colorScale(country.m1);
|
||||
d[country.country] = country;
|
||||
}
|
||||
|
||||
@ -60,7 +64,7 @@ function worldMapChart(slice) {
|
||||
highlightFillColor: '#005a63',
|
||||
highlightBorderWidth: 1,
|
||||
popupTemplate: function(geo, data) {
|
||||
return '<div class="hoverinfo"><strong>' + data.name + '</strong><br>'+ f(data.m1) + '</div>';
|
||||
return '<div class="hoverinfo"><strong>' + data.name + '</strong><br>' + f(data.m1) + '</div>';
|
||||
},
|
||||
},
|
||||
bubblesConfig: {
|
||||
@ -70,7 +74,7 @@ function worldMapChart(slice) {
|
||||
popupOnHover: true,
|
||||
radius: null,
|
||||
popupTemplate: function(geo, data) {
|
||||
return '<div class="hoverinfo"><strong>' + data.name + '</strong><br>'+ f(data.m2) + '</div>';
|
||||
return '<div class="hoverinfo"><strong>' + data.name + '</strong><br>' + f(data.m2) + '</div>';
|
||||
},
|
||||
fillOpacity: 0.5,
|
||||
animate: true,
|
||||
@ -95,7 +99,7 @@ function worldMapChart(slice) {
|
||||
slice.done(json);
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
render: render,
|
||||
|
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="small_table">{{ dataset.database }}</td>
|
||||
<td class="small_table">{{ dataset.owner }}</td>
|
||||
<td class="small_table">{{ dataset.owner or '' }}</td>
|
||||
<td class="small_table"><a class="btn btn-default" href="{{ dataset.default_endpoint }}"><i class='fa fa-line-chart'/></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -156,15 +156,13 @@ class BaseViz(object):
|
||||
filters.append((col, op, eq))
|
||||
|
||||
# Extra filters (coming from dashboard)
|
||||
extra_filters = form_data.get('extra_filters', [])
|
||||
extra_filters = form_data.get('extra_filters')
|
||||
if extra_filters:
|
||||
extra_filters = json.loads(extra_filters)
|
||||
for slice_filters in extra_filters.values():
|
||||
if slice_filters:
|
||||
for col, vals in slice_filters:
|
||||
if col and vals:
|
||||
filters += [(col, 'in', ",".join(vals))]
|
||||
|
||||
for col, vals in slice_filters.items():
|
||||
if col and vals:
|
||||
filters += [(col, 'in', ",".join(vals))]
|
||||
return filters
|
||||
|
||||
def query_obj(self):
|
||||
|
Loading…
Reference in New Issue
Block a user