How to update Cal-HeatMap? - d3.js

I am using Cal-HeatMap:
cal.init({
data: "data/datas.json",
domain: "day", // Group data by days
subDomain: "hour", // Split each day by hours
range: 10, // Number of days to display
browsing: true,
cellSize: 15,
highlight: ["now"],
previousSelector: "#previousSelector-a-previous",
nextSelector: "#previousSelector-a-next",
subDomainTextFormat: function (date, value) {
return value;
},
onClick: function (date, count) {
alert("Oh gosh, " + count + " things occured on " + date.toISOString());
}
});
How can I update using JSON, I did this:
cal.update("data/datas.js");
cal.options.data = "data/datas.json";
cal.next();
I hit an error at:
var c=new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours())
Error:
Unable to get property for getFullYear()....

Related

Part of my lambda function executes twice

I'm writing AWS lambda function that should update daily statistics of a player each time when (s)he performs a drill. Function is being triggered once, with 0 retries configured, on new DynamoDB row event.
I'm testing the function alone, I'm certain I create only one row in DynamoDB that triggers lambda execution. Now to the funny part. My lambda is executed once as a whole, but some part of it is executed twice within the same request.
Here's the lambda code:
const AWS = require('aws-sdk');
var docClient = new AWS.DynamoDB.DocumentClient({region: 'us-west-2'});
const dailyStatsTableName = 'xxx';
const weeklyStatsTableName = 'yyy';
const monthlyStatsPlayerTableName = 'zzz';
const requestsTableName = 'qqq';
exports.handler = async (event, context, callback) => {
//Ensure idempotency of lambda as a whole
let requestID = context.awsRequestId;
let requestAlreadyProcessed = false;
await getRequest(requestsTableName, requestID, (err, data) => {
if (err) {
console.log(err);
} else {
if (data.Item) {
requestAlreadyProcessed = true;
}
}
});
if (requestAlreadyProcessed) {
console.log("This request has already been processed. Aborting.");
return;
}
console.log("Processing new assigned drill performance event. RequestID: " + requestID);
console.log(event);
const record = event.Records[0].dynamodb;
console.log(record);
if (!record || !record.NewImage) {
console.log("New record image undefined");
return;
}
console.log(record.NewImage);
//Get performed touches to count them in statistics
let touches = 0;
try {
touches = parseInt(record.NewImage.touches.N, 10);
} catch (error) {
console.error(error);
}
//Unpack date from record.NewImage.createdAt string
let performanceDate = new Date(Date.parse(record.NewImage.createdAt.S));
console.log("CreatedAt date: " + performanceDate);
//Get daily statistics object from table - I want to update if already exist
let dailyStats = {
drillID: record.NewImage.drillID.S,
targetUserID: record.NewImage.targetUserID.S,
performDay: performanceDate.getDate(),
performMonth: performanceDate.getMonth(),
performYear: performanceDate.getFullYear(),
performDate: performanceDate.toISOString(),
touches: 0,
id: undefined
};
let result = await getDailyStats(dailyStatsTableName, dailyStats.performDay, dailyStats.performMonth, dailyStats.performYear, dailyStats.drillID, dailyStats.targetUserID, (err, data) => {
if (err) {
console.log(err);
} else {
if (data.Items.length !== 0) {
console.log("Found daily stats object"); //this console.log is logged twice. Everything below that line is executed twice.
dailyStats = data.Items[0];
}
}
return "success";
});
//Create or update daily statistics
if (!dailyStats.id) {
console.log("DailyStats ID not found. Creating new with touches " + touches);
dailyStats.touches = touches;
result = await createDailyStats(dailyStatsTableName, dailyStats, requestID, (err, data) => {
if (err) {
console.log(err);
} else {
console.log("Success creating daily stats " + dailyStats.drillID + " " + dailyStats.targetUserID + " " + dailyStats.touches);
}
return "success";
});
} else {
console.log("DailyStats ID found. Updating existing with touches " + touches);
result = await updateDailyStats(dailyStatsTableName, dailyStats.id, touches, requestID, (err, data) => {
if (err) {
console.log(err);
} else {
console.log("Success updating daily stats " + dailyStats.drillID + " " + dailyStats.targetUserID + " " + touches);
}
return "success";
});
}
//Mark this request as processed to ensure idempotency of lambda as a whole
result = await createProcessedRequest(requestsTableName, requestID, (err, data) => {
if (err) {
console.log(err);
} else {
console.log("Success creating processed request " + requestID);
}
return "success";
});
return "success";
};
function createDailyStats(tableName, stats, requestID, callback) {
let now = new Date();
let dateTimeString = now.toISOString();
let params = {
TableName:tableName,
Item:{
"__typename": "PersonalDrillDailyStatistic",
"createdAt": dateTimeString,
"updatedAt": dateTimeString,
"id": stats.id ? stats.id : createUUID(),
"drillID": stats.drillID,
"targetUserID": stats.targetUserID,
"touches": stats.touches,
"performDay": stats.performDay,
"performMonth": stats.performMonth,
"performYear": stats.performYear,
"lastRequestID": requestID
}
};
console.log("Adding a new daily stats (with id) item... " + stats.drillID + " " + stats.targetUserID + " " + stats.touches);
return docClient.put(params, callback).promise();
}
function updateDailyStats(tableName, statsID, touches, requestID, callback) {
var params = {
TableName:tableName,
Key:{
"id": statsID
},
UpdateExpression: "set touches = touches + :val, lastRequestID = :reqID",
ExpressionAttributeValues:{
":val": touches,
":reqID": requestID
},
ConditionExpression: "lastRequestID <> :reqID", //conditional check exception is being thrown during second call, hence Exception in logs output
ReturnValues:"UPDATED_NEW"
};
console.log("Updating daily stats (with id) item... " + statsID + " " + touches);
return docClient.update(params, callback).promise();
}
function getDailyStats(tableName, performDay, performMonth, performYear, drillID, targetUserID, callback) {
console.log("Querying for daily statistics |" + performDay + "." + performMonth + "." + performYear + "| userID: |" + targetUserID + "| drillID: |" + drillID + "| from table " + tableName);
let params = {
TableName: tableName,
FilterExpression: "drillID = :drill_id and targetUserID = :user_id and performDay = :day and performMonth = :month and performYear = :year",
ExpressionAttributeValues: {
":drill_id": drillID,
":user_id": targetUserID,
":day": performDay,
":month": performMonth,
":year": performYear,
}
};
return docClient.scan(params, callback).promise();
}
function createUUID(){
(...)
}
function getRequest(tableName, requestID, callback) {
let params = {
TableName: tableName,
Key: {
"id": requestID
}
};
return docClient.get(params, callback).promise();
}
function createProcessedRequest(tableName, requestID, callback) {
let params = {
TableName:tableName,
Item:{
"id": requestID,
"name": requestID
}
};
return docClient.put(params, callback).promise();
}
Here's CloudWatch output for this lambda execution:
2021-04-16T22:24:49.754+02:00 START RequestId: 8766c005-c1f3-42fb-aee9-9e8352da67ed Version: $LATEST
2021-04-16T22:24:50.464+02:00 2021-04-16T20:24:50.464Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO Processing new assigned drill performance event. RequestID: 8766c005-c1f3-42fb-aee9-9e8352da67ed
2021-04-16T22:24:50.523+02:00 2021-04-16T20:24:50.523Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO { Records: [ { eventID: 'e09a400894c178ef66840f54e71b6c26', eventName: 'INSERT', eventVersion: '1.1', eventSource: 'aws:dynamodb', awsRegion: 'us-west-2', dynamodb: [Object], eventSourceARN: 'arn:aws:dynamodb:us-west-2:900776852541:table/FDrillPerformance-y22t7izqyvb2xiruvbf4zhadvm-fissiondev/stream/2021-04-15T21:48:06.158' } ] }
2021-04-16T22:24:50.541+02:00 2021-04-16T20:24:50.541Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO { ApproximateCreationDateTime: 1618604689, Keys: { id: { S: '7321fcf5-fed2-402a-b1cf-7667e958f73a' } }, NewImage: { createdAt: { S: '2021-04-16T20:24:49.077Z' }, touches: { N: '25' }, __typename: { S: 'FDrillPerformance' }, drillID: { S: '01adc7e6-67be-4bdf-828b-36833cbd7070' }, targetUserID: { S: 'd4a95710-c4fb-4f0f-8355-76082e41c43a' }, id: { S: '7321fcf5-fed2-402a-b1cf-7667e958f73a' }, updatedAt: { S: '2021-04-16T20:24:49.077Z' } }, SequenceNumber: '218143500000000009280556527', SizeBytes: 269, StreamViewType: 'NEW_IMAGE' }
2021-04-16T22:24:50.561+02:00 2021-04-16T20:24:50.561Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO { createdAt: { S: '2021-04-16T20:24:49.077Z' }, touches: { N: '25' }, __typename: { S: 'FDrillPerformance' }, drillID: { S: '01adc7e6-67be-4bdf-828b-36833cbd7070' }, targetUserID: { S: 'd4a95710-c4fb-4f0f-8355-76082e41c43a' }, id: { S: '7321fcf5-fed2-402a-b1cf-7667e958f73a' }, updatedAt: { S: '2021-04-16T20:24:49.077Z' } }
2021-04-16T22:24:50.581+02:00 2021-04-16T20:24:50.581Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO CreatedAt date: Fri Apr 16 2021 20:24:49 GMT+0000 (Coordinated Universal Time)
2021-04-16T22:24:50.581+02:00 2021-04-16T20:24:50.581Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO Querying for daily statistics |16.3.2021| userID: |d4a95710-c4fb-4f0f-8355-76082e41c43a| drillID: |01adc7e6-67be-4bdf-828b-36833cbd7070| from table PersonalDrillDailyStatistic-y22t7izqyvb2xiruvbf4zhadvm-fissiondev
2021-04-16T22:24:50.784+02:00 2021-04-16T20:24:50.783Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO Found daily stats object
2021-04-16T22:24:50.784+02:00 2021-04-16T20:24:50.784Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO DailyStats ID found. Updating existing with touches 25
2021-04-16T22:24:50.784+02:00 2021-04-16T20:24:50.784Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO Updating daily stats (with id) item... ab00afe1-ed4b-4895-b1bb-31ac570fe46d 25
2021-04-16T22:24:50.883+02:00 2021-04-16T20:24:50.883Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO Found daily stats object
2021-04-16T22:24:51.302+02:00 2021-04-16T20:24:51.302Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO Success updating daily stats 01adc7e6-67be-4bdf-828b-36833cbd7070 d4a95710-c4fb-4f0f-8355-76082e41c43a 25
2021-04-16T22:24:51.401+02:00 2021-04-16T20:24:51.384Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO ConditionalCheckFailedException: The conditional request failed at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27) at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20) at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10) at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14) at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10) at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12) at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10 at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9) at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12) at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18) { code: 'ConditionalCheckFailedException', time: 2021-04-16T20:24:51.383Z, requestId: 'H8PC553OQABGJKR9KFIJMR1EHJVV4KQNSO5AEMVJF66Q9ASUAAJG', statusCode: 400, retryable: false, retryDelay: 36.82252581429517 }
2021-04-16T22:24:51.462+02:00 2021-04-16T20:24:51.462Z 8766c005-c1f3-42fb-aee9-9e8352da67ed INFO Success creating processed request 8766c005-c1f3-42fb-aee9-9e8352da67ed
2021-04-16T22:24:51.482+02:00 END RequestId: 8766c005-c1f3-42fb-aee9-9e8352da67ed
2021-04-16T22:24:51.482+02:00 REPORT RequestId: 8766c005-c1f3-42fb-aee9-9e8352da67ed Duration: 1728.11 ms Billed Duration: 1729 ms Memory Size: 128 MB Max Memory Used: 91 MB Init Duration: 413.89 ms
So, you can see that even though lambda is called once, some parts of it are called twice, and I don't know how to deal with it. I need to update weekly and monthly statistics as well, so the problem will get more complicated. Hack with ConditionExpression on last request ID works, but I'd ensure that code inside my function is not invoked twice rather than try to do such workarounds.
Following comment of #Jason Wadsworth, I changed all function invocations in exports.handler function by removing callback functions. Please note that I left callback parameters in dynamo related functions like updateDailyStats - without it, for some reason code didn't write to database.

