I need to create dynamic borders to labels and sub labels of chart.js graph. Is there any way of achieving this scenario?.
Below is the output I am expecting.
Labels and sub labels are having borders
Has anyone been able to achieve this with the library?
Thanks in advance.
I have tried this code but unable to get borders to labels.
var data = [{"omlPartgroupid":"191 ","xmonth":"10","xyear":"2015","QTY":"52"},{"omlPartgroupid":"191 ","xmonth":"11","xyear":"2015","QTY":"145"},{"omlPartgroupid":"191 ","xmonth":"12","xyear":"2015","QTY":"122"},{"omlPartgroupid":"191 ","xmonth":"1","xyear":"2016","QTY":"348"},{"omlPartgroupid":"191 ","xmonth":"2","xyear":"2016","QTY":"460"},{"omlPartgroupid":"191 ","xmonth":"3","xyear":"2016","QTY":"187"},{"omlPartgroupid":"191 ","xmonth":"4","xyear":"2016","QTY":"109"},{"omlPartgroupid":"191 ","xmonth":"5","xyear":"2016","QTY":"234"},{"omlPartgroupid":"191 ","xmonth":"6","xyear":"2016","QTY":"166"},{"omlPartgroupid":"191 ","xmonth":"7","xyear":"2016","QTY":"186"},{"omlPartgroupid":"191 ","xmonth":"8","xyear":"2016","QTY":"250"},{"omlPartgroupid":"191 ","xmonth":"9","xyear":"2016","QTY":"1077"},{"omlPartgroupid":"191 ","xmonth":"10","xyear":"2016","QTY":"594"},{"omlPartgroupid":"193 ","xmonth":"10","xyear":"2015","QTY":"39"},{"omlPartgroupid":"193 ","xmonth":"11","xyear":"2015","QTY":"183"},{"omlPartgroupid":"193 ","xmonth":"12","xyear":"2015","QTY":"136"},{"omlPartgroupid":"193 ","xmonth":"1","xyear":"2016","QTY":"212"},{"omlPartgroupid":"193 ","xmonth":"2","xyear":"2016","QTY":"460"},{"omlPartgroupid":"193 ","xmonth":"3","xyear":"2016","QTY":"176"},{"omlPartgroupid":"193 ","xmonth":"4","xyear":"2016","QTY":"187"},{"omlPartgroupid":"193 ","xmonth":"5","xyear":"2016","QTY":"174"},{"omlPartgroupid":"193 ","xmonth":"6","xyear":"2016","QTY":"151"},{"omlPartgroupid":"193 ","xmonth":"7","xyear":"2016","QTY":"164"},{"omlPartgroupid":"193 ","xmonth":"8","xyear":"2016","QTY":"237"},{"omlPartgroupid":"193 ","xmonth":"9","xyear":"2016","QTY":"798"},{"omlPartgroupid":"193 ","xmonth":"10","xyear":"2016","QTY":"662"},{"omlPartgroupid":"195 ","xmonth":"10","xyear":"2015","QTY":"9"},{"omlPartgroupid":"195 ","xmonth":"11","xyear":"2015","QTY":"38"},{"omlPartgroupid":"195 ","xmonth":"12","xyear":"2015","QTY":"35"},{"omlPartgroupid":"195 ","xmonth":"1","xyear":"2016","QTY":"68"},{"omlPartgroupid":"195 ","xmonth":"2","xyear":"2016","QTY":"161"},{"omlPartgroupid":"195 ","xmonth":"3","xyear":"2016","QTY":"73"},{"omlPartgroupid":"195 ","xmonth":"4","xyear":"2016","QTY":"69"},{"omlPartgroupid":"195 ","xmonth":"5","xyear":"2016","QTY":"56"},{"omlPartgroupid":"195 ","xmonth":"6","xyear":"2016","QTY":"55"},{"omlPartgroupid":"195 ","xmonth":"7","xyear":"2016","QTY":"50"},{"omlPartgroupid":"195 ","xmonth":"8","xyear":"2016","QTY":"114"},{"omlPartgroupid":"195 ","xmonth":"9","xyear":"2016","QTY":"1046"},{"omlPartgroupid":"195 ","xmonth":"10","xyear":"2016","QTY":"883"},{"omlPartgroupid":"197 ","xmonth":"10","xyear":"2015","QTY":"34"},{"omlPartgroupid":"197 ","xmonth":"11","xyear":"2015","QTY":"76"},{"omlPartgroupid":"197 ","xmonth":"12","xyear":"2015","QTY":"114"},{"omlPartgroupid":"197 ","xmonth":"1","xyear":"2016","QTY":"173"},{"omlPartgroupid":"197 ","xmonth":"2","xyear":"2016","QTY":"327"},{"omlPartgroupid":"197 ","xmonth":"3","xyear":"2016","QTY":"134"},{"omlPartgroupid":"197 ","xmonth":"4","xyear":"2016","QTY":"125"},{"omlPartgroupid":"197 ","xmonth":"5","xyear":"2016","QTY":"200"},{"omlPartgroupid":"197 ","xmonth":"6","xyear":"2016","QTY":"104"},{"omlPartgroupid":"197 ","xmonth":"7","xyear":"2016","QTY":"99"},{"omlPartgroupid":"197 ","xmonth":"8","xyear":"2016","QTY":"191"},{"omlPartgroupid":"197 ","xmonth":"9","xyear":"2016","QTY":"845"},{"omlPartgroupid":"197 ","xmonth":"10","xyear":"2016","QTY":"578"},{"omlPartgroupid":"199 ","xmonth":"10","xyear":"2015","QTY":"35"},{"omlPartgroupid":"199 ","xmonth":"11","xyear":"2015","QTY":"75"},{"omlPartgroupid":"199 ","xmonth":"12","xyear":"2015","QTY":"76"},{"omlPartgroupid":"199 ","xmonth":"1","xyear":"2016","QTY":"105"},{"omlPartgroupid":"199 ","xmonth":"2","xyear":"2016","QTY":"229"},{"omlPartgroupid":"199 ","xmonth":"3","xyear":"2016","QTY":"147"},{"omlPartgroupid":"199 ","xmonth":"4","xyear":"2016","QTY":"73"},{"omlPartgroupid":"199 ","xmonth":"5","xyear":"2016","QTY":"50"},{"omlPartgroupid":"199 ","xmonth":"6","xyear":"2016","QTY":"58"},{"omlPartgroupid":"199 ","xmonth":"7","xyear":"2016","QTY":"103"},{"omlPartgroupid":"199 ","xmonth":"8","xyear":"2016","QTY":"4230"},{"omlPartgroupid":"199 ","xmonth":"9","xyear":"2016","QTY":"2570"},{"omlPartgroupid":"199 ","xmonth":"10","xyear":"2016","QTY":"730"}];
var omlPartgroupid =[];
var xyear =[];
var xmonth =[];
var QTY=[];
var labelData = [];
for(var i in data){
omlPartgroupid.push("PartGroup"+ data[i].omlPartgroupid);
xyear.push(data[i].xyear);
xmonth.push(data[i].xmonth);
QTY.push(data[i].QTY);
labelData.push(data[i].xmonth + "|" + data[i].xyear + "|" + data[i].omlPartgroupid);
}
var chartdata ={
labels:labelData,
datasets :[
{
backgroundColor: 'rgba(200,200,200,0.75)',
borderColor: 'rgba(200,200,200,0.75)',
hoverBackground: 'rgba(200,200,200,1)',
hoverBorderColor: 'rgba(200,200,200,1)',
xAxisID:'time',
data:QTY
}
]
};
var ctx=$("#mycanvas");
var barGraph =new Chart(ctx,{
type: 'bar',
data: chartdata,
options: {
scales: {
xAxes:[ {
id: 'time',
type: 'category',
ticks: {
callback: function(label) {
var labelArray = label.split("|");
return labelArray[0] + "/" + labelArray[1];
}
}
},
{
id: 'partGroup',
type: 'category',
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
ticks: {
display:true,
callback: function(label) {
var labelArray = label.split("|");
return labelArray[0] === "10" && labelArray[1] == "2015" ? labelArray[2] : "";
}
}
}
]
}
}
});
<canvas id="mycanvas">
My web application which is using highchart v4.2.5 runs fine. However,when I update chrome to 62.0.3202.62, It goes wrong. Here is the error message:
highcharts.unminified.js:25 Uncaught TypeError: Cannot use 'in' operator to search for '0' in arguments_marker
at forEach (<anonymous>)
at s (highcharts.unminified.js:25)
at c.drawTrackerGraph [as drawTracker] (highcharts.unminified.js:330)
at c.render (highcharts.unminified.js:271)
at highcharts.unminified.js:232
at Array.forEach (<anonymous>)
at s (highcharts.unminified.js:25)
at C.Chart.renderSeries (highcharts.unminified.js:231)
at C.Chart.render (highcharts.unminified.js:233)
at C.Chart.firstRender (highcharts.unminified.js:236)
Only the data and the chrome version will results in the problem.Data is too big, so I keep it in a txt file.However , I can't upload the txt file, so I just give a sample of the data. My javascript code is as follows:
<div id="perfCPU"></div>
var mydata = [{x: "1509562856000",y: 137.55},{x: "1509562857000",y: 137.67},{x: "1509562858000",y: 137.67},{x: "1509562859000",y: 137.68},{x: "1509562861000",y: 137.83},{x: "1509562862000",y: 137.89}]
specialLine({domId: 'perfCPU', unit: "%", name: 'CPU', data: mydata,color: '#ffc966'})
function formatTime(unixTimeStamp) {
var date = new Date(unixTimeStamp) ;
var hours = date.getHours()
var minutes = "0" + date.getMinutes() //如果是3分4秒,那么返回的分钟数字是3.如果是13分4秒,返回的分钟数字是13
var seconds = "0" + date.getSeconds()
return hours + ":" + minutes.substr(-2) + ":" + seconds.substr(-2) //-2是从倒数第2个元素开始
}
function specialLine(config) {
//计算tickPositions的值
//转化data的横坐标为数字
var length = config.data.length
if (length > 0) {
var i =0 ;
for (i; i< length; i++) {
config.data[i].x = config.data[i].x - '' //将 "1487312495" to number
}
var startTime = config.data[0].x - '';
var endTime = config.data[length - 1].x - '';
var interval = ~~((endTime - startTime) /3)
var tickPositions = [];
if (length >=4) {
tickPositions = [startTime,startTime +interval,startTime +2*interval,endTime]
}else if(length == 3) {
tickPositions = [startTime, ~~((endTime + startTime)/2),endTime]
} else if(length == 2) {
tickPositions = [startTime,endTime]
} else if(length == 1) {
tickPositions = [startTime]
}
Highcharts.chart(config.domId, {
title: {
text: '',
},
xAxis: {
tickPositions: tickPositions,
labels: {
enabled: true,
formatter: function () {
//将timestamp转化为日期
return formatTime(this.value)
}
}
},
tooltip: {
//将timestamp转化为时间
useHTML: true,
formatter: function() {
//return DrawPic.formatTime(this.point.x) + '<br>' + config.name + ':' +this.point.y + config.unit
var showHtml = formatTime(this.point.x) + '<br>' + config.name + ':' +this.point.y + config.unit
return showHtml
}
},
legend: {
enabled: false
},
plotOptions: {
line: {
dataLabels: {
enabled: false
}
},
series: {
color: '#ffc966',
turboThreshold:0
}
},
credits: {
enabled: false
},
series: [{
name: 'whatever',
data: config.data
}]
});
}
}
https://jsfiddle.net/phbLL3q8/
I am working on adding ajax call to paper-icon-buttons that are rendered in an ag-grid cell renderer. Here is the script in my custom polymer component. The paper-icon-buttons do show up and clicking on them causes the ripple, but the functions in the on-tap are not being called.
Is there a better way to add the paper-icon-button entries to the cell? How can I add the registration of the on-tap properly?
Thank you!
<script>
function sourceRenderer(params) {
if (params.value)
return '<span>' + params.value + ''
else
return null;
}
function innerCellRendererA(params) {
var imageFullUrl = '/images/' + params.data.type + '.png';
if (params.data.type == 'entity') {
var entityUrl = '/analyze/' + params.data.asource + '/' + params.data.amodel + '/' + params.data.sourceName;
return '<img src="'+imageFullUrl+'" style="padding-left: 4px;" /> ' + params.data.name + ' (' + params.data.sourceName + ')';
}
else if (params.data.type == 'model') {
var entityUrl = '/harvest/' + params.data.asource + '/' + params.data.name;
return '<img src="'+imageFullUrl+'" style="padding-left: 4px;" /> ' + params.data.name + '';
}
else
return '<paper-icon-button src="'+imageFullUrl+'" on-tap="testjdbc" data-args="'+params.data.classname+'~~'+params.data.url+'~~'+params.data.username+'~~'+params.data.password+'"></paper-icon-button> ' +
'<paper-icon-button src="/images/database_export.svg" on-tap="harvestmodel" data-args="'+params.data.classname+'~~'+params.data.url+'~~'+params.data.username+'~~'+params.data.password+'"></paper-icon-button> ' + params.data.name;
}
Polymer({
is: 'easymetahub-analyze',
properties: {
sourcelist: {
type: Array,
notify: true
}
},
testjdbc: function(e){
alert('Foo');
var args = e.target.getAttribute('data-args').split('~~');
},
harvestmodel: function(e){
alert('Bar');
var args = e.target.getAttribute('data-args').split('~~');
},
handleData: function(e) {
var resp = e.detail.response;
this.sourcelist = resp;
},
ready: function() {
},
attached: function() {
agGrid.initialiseAgGridWithWebComponents();
var columnDefs = [
{
headerName: "Name",
'field': 'name',
width: 350,
cellRenderer: 'group',
sort: "asc",
cellRendererParams: {
innerRenderer: innerCellRendererA
}
},
{headerName: "Database Type", field: "databasetype", width: 120 },
{headerName: "URL", width: 250, field: "url" },
{headerName: "User Name", field: "username", width: 120 }
];
var gridOptions = {
columnDefs: columnDefs,
enableColResize: true,
rowHeight: 36,
enableSorting: true,
getNodeChildDetails: function(file) {
if (file.children) {
return {
group: true,
children: file.children,
expanded: file.open,
field: 'name',
key: file.name
};
} else {
return null;
}
},
onGridReady: function(params) {
params.api.sizeColumnsToFit();
}
};
this.$.myGrid.setGridOptions(gridOptions);
var eInput = this.$.quickFilterInput;
eInput.addEventListener("input", function () {
var text = eInput.value;
gridOptions.api.setQuickFilter(text);
});
},
detached: function() {
this.$.myGrid.api.destroy();
}
});
</script>
agGrid's grid options has a property for a callback -- onModelUpdated -- that is called when new rows are added to the grid.
attached: function() {
var self = this;
var gridOptions = {
...
onModelUpdated: function(e) {
self._bindGridIconTap();
}
};
}
You could use this event to query the grid for its paper-icon-buttons and add their on-tap attributes as event handlers.
_bindGridIconTap: function() {
this._bindActionsOnGrid('paper-icon-button', 'tap');
},
_bindActionsOnGrid: function(selector, eventName) {
var self = this;
var buttons = this.$.myGrid.querySelectorAll(selector);
buttons.forEach(function(b) {
self._bindEvent(b, eventName);
});
},
_bindEvent: function(el, eventName) {
var self = this;
var methodName = el.getAttribute('on-' + eventName);
var method = self[methodName];
if (method) {
el.addEventListener(eventName, function(e) {
method(e);
e.stopPropagation();
e.preventDefault();
return false;
});
} else {
console.warn(el.localName, 'listener method not found:', methodName);
}
}
plunker
Note you have a bug in:
var args = e.target.getAttribute('data-args').split('~~');
In a tap event for paper-icon-button, e.target is the icon image. You actually want e.currentTarget, which I've done for you in the Plunker.
following the documentation here
I have my own web service with JSON data just for testing purposes here
Ti.API.info('Received text: ' + this.responseText); shows the JSON in console, but when i try display in table I get undefined?
The documentation example uses json.figters.length --- i used json.places.length, as it is the name on array list on my web application.
var win = Ti.UI.createWindow();
var table = Ti.UI.createTableView();
var tableData = [];
var json, places, place, i, row, countryLabel, capitalLabel;
var xhr = Ti.Network.createHTTPClient({
onload : function(){
Ti.API.info('Received text: ' + this.responseText);
json = JSON.parse(this.responseText);
for (i=0; i < json.places.length; i++)
{
place = json.places[i];
row = Ti.UI.createTableViewRow({
height: '60dp'
});
countryLabel = Ti.UI.createLabel({
text: place.country,
font:{
fontSize:'24dp'
},
height: 'auto',
left: '10dp',
top: '5dp',
color: '#000',
touchEnabled:false
});
capitalLabel = Ti.UI.createLabel({
text:'"' + place.captial + '"',
font:{
fontSize:'16dp'
},
height: 'auto',
left: '15dp',
top: '5dp',
color: '#000',
touchEnabled:false
});
row.add(countryLabel);
row.add(capitalLabel);
tableData.push(row);
}//end for
table.setData(tableData);
},
onerror: function() {
Ti.API.info('error, HTTP status = ' + this.status);
alert('Error Reading Data');
},
timeout:5000
});
xhr.open("GET", "http://130.206.127.43:8080/Test");
xhr.send();
win.add(table);
win.open();
you're pushing 2 labels into a row, but a row does not have a wrapper view.
Try something like this:
var rowView Ti.UI.createView({height: 60, layout: 'horizontal'});
rowView.add(countryLabel);
rowView.add(capitalLabel);
row.add(rowView);
tableData.push(row);
I want to save my ViewModel to my SQL server. The standard knockout ko.toJSON(viewModel) keeps giving me an undefined error, so after some digging i found this Question, but still keeps giving me undefined.
Here is the code for my viewmodel, this is just a currency conversion table that gets the Conversion Rate between 2 currencies.
//ko Event Handler for datepicker.js
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(element).datepicker(options).on("changeDate", function (ev) {
var observable = valueAccessor();
observable(ev.date);
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).datepicker("setValue", value);
}
};
//Currency Model Definition
var currency = function (data) {
var self = this;
self.DateCreated = ko.observable(formatJsonDate(data.DateCreated));
self.CurrencyFrom = ko.observable(data.CurrencyFrom);
self.CurrencyTo = ko.observable(data.CurrencyTo);
self.ConversionRate = ko.observable(data.ConversionRate);
//Yhoo Finance API
ko.computed(function () {
var from = self.CurrencyFrom(),
to = self.CurrencyTo();
if (!from || !to) {
self.ConversionRate("N/A");
return;
}
getRate(from, to).done(function (YahooData) {
console.log("got yahoo data for [" + from + "," + to + "]: ", YahooData);
self.ConversionRate(YahooData.query.results.row.rate);
});
});
}
var NewDate = new Date().getFullYear() + '-' + ("0" + (new Date().getMonth() + 1)).slice(-2) + '-' + new Date().getDate();
var CurrencyModel = function (Currencies) {
var self = this;
self.Currencies = ko.observableArray(Currencies);
self.AddCurrency = function () {
self.Currencies.push({
DateCreated: NewDate,
CurrencyFrom: "",
CurrencyTo: "",
ConversionRate: ""
});
};
self.RemoveCurrency = function (Currency) {
self.Currencies.remove(Currency);
};
self.Save = function () {
$.ajax({
url: "#",
contentType: 'application/json',
data: ko.mapping.toJSON(CurrencyModel),
type: "POST",
dataType: 'json',
success: function (data) {
//I get undefined....
alert(ko.mapping.toJSON(CurrencyModel));
},
error: function (data) { alert("error" + data); }
});
}
$.ajax({
url: "CurrencyConfiguration.aspx/GetConfiguredCurrencies",
data: '{}',
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "JSON",
timeout: 10000,
success: function (Result) {
// callback(Result);
var MappedCurrencies =
$.map(Result.d,
function (item) {
getRate(item.CurrencyFrom, item.CurrencyTo);
return new currency(item);
}
);
self.Currencies(MappedCurrencies);
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
};
function formatJsonDate(jsonDate) {
var FormatDate = new Date(parseInt(jsonDate.substr(6)));
var Output = FormatDate.getFullYear() + '-' + ("0" + (FormatDate.getMonth() + 1)).slice(-2) + '-' + FormatDate.getDate();
return (Output);
};
function getRate(from, to) {
return $.getJSON("http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D" + from + to + "%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=?");
}
function callback(data) {
if (viewModel) {
// model was initialized, update it
ko.mapping.fromJS(data, viewModel);
} else {
// or initialize and bind
viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
}
}
$('#Date').datepicker();
$(document).ready(function () {
var VM = new CurrencyModel();
ko.applyBindings(VM);
})
data: ko.mapping.toJSON(CurrencyModel)
You are trying to JSONify the definition not the actual instance
Isn't the method that you want to use:
ko.toJSON
rather than off the mapping object?