I'm trying to display data in a stacked graph using kendo ui. Here is my code:
var data = [
// June
{ Start: "2014-06-01T00:00:00", Name : "Series 1", Value: 1 },
{ Start: "2014-06-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-06-01T00:00:00", Name : "Series 3", Value: 10 },
// July
{ Start: "2014-07-01T00:00:00", Name : "Series 1", Value: 2 },
{ Start: "2014-07-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-07-01T00:00:00", Name : "Series 3", Value: 2 },
// August
{ Start: "2014-08-01T00:00:00", Name : "Series 1", Value: 3 },
{ Start: "2014-08-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-08-01T00:00:00", Name : "Series 3", Value: 1 },
// September
{ Start: "2014-09-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-09-01T00:00:00", Name : "Series 3", Value: 3 },
// October
{ Start: "2014-10-01T00:00:00", Name : "Series 1", Value: 1 },
{ Start: "2014-10-01T00:00:00", Name : "Series 3", Value: 3 }
]
var stocksDataSource = new kendo.data.DataSource({
data: data,
group: {
field: "Name"
},
sort: [{ field: "Start", dir: "asc"} ]
});
function createChart() {
$("#chart").kendoChart({
dataSource: stocksDataSource,
series: [{
type: "column",
field: "Value",
name: "#= group.value #",
stack: true,
tooltip: {
template: "#=kendo.toString(new Date(category), 'd MMM yyyy')#<br/>" +
"#=dataItem.Name#<br/>"+
"Value: #=dataItem.Value#",
visible: true
},
}],
categoryAxis: {
field: "Start",
type: "date",
labels: {
format: "MMM"
}
}
});
}
$(document).ready(createChart);
$(document).bind("kendo:skinChange", createChart);
Note that September and October data do not have values for some series. This completely screws up the chart display in quite unexplainable way:
As you can see both September and October data do not match the json. It's especially weird with October data because three values are displayed whereas only 2 are given.
Here is JSFiddle: http://jsfiddle.net/12ob7qmx/6/
Are there any settings on the chart that I can set so it works, or will I have to loop through the dataset and fill in missing data with zero values?
The way I solved this issue is by looping through my data and adding missing values with 0's.
I don't think there is a better way, than what you suggested yourself. :(
I found a question concerning this issue on the Telerik forums:
The behavior you have observed is expected as the categorical charts
(bar, area etc.) require a matching set of data points (the value can
be null but it should persist in the data). I am afraid there is no
built-in functionality which will automatically set 0 for the missing
values - you should modify your data.
I am afraid the implementation of this functionality is not in our immediate plans, however we may consider it for future versions of the product.
I haven't found more recent information, but as far as I know this hasn't been fixed.
It' looks like I'm out of luck and I need to fix up the data. In my actual solution I'm doing that server-side, but for posterity if anyone needs a kickstart with a purely js fix, this is the starting point:
function fixData(data) {
var lookup =[], start = [], name = [], result =[];
for (i = 0, len = data.length; i < len; ++i) {
start[data[i].Start] = true;
name[data[i].Name] = true;
lookup[data[i].Start + "," + data[i].Name] = data[i].Value;
}
for (var currentStart in start) {
for (var currentName in name) {
var entry = {Start: currentStart, Name: currentName};
entry.Value = lookup[currentStart + "," + currentName] || 0;
result.push(entry);
}
}
return result;
}
JSFiddle: http://jsfiddle.net/12ob7qmx/8/
Related
I am trying to make a simple quiz. Somehow I always have an error
"Vue is not defined"
However, it actually is defined right there. I don't exactly undertand what is the reason. The website link is here.
The script is right in a head of the page. I have tried to use javascript code as a separate file, but the error is the same. I am a novice in javascript, so any help would be really appreciated.
"use strict";
window.onload = function() {
var quiz = {
title: 'What superhero are you?',
questions: [{
text: "How would you describe your personality?",
responses: [{
text: 'Im serious and dark',
value: 'Batman'
},
{
text: 'Arrogant, but charming',
value: 'Superman'
},
{
text: 'Fun and easy going',
value: 'The Flash'
}
]
},
{
text: "Why did you want to become a superhero?",
responses: [{
text: 'For the thrills',
value: 'The Flash'
},
{
text: 'For justice',
value: 'Batman'
},
{
text: 'For popularity',
value: 'Superman'
}
]
},
{
text: "Who would you most hang around with?",
responses: [{
text: 'Wonder Woman',
value: 'Superman'
},
{
text: 'Green Arrow',
value: 'The Flash'
},
{
text: 'Robin',
value: 'Batman'
}
]
},
{
text: "What's your favourite colour?",
responses: [{
text: 'Black',
value: 'Batman'
},
{
text: 'Red',
value: 'The Flash'
},
{
text: 'Blue',
value: 'Superman'
}
]
},
{
text: "When do you help people?",
responses: [{
text: 'Every chance I can',
value: 'The Flash'
},
{
text: 'At night',
value: 'Batman'
},
{
text: 'When they need me to',
value: 'Superman'
}
]
},
]
};
var app = new Vue({
el: '#app',
data: {
quiz: quiz,
questionIndex: 0,
userResponses: Array()
},
methods: {
// Go to next question
next: function() {
this.questionIndex++;
console.log(this.userResponses);
},
// Go to previous question
prev: function() {
this.questionIndex--;
},
score: function() {
//find the highest occurence in responses
var modeMap = {};
var maxEl = this.userResponses[0],
maxCount = 1;
for (var i = 0; i < this.userResponses.length; i++) {
var el = this.userResponses[i];
if (modeMap[el] == null)
modeMap[el] = 1;
else
modeMap[el]++;
if (modeMap[el] > maxCount) {
maxEl = el;
maxCount = modeMap[el];
}
}
return maxEl;
}
}
});
}
If you'll check the source code of your site You will see script for Vue is not loaded. So giving error Vue is not defined. Add below script in head of your page.
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.22/dist/vue.js"></script>
You can read here, how to use Vue in your project.
You are actually not loading Vue. Make sure to load Vue before instantiating an instance of it.
You can either load the script using a CDN, as Ashish showed, or save the script to your local machine, and including it in your page.
<script src="/js/vue-2.5.22.min.js" type="text/javascript"/>
Where /js/vue-2.5.22.min.js is the relative path to the location of Vue.
I am working on Timeline charts in angularjs google chart API.
From Timeline chart API i understood that only 4 columns are allowed and the other column would be a tooltip column.
I have a requirement where i am attaching the ID of that row along with the description and i want to pass that ID when the row is clicked but dont want to show on the label.
js code:
angular.module('myApp', ['googlechart'])
.controller('myController', function($scope,$timeout) {
var chart1 = {};
chart1.type = "Timeline";
chart1.displayed = false;
var container = document.getElementById('timeline')
chart1.data = {
"cols": [{
id: "month",
label: "Month",
type: "string"
}, {
id: "description",
label: "Description",
type: "string"
}, {
id: "start",
label: "start",
type: "date"
}, {
id: "end",
label: "end",
type: "date"
}],
"rows": [{
c: [{
v: "January"
}, {
v: "Jan text here -$# 1001".trim().split(' -$#')[0]
}, {
v: new Date(2018, 3, 1)
}, {
v:new Date(2018, 4, 12)
} ]
}, {
c: [{
v: "February"
}, {
v: "feb text here -$# 1002".trim().split(' -$#')[0]
}, {
v: new Date(2018,4, 1)
}, {
v: new Date(2018, 4, 15)
} ]
} , {
c: [{
v: "april"
}, {
v: "april text here -$# 1003".trim().split(' -$#')[0]
}, {
v: new Date(2018,5, 1)
}, {
v: new Date(2018, 7, 15)
} ]
} ]
};
chart1.options = {
timeline: {
showRowLabels: false,
},
};
$scope.seriesSelected = function(selectedItem) {
var rowValue = chart1.data.rows[selectedItem.row].c[1].v;
alert(rowValue);
}
$scope.myChart = chart1;
});
In the above js code, i am attaching the rowID like 1001,1002,.. to the description column (Jan text here -$# 1001".trim().split(' -$#')[0]), but using trim() because i should not show the ID on the screen. When clicked on the row
var rowValue = chart1.data.rows[selectedItem.row].c[1].v; i wanted to get the entire value as Jan text here -$# 1001 but it is not showing the ID values as shown in the demo link. Any inputs on how to pass the ID values (1001,1002..) appended in the description to the $scope.seriesSelected .
PS: Is it possible to include another column where i can assign the ID values(1001,1002..), but it should not be shown on the webpage/tooltip.
you can assign properties to each cell, row, or column...
c: [{
v: "January"
}, {
v: "Jan text here", p: {id: 1001}
},
...
and use data table methods to get / set...
dataTable.getProperty(rowIndex, columnIndex, name);
dataTable.setProperty(rowIndex, columnIndex, name, value);
or access the property directly from the json used as the data table...
chart1.data.rows[selectedItem.row].c[1].p.id
I have a table in mysql with a lot of columns to update dynamically.
The front end is passing an object like this:
"columns2update":
[{ name: "column1", val: "Y" },
{ name: "column4", val: "Y" },
{ name: "column5", val: "Y" },
{ name: "column8", val: "Y" },
{ name: "column12", val: "Y" },
{ name: "column22", val: "Y" },
{ name: "column43", val: "Y" },
{ name: "column55", val: "Y" },
{ name: "column76", val: "Y" },
{ name: "column85", val: "Y" }]
Object will be different depending on what columns has been selected.
How do I loop thru this object? Update the columns in the object name: ? A stored proc would be best if possible.
It would be terrible to pass all the columns names to update just a few columns.
mysqlPool.getConnection(function(error,conn){
conn.query("SET #p1 = 53; SET #p2 = 20; SET #p3 = 0; SET #p4 = 15; CALL PROC_NAME( #p1, #p2, #p3, #p4)", function(error,results)
{
if (error)
{
console.error(error);
throw error;
}else{
console.log(results);
Thanks in advance.
I used brute force to fix this issue. I will find an elegant solutions later. Its actually fast but the code maintenance will be an issue.
Im trying to loop through an array only i cant seem to extract the data from my array...
http://jsfiddle.net/338Ud/
var listTicker = function (options) {
var defaults = {
list: [],
startIndex: 0,
interval: 3 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function (index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value = options.list[index];
options.trickerPanel.fadeOut(function () {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function () {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
}
var textlist = new Array({
id: 0,
name: 'Antonia Lallement',
title: '\u003cp\u003e\u003cspan\u003eConsultant\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI started as a resourcer at company three months ago so I\u0026rsquo;m a new team member. Sin...',
image: 'antonia.jpg'
}, {
id: 1,
name: 'Camilla Gobel',
title: '\u003cp\u003e\u003cspan\u003eBusiness Manager\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI joined company in 2011. As a multilingual Consultant, my initial focus was the provisi...',
image: 'camilla.jpg'
}, {
id: 2,
name: 'Mark Dorey',
title: '\u003cp\u003e\u003cspan\u003eDiscipline Manager (Process, Subsea, Project, Safety)\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eWhen I joined company I started as a resourcing specialist and worked across Search and ...',
image: 'mark.jpg'
}, {
id: 3,
name: 'Sadia Butt',
title: '\u003cp\u003e\u003cspan\u003eDiscipline Manager (Mechanical, Piping, Structural)\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI couldn\u0026rsquo;t have asked for a better company to work for! After working as a resourc...',
image: 'sadia.jpg'
}, {
id: 4,
name: 'Samantha Linnert',
title: '\u003cp\u003e\u003cspan\u003ePayroll Assistant\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI began at company as an operations assistant learning to spec CVs and post jobs. Shortl...',
image: 'samantha.jpg'
}, {
id: 5,
name: 'Simon Cottenham',
title: '\u003cp\u003e\u003cspan\u003eConsultant, Middle East\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI have been with company for exactly one year now, I never would have believed that I wo...',
image: 'simon.jpg'
}, {
id: 6,
name: 'Vicky Spencer',
title: '\u003cp\u003e\u003cspan\u003ePayroll Manager\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI started my career at company in July 2012 initially covering maternity leave, managing...',
image: 'vicky.jpg'
});
$(function () {
listTicker({
list: textlist,
startIndex: 0,
trickerPanel: $('.textbox'),
interval: 3 * 1000,
});
});
you are adding object to a html .... use . operator to get the actual values
....
options.trickerPanel.fadeOut(function () {
$(this).html(value.id).fadeIn();
//--------^^^----here
}
i am taking id from the object and showing it in the div.. you can add whatever you need there..
$(this).html(value.title).fadeIn(); //to get title
fiddle here
$.each(textlist, function(index, value){
//do stuff with your array
});
Pasting just the diff, i tried to get the data here below.
From the code above.
options.trickerPanel.fadeOut(function () {
$(this).html(value).fadeIn();
});
The diff,
options.trickerPanel.fadeOut(function () {
$(this).html(value.bio).fadeIn();
});
The difference, is value is the entire array object being passed to the fadeOut function, accessing each elements in the array gives the result.
Being very new to Kendo UI and Knockout (3 days!), I'm trying to convert a legacy Java applet to Javascript. So far, creating and binding the kendoGrid was relatively easy:
function JobViewModel() {
var self = this;
self.jobData = new ko.observableArray([]);
self.grdJobs = {
scrollable: true,
sortable: true,
filterable: false,
columnMenu: true,
resizable: true,
columns: [
{ title: "Job ID", field: "jobID" },
{ title: "Owner", field: "owner" },
{ title: "Description", field: "description" },
{ title: "State", field: "runState" },
{ title: "Start Time", field: "timeStart" },
{ title: "End Time", field: "timeEnd" },
{ title: "Elapsed Time", field: "timeElapsed" },
{ title: "Progress", field: "progress" },
{ title: "Agent", field: "agent" },
{ title: "Last Action", field: "lastAction" }
],
selectable: "single"
};
};
The data coming back from the server are an array of JSON objects (of any length) something like the following (shortened for brevity):
[{0: 1, 2: 3, 4: 5, ...}, {0: 1, 2: 21, 4: 5, ...}, {0: 1, 2: 23, 4: 5, ...}]
This array of objects which are numeric key/value pairs are mapped to a dictionary object where the numeric keys are paired with string values something like:
{
0: "State"
1: "Finished"
2: "JOB ID"
3: "54759"
4: "Owner"
5: "John"
...
21: "54758"
...
23: "54757"
...
}
What I need to get is the mapped strings from the dictionary as they relate to the array of JSON objects. The approach I tried was to JSON.stringify(obj[i]) but then I wasn't sure what I could do with it (maybe use it in a ko.observable that could be assigned to the kendoGrid?) Anyway, what I'm after based on the sample data I've shown above is a grid with column headers "JOB ID", "Owner", and "State" and 3 rows of jobs (54757, 54758, 54759) all owned by John and State Finished.
I hope this all made sense. I guess what I really need is how to take JSON and convert it into something usable that can be populated into a Kendo Grid. Thanks for helping out a JS/JSON/Kendo/Knockout neophyte!
You could try to map those two arrays you have to another array with elements you can use.
I made a simple jsFiddle to demonstrate this: jsFiddle
The code is pretty straight forward:
var data = [{ 0: 1, 2: 3 }, { 0: 4, 2: 3 }];
var mapping = { 0: 'State', 1: 'Finished', 2: 'Owner', 3: 'John', 4: 'Pending' };
var realData = [];
$.each(data, function(index, obj) {
var arrayElem = {};
$.each(obj, function(key, value) {
arrayElem[mapping[key]] = mapping[value];
});
realData.push(arrayElem);
});