How to integrate KendoUI chart with SignalR

i want to create a real time chart, using Kendo ui chart and signalr. I see this example, but has no code. So i try alone.
A little demonstration of my code:
At first I created a kendo chart
function queueActivityChart() {
$("#queueActivityChart").kendoChart({
legend: {
visible: true
},
seriesDefaults: {
labels: {
visible: true,
format: "{0}",
background: "transparent"
}
},
series: [{
type: "line",
field: "Incoming",
categoryField: "DateTime",
}],
valueAxis: {
labels: {
format: "{0}"
},
line: {
visible: false
}
},
categoryAxis: {
labels:
{
rotation: -90,
dateFormats:
{
seconds: "ss",
minutes: "HH:mm:ss",
hours: "HH:mm",
days: "dd/MM",
months: "MMM 'yy",
years: "yyyy"
}
}, type: "Date", field: "DateTime", baseUnit: "seconds"
}
});
var chart = $("#queueActivityChart").data("kendoChart");
chart.options.transitions = false;
}
$(document).ready(queueActivityChart);
$(document).bind("kendo:skinChange", queueActivityChart);
Then I have this part of code, that get from server data
$scope.signalRData = [];
$scope.signalR.on('receiveCounters', function (data) {
$scope.queueData = data;
for (var i = 0; i < data.length; i++) {
$scope.signalRData.push(data[i]);
}
while ($scope.signalRData.length > 12) {
$scope.signalRData.splice(0, 1);
}
$("#queueActivityChart").data("kendoChart").setDataSource(
new kendo.data.DataSource({
group: {
field: "Name"
},
data: $scope.signalRData
}));
});
This works! And I get a picture of the latest updated items.
But the problem is that this chart is like to put one picture in front of other. I mean that this is the first time that load Data Source; that creates a chart of my data, the second time my data has changed, some values are still in my array some others has move out, the third too.
It seems like it puts a picture of my current data in front of the
previous data. It's not smoothie and cannot use chart's legend
property because I initialize my Data Source everytime.
Can someone help me how can create a smoothie kendo chart with real time data like the kendo official example? Also can somehow to add scroller to bottom?
I looked at the code for the benchmark and I think you may be missing in your chart which is renderAs: "canvas"
Also, in the example, the data is kept locally (saved) and then moved so it creates that "smooth" effect you may be talking about.
Here is the code that you can be of interest:
function step() {
addPoint();
$("#chart").data("kendoChart").refresh();
frames++;
if (playing) {
kendo.animationFrame(step);
}
}
function addPoint() {
var stockData,
change,
lastValue;
// Shift existing categories to the left and add the next date at the end
lastDate = new Date(lastDate.getTime() + TICKS_PER_DAY);
categoryList.push((lastDate.getMonth() + 1) + "/" + (lastDate.getDay() + 1));
if (categoryList.length > POINTS) {
categoryList.shift();
}
for (var i = 0; i < stocks.length; i++) {
stockData = stocks[i];
change = (Math.random() > 0.5 ? 1 : - 1) * Math.random() * 10;
lastValue = stockData[stockData.length - 1] || Math.random() * 10;
// Add a new pseudo-random data point
stockData.push(Math.min((i + 1) * 20, Math.max((i + 1) * 10, lastValue + change)));
// Shift the data points of each series to the left
if (stockData.length > POINTS) {
stockData.shift();
}
}
}
Check out the source code of your example for the full source code and use the dojo to test our their code and play around with it easily

How to filter/sort OpenUI5 Grid by column, which is nested in the json?

I'm now testing the capabilities of this grid and I'm having a look at this example at the moment.
Last week, I tried some basic loading of data, returned from the controller of the MVC app that I'm working on. It returns json, which I then give to the grid to be displayed.
The data, that I want to show, is stored in multiple tables. For now, I load data from only two of them for simplicity, because I'm only testing the capabilities of the grid - will it suit our needs.
The data, which arrives at the grid (in js), looks something like this:
{
Cars: [
{
car_Number: '123',
car_Color: 'red',
car_Owner: Owner: {
owner_ID: '234',
owner_Name: 'John'
},
car_DateBought: '/Date(1450648800000)/'
},
{
car_Number: '456',
car_Color: 'yellow',
car_Owner: Owner: {
owner_ID: '345',
owner_Name: 'Peter'
},
car_DateBought: '/Date(1450648800000)/'
},
{
car_Number: '789',
car_Color: 'green',
car_Owner: Owner: {
owner_ID: '567',
owner_Name: 'Michael'
},
car_DateBought: '/Date(1450648800000)/'
}
]
}
Here is some sample code of what I have done so far:
$.ajax({
type: 'post',
url: BASE_HREF + 'OpenUI5/GetAllCars',
success: function (result) {
var dataForGrid = result['rows'];
debugger;
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(dataForGrid);
var oTable = new sap.ui.table.Table({
selectionMode: sap.ui.table.SelectionMode.Multi,
selectionBehavior: sap.ui.table.SelectionBehavior.Row,
visibleRowCountMode: sap.ui.table.VisibleRowCountMode.Auto,
minAutoRowCount: 10,
//visibleRowCount: 10,
showNoData: false
});
// define the Table columns and the binding values
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({
text: "ID of car"
}),
template: new sap.ui.commons.TextView({ text: "{car_Number}" }),
sortProperty: "car_Number", // https://sapui5.netweaver.ondemand.com/sdk/test-resources/sap/ui/table/demokit/Table.html#__2
filterProperty: "car_Number"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Color of car" }),
template: new sap.ui.commons.TextView({ text: "{car_Color}" }),
sortProperty: "car_Color",
filterProperty: "car_Color"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Car Owner ID" }),
template: new sap.ui.commons.TextView({
// does not work like this -> text: "{Owner.owner_ID}"
text: {
path: 'Owner',
formatter: function (owner) {
return owner !== null ? owner['owner_ID'] : '';
}
}
}),
sortProperty: "Owner.owner_ID", // these two don't work
filterProperty: "Owner.owner_ID"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Car Owner Name" }),
template: new sap.ui.commons.TextView({
// does not work like this -> text: "{Owner.owner_Name}"
text: {
path: 'Owner',
formatter: function (owner) {
return owner !== null ? owner['Name'] : '';
}
}
}),
sortProperty: "Owner.owner_Name", // these two don't work
filterProperty: "Owner.owner_Name"
}));
var dateType = new sap.ui.model.type.Date({ // http://stackoverflow.com/questions/22765286/how-to-use-a-table-column-filter-with-formatted-columns
pattern: "dd-MM-yyyy"
});
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({ text: "Date bought" }),
template: new sap.ui.commons.TextView({
text: {
path: 'car_DateBought',
formatter: dateFormatterBG
}
}),
sortProperty: "car_DateBought",
filterProperty: "car_DateBought",
filterType: dateType
}));
oTable.setModel(oModel);
oTable.bindRows("/");
oTable.placeAt("testTable", "only");
},
error: function (xhr, status, errorThrown) {
console.log("XHR:");
console.log(xhr);
console.log("Status:");
console.log(status);
console.log("ErrorThrown:");
console.log(errorThrown);
}
});
My problems:
I cannot sort or filter the list of cars by owner_ID or owner_Name. How should I do the filtering and sorting? Should it be done with the help of a formatter function in some way, or...?
I can sort by car_DateBought, but I cannot filter the cars by this field. First, I tried setting filterType: dateType, then I tried setting it to filterType: dateFormatterBG(it turns out, that dateType does exactly the same thing as my own dateFormatterBG does, btw).
function dateFormatterBG(cellvalue, options, rowObject) {
var formatedDate = '';
if ((cellvalue != undefined)) {
var date = new Date(parseInt(cellvalue.substr(6)));
var month = '' + (date.getMonth() + 1);
var day = '' + date.getDate();
var year = date.getFullYear();
if (month.length < 2) {
month = '0' + month;
}
if (day.length < 2) {
day = '0' + day;
}
formatedDate = [day, month, year].join('-');
}
return formatedDate;
}
Anyway, as I said, I tried both, but it doesn't work. When I click on the header of a column like in the example in the first link, I don't get any sort of a datepicker. How can I tell OpenUI5, that this column needs to be filtered by date and it should provide the user with a datepicker, when he/she clicks on the 'Filter' input field at the bottom of the dropdown menu? When I try to write the date in the filter field like '07-11-2016' (the way it is formatted), I get an empty table/grid. If I try to enter the huge number from field car_DateBought in the json object, all available rows in the table stay the same and when I reclick on the header, the filter field at the bottom of the dropdown menu appears with error-state.
Thank you in advance for your help and pieces of advice!
Edit:
This is just sample, dummy data. I try to load the real data and I see, that in the table I've got a couple of rows with date, which is today (07-11-2016, or 11/7/2016 if you prefer). That's why getting an empty table after trying to filter means it's not working correctly.
Sorting: in a sample I am looking at the following appears in the controller:
onInit : function () {
this._IDSorter = new sap.ui.model.Sorter("my_id", false);
},
....
Then in the view there is a button defined in the header column as
<Column>
<Label text="Project"/>
<Button icon="sap-icon://sort" press="onSortID" />
</Column>
And back in the controller there is a further function:
onSortID: function(){
this._IDSorter.bDescending = !this._IDSorter.bDescending;
this.byId("table").getBinding("items").sort(this._IDSorter);
},
I read this collectively as defining a sorter in the onInit(), then toggle/reversing it in the click event of the sort button in the column header via the onSortId() function. The OpenUI5 API doc re sorters indicates there are more parameters in the sorter constructor for initial sort direction and sorting function.
Following this pattern, for your needs to sort on the owner_ID or owner_Name, I assume you could set up a sorter as
this._OwnerIDSorter = new sap.ui.model.Sorter("car_Owner/owner_ID", false);
this._OwnerNameSorter = new sap.ui.model.Sorter("car_Owner/owner_Name", false);

ZoomRange Highstock works not correct?

I made a Highstock diagramm and got aproblem with zooming on the yAxis.
I have a Button and 2 textfield to get the wanted min/max values for the axis. With min:0, max: 100 it works well. With min:0, max:80 it doesn't (max will still be 100 in the Diagramm).
If I use the mouse for zooming it works well (even a min of: 3.7 and a max of 3.894 is possible). But using the mouse is not an Option, because in the later Diagramm there will be 3 yAxes with individual zoom.
$(function () {
var seriesOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'];
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createChart() {
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 4
},
chart:{
zoomType: 'xy'
},
yAxis: [
{
labels: {
format: '{value}',
},
height: '100%',
opposite: false,
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
],
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: seriesOptions
},
function(chart){
$('#btn').click(function(){
var min = temp_min.value,
max = temp_max.value;
chart.yAxis[0].setExtremes((min),(max));
});
});
}
$.each(names, function (i, name) {
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function (data) {
if(seriesCounter==0){
seriesOptions[i] = {
name: name,
data: data,
yAxis: 0
};
} else {
seriesOptions[i] = {
name: name,
data: data,
yAxis: 0
};
}
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter += 1;
if (seriesCounter === names.length) {
createChart();
}
});
});
});
JSFiddle
Another Question: Is it possible to set up a scrollbar for the yAxis as well?
Thanks for your help, Patrick
This is related with fact that tickInterval is not regular, so is rounded to value (like 100). The solution is using tickPositioner which calculates ticks, based on extremes which you define.
tickPositioner: function (min,max) {
var positions = [],
tick = Math.floor(min),
increment = Math.ceil((max - min) / 5);
for (tick; tick - increment <= max; tick += increment) {
positions.push(tick);
}
return positions;
},
http://jsfiddle.net/6s11kcwd/
The scrollbar is supported only for xAxis.

Kendo UI grid number column with template won't filter

I created a Kendo UI grid with two columns.
One is just a number called num0.
the other is is called num1 and it's data is created from num0 through a
template.
The filter on num0 works find.
The filter on num1 shows up and you can use it but
no matches are found. ie: filter on num1 and select "Is equal" and enter "2",
then click "Filter"
and grid is emptied when it should have shown the 1st record.
Also, I made the num0 column editable and the num1 column not editable.
I would like num1 column to change if num0 is edited.
I think it has something to do with the "template" that I am using
to fill num1 column.
What do I need to do to fix this so the filter works?
Thanks
http://jsfiddle.net/elbarto99/acyxekgx/
$(document).ready(function()
{
// Define the datasource for the grid.
var dsNums = new kendo.data.DataSource({
// NOTE: I don't want a num1: data field set to static values.
// I would like one that is set from "num0 + 1" and when num0 data is edited
// num1 would be updated to "num0 + 1"
data: [
{ num0: 1 },
{ num0: 2 },
{ num0: 3 },
{ num0: 4 },
],
schema:
{
model:
{
id: "myGridID",
fields:
{
num0: { type: "number" },
num1: { type: "number", editable: false },
}
}
}
});
// Create the grid.
var _grid = $("#grid").kendoGrid({
dataSource: dsNums,
filterable: { extra: false },
editable: true,
columns: [
{ field: "num0" , title: "Num 0" , width: "90px", },
// Add 1 to num0 and display in num1 column
// Note: A filter shows up and is for numbers but doesn't work
// I think it doesn't work because I am using a template.
//
// What do I need to do to make the filter for column num1 work like it does for num0?
{ field: "num1" , title: "Num 1 - Filter shows up but doesn't find matchs. :-(" , width: "90px", template: "#= num0 + 1 #", },
],
}).data("kendoGrid");
});
num1 value is not part of the data so filter will not filter by it. Filters work at datasource level and not presentation.
What you might do is computing that same value on schema.parse function. Something like:
parse: function(d) {
$.each(d, function(idx, elem) {
elem.num1 = elem.num0 + 1;
});
return d;
}
Your JSFiddle modified here: http://jsfiddle.net/OnaBai/acyxekgx/2/
Thanks OnaBai:
I modified your jfiddle
and add some editable settings so num0 column is editable and num1 column is not editable.
Is there a way to make num1's data and presentation get updated to num0 + 1 if num0 is edited?
ie: num0 changed to 11, num1's data gets changed to num0+1 or 12,
and filter on num1 to find 12 will list row 1.
Also, make the presentation of num1 set to 12 so the user can see the change.
http://jsfiddle.net/elbarto99/acyxekgx/
// Define the datasource for the grid.
var dsNums = new kendo.data.DataSource({
// NOTE: I don't want a num1: data field set to static values.
// I would like one that is set from "num0 + 1" and when num0 data is edited
// num1 would be updated to "num0 + 1"
data: [
{ num0: 1 },
{ num0: 2 },
{ num0: 3 },
{ num0: 4 }
],
schema:
{
model:
{
id: "myGridID",
fields:
{
num0: { type: "number" },
num1: { type: "number", editable: false }
}
},
// This changes the data for num1 at load time but
// if the data in num0 is edited this doesn't change data for num1
// at edit time.
parse: function(d) {
$.each(d, function(idx, elem) {
elem.num1 = elem.num0 + 1;
});
return d;
}
}
});
// Create the grid.
var _grid = $("#grid").kendoGrid({
dataSource: dsNums,
filterable: { extra: false },
editable: true,
columns: [
{ field: "num0", title: "Num 0", width: "90px" },
{ field: "num1", title: "Num 1", width: "90px" }
]
}).data("kendoGrid");

Resources