Appending a class to a javascript calendar given the data (clndr.js) - javascript

I am looking to assign a class to each clndr.js event that appears in my calendar based on the value itself. var temp shows an example of the data received. I want to the style each event on type being 1 or 2. The code shows the default template which I want to modify to simply add in the value passed in type as a class so I can then style it.
link to the source library on github
link to a similar problem on github
// This is the default calendar template. This can be overridden.
var clndrTemplate =
"<div class='clndr-controls'>" +
"<div class='clndr-control-button'>" +
"<span class='clndr-previous-button'>previous</span>" +
"</div>" +
"<div class='month'><%= month %> <%= year %></div>" +
"<div class='clndr-control-button rightalign'>" +
"<span class='clndr-next-button'>next</span>" +
"</div>" +
"</div>" +
"<table class='clndr-table' border='0' cellspacing='0' cellpadding='0'>" +
"<thead>" +
"<tr class='header-days'>" +
"<% for(var i = 0; i < daysOfTheWeek.length; i++) { %>" +
"<td class='header-day'><%= daysOfTheWeek[i] %></td>" +
"<% } %>" +
"</tr>" +
"</thead>" +
"<tbody>" +
"<% for(var i = 0; i < numberOfRows; i++){ %>" +
"<tr>" +
"<% for(var j = 0; j < 7; j++){ %>" +
"<% var d = j + i * 7; %>" +
"<td class='<%= days[d].classes %>'>" +
"<div class='day-contents <%= days[d].type %>'><%= days[d].day %></div>" +
"</td>" +
"<% } %>" +
"</tr>" +
"<% } %>" +
"</tbody>" +
"</table>";
var calendars = {};
$(document).ready(function () {
var thisMonth = moment().format('YYYY-MM');
var eventArray = {{ data|tojson }};
var temp = [{
date: thisMonth + '-22',
type: 1
}, {
date: thisMonth + '-27',
type: 2
}, {
date: thisMonth + '-13',
type: 1
}];
calendars.clndr1 = $('.cal1').clndr({
events: eventArray,
targets: {
day: 'day',
},
clickEvents: {
click: function (target) {
console.log('Cal-1 clicked: ', target);
},
today: function () {
console.log('Cal-1 today');
},
nextMonth: function () {
console.log('Cal-1 next month');
},
previousMonth: function () {
console.log('Cal-1 previous month');
},
onMonthChange: function () {
console.log('Cal-1 month changed');
},
nextYear: function () {
console.log('Cal-1 next year');
},
previousYear: function () {
console.log('Cal-1 previous year');
},
onYearChange: function () {
console.log('Cal-1 year changed');
},
nextInterval: function () {
console.log('Cal-1 next interval');
},
previousInterval: function () {
console.log('Cal-1 previous interval');
},
onIntervalChange: function () {
console.log('Cal-1 interval changed');
}
},
multiDayEvents: {
singleDay: 'date',
endDate: 'endDate',
startDate: 'startDate'
},
showAdjacentMonths: true,
adjacentDaysChangeMonth: false
});
// Bind all clndrs to the left and right arrow keys
$(document).keydown(function (e) {
// Left arrow
if (e.keyCode == 37) {
calendars.clndr1.back();
calendars.clndr2.back();
calendars.clndr3.back();
}
// Right arrow
if (e.keyCode == 39) {
calendars.clndr1.forward();
calendars.clndr2.forward();
calendars.clndr3.forward();
}
});
});

I don't know your code, so I'm working with the test of CLNDR from github - folder "tests".
Add at the bottom of test.js (basically just make sure it's after clndr activation)
var thisMonth = moment().format('YYYY-MM');
var temp = [{
date: thisMonth + '-22',
type: 1
}, {
date: thisMonth + '-27',
type: 2
}, {
date: thisMonth + '-13',
type: 1
}];
for (event of temp) {
$('.calendar-day-' + event.date).addClass('ev-type-' + event.type);
};
Then add some css styles to test.html <head> just to clearly see it's working
.ev-type-1 {
background: #F00 !important;
color: #fff !important;
}
.ev-type-2 {
background: #0F0 !important;
color: #fff !important;
}

Related

jquery checkbox listener for loop

SOLUTION
https://github.com/Campos696/Attendance/commit/28177ff5cf285e9616faddae74fa6f0288a8667a
i have this javascript file:
https://github.com/Campos696/Attendance/blob/master/js/app.js
and am trying to make it so that the checkboxes created by the bodyView, have click listeners, however right now i can only create a listener for one checkbox at a time, is there any way to improve this?
And whether i check or uncheck it does the same thing(decreases daysMissed).
Here is the relevant part of the code:
var bodyView = {
init: function() {
this.render();
},
render: function() {
var student, i, x;
var schoolDays = octopus.getSchoolDays();
var students = octopus.getStudents();
for(i = 0;i < students.length; i++) {
octopus.setCurrentStudent(students[i]);
var daysMissed = octopus.getDaysMissed();
$('#students').append('<tr class="'+i+'"><td class="name-col">' + students[i].name + '</td></tr>');
for(x = 1;x < schoolDays; x++) {
$('.'+i).append('<td id="check'+i+'" class="attend-col"><input type="checkbox"></td>');
};
$('.'+i).append('<td class="missed-col">'+ daysMissed + '</td>');
};
$(function(){
$('#check0').click(function() {
octopus.setCurrentStudent(students[0]);
if($(this).is(':checked')){
octopus.incrementDaysMissed();
} else if(!$(this).is(':checked')){
octopus.decreaseDaysMissed();
}
})
})
}
}
FUNCTION EDIT
$(function(){
$('[id^=check] :checkbox').on('change', function(e) {
var daysMissed = $(this).closest('tr').find('td:last');
if (this.checked) {
octopus.decreaseDaysMissed();
daysMissed.html(octopus.getDaysMissed());
} else {
octopus.incrementDaysMissed();
daysMissed.html(octopus.getDaysMissed());
}
})
})
IDs must be unique. That means you need to change the following line:
$('.'+i).append('<td id="check'+i+'" class="attend-col"><input type="checkbox"></td>');
with:
$('.'+i).append('<td id="check'+ i + x +'" class="attend-col"><input type="checkbox"></td>');
^^^^^^^^
In this way each td has an id like: check01.....check46...
Second issue: change the click event with the change event and attach it to:
$('[id^=check] :checkbox').on('change', function(e) {
select each td having an id starting with check and for each td get the child checkbox.
var model = {
currentStudent: null,
schoolDays: 12,
students: [
{
name: "Slappy the Frog",
daysMissed: 12
},
{
name: "Lilly the Lizard",
daysMissed: 12
},
{
name: "Paulrus the Walrus",
daysMissed: 12
},
{
name: "Gregory the Goat",
daysMissed: 12
},
{
name: "Adam the Anaconda",
daysMissed: 12
}
]
};
// Octopus
var octopus = {
init: function () {
model.currentStudent = model.students[0];
headerView.init();
bodyView.init();
},
getStudents: function () {
return model.students;
},
setCurrentStudent: function (student) {
model.currentStudent = student;
},
getSchoolDays: function () {
return model.schoolDays + 1;
},
getDaysMissed: function () {
return model.currentStudent.daysMissed;
},
incrementDaysMissed: function () {
model.currentStudent.daysMissed++;
},
decreaseDaysMissed: function () {
model.currentStudent.daysMissed--;
}
};
// View
var headerView = {
init: function () {
this.render();
},
render: function () {
var i;
var schoolDays = octopus.getSchoolDays();
$('#header').append('<th class="name-col">Student Name</th>');
for (i = 1; i < schoolDays; i++) {
$('#header').append('<th>' + i + '</th>');
}
;
$('#header').append('<th class="missed-col">Days Missed</th>');
}
};
var bodyView = {
init: function () {
this.render();
},
render: function () {
var student, i, x;
var schoolDays = octopus.getSchoolDays();
var students = octopus.getStudents();
$('#students').empty();
for (i = 0; i < students.length; i++) {
octopus.setCurrentStudent(students[i]);
var daysMissed = octopus.getDaysMissed();
$('#students').append('<tr class="' + i + '"><td class="name-col">' + students[i].name + '</td></tr>');
for (x = 1; x < schoolDays; x++) {
$('.' + i).append('<td id="check' + i + x + '" class="attend-col"><input type="checkbox"></td>');
}
$('.' + i).append('<td class="missed-col">' + daysMissed + '</td>');
}
$(function(){
$('[id^=check] :checkbox').on('change', function(e) {
var colId = $(this).closest('td').index();
var rowId = $(this).closest('tr').index();
var studentName =
$(this).closest('tr').find('td:first').text();
console.log('Student: <' + studentName +
'> on day: ' + colId + ' changed to: ' +
this.checked + ' Col: ' + colId + ' Row: ' + rowId);
})
})
}
}
$(function () {
octopus.init();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://rawgit.com/Campos696/Attendance/master/css/style.css">
<h1>Udacity Attendance</h1>
<table>
<thead>
<tr id="header"></tr>
</thead>
<tbody id="students"></tbody>
</table>
Use the input:checkbox selector to get all checkboxes:
$(function(){
$("input:checkbox").click(function() {
octopus.setCurrentStudent(students[0]);
if($(this).prop("checked",true)){
octopus.incrementDaysMissed();
} else {
octopus.decreaseDaysMissed();
}
});
});

Find and remove date in jQuery

I use RSS to get posts from my WordPress website and in its name have date in title and I want to remove the date from its title and use date from rss instead
The Result I want (image) I want to remove date on title (red cross) and use rss date(green underline) instead
The problem is date format in title is not international format
Any idea to make jQuery to detect this date formula and replace(remove) it?
HTML
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="http://momentjs.com/downloads/moment-with-langs.min.js"></script>
<script type="text/javascript" src="http://www.sd.ac.th/main/wp-content/rss_fetch/FeedEk.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#divRss').FeedEk({
FeedUrl: 'http://www.sd.ac.th/main/?feed=rss2&cat=121',
//FeedUrl: 'http://www.sd.ac.th/main/?feed=rss2&cat=234',
MaxCount: 10,
ShowPubDate: true,
ShowDesc: false
});
/*setInterval(function(){
$('.itemTitle a').each(function() {
var text = $(this).text();
$(this).text(text
.replace('[', '')
.replace(']', '')
.replace('59', '')
.replace('60', '')
);
});}
, 1);*/
});
function reloadFunction() {
location.reload();
}
</script>
<button onclick="reloadFunction()">R</button>
<link rel="stylesheet" href="path/to/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="http://www.sd.ac.th/main/wp-content/rss_fetch/rss_style.css">
<div id="divRss"></div>
FeedEk.js (Plugin that I use for fetching my feed)
/*
* FeedEk jQuery RSS/ATOM Feed Plugin v3.0 with YQL API
* http://jquery-plugins.net/FeedEk/FeedEk.html https://github.com/enginkizil/FeedEk
* Author : Engin KIZIL http://www.enginkizil.com
*/
(function ($) {
$.fn.FeedEk = function (opt) {
var def = $.extend({
MaxCount: 5,
ShowDesc: true,
ShowPubDate: true,
DescCharacterLimit: 0,
TitleLinkTarget: "_blank",
DateFormat: "",
DateFormatLang:"en"
}, opt);
var id = $(this).attr("id"), i, s = "", dt;
$("#" + id).empty();
if (def.FeedUrl == undefined) return;
$("#" + id).append('<img src="loader.gif" />');
var YQLstr = 'SELECT channel.item FROM feednormalizer WHERE output="rss_2.0" AND url ="' + def.FeedUrl + '" LIMIT ' + def.MaxCount;
$.ajax({
url: "https://query.yahooapis.com/v1/public/yql?q=" + encodeURIComponent(YQLstr) + "&format=json&diagnostics=false&callback=?",
dataType: "json",
success: function (data) {
$("#" + id).empty();
if (!(data.query.results.rss instanceof Array)) {
data.query.results.rss = [data.query.results.rss];
}
$.each(data.query.results.rss, function (e, itm) {
s += '<li><div class="itemTitle"><a href="' + itm.channel.item.link + '" target="' + def.TitleLinkTarget + '" >' + itm.channel.item.title + '</a></div>';
if (def.ShowPubDate){
dt = new Date(itm.channel.item.pubDate);
s += '<div class="itemDate">';
if ($.trim(def.DateFormat).length > 0) {
try {
moment.lang(def.DateFormatLang);
s += moment(dt).format(def.DateFormat);
}
catch (e){s += dt.toLocaleDateString();}
}
else {
s += dt.toLocaleDateString();
}
s += '</div>';
}
if (def.ShowDesc) {
s += '<div class="itemContent">';
if (def.DescCharacterLimit > 0 && itm.channel.item.description.length > def.DescCharacterLimit) {
s += itm.channel.item.description.substring(0, def.DescCharacterLimit) + '...';
}
else {
s += itm.channel.item.description;
}
s += '</div>';
}
});
$("#" + id).append('<ul class="feedEkList">' + s + '</ul>');
}
});
};
})(jQuery);
If it is always and the only thing between brackets ([ and ]) and it's always at the end of the string then use this:
text = text.replace(/(\[.*\])$/, replacementDateString);
Read about Regular Expression.

How to change tooltip content in c3js

I'm working on a timeline display and I have data that I want to show on the tooltip. currently it only shows the value at each time. and I cannot find a way to change it. the example below shows how to change the value's format but not what values are displayed
var chart = c3.generate({
data: {
columns: [
['data1', 30000, 20000, 10000, 40000, 15000, 250000],
['data2', 100, 200, 100, 40, 150, 250]
],
axes: {
data2: 'y2'
}
},
axis : {
y : {
tick: {
format: d3.format("s")
}
},
y2: {
show: true,
tick: {
format: d3.format("$")
}
}
},
tooltip: {
format: {
title: function (d) { return 'Data ' + d; },
value: function (value, ratio, id) {
var format = id === 'data1' ? d3.format(',') : d3.format('$');
return format(value);
}
//value: d3.format(',') // apply this format to both y and y2
}
}
});
it's taken from http://c3js.org/samples/tooltip_format.html
they do admit that there isn't an example for content editing but I couldn't find anything in the reference or forums, but a suggestion to change the code (it's here: https://github.com/masayuki0812/c3/blob/master/c3.js in line 300) and below:
__tooltip_contents = getConfig(['tooltip', 'contents'], function (d, defaultTitleFormat, defaultValueFormat, color) {
var titleFormat = __tooltip_format_title ? __tooltip_format_title : defaultTitleFormat,
nameFormat = __tooltip_format_name ? __tooltip_format_name : function (name) { return name; },
valueFormat = __tooltip_format_value ? __tooltip_format_value : defaultValueFormat,
text, i, title, value, name, bgcolor;
for (i = 0; i < d.length; i++) {
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
if (! text) {
title = titleFormat ? titleFormat(d[i].x) : d[i].x;
text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
}
name = nameFormat(d[i].name);
value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
bgcolor = levelColor ? levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
text += "<td class='value'>" + value + "</td>";
text += "</tr>";
}
return text + "</table>";
})
did anyone attempted to do so? developed some function to facilitate the process? have any tips on how to do so correctly? I do not know how to change their code in a way I could use more data or data different than the d value the function gets.
If you use the function getTooltipContent from https://github.com/masayuki0812/c3/blob/master/src/tooltip.js#L27 and add it in the chart declaration, in tooltip.contents, you'll have the same tooltip content that the default one.
You can make changes on this code and customize it as you like. One detail, as CLASS is not defined in the current scope, but it's part chart object, I substituted CLASS for $$.CLASS, maybe you don't even need this Object in your code.
var chart = c3.generate({
/*...*/
tooltip: {
format: {
/*...*/
},
contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
var $$ = this, config = $$.config,
titleFormat = config.tooltip_format_title || defaultTitleFormat,
nameFormat = config.tooltip_format_name || function (name) { return name; },
valueFormat = config.tooltip_format_value || defaultValueFormat,
text, i, title, value, name, bgcolor;
for (i = 0; i < d.length; i++) {
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
if (! text) {
title = titleFormat ? titleFormat(d[i].x) : d[i].x;
text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
}
name = nameFormat(d[i].name);
value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + $$.CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
text += "<td class='value'>" + value + "</td>";
text += "</tr>";
}
return text + "</table>";
}
}
});
If you want to control tooltip render and use default rendering depending on data value you can use something like this:
tooltip: {
contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
if (d[1].value > 0) {
// Use default rendering
return this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color);
} else {
return '<div>Show what you want</div>';
}
},
format: {
/**/
}
}
In my case i had to add the day for the date value(x axis) in tool tip. Finally i came came up with the below solution
References for js and css
https://code.jquery.com/jquery-3.2.1.js
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js
https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js
https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css
function toDate(dateStr)
{
var numbers = dateStr.match(/\d+/g);
return new Date(numbers[0], numbers[1]-1, numbers[2]);
}
function GetMonthFromString(month)
{
var months = {'Jan' : '01','Feb' : '02','Mar':'03','Apr':'04',
'May':'05','Jun':'06','Jul':'07','Aug':'08','Sep':'09',
'Oct':'10','Nov':'11','Dec':'12'};
return months[month];
}
function GetFullDayName(formatteddate)
{
var weekday = new Array(7);
weekday[0] = "Sunday";
weekday[1] = "Monday";
weekday[2] = "Tuesday";
weekday[3] = "Wednesday";
weekday[4] = "Thursday";
weekday[5] = "Friday";
weekday[6] = "Saturday";
var dayofdate = weekday[formatteddate.getDay()];
return dayofdate;
}
//Chart Data for x-axis, OnHours and AvgHours
function CollectChartData()
{
var xData = new Array();
var onHoursData = new Array();
var averageHoursData = new Array();
var instanceOccuringDatesArray = ["2017-04-20","2017-04-21","2017-04-22","2017-04-23","2017-04-24","2017-04-25","2017-04-26","2017-04-27","2017-04-28","2017-04-29","2017-04-30","2017-05-01","2017-05-02","2017-05-03","2017-05-04","2017-05-05","2017-05-06","2017-05-07","2017-05-08","2017-05-09","2017-05-10","2017-05-11","2017-05-12","2017-05-13","2017-05-14","2017-05-15","2017-05-16","2017-05-17","2017-05-18","2017-05-19","2017-05-20"];
var engineOnHoursArray = ["4.01","14.38","0.10","0.12","0.01","0.24","0.03","6.56","0.15","0.00","1.15","0.00","1.21","2.06","8.55","1.41","0.03","1.42","0.00","3.35","0.02","3.44","0.05","5.41","4.06","0.02","0.04","7.26","1.02","5.09","0.00"];
var avgUtilizationArray = ["2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29","2.29"];
xData.push('x');
onHoursData.push('OnHours');
averageHoursData.push('Project Average');
for(var index=0;index<instanceOccuringDatesArray.length;index++)
{
xData.push(instanceOccuringDatesArray[index]);
}
for(var index=0;index<engineOnHoursArray.length;index++)
{
onHoursData.push(engineOnHoursArray[index]);
}
for(var index=0;index<avgUtilizationArray.length;index++)
{
averageHoursData.push(avgUtilizationArray[index]);
}
var Data = [xData, onHoursData, averageHoursData];
return Data;
}
function tooltip_contents(d, defaultTitleFormat, defaultValueFormat, color) {
var $$ = this, config = $$.config, CLASS = $$.CLASS,
titleFormat = config.tooltip_format_title || defaultTitleFormat,
nameFormat = config.tooltip_format_name || function (name) { return name; },
valueFormat = config.tooltip_format_value || defaultValueFormat,
text, i, title, value, name, bgcolor;
// You can access all of data like this:
//$$.data.targets;
for (i = 0; i < d.length; i++) {
if (! text) {
title = titleFormat ? titleFormat(d[i].x) : d[i].x;
var arr = title.split(" ");
var datestr = new Date().getFullYear().toString() + "-"+ GetMonthFromString(arr[1]) + "-"+ arr[0];
var formatteddate = toDate(datestr);
var dayname = GetFullDayName(formatteddate);
title = title + " (" + dayname + ")";
text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
}
name = nameFormat(d[i].name);
var initialvalue = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
if (initialvalue.toString().indexOf('.') > -1)
{
var arrval = initialvalue.toString().split(".");
value = arrval[0] + "h " + arrval[1] + "m";
}
else
{
value = initialvalue + "h " + "00m";
}
bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
text += "<td class='value'>" + value + "</td>";
text += "</tr>";
}
return text + "</table>";
}
$(document).ready(function () {
var Data = CollectChartData();
var chart = c3.generate({
data: {
x: 'x',
columns: Data
},
axis: {
x: {
type: 'timeseries',
tick: {
rotate: 75,
//format: '%d-%m-%Y'
format: '%d %b'
}
},
y : {
tick : {
format: function (y) {
if (y < 0) {
}
return y;
}
},
min : 0,
padding : {
bottom : 0
}
}
},
tooltip: {
contents: tooltip_contents
}
});
});
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet" />
<div id="chart"></div>
When we have a stacked bar chart and we would like to show "Total" in the tooltip (but not in the chart as a bar/stack) this can come handy.
C3 charts use a array to store the data for tooltips and before the tooltips are displayed we are adding totals (or anyother data as per our requirement). By doing this though the totals is not available as a stack it is shown in the tooltip.
function key_for_sum(arr) {
return arr.value; //value is the key
};
function sum(prev, next) {
return prev + next;
}
var totals_object = {};
totals_object.x = d[0]['x'];
totals_object.value = d.map(key_for_sum).reduce(sum);
totals_object.name = 'total';
totals_object.index = d[0]['index'];
totals_object.id = 'total';
d.push(totals_object);
Above code has been added to ensure that total is available in
C3.js Stacked Bar chart's tooltip
var chart = c3.generate({
/*...*/
tooltip: {
format: {
/*...*/
},
contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
function key_for_sum(arr) {
return arr.value; //value is the key
}
function sum(prev, next) {
return prev + next;
}
var totals_object = {};
totals_object.x = d[0]['x'];
totals_object.value = d.map(key_for_sum).reduce(sum);// sum func
totals_object.name = 'total';//total will be shown in tooltip
totals_object.index = d[0]['index'];
totals_object.id = 'total';//c3 will use this
d.push(totals_object);
var $$ = this,
config = $$.config,
titleFormat = config.tooltip_format_title || defaultTitleFormat,
nameFormat = config.tooltip_format_name || function (name) {
return name;
},
valueFormat = config.tooltip_format_value || defaultValueFormat,
text, i, title, value, name, bgcolor;
for (i = 0; i < d.length; i++) {
if (!(d[i] && (d[i].value || d[i].value === 0))) {
continue;
}
if (!text) {
title = titleFormat ? titleFormat(d[i].x) : d[i].x;
text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
}
name = nameFormat(d[i].name);
value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + $$.CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
text += "<td class='value'>" + value + "</td>";
text += "</tr>";
}
return text + "</table>";
}
}
Adding additional content or non-numerical data into the chart tooltips can be done.
This builds on #supita's excellent answer http://stackoverflow.com/a/25750639/1003746.
Its possible to insert additional metadata about each line into the classes parameter when generating/updating the chart. These can then be added as rows to the tooltip.
This doesn't seem to affect the chart - unless you are using the data.classes feature.
data: {
classes: {
data1: [{prop1: 10, prop2: 20}, {prop1: 30, prop2: 40}],
data2: [{prop1: 50, prop2: 60}'{prop1: 70, prop2: 80}]
}
}
To pick up the metadata in the config.
tooltip: {
contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
const $$ = this;
const config = $$.config;
const meta = config.data_classes;
...
for (i = 0; i < d.length; i++) {
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
if (! text) {
...
}
const line = d[0].id;
const properties = meta.classes[line];
const property = properties? properties[i] : null;
Then add the following rows to the table to show the new properties.
if (property ) {
text += "<tr class='" + $$.CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>PROP1</td>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + property.prop1 + "</td>";
text += "</tr>";
text += "<tr class='" + $$.CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>PROP2</td>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" +
property.prop2+ " cm/s</td>";
If anybody cares, here is a ClojureScript version of the above algorithm (e.g. supita's answer), slightly simplified (without support for config). (This is probably nothing the OP asked for, but as of now there are so few resources on the net on this topic that most people might wind up here.)
:tooltip {
:contents
(fn [d default-title-format default-value-format color]
(this-as this
(let [this-CLASS (js->clj (.-CLASS this) :keywordize-keys true)
tooltip-name-class (:tooltipName this-CLASS)
rows (js->clj d :keywordize-keys true)
title-row (->> (first rows) (#(str "<table class='" (:tooltip this-CLASS)
"'><tr><th colspan='2'>"
(default-title-format (:x %)) "</th></tr>")))
data-rows (->> rows
(map #(str "<tr class='" tooltip-name-class "--" (:id %) "'>"
"<td class='name'><span style='background-color:"
(color (:id %)) "'></span>" (:name %) "</td>"
"<td class='value'>" (default-value-format (:value %)) "</td>"
"</tr>")))]
(str title-row (string/join data-rows) "</table>"))))}
Your question is about changing the content of the tooltip in c3js.
The tooltip has 3 variables
+----------------+
| title |
+----------------+
| name | value |
+----------------+
Plus, you want to add 'name' from an additional variable, other than those used in 'column'.
tooltip: {
format: {
title(x, index) { return ''; },
name(name, ratio, id, index) { return lst[index + 1]; },
value(value, ratio, id, index) { return value; }
}
},
this worked for me, feel free to play around with the arguments, to get what you need.
I faced a problem which is related tooltip position and style for c3 before. in order to arrange tooltip in c3 freely, my suggestion is manipulating tooltip with d3.
// internal = chart.internal()
const mousePos = d3.mouse(internal.svg.node()); // find mouse position
const clientX = mousePos[0]; //for x
const clientY = mousePos[1]; //for y
const tooltip = d3.select("#tooltip"); //select tooltip div (apply your style)
tooltip.style("display", "initial"); //show tooltip
tooltip.style("left", clientX - mouseOffSet.X + "px"); // set position
tooltip.style("top", clientY - mouseOffSet.Y + "px"); // set position
tooltip.html("<span>" + content + "</span>");
// you can arrange all content and style whatever you want
<div
id="tooltip"
className="your-style"
style={{ display: "none", position: "absolute" }}
/>
Good luck!!

Problems with remove timestamps in JQuery

When I double click the card the dialog pops up, and it is then possible to create comments. So far so good. When creating the comments it is possible to delete it.
The issue is, that the timestamps can't be removed. The way I'm trying to remove the timestamps is by this line: $('.labelStyle').remove();
I want to be able to remove the timestamps, like the others elements but how?
Live Demo
JQuery: "click" handler
$('#divComments').on('click', '.delete', function (e) {
var uniqueval = $(this).attr("for")
var NameOfDataValue = $('label[for=' + uniqueval + ']').text();
$('img[for=' + uniqueval + ']').remove();
$('label[for=' + uniqueval + ']').remove();
$('p[for=' + uniqueval + ']').remove();
$('.labelStyle').remove();
var arr = $('#divComments').data('comments');
var theIndex = -1;
for (var i = 0; i < arr.length; i++) {
if (arr[i].commentString== NameOfDataValue) {
theIndex = i;
break;
}
}
if (theIndex == -1) {
alert("Error");
}
else {
$('#divComments').data("comments").splice(theIndex, 1);
}
});
JQuery: Add comment function
function addComment(commentString) {
var container = $('#divComments');
var inputs = container.find('label');
var id = inputs.length + 1;
var data1 = {
commentString: commentString
};
var div = $('<div />', { class: 'CommentStyle' });
$('<label />', {
id: 'comment' + id,
for: 'comment' + id,
text: commentString
}).on('change', function () {
data1.commentString = $(this).text();
}).appendTo(div);
$('<br/>').appendTo(div);
var $Image = $('<img />',
{
"src": "/Pages/Images/alert.png",
"class": "CommentImage",
"for": "comment" + id
}).appendTo(container);
var d = new Date();
var $fulaDate = $('<div>' + d.getDate()
+ "-" + monthNames[d.getMonth()]
+ "-" + d.getFullYear()
+ "//" + d.getHours()
+ ":" + d.getMinutes()
+ '</div>').addClass('labelStyle').append(' ~').appendTo(div);
var $edit = $('<p />', {
class: 'edit',
for: 'comment' + id,
text: 'Edit'
}).append(' ~').appendTo(div);
var $delete = $('<p />', {
class: 'delete',
for: 'comment' + id,
text: 'Delete'
}).appendTo(div);
div.appendTo(container).focus();
container.data('comments').push(data1);
}
You could do:
$(this).parent().find('.labelStyle').remove();
This will select the parent of the clicked button (.CommentStyle) then find the .labelStyle and remove it.

multiple onload error in HTML

HTML:-
In the body tag I have used onload="variable2.init() ; variable1.init();".
JavaScript:-
var variable1 = {
rssUrl: 'http://feeds.feedburner.com/football-italia/pAjS',
init: function() {
this.getRSS();
},
getRSS: function() {
jQuery.getFeed({
url: variable1.rssUrl,
success: function showFeed(feed) {
variable1.parseRSS(feed);
}
});
},
parseRSS: function(feed) {
var main = '';
var posts = '';
var className = 'even';
var pst = {};
for (i = 0; i < feed.items.length; i++) {
pst = variable1.parsefootballitaliaRSS(feed.items[i]);
if (className == 'odd') {
className = 'even';
}
else {
className = 'odd';
}
var shorter = pst.story.replace(/<(?:.|\n)*?>/gm, '');
item_date = new Date(feed.items[i].updated);
main += '<div id="content1" class="post-main ' + className + '" onclick="mwl.setGroupTarget(\'#screens1\', \'#blog_posts1\', \'ui-show\', \'ui-hide\');mwl.setGroupTarget(\'#blog_posts1\', \'#post' + (i+1) + '\', \'ui-show\', \'ui-hide\');">';
main += '<b>' + pst.title.trunc(55, true) + '</b><br />' + shorter.trunc(30, true);
main += '<div class="datetime">' + item_date.getDateTime() + '</div></div>';
posts += '<div class="post-wrapper ui-hide" id="post' + (i+1) + '">';
posts += '<div class="post-title"><b>' + pst.title + '</b></div>';
posts += feed.items[i].description;
posts += '</div>';
}
jQuery('#main_screen1').html(main);
jQuery('#blog_posts1').html(posts);
},
parsefootballitaliaRSS: function(item) {
var match = item.description.match('src="([^"]+)"');
var part = item.description.split('<font size="-1">');
var arr = {
title: item.title,
link: item.link,
image: match,
site_title: item.title,
story: item.description
};
return arr;
}
};
var variable2 = {
weatherRSS: 'http://feeds.feedburner.com/go/ELkW',
init: function() {
this.getWeatherRSS();
},
getWeatherRSS: function() {
jQuery.getFeed({
url: variable2.weatherRSS,
success: function showFeed(feed) {
variable2.parseWeather(feed);
}
});
},
parseWeather: function(feed) {
var main = '';
var posts = '';
var className = 'even';
var pst = {};
for (i = 0; i < feed.items.length; i++) {
pst = variable2.parsegoRSS(feed.items[i]);
if (className == 'odd') {
className = 'even';
}
else {
className = 'odd';
}
var shorter = pst.story.replace(/<(?:.|\n)*?>/gm, '');
item_date = new Date(feed.items[i].updated);
main += '<div id="content2" class="post-main ' + className + '" onclick="mwl.setGroupTarget(\'#screens2\', \'#blog_posts2\', \'ui-show\', \'ui-hide\');mwl.setGroupTarget(\'#blog_posts2\', \'#post' + (i+1) + '\', \'ui-show\', \'ui-hide\');">';
main += '<b>' + pst.title.trunc(55, true) + '</b><br />' + shorter.trunc(30, true);
main += '<div class="datetime">' + item_date.getDateTime() + '</div></div>';
posts += '<div class="post-wrapper ui-hide" id="post' + (i+1) + '">';
posts += '<div class="post-title"><b>' + pst.title + '</b></div>';
posts += feed.items[i].description;
posts += '</div>';
}
jQuery('#main_screen2').html(main);
jQuery('#blog_posts2').html(posts);
},
parsegoRSS: function(item) {
var match = item.description.match('src="([^"]+)"');
var part = item.description.split('<font size="-1">');
var arr = {
title: item.title,
link: item.link,
image: match,
site_title: item.title,
story: item.description
};
return arr;
}
};
When I run the program it only reads one of the variables i.e. either 1 or 2.
How can I correct them to read both the variables?
Use this.
<script type="text/javascript">
window.onload = function() {
variable1.init();
variable2.init();
}
</script>
Try this
<body onload="callFunctions()">
JS-
function callFunctions()
{
variable1.init();
variable2.init();
}
Update-
Also
there are other different ways to call multiple functions on page load
Hope it hepls you.

Categories

Resources