How Can I append text to c3.js regions? I have three regions in my chart and I would like to append three different texts to them. So far I have tried to use d3.js but with no success
var rectOffset = (( d3.select(this).attr("x") ) * 1) + 25;
d3.selectAll(".c3-region-0 rect")
.append("text")
.text("Some Text")
.attr("dy","15px")
.attr("dx",rectOffset+"px")
I get an error
TypeError: Cannot read property 'getAttribute' of null
at Array.d3_selectionPrototype.attr (d3.js:578)
jsfiddle
code:
var chart = c3.generate({
bindto: '#chart',
data: {
x: 'x',
columns: [
["x", "2016-01-04", "2016-01-05", "2016-01-06", "2016-01-07", "2016-01-08", "2016-01-09", "2016-01-10", "2016-01-11", "2016-01-12", "2016-01-13", "2016-01-14", "2016-01-15", "2016-01-16", "2016-01-17", "2016-01-18", "2016-01-19", "2016-01-20", "2016-01-21", "2016-01-22", "2016-01-23", "2016-01-24", "2016-01-25", "2016-01-26", "2016-01-27", "2016-01-28", "2016-01-29", "2016-01-30", "2016-01-31", "2016-02-01", "2016-02-02", "2016-02-03"],
["Democrates", 49.85, 49.89, 49.82, 49.51, 49.42, 49.33, 49.24, 49.64, 49.57, 49.57, 49.01, 48.67, 48.7, 48.7, 48.7, 48.63, 48.63, 48.63, 48.63, 48.63, 48.61, 48.61, 48.68, 48.76, 48.84, 48.73, 48.76, 48.79, 48.81, 49.68, 49.63],
["Republicans", "50.15", "50.11", "50.18", "50.49", "50.58", "50.67", "50.76", "50.36", "50.43", "50.43", "50.99", "51.33", "51.30", "51.30", "51.30", "51.37", "51.37", "51.37", "51.37", "51.37", "51.39", "51.39", "51.32", "51.24", "51.16", "51.27", "51.24", "51.21", "51.19", "50.32", "50.37"]
],
colors: {
Democrates: '#4575b4',
Republicans: '#d73027'
},
},
axis: {
x: {
type: 'timeseries',
max: '2016-11-08',
tick: {
values: ["2016-02-01", "2016-06-14", "2016-11-08", "2016-09-26", "2016-10-19", "2016-07-18", "2016-07-28" ],
format: function (x) {
if (x == "Mon Feb 01 2016 00:00:00 GMT+0100 (CET)"){
return 'Feb 01' + 'Primaries and Caucuses '
} else if (x == "Tue Nov 08 2016 00:00:00 GMT+0100 (CET)") {
return 'Nov 08 Election Day'
} else if (x == "Mon Sep 26 2016 00:00:00 GMT+0200 (CEST)") {
return ' Sep 26 Start of Presidential Debates'
} else if (x == "Mon Jul 18 2016 00:00:00 GMT+0200 (CEST)") {
return 'Jul 25 Announcement of Nominees'
} else {
var format= d3.time.format("%b %d");
var date = format(x)
return date
}},
fit: false
}
}
},
grid: {
y: {
lines: [
{value: 50},
]
},
x: {
lines: [
{value: "2016-01-08", text: "Want to rorate this text in 180 degrees",
class: "xLineLable", position: "end"}
]
}
},
regions: [
{axis: 'x', start: "2016-02-01", end: "2016-06-14", class: 'regionX'},
{axis: 'x', start: "2016-07-18", end: "2016-07-28", class: 'regionX'},
{axis: 'x', start: "2016-09-26", end: "2016-10-19", class: 'regionX'}
]
});
You can't add text to a rect, you'll need to add it as a sibling element under the c3-region group element, which is a bit of a pain in d3 (and rectoffset needs to be a function, or the d3.select(this) gets the top-level dom node). In rectOffset I select the text's parentNode, then grab it's rect child node.
There were a couple of other gotchas that stopped the text turning up that I didn't expect.. attr always returns a string so .attr(x)+25 would return "75"+25 -> 7525, needed to cast to a number with '+'... I ended up using text-anchor instead anyways. Plus the fill-opacity needed to be adjusted for the text to be seen even when in the right spot. That had me flummoxed for a while.
var rectOffset = function () { return +d3.select(this.parentNode).select("rect").attr("x"); };
d3.selectAll(".c3-region-0")
.append("text")
.text("Some Text")
.attr("dy","15")
.attr("dx",rectOffset)
.style("fill-opacity", 1)
.attr("text-anchor", "start")
;
http://jsfiddle.net/yrzxj3x2/35/
Related
I have a slots collection.
Whose response is given below:
{
"_id" : ObjectId("5e32e55c9c058304f71eab70"),
"date" : ISODate("2020-07-27T00:00:00.000Z"),
"dayOfWeek" : 1,
"startTime" : 600,
"isBooked" : false,
"isClosed" : false
},
{
"_id" : ObjectId("5e32e55c9c058304f71eab71"),
"date" : ISODate("2020-07-27T00:00:00.000Z"),
"dayOfWeek" : 1,
"startTime" : 615,
"isBooked" : false,
"isClosed" : false
},
{
"_id" : ObjectId("5e32e55c9c058304f71eab72"),
"date" : ISODate("2020-07-27T00:00:00.000Z"),
"dayOfWeek" : 1,
"startTime" : 630,
"isBooked" : true,
"isClosed" : true
},
{
"_id" : ObjectId("5e32e55c9c058304f71eab73"),
"date" : ISODate("2020-07-27T00:00:00.000Z"),
"dayOfWeek" : 1,
"startTime" : 645,
"isBooked" : false,
"isClosed" : false
}
I have an array of startTime like:
[ 615, 630 ]
And I want to get all selected value not any one. I want to get all slots for 615, 630.
If any one slot is not available than I don't need those results.
Here are my queries: (with $all)
db.slots.find({ isBooked: false, isClosed: false, date: { $gte: new Date("Mon, 27 Jul 2020 00:00:00 GMT"), $lte: new Date("Mon, 27 Jul 2020 00:00:00 GMT") }, startTime: { $all: [ 615, 630 ] } })
It gives nothing. I know why? (It's only for testing)
With $in:
db.slots.find({ isBooked: false, isClosed: false, date: { $gte: new Date("Mon, 27 Jul 2020 00:00:00 GMT"), $lte: new Date("Mon, 27 Jul 2020 00:00:00 GMT") }, startTime: { $in: [ 615, 630 ] } })
It gives one record.
{
"_id" : ObjectId("5e32e55c9c058304f71eab71"),
"date" : ISODate("2020-07-27T00:00:00.000Z"),
"dayOfWeek" : 1,
"startTime" : 615,
"isBooked" : false,
"isClosed" : false
}
If 615 and 630 records available than I get both records otherwise I don't need this one record. I want complete set of [ 615, 630 ] records.
I don't know it is possible with just find(), but it is possible with aggregate(), there are many ways in aggregation but i am suggesting one of them,
get records in c1 for your first condition [ 615, 630 ]
get records in c2 for your first and second other conditions
db.getCollection('datetime').aggregate([
{
$facet: {
// will create a array of your first matching condition
c1: [
{
$match: {
startTime: { $in: [ 615, 630 ] }
}
}
],
// will create a array of your second matching condition
c2: [
{
$match: {
startTime: { $in: [ 615, 630 ] },
isBooked: false,
isClosed: false,
date: {
$gte: new Date("Mon, 27 Jul 2020 00:00:00 GMT"),
$lte: new Date("Mon, 27 Jul 2020 00:00:00 GMT")
}
}
}
]
}
},
condition will check both c1 and c2 are same then return one of them otherwise blank array in result key.
{
$project: {
result: {
$cond: [
// check condition if both are same then then return one of them otherwise empty
{ $setEquals: ["$c1", "$c2"]},
"$c1",
[]
]
}
}
},
unwind result because we need to replace result in root
replace result in root
// unwind main result because it is array
{ $unwind: "$result" },
// replace your unwind result in root it will make multiple object
{
$replaceRoot: {
newRoot: "$result"
}
}
])
For the explanation purpose i have divided in to parts, you can merge easily as all are in sequence.
Working playground: https://mongoplayground.net/p/dxZN9TMlR61
I have this code about custom search with daterange picker.
But when i cek this code with alert, part of $.fn.dataTable.ext.search.push not execute
$('.input-daterange-datepicker').on('apply.daterangepicker', function(ev, picker) {
var start = picker.startDate;
var end = picker.endDate;
alert(start); //Can display
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
alert('hahahahahaah'); //Can't display
console.log(settings.nTable.id);
if ( settings.nTable.id !== 'donatur' ) {
return true;
}
var min = start;
var max = end;
var startDate = new Date(data[0]);
alert(startDate);
if (min == null && max == null) {
return true;
}
if (min == null && startDate <= max) {
return true;
}
if (max == null && startDate >= min) {
return true;
}
if (startDate <= max && startDate >= min) {
return true;
}
return false;
}
);
donatur.draw();
$.fn.dataTable.ext.search.pop();
});
var donatur = $("#donatur").DataTable({
"ajaxSource": base_url+"admin/getDonaturFundraiser/"+parameter,
"columns": [
{ "data": "tanggal_ambil" },
{ "data": "id" },
{ "data": "nama" },
{ "data": "jenis" },
{ "data": "donasi" },
{ "data": "tanggal" },
{ data: null, render: function ( data, type, row ) {
return '<button type="button" data-id="'+data.id+'" data-nama="'+data.nama+'" data-jenis="'+data.jenis+'" data-donasi="'+data.donasi+'" class="btn btn-primary" data-toggle="modal" data-target="#modalDonatur"><i class="fa fa-pencil"></i></button> | <button class="btn btn-danger sa-warning" id="'+data.id+'"><i class="fa fa-trash"></i></button>'
} }
]
});
My code reference Filter datatable with date range
Have you included the external dependencies? See for example this link: https://jsfiddle.net/ankepv5v/79/
HTML code:
<body>
<div id="reportrange" class="btn btn-success btn-lg">
<span></span> <b class="caret"></b>
</div>
<hr>
<br>
<table id="example" class="table table-striped" cellspacing="0" width="100%"></table>
</body>
Javascript code:
$(document).ready(function() {
$(function() {
var start = moment("2017-01-01 12:34:16");
var end = moment("2018-03-03 10:08:07");
function cb(start, end) {
$('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
}
}, cb);
cb(start, end);
});
$('#reportrange').on('apply.daterangepicker', function(ev, picker) {
var start = picker.startDate;
var end = picker.endDate;
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
var min = start;
var max = end;
var startDate = new Date(data[1]);
if (min == null && max == null) {
return true;
}
if (min == null && startDate <= max) {
return true;
}
if (max == null && startDate >= min) {
return true;
}
if (startDate <= max && startDate >= min) {
return true;
}
return false;
}
);
table.draw();
$.fn.dataTable.ext.search.pop();
});
var dataSet = [
['2093',
'Feb 23, 2018',
'asd asd ',
'asd#hotmail.com',
'£ 50',
'£0.00',
"Feb 23, 2019",
],
['2092',
'Feb 23, 2018',
'asddd asddd',
'dddd#hotmail.com',
'£ 50',
'£0.00',
"Feb 23, 2019",
],
['2050',
'Feb 20, 2018',
'Angus Fret',
'angus#fgf.co.uk',
'£ 50',
'£0.00',
"Feb 20, 2019",
],
['2048',
'Feb 19, 2018',
'John Smith',
'john#smith.com',
'£ 50',
'£0.00',
"Feb 19, 2019",
],
['2046',
'Feb 19, 2018',
'Ana Ana',
'ana#talktalk.net',
'£ 50',
'£0.00',
"Feb 19, 2019",
],
['2045',
'Feb 19, 2018',
'Ray N',
'rayn#nn.com',
'£ 50',
'£0.00',
"Feb 19, 2019",
],
['2044',
'Feb 16, 2018',
'Paul N',
'paul#gmail.com',
'£ 200',
'£0.00',
"Feb 16, 2019",
],
['2042',
'Feb 13, 2018',
'Bradley New',
'new-marden#hotmail.com',
'£ 100',
'£0.00',
"Feb 13, 2019",
],
['2012',
'Jan 27, 2018',
'Mark Zuckenberg',
'markzeg#me.com',
'£ 150',
'£0.00',
"Jan 27, 2019",
],
];
var table = $('#example').DataTable({
"order": [
[0, "desc"]
],
lengthChange: false,
data: dataSet,
columns: [{
title: "ORDER ID"
},
{
title: "ORDER DATE"
},
{
title: "PURCHASED BY"
},
{
title: "RECIPIENT"
},
{
title: "ORDER TOTAL"
},
{
title: "VAT"
},
{
title: "EXPIRY"
}
]
});
});
On the left side of the JsFiddle page, there is "Resources". Click on Resources to see the external javascript dependencies. You can see them in the below image:
Please test again your solution, right click on the page and select "Inspect". Go to the "console" tab and see if there are Javascript issues. https://developers.google.com/web/tools/chrome-devtools/javascript
SECOND SOLUTION
Try the following code:
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
alert('hahahahahaah'); //Can't display
console.log(settings.nTable.id);
if ( settings.nTable.id !== 'donatur' ) {
return true;
}
var min = start;
var max = end;
var startDate = new Date(data[0]);
alert(startDate);
if (min == null && max == null) {
return true;
}
if (min == null && startDate <= max) {
return true;
}
if (max == null && startDate >= min) {
return true;
}
if (startDate <= max && startDate >= min) {
return true;
}
return false;
}
);
$('.input-daterange-datepicker').on('apply.daterangepicker', function(ev, picker) {
var start = picker.startDate;
var end = picker.endDate;
alert(start); //Can display
donatur.draw();
$.fn.dataTable.ext.search.pop();
});
I have an object
{
YHOO: [
{
date: Fri Apr 12 1996 00:00:00 GMT-0400 (EDT),
open: 25.25,
high: 43,
low: 24.5,
close: 33,
volume: 408720000,
adjClose: 1.38,
symbol: 'YHOO'
},
...
{
date: Thu Nov 14 2013 00:00:00 GMT-0500 (EST),
open: 35.07,
high: 35.89,
low: 34.76,
close: 35.69,
volume: 21368600,
adjClose: 35.69,
symbol: 'YHOO'
}
],
GOOGL: [
{
date: Thu Aug 19 2004 00:00:00 GMT-0400 (EDT),
open: 100,
high: 104.06,
low: 95.96,
close: 100.34,
volume: 22351900,
adjClose: 100.34,
symbol: 'GOOGL'
},
...
{
date: Thu Nov 14 2013 00:00:00 GMT-0500 (EST),
open: 1033.92,
high: 1039.75,
low: 1030.35,
close: 1035.23,
volume: 1166700,
adjClose: 1035.23,
symbol: 'GOOGL'
}
],
...
}
How do I alter this object so it becomes an array with
[
{
date: Fri Apr 12 1996 00:00:00 GMT-0400 (EDT),
YHOO: 33,
GOOG: 100.34
},
...
]
I know it can become a problem that they potentially not have the same dates, so I guess I should just say that one of the companies have the right dates, and then merge the other companies to these dates and omit those dates that are not in the already selected company.
I guess I should do something like
var data = [];
obj.YHOO.forEach((quote) => {
data.push({
date: quote.date,
YHOO: quote.price,
GOOG: ?
});
});
and instead of the question mark, I can loop through all the objects in array.GOOG and check if the date matches quote.date.
The big problem is that this seems quite computational heavy and the names of the companies can vary, so I cannot guarantee that YHOO and GOOG are present.
I am not very conversant with javascript.I have a jquery datatable loaded using an ajax call as follows:
$('#table').dataTable( {
"processing": true,
"serverSide": true,
"ajax": "http://api.mywebsite.com/report",
"columns": [
{ "data": "date" },
{ "data": "ordernumber" },
{ "data": "totalsales" },
{ "data": "subtotal" }
]
} );
I want to load the dataTable together with a Google chart but I have no clue how to get the data object from above dataTable initialization to the the Google code below and trigger the same routine every time the datable is re-populated:
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Date', 'Sales'],
['20 Jan - Feb 04', 10340 ],
['20 Feb - Mar 05', 23470 ],
['20 June - Dec 06', 450 ],
['20 Mar - Aug 07', 3030 ]
]);
var options = {
title: 'Company Performance'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
Is there a way I can replace below
`['Date', 'Sales'],
['20 Jan - Feb 04', 10340 ],
['20 Feb - Mar 05', 23470 ],
['20 June - Dec 06', 450 ],
['20 Mar - Aug 07', 3030 ]`
with something like:
dataTable.data[date]
This is quite easy. I notice you are using dataTables 1.10.x, and then you can use the API to iterate over each row, and build up a data array google visualization will use :
$("#buildChart").click(function() {
var dataArray = [];
dataArray.push([ 'date', 'totalsales' ]);
table.rows().data().each(function(value, index) {
dataArray.push([ value.date, value.totalsales ]);
});
drawChart(dataArray);
});
and the called drawChart function is pretty much like the one in your question :
function drawChart(dataArray) {
var data = google.visualization.arrayToDataTable(dataArray);
var options = {
title: 'dataTables to google visualization'
};
var chart = new google.visualization.LineChart(document.getElementById('chart'));
chart.draw(data, options);
}
see demo using your data -> http://jsfiddle.net/9wvvh8sk/
I have the following
<div id="chart"></div>
<script src="js/flot/jquery.flot.js"></script>
<script src="js/flot/jquery.flot.tooltip.min.js"></script>
<script src="js/flot/jquery.flot.resize.js"></script>
var sessions = [
[1418706000000, 14813],
[1418792400000, 39580],
[1418878800000, 51193],
[1418965200000, 66700],
[1419051600000, 108737],
[1419138000000, 101081],
[1419224400000, 94449],
[1419310800000, 109039],
[1419397200000, 92329],
[1419483600000, 68942],
[1419570000000, 75391],
[1419656400000, 120016],
[1419742800000, 132495],
[1419829200000, 103469],
[1419915600000, 88940],
[1420002000000, 59938],
[1420088400000, 72359],
[1420174800000, 74663]
];
var users = [
[1418706000000, 2632],
[1418792400000, 9588],
[1418878800000, 9273],
[1418965200000, 10839],
[1419051600000, 14948],
[1419138000000, 11226],
[1419224400000, 13394],
[1419310800000, 10493],
[1419397200000, 8482],
[1419483600000, 2375],
[1419570000000, 5783],
[1419656400000, 10068],
[1419742800000, 8288],
[1419829200000, 5423],
[1419915600000, 4866],
[1420002000000, 1862],
[1420088400000, 5560],
[1420174800000, 1257]
];
function doPlot(position) {
$.plot($("#chart"), [{
data: sessions,
label: "Sessions"
}, {
data: revenue,
label: "Revenue",
yaxis: 2
}], {
xaxes: [{
mode: 'time'
}],
yaxes: [{
min: 0
}, {
alignTicksWithAxis: position == "right" ? 1 : null,
position: position
}],
legend: {
position: 'sw'
},
grid: {
hoverable: true
},
tooltip: true,
tooltipOpts: {
content: "%s for %x was %y",
xDateFormat: "%y-%0m-%0d",
onHover: function (flotItem, $tooltipEl) {
}
}
});
}
doPlot("right");
Thhis displays figures for both sessions and users on dates that there isn't even data for. The last date that there is data for is Dec 27th. Yet, this line graph shows data for up until Jan 2nd.
Here is a working example here
Any ideas?
According to your last data entry in each array element time = 1420174800000, so:
var date = new Date(1420174800000);
// output "Fri, 02 Jan 2015 05:00:00 GMT"
console.log(date.toGMTString());
I converted your data to dates:
date = new Date(sessions[i][0])
It contains dates between Dec 16 2014 and Jan 02 2015. You can see it in this fiddle.
When you fill your arrays, you should convert your dates to numbers simply with:
sessions[i] = [Number(date), value];
I'm not sure how you meant Date('D, M j'), I assume it's a string like "Date(month,day,year)". An example of converting this kinf of json to plottable data: in this other fiddle.
Actually, I reversed the day and month, but you get the idea. :)