There is a chart that shows the statistics , production has been sold in any quantity in any city.
enter image description here
I need to add another value , for what amount it was sold . On the second day I'm sitting , I can not figure out how to do it .
here is the link
function ev(str) {
eval(str)
}
function regression(x, y, typ) {
var type = (typ == null) ? 'linear' : typ;
var N = x.length;
var slope;
var intercept;
var SX = 0;
var SY = 0;
var SXX = 0;
var SXY = 0;
var SYY = 0;
var Y = [];
var X = [];
if (type == 'linear') {
X = x;
Y = y;
} else if (type == 'exp' || type == 'exponential') {
for (var i = 0; i < y.length; i++) {
// ignore points <= 0, log undefined.
if (y[i] <= 0) {
N = N - 1;
} else {
X.push(x[i]);
Y.push(Math.log(y[i]));
}
}
}
for (var i = 0; i < N; i++) {
SX = SX + X[i];
SY = SY + Y[i];
SXY = SXY + X[i] * Y[i];
SXX = SXX + X[i] * X[i];
SYY = SYY + Y[i] * Y[i];
}
slope = (N * SXY - SX * SY) / (N * SXX - SX * SX);
intercept = (SY - slope * SX) / N;
return [slope, intercept];
}
function linearRegression(X, Y) {
var ret;
ret = regression(X, Y, 'linear');
return [ret[0], ret[1]];
}
function expRegression(X, Y) {
var ret;
var x = X;
var y = Y;
ret = regression(x, y, 'exp');
var base = Math.exp(ret[0]);
var coeff = Math.exp(ret[1]);
return [base, coeff];
}
function fitData(data, typ) {
var type = (typ == null) ? 'linear' : typ;
var ret;
var res;
var x = [];
var y = [];
var ypred = [];
for (i = 0; i < data.length; i++) {
if (data[i] != null && Object.prototype.toString.call(data[i]) === '[object Array]') {
if (data[i] != null && data[i][0] != null && data[i][1] != null) {
x.push(data[i][0]);
y.push(data[i][1]);
}
} else if (data[i] != null && typeof data[i] === 'number') { //If type of X axis is category
x.push(i);
y.push(data[i]);
} else if (data[i] != null && Object.prototype.toString.call(data[i]) === '[object Object]') {
if (data[i] != null && data[i].x != null && data[i].y != null) {
x.push(data[i].x);
y.push(data[i].y);
}
}
}
if (type == 'linear') {
ret = linearRegression(x, y);
for (var i = 0; i < x.length; i++) {
res = ret[0] * x[i] + ret[1];
ypred.push([x[i], res]);
}
return {
data: ypred,
slope: ret[0],
intercept: ret[1],
y: function(x) {
return (this.slope * x) + this.intercept;
},
x: function(y) {
return (y - this.intercept) / this.slope;
}
};
} else if (type == 'exp' || type == 'exponential') {
ret = expRegression(x, y);
for (var i = 0; i < x.length; i++) {
res = ret[1] * Math.pow(ret[0], x[i]);
ypred.push([x[i], res]);
}
ypred.sort();
return {
data: ypred,
base: ret[0],
coeff: ret[1]
};
}
}
function showGraph(zero) {
zero = typeof zero === "undefined" ? true : zero
sourceData.sort(function(a, b) {
return a[0] - b[0]
})
series = {}
seriesSum = []
dateStart = new Date(sourceData[0][0].toString().replace(/(\d{4})(\d{2})(\d{2})/g, "$1-$2-$3"))
dateEnd = new Date(sourceData[sourceData.length - 1][0].toString().replace(/(\d{4})(\d{2})(\d{2})/g, "$1-$2-$3"))
sourceData.map(function(entry) {
var date = new Date(entry[0].toString().replace(/(\d{4})(\d{2})(\d{2})/g, "$1-$2-$3"))
var microtime = date.getTime()
var dealer = entry[2]
var sum = entry[3]
//int
if (typeof entry[1] === "undefined") {
entry[1] = 0
}
//create group
if (typeof series[dealer] === "undefined") {
series[dealer] = []
}
//find similar day
if (series[dealer].length > 0 && series[dealer][series[dealer].length - 1][0] === microtime) {
series[dealer][series[dealer].length - 1][1] += entry[1]
} else {
series[dealer].push([microtime, entry[1]])
}
//mixed sum
if (seriesSum.length > 0 && seriesSum[seriesSum.length - 1][0] === microtime) {
seriesSum[seriesSum.length - 1][1] += entry[1]
} else {
seriesSum.push([microtime, entry[1]])
}
})
seriesByName = {}
seriesArray = []
_.map(series, function(days, dealer) {
var newDays = []
if (zero) {
for (var dateTemp = new Date(dateStart.getTime()), i = 0; dateTemp < dateEnd; dateTemp.setDate(dateTemp.getDate() + 1)) {
var microtime = dateTemp.getTime()
try {
if (days[i][0] == microtime) {
newDays.push(days[i])
i++
} else {
newDays.push([microtime, 0])
}
} catch (error) {}
}
} else {
newDays = days
}
seriesByName[dealer] = newDays
seriesArray.push({
name: dealer,
data: newDays,
id: dealer,
dataGrouping: {
approximation: "sum",
enabled: true,
forced: true,
units: [
['day', [1]]
],
dateTimeLabelFormats: {
week: ['За 7 дней начиная от "%A, %b %e, %Y"', '%A, %b %e', '-%A, %b %e, %Y']
}
}
})
})
graphContainer = $('#graph').highcharts('StockChart', {
rangeSelector: {
buttons: [, {
type: 'month',
count: 1,
text: '1м'
}, {
type: 'month',
count: 2,
text: '2м'
}, {
type: 'month',
count: 6,
text: '6м'
}, {
type: 'year',
count: 1,
text: '1г'
}, {
type: 'all',
text: 'Весь'
}],
selected: 5
},
tooltip: {
//pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
animation: false,
valueDecimals: 0
},
yAxis: [{
/*labels: {
formatter: function () {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},*/
}, {
labels: {
enabled: false
}
}],
plotOptions: {
series: {
//compare: 'percent'
}
},
series: seriesArray,
legend: {
align: 'center',
verticalAlign: 'bottom',
layout: 'horizontal',
enabled: true
}
})
graph = graphContainer.highcharts()
grouped = false
$('#groupWeek').on('click', function() {
for (var i = 0; i < graph.series.length; i++) {
var serie = graph.series[i]
if (grouped) {
serie.update({
dataGrouping: {
units: [
['day', [1]]
]
}
})
} else {
serie.update({
dataGrouping: {
units: [
['week', [1]]
]
}
})
}
}
grouped = grouped ? false : true
if (grouped) {
$(this).text('Убрать группировку')
} else {
$(this).text('Группировать по неделям')
}
})
percent = false
$('#changePercent').on('click', function() {
for (var i = 0; i < graph.series.length; i++) {
var serie = graph.series[i]
if (percent) {
serie.update({
compare: 'value'
})
} else {
serie.update({
compare: 'percent'
})
}
}
percent = percent ? false : true
if (percent) {
$(this).text('Представить в значениях')
} else {
$(this).text('Представить в процентах')
}
})
trend = false
trendArrayId = []
$('#showTrendline').on('click', function() {
if (grouped) $('#groupWeek').trigger('click')
if (trend) {
while (trendArrayId.length) {
graph.get(trendArrayId.pop()).remove()
}
} else {
var countSeries = graph.series.length
for (var iteratorSeries = 0; iteratorSeries < countSeries; iteratorSeries++) {
var serie = graph.series[iteratorSeries]
if (serie.name !== 'Navigator') {
var data = fitData(seriesByName[serie.name]).data
trendArrayId.push('trend_' + serie.name)
graph.addSeries({
data: data,
color: serie.color,
visible: serie.visible,
linkedTo: serie.name,
name: 'Тенденция (' + serie.name + ')',
id: 'trend_' + serie.name,
dataGrouping: {
approximation: "sum",
enabled: true,
forced: true,
units: [
['day', [1]]
]
}
})
}
}
}
trend = trend ? false : true
if (trend) {
$(this).text('Убрать линии тенденции')
} else {
$(this).text('Вывести линии тенденции')
}
})
}
var sourceData = [
[20140829, 63, "Москва и МО", 100],
[20140930, 1, "Краснодар", 100],
[20140819, 1, "Краснодар", 100],
[20141120, 1, "Краснодар", 100],
[20141010, 1, "Краснодар", 100],
[20141003, 2, "Краснодар", 100],
[20140825, 81, "Москва и МО", 100],
[20140822, 77, "Москва и МО", 100],
[20140918, 90, "Москва и МО", 100],
[20140930, 128, "Москва и МО", 100],
[20141031, 85, "Москва и МО", 100],
[20140827, 105, "Москва и МО", 100],
[20141027, 141, "Москва и МО", 100],
];
if (!oldBrowser) {
$(showGraph(false));
}
One option would be to add a hidden series with your extra value to the chart series: { visible: false ... } and display the value only in the tooltip.
You can override the tooltip formatter using the following property:
http://api.highcharts.com/highcharts#tooltip.formatter
Ensuring you have tooltip: { shared: true ... } setting, you can access all series values for a given x value.
This gives you the flexibility to use a hidden series OR another option would be to have a reference dictionary that you can use to look up your extra value (using the x value as the key) and render it in the tooltip.
Related
i am trying to access the properties of a chart point in a Highcharts chart that is being used in a React application, but when i click on the point, the event.target object that is passed to the event handler function is showing all keys as null.
my graph has some filters to sort data by week, last 30 days, custom, and today.
when i click on any point before filtering event.target function shows object fulfilled with every key but when i filtered and my gaprh gets updated with new value which works fine but event.target start showing all keys as null
export const getChartConfig = (
showingStats,
data,
labels,
graphFilter,
filter,
dates,
pointerClickSetter,
) => {
let line1Data = [];
let line2Data = [];
let line3Data = [];
let line4Data = [];
let line5Data = [];
let line6Data = [];
let yAxisLabels = ['', ''];
const totalNeeded = labels.length;
const totalFilled = data.length;
if (totalNeeded === totalFilled) {
Array(totalNeeded)
.fill(0)
.map((item, index) => {
line1Data.push([labels[index], data[index].panelPower]);
line2Data.push([labels[index], data[index].panelVoltage]);
line3Data.push([labels[index], data[index].batteryVoltage]);
line4Data.push([labels[index], data[index].batteryPower]);
line5Data.push([labels[index], data[index].generatedEnergy]);
line6Data.push([labels[index], data[index].consumedEnergy]);
});
} else {
if (filter === 'hourly') {
labels.map((item) => {
const indexOf = [...data].findIndex((eachItem) => {
if (dayjs().date() == dayjs(eachItem.date).utc().format('DD')) {
return dayjs(eachItem.date).utc().format('HH') == item;
}
});
if (indexOf !== -1) {
const format = dayjs(data[indexOf].date).utc().format('HH');
if (format == item) {
line1Data.push([item, data[indexOf].panelPower]);
line2Data.push([item, data[indexOf].panelVoltage]);
line3Data.push([item, data[indexOf].batteryVoltage]);
line4Data.push([item, data[indexOf].batteryPower]);
line5Data.push([item, data[indexOf].generatedEnergy]);
line6Data.push([item, data[indexOf].consumedEnergy]);
} else {
line1Data.push([item, 0]);
line2Data.push([item, 0]);
line3Data.push([item, 0]);
line4Data.push([item, 0]);
line5Data.push([item, 0]);
line6Data.push([item, 0]);
}
} else {
line1Data.push([item, 0]);
line2Data.push([item, 0]);
line3Data.push([item, 0]);
line4Data.push([item, 0]);
line5Data.push([item, 0]);
line6Data.push([item, 0]);
}
});
} else if (filter === 'daily') {
const lastNDays = graphFilter === 'Last 7 Days' ? getLastNDays(7) : labels;
lastNDays.map((item, index) => {
const indexOf = [...data].findIndex((eachItem) => {
return dayjs(eachItem.date).utc().format('DD-MMM-YYYY') === item;
});
if (indexOf !== -1) {
line1Data.push([labels[index], data[indexOf].panelPower]);
line2Data.push([labels[index], data[indexOf].panelVoltage]);
line3Data.push([labels[index], data[indexOf].batteryVoltage]);
line4Data.push([labels[index], data[indexOf].batteryPower]);
line5Data.push([labels[index], data[indexOf].generatedEnergy]);
line6Data.push([labels[index], data[indexOf].consumedEnergy]);
} else {
line1Data.push([labels[index], 0]);
line2Data.push([labels[index], 0]);
line3Data.push([labels[index], 0]);
line4Data.push([labels[index], 0]);
line5Data.push([labels[index], 0]);
line6Data.push([labels[index], 0]);
}
});
} else if (filter === 'weekly') {
const lastNWeeks = getNWeeks(5);
const lastNDays = getLastNDays(30);
let tempDates = [...data].map((eachItem) => dayjs(eachItem.date).utc().format('DD-MMM-YYYY'));
let includedArr = tempDates.map((tempDate) => {
let tempDateObj = dayjs(tempDate);
for (let i = 0; i <= lastNWeeks.length - 1; i++) {
if (dayjs(tempDateObj > lastNWeeks[i]) && tempDateObj < dayjs(lastNWeeks[i + 1])) {
return lastNWeeks[i];
}
}
});
lastNWeeks.map((item, index) => {
const indexOf = includedArr.indexOf(item);
if (indexOf !== -1) {
line1Data.push([labels[index], data[indexOf].panelPower]);
line2Data.push([labels[index], data[indexOf].panelVoltage]);
line3Data.push([labels[index], data[indexOf].batteryVoltage]);
line4Data.push([labels[index], data[indexOf].batteryPower]);
line5Data.push([labels[index], data[indexOf].generatedEnergy]);
line6Data.push([labels[index], data[indexOf].consumedEnergy]);
} else {
line1Data.push([labels[index], 0]);
line2Data.push([labels[index], 0]);
line3Data.push([labels[index], 0]);
line4Data.push([labels[index], 0]);
line5Data.push([labels[index], 0]);
line6Data.push([labels[index], 0]);
}
});
}
}
const allSeries = [];
if (showingStats[0].showing) {
allSeries.push(getSeriesConfig('#5ad8a6', line1Data, 'Solid', 0, false));
}
if (showingStats[1].showing) {
allSeries.push(getSeriesConfig('#5ad8a6', line2Data, 'ShortDot', 1, true));
}
if (showingStats[2].showing) {
allSeries.push(getSeriesConfig('#e8684a', line3Data, 'ShortDot', 0, false));
}
if (showingStats[3].showing) {
allSeries.push(getSeriesConfig('#e8684a', line4Data, 'Solid', 1, true));
}
if (showingStats[4].showing) {
allSeries.push(getSeriesConfig('#0000FF', line5Data, 'Solid', 0, false));
}
if (showingStats[5].showing) {
allSeries.push(getSeriesConfig('#0000FF', line6Data, 'ShortDot', 1, true));
}
showingStats.forEach((stat) => {
if (stat.value.includes('voltage') && stat.showing) {
yAxisLabels[1] = 'Voltage (Volts)';
}
if (stat.value.includes('current') && stat.showing) {
yAxisLabels[0] = 'Current (Amperes)';
}
});
const options = {
chart: {
type: 'line',
zoomType: 'x',
},
reflow: true,
credits: false,
exporting: {
enabled: false,
},
title: {
text: '',
},
// Current (Amperes)
//
yAxis: [
{
// Secondary yAxis
title: {
text: yAxisLabels[0],
},
labels: {
format: '{value}',
},
},
{
// Primary yAxis
labels: {
format: '{value}',
},
title: {
text: yAxisLabels[1],
},
opposite: true,
},
],
xAxis: {
type: 'category',
tickInterval: 1,
categories: [...labels],
accessibility: {
rangeDescription: '',
},
crosshair: {
width: 1,
color: '#2296f3',
},
},
plotOptions: {
spline: {
states: {
hover: {
enabled: true, //shows dots when hover on the line
},
},
marker: {
enabled: false,
},
},
series: {
allowPointSelect: true,
point: {
events: {
select: pointerClickSetter, //<---- here is the problem --- pointerClickSetter is a setter funtion of useState ---
},
},
// data: allSeries,
label: {
connectorAllowed: true,
},
pointStart: 1,
},
},
tooltip: {
backgroundColor: '#ffffff',
borderColor: '#ffffff',
crosshairs: [true, false],
formatter: function () {
const value1 = line1Data[labels.indexOf(this.x)][1].toFixed(2) || 0;
const value2 = line2Data[labels.indexOf(this.x)][1].toFixed(2) || 0;
const value3 = line3Data[labels.indexOf(this.x)][1].toFixed(2) || 0;
const value4 = line4Data[labels.indexOf(this.x)][1].toFixed(2) || 0;
const value5 = line5Data[labels.indexOf(this.x)][1].toFixed(2) || 0;
const value6 = line6Data[labels.indexOf(this.x)][1].toFixed(2) || 0;
return (
'Panel Voltage: <b>' +
value2 +
'V</b>' +
'<br><br>Panel Current: <b>' +
value1 +
'A</b>' +
'<br><br>Battery Voltage: <b>' +
value4 +
'V</b>' +
'<br><br>Battery Current: <b>' +
value3 +
'A</b>' +
'</b>' +
'<br><br>Solar Generation: <b>' +
value5 +
'Wh</b>' +
'</b>' +
'<br><br>Power Consumption: <b>' +
value6 +
'Wh</b>'
);
},
},
series: [...allSeries],
};
return options;
};
<HighchartsReact
highcharts={Highcharts}
options={getChartConfig(
showingStats,
data,
labels,
graphFilter,
graphSubFilter,
currentDates,
chartPointerSetter,
)}
/>
That's because the getChartConfig function is called again on state change which triggers unnecessary chart updating through the HighchartsReact component.
You should keep your chart options in a state, memorize them or if your chart is static, disable the allowChartUpdate option.
<HighchartsReact
...
allowChartUpdate={false}
/>
Docs: https://github.com/highcharts/highcharts-react#optimal-way-to-update
The issue detail:
1. I implement the feature with the vue-slider-component module, but that has a lot of warnings when I move the dots on the slider.
2. I know that the reason is that I used v-for to point to an object that will change, but I do not know how to fix this issue.
the following link is my test site:
https://jsfiddle.net/ncwv84x9/
enter image description here
My codes:
code1 (Html)
<div id="app">
<div class="box" v-for="(item,index) in columnvalue">
<label>{{item.text}}</label>
<input v-model="value[index]" />
</div>
<hr />
<br />
<vue-slider v-model="value" :order="false" :tooltip="'always'" :process="false" :marks="marks" :width="600">
<template slot="tooltip" slot-scope="{index}">
<div>{{getText(index)}}</div>
</template>
</vue-slider>
</div>
JavaScript + Vue:
new Vue({
el: '#app',
components: {
VueSlider: window['vue-slider-component']
},
data: function() {
return {
// collect the all values
columnvalue: [],
// stored disease value
pet_name: [{
text: 'dog',
index: 0
},
{
text: 'cat',
index: 1
}
],
// stored drug value
feeder_name: [{
text: 'Sam',
index: 0
}],
// from age filter
age: [
65, 100
],
test: "",
value: [],
process: dotsPos => [
[dotsPos[0], dotsPos[1], {
backgroundColor: 'pink'
}],
[dotsPos[1], dotsPos[2], {
backgroundColor: 'blue'
}],
[dotsPos[2], dotsPos[3], {
backgroundColor: 'black'
}],
],
after: {},
relations: [],
marks: {
'0': {
label: 'start',
margin: '0 0 0 10px'
},
'100': {
label: 'end',
labelStyle: {
left: '100%',
margin: '0 0 0 10px',
top: '50%',
transform: 'translateY(-50%)'
}
}
}
}
},
created: function() {
//vue instance 被 constructor 建立後,在這裡完成 data binding
let tmpArray = this.pet_name.concat(this.feeder_name);
let tmpValueArray = [];
for (i = 0; i < tmpArray.length; i++) {
tmpArray[i].index = i;
tmpValueArray.push(0);
}
this.columnvalue = tmpArray;
this.value = tmpValueArray;
},
methods: {
getText(index) {
const ani = this.columnvalue.find((v) => v.index == index).text;
this.after = {
...this.after,
[ani]: this.value[index]
}
return ani;
},
getNodeRelation() {
const indexs = this.after;
let result = [];
let result2 = [];
let placement = [];
for (obj in indexs) {
placement.push([obj, indexs[obj]]);
}
placement.sort(function(a, b) {
/* console.log(a[1]) */
return a[1] - b[1];
})
for (i = 0; i < placement.length; i++) {
if (i + 1 >= placement.length) {
break;
}
let distance = placement[i + 1][1] - placement[i][1];
let predicate = "";
if (distance > 0) {
predicate = "after";
} else if (distance == 0 && placement[i + 1][1] == 0) {
predicate = "hasUse";
} else {
predicate = "same";
}
let source = {
label: placement[i][0],
index: i
};
let target = {
label: placement[i + 1][0],
index: i
};
// store the 4-tuple reprsentations about slider
result2.push({
source: source,
target: target,
type: predicate,
days: distance
});
}
/* this.relations = "{\"relation\":" + JSON.stringify(result2)+"}" */
;
this.relations = JSON.stringify(result2);
},
getAllFilters() {
let vm = this;
let beginHas = true;
if (vm.relations.length == 0) {
vm.getNodeRelation();
beginHas = false;
}
let result = {
age: vm.age,
disease_name: vm.disease_name,
drug_name: vm.drug_name,
relation: vm.relations
};
if (!beginHas) {
vm.relations = [];
}
this.test = JSON.stringify(result);
}
},
})
I get a infinite loop error which disappears when I remove this section in getText()
this.after = {
...this.after,
[ani]: this.value[index]
}
This is because there is some reactivity triggered and re-renders the dom, which calls that function, which renders the dom and so on...
I have this code from an old website. I want to initialize this function in my custom js file. But I can't understand how to call this function in my custom.js file. Actually, This code performs as like as a scrollable slider which behaves that when I scroll to down than previous & next scroll step will be opacity 0 and current step opacity will be 1.
(window.webpackJsonpOdmans = window.webpackJsonpOdmans || []).push([
[64], {
433: function(t, e, i) {},
435: function(t, e, i) {
var n = {
"./oddmans-cross-grey.svg": 436,
"./global-scroll.svg": 437
};
function s(t) {
var e = o(t);
return i(e)
}
function o(t) {
var e = n[t];
if (!(e + 1)) {
var i = new Error("Cannot find module '" + t + "'");
throw i.code = "MODULE_NOT_FOUND", i
}
return e
}
s.keys = function() {
return Object.keys(n)
}, s.resolve = o, t.exports = s, s.id = 435
},
436: function(t, e, i) {
"use strict";
i.r(e), e.default = {
id: "icon-oddmans-cross-grey-usage",
viewBox: "33 -33 88 88",
url: i.p + "scroll-steps.svg#icon-oddmans-cross-grey",
toString: function() {
return this.url
}
}
},
437: function(t, e, i) {
"use strict";
i.r(e), e.default = {
id: "icon-global-scroll-usage",
viewBox: "0 0 14 22",
url: i.p + "scroll-steps.svg#icon-global-scroll",
toString: function() {
return this.url
}
}
},
482: function(t, e, i) {
"use strict";
i.r(e), i(16), i(11), i(12), i(433);
var n = i(1),
s = (i(28), i(34), i(35), i(36), i(5), i(6), i(29), i(3), i(8), i(9), i(10), i(0)),
o = i(4),
r = i.n(o),
a = i(2);
function l(t) {
return (l = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) {
return typeof t
} : function(t) {
return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t
})(t)
}
function h(t) {
return (h = Object.setPrototypeOf ? Object.getPrototypeOf : function(t) {
return t.__proto__ || Object.getPrototypeOf(t)
})(t)
}
function u(t, e) {
return (u = Object.setPrototypeOf || function(t, e) {
return t.__proto__ = e, t
})(t, e)
}
function c(t) {
if (void 0 === t) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return t
}
var d = function(t) {
function e() {
var t, i, n;
! function(t, i) {
if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
}(this);
for (var s = arguments.length, o = new Array(s), r = 0; r < s; r++) o[r] = arguments[r];
return (i = !(n = (t = h(e)).call.apply(t, [this].concat(o))) || "object" !== l(n) && "function" != typeof n ? c(this) : n).setBinds = i.setBinds.bind(c(c(i))), a.f.isTouch && !a.f.deviceTypeByViewport !== a.c ? i.onTouchDetect() : (i.setBinds(), i.initContent()), i
}
var i;
return function(t, e) {
if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
t.prototype = Object.create(e && e.prototype, {
constructor: {
value: t,
writable: !0,
configurable: !0
}
}), e && u(t, e)
}(e, s.a), (i = [{
key: "setBinds",
value: function() {
this.showNextStep = this.showNextStep.bind(this), this.initContent = this.initContent.bind(this), this.onScroll = this.onScroll.bind(this), this.setIndex = this.setIndex.bind(this), this.change = this.change.bind(this), this.setHiddens = this.setHiddens.bind(this), this.addListeners = this.addListeners.bind(this), this.goScroll = this.goScroll.bind(this)
}
}, {
key: "onTouchDetect",
value: function() {
this.element.classList.add("scroll-steps--second-style")
}
}, {
key: "initContent",
value: function() {
this.steps = this.refs.steps, this.btn = this.refs.btn, this.cross = this.refs.cross, this.scrollIcon = this.refs.scrollIcon, this.toDown = !0, this.blockEvent = !1, this.duration = 600, this.index = 0, this.height = this.element.getBoundingClientRect().height;
for (var t = 0; t < this.steps.length; t++) this.steps[t].style.visibility = "hidden", this.steps[t].style.opacity = 0, this.steps[t].hiddenElements = function(t) {
if (Array.isArray(t)) {
for (var e = 0, i = new Array(t.length); e < t.length; e++) i[e] = t[e];
return i
}
}(e = this.steps[t].querySelectorAll(".hidden")) || function(t) {
if (Symbol.iterator in Object(t) || "[object Arguments]" === Object.prototype.toString.call(t)) return Array.from(t)
}(e) || function() {
throw new TypeError("Invalid attempt to spread non-iterable instance")
}(), this.steps[t].header = this.steps[t].querySelector(".scroll-steps__title");
var e;
this.setIndex(), this.currentStep.style.visibility = "", this.currentStep.style.opacity = 1, this.setHiddens(this.currentStep, "remove"), this.addListeners()
}
}, {
key: "addListeners",
value: function() {
var t = this;
this.btn.addEventListener("click", function() {
t.toDown = !0, t.goScroll(t.height)
}), document.body.addEventListener("wheel", this.onScroll)
}
}, {
key: "goScroll",
value: function(t) {
r()({
targets: "body, html",
duration: 500,
scrollTop: t,
easing: "easeInOutQuart"
})
}
}, {
key: "setHiddens",
value: function(t, e) {
for (var i = 0; i < t.hiddenElements.length; i++) t.hiddenElements[i].classList[e]("hidden")
}
}, {
key: "onScroll",
value: function(t) {
this.blockEvent && t.preventDefault();
var e = window.pageYOffset < .6 * this.height;
if (!this.blockEvent && e) {
var i = t.deltaY;
i > 0 && this.nextStep ? (t.preventDefault(), this.toDown = !0, this.change()) : i < 0 && this.previousStep && (t.preventDefault(), this.toDown = !1, window.pageYOffset > 0 && e && this.goScroll(0), this.change())
}
}
}, {
key: "change",
value: function() {
this.index >= 0 && this.index < this.steps.length && (this.blockEvent = !0, 0 === this.index && (this.scrollIcon.classList.add("hidden"), console.log("hided")), this.setHiddens(this.currentStep, "add"), r()({
targets: this.currentStep.header,
opacity: 0,
translateY: this.toDown ? "-50px" : "50px",
duration: .7 * this.duration,
easing: "easeInSine"
}), r()({
targets: this.currentStep,
opacity: 0,
translateY: [{
value: "-50%",
duration: 0
}, {
value: this.toDown ? "-90%" : "-10%",
duration: this.duration
}],
duration: this.duration,
easing: "easeInSine",
complete: this.showNextStep
}))
}
}, {
key: "showNextStep",
value: function() {
var t = this;
this.currentStep.style.visibility = "hidden";
var e = this.toDown ? this.nextStep : this.previousStep;
e.style.visibility = "", this.toDown ? this.index++ : this.index--, this.setIndex(), 0 === this.index && this.scrollIcon.classList.remove("hidden"), r()({
targets: this.cross,
rotate: [{
value: 0,
duration: 0
}, {
value: this.toDown ? 90 : -90,
duration: .7 * this.duration
}],
easing: "easeInOutSine"
}), r()({
targets: e.header,
opacity: [{
value: 0,
duration: 0
}, {
value: 1,
duration: .7 * this.duration
}],
translateY: [{
value: this.toDown ? "-50px" : "50px",
duration: 0
}, {
value: 0,
duration: .7 * this.duration
}],
easing: "easeOutSine"
}), r()({
targets: e,
opacity: [{
value: 0,
duration: 0
}, {
value: 1,
duration: this.duration
}],
translateY: [{
value: this.toDown ? "-10%" : "-90%",
duration: 0
}, {
value: "-50%",
duration: this.duration
}],
easing: "easeOutSine",
complete: function() {
t.blockEvent = !1, t.setHiddens(e, "remove")
}
})
}
}, {
key: "setIndex",
value: function() {
this.previousStep = this.steps[this.index - 1] || null, this.currentStep = this.steps[this.index], this.nextStep = this.steps[this.index + 1] || null
}
}]) && function(t, e) {
for (var i = 0; i < e.length; i++) {
var n = e[i];
n.enumerable = n.enumerable || !1, n.configurable = !0, "value" in n && (n.writable = !0), Object.defineProperty(t, n.key, n)
}
}(e.prototype, i), e
}(),
p = i(435);
p.keys().forEach(p), n.a.getInstance().define("scroll-steps", d)
}
},
[
[482, 0]
]
]);
I want to set different baground color for each cell in xslx in angular4.
But no style effect appear on excel.Is there any solution?
My code is below.
import { saveAs } from 'file-saver';
const XLSX = require('xlsx');
const wb = {SheetNames: [], Sheets: {}};
const ws_name = 'Report';
/* create worksheet: */
const ws: any = {};
/* the range object is used to keep track of the range of the sheet */
const range = { s: { c: 0, r: 0 }, e: { c: 0, r: 0 } };
/* Iterate through each element in the structure */
for (let R = 0; R < data.length; R++) {
if (range.e.r < R) {
range.e.r = R;
}
for (let C = 0; C < data[R].length; C++) {
if (range.e.c < C) {
range.e.c = C;
}
// tslint:disable-next-line:max-line-length
const cell = { v: data[R][C], s: { alignment: { textRotation: 90 }, font: { sz: 16, bold: true, color: '#FF00FF' }, fill: { bgColor: '#FFFFFF' } }, t: 's' };
if (cell.v == null) {
continue;
}
/* create the correct cell reference */
const cell_ref = XLSX.utils.encode_cell({ c: C, r: R });
/* determine the cell type */
if (typeof cell.v === 'number') {
cell.t = 'n';
} else if (typeof cell.v === 'boolean') {
cell.t = 'b';
} else {
cell.t = 's';
}
/* add to structure */
ws[cell_ref] = cell;
}
}
ws['!ref'] = XLSX.utils.encode_range(range);
const wscols = [
{ wch: 4 }, // "characters"
{ wch: 3 },
{ wch: 20 },
{ wch: 45 },
{ wch: 13 },
{ wch: 30 },
{ wch: 15 },
{ wch: 5 },
{ wch: 20 },
{ wch: 3 },
{ wch: 15 },
{ wch: 15 },
{ wch: 12 },
{ wch: 75 }
];
ws['!cols'] = wscols;
wb.SheetNames.push(ws_name);
/**
* Set worksheet sheet to "narrow".
*/
ws['!margins'] = { left: 0.25, right: 0.25, top: 0.75, bottom: 0.75, header: 0.3, footer: 0.3 };
wb.Sheets[ws_name] = ws;
const wbout = XLSX.write(wb, {
type: 'binary',
bookSST: true,
bookType: 'xlsx',
cellStyles: true
});
saveAs(new Blob([this.s2ab(wbout)], { type: 'application/octet-stream' }), 'report.xlsx');
I installed both xlsx and xlsx-styles.
npm install xlsx ,
npm install xlsx-style
Any one can help me to find the solution.Thanks in advance.
I'm making an application and I have to display data in a chart. I also only want the last 5 transactions entered to display.
I'm using Backbone.js and Chart.js. In my prototype displaying data was no problem because I just bootstrapped the data. But now that I'm trying to pull the data from my Backbone Collection it's not working. I only get a transparent image
// Model
(function (exports) {
var Transaction = Backbone.Model.extend({
defaults: {
amount: 0,
transactionDate: "",
transactionType: "debit",
category: "miscellaneous",
description: ""
},
categories: [
"salary",
"rent",
"miscellaneous"
],
transactionTypes: [
"credit",
"debit"
],
initialize: function() {
this.set({transactionDate: this.attributes.transactionDate || Date.now()}, {validate: true});
},
validate: function(attrs, options) {
if (attrs['transactionType'] !== undefined &&
!_.contains(this.transactionTypes, attrs['transactionType'].toLowerCase())) {
return 'Invalid type: ' + attrs['transactionType'];
} else if (attrs['category'] !== undefined &&
!_.contains(this.categories, attrs['category'].toLowerCase())) {
return 'Invalid category: ' + attrs['category'];
} else if (attrs['transactionDate'] !== undefined &&
_.isNaN(parseInt(attrs['transactionDate'])) || attrs['transactionDate'] < 0) {
return 'Invalid date: '+ attrs['transactionDate'];
} else if (attrs['amount'] !== undefined &&
_.isNaN(parseInt(attrs['amount'])) || attrs['amount'] < 0) {
return 'Invalid amount: '+ attrs['amount'];
}
return null;
}
});
// export for global use
exports.expensus.Models.Transaction = Transaction;
}(this));
This is the collection I'm using ..
;(function (exports) {
var Transactions = Backbone.Collection.extend({
// stuff and thangs
model: expensus.Models.Transaction,
localStorage: new Backbone.LocalStorage('TransactionsCollection'),
latestFive: function(toJSON) {
this.sortByDate(-1); // sort latest first
if (!toJSON) {
return _.first(this.models, 5);
} else {
var models = _.first(this.models, 5),
idx = -1,
json = [],
model;
while (model = models[++idx]) {
json.push(model.attributes);
}
return json;
}
},
sortByDate: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("transactionDate");
};
this.sort();
},
sortByAmount: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("amount");
};
this.sort();
}
});
exports.expensus.Collections.Transactions = Transactions;
}(this));
And this is the Chart View, I get no errors in dev tools so I'm really at a loss ...
;(function (exports){
var ChartView = Backbone.View.extend({
el: ".home-page",
template: Handlebars.compile($("#chart-template").html()),
chart: null,
initialize: function () {
this.listenTo(this.collection, "add", this.render);
this.listenTo(this.collection, "change", this.render);
this.$(".chart-view-div").html(this.template());
this.chart = new Chart($("#expense-chart")[0].getContext("2d"));
this.render();
},
render: function() {
var self = this;
var data = this.chartData();
self.chart.Doughnut(data, {
responsive: true,
animateScale: true
});
},
chartData: function() {
var collection = this.collection.latestFive(true);
var data = {
vals: [],
labels: [],
allData: []
};
var getData = function(color, highlight, labels, vals, collection) {
var object = {
color: color,
highlight: highlight,
chartData: [
{
value: "",
label: ""
}
]
};
for (var i = 0; i < labels.length; i++ ) {
object.chartData.push(0);
}
for (var j = 0; j < vals.length; j++ ) {
object.chartData.push(0);
}
for (var i = 0; i < collection.length; i++ ) {
var item = collection[i];
var label = labels.indexOf(item.category);
var val = vals.indexOf(item.amount);
object.chartData[ { value: val, label: label } ]++;
}
return object;
};
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
for (var i = 0; i < collection.length; i++ ) {
var object = collection[i];
var color = getRandomColor();
var highlight = getRandomColor();
data.labels.push(object.category);
data.vals.push(object.amount);
data.allData.push(getData(color, highlight, data.labels, data.vals, collection));
}
return data;
}
});
exports.expensus.Views.ChartView = ChartView;
}(this));
My Add Transaction View
;(function (exports) {
var AddTransactionView = Backbone.View.extend({
el: "#add-transaction-page",
events: {
"submit .add-transaction-form": "addTransaction"
},
initialize: function() {
this.form = this.$(".add-transaction-form")[0];
},
addTransaction: function(evt) {
if (evt) {
evt.preventDefault();
}
var m = new expensus.Models.Transaction({
transactionDate: Date.now(),
transactionType: this.form["trans-type"].value,
amount: this.form["trans-amount"].value,
description: this.form["trans-description"].value,
category: this.form["trans-category"].value
});
if(m.validationError === null) {
this.collection.add(m);
m.save();
$(this.el).modal("hide");
this.form.reset();
} else {
alert("Model is invalid: " + m.validationError);
}
}
});
exports.expensus.Views.AddTransactionView = AddTransactionView;
}(this));
This is as far as I could get. I've done this before with a different kind of chart but can't for the life of me figure it out with the Doughnut chart.
Thanks, everyone
The main thing i can see is that you pass the chart data which is not in the format that chartjs expects, so it should be an array of objects which have the properties value label and color but you are passing it something different. so a quick fix for that would be to construct an array as described
// Model
var Transaction = Backbone.Model.extend({
defaults: {
amount: 0,
transactionDate: "",
transactionType: "debit",
category: "miscellaneous",
description: ""
},
categories: [
"salary",
"rent",
"miscellaneous"
],
transactionTypes: [
"credit",
"debit"
],
initialize: function() {
this.set({
transactionDate: this.attributes.transactionDate || Date.now()
}, {
validate: true
});
},
validate: function(attrs, options) {
if (attrs['transactionType'] !== undefined && !_.contains(this.transactionTypes, attrs['transactionType'].toLowerCase())) {
return 'Invalid type: ' + attrs['transactionType'];
} else if (attrs['category'] !== undefined && !_.contains(this.categories, attrs['category'].toLowerCase())) {
return 'Invalid category: ' + attrs['category'];
} else if (attrs['transactionDate'] !== undefined && _.isNaN(parseInt(attrs['transactionDate'])) || attrs['transactionDate'] < 0) {
return 'Invalid date: ' + attrs['transactionDate'];
} else if (attrs['amount'] !== undefined && _.isNaN(parseInt(attrs['amount'])) || attrs['amount'] < 0) {
return 'Invalid amount: ' + attrs['amount'];
}
return null;
}
});
var Transactions = Backbone.Collection.extend({
// stuff and thangs
model: Transaction,
latestFive: function(toJSON) {
this.sortByDate(-1); // sort latest first
if (!toJSON) {
return _.first(this.models, 5);
} else {
var models = _.first(this.models, 5),
idx = -1,
json = [],
model;
while (model = models[++idx]) {
json.push(model.attributes);
}
return json;
}
},
sortByDate: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("transactionDate");
};
this.sort();
},
sortByAmount: function(dir) {
dir = dir || -1;
this.comparator = function(transaction) {
return dir * transaction.get("amount");
};
this.sort();
}
});
var ChartView = Backbone.View.extend({
el: ".home-page",
template: Handlebars.compile($("#chart-template").html()),
chart: null,
initialize: function() {
this.listenTo(this.collection, "add", this.render);
this.listenTo(this.collection, "change", this.render);
this.$(".chart-view-div").html(this.template());
this.chart = new Chart(this.$("#expense-chart")[0].getContext("2d"));
this.render();
},
render: function() {
var self = this;
var data = this.chartData();
this.chart.Doughnut(data, {
responsive: true,
animateScale: true
});
},
chartData: function() {
var collection = this.collection.latestFive(true);
var data = [];;
var getData = function(color, highlight, labels, vals, collection) {
var object = {
color: color,
highlight: highlight,
chartData: [{
value: "",
label: ""
}]
};
for (var i = 0; i < labels.length; i++) {
object.chartData.push(0);
}
for (var j = 0; j < vals.length; j++) {
object.chartData.push(0);
}
for (var i = 0; i < collection.length; i++) {
var item = collection[i];
var label = labels.indexOf(item.category);
var val = vals.indexOf(item.amount);
object.chartData[{
value: val,
label: label
}] ++;
}
return object;
};
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
for (var i = 0; i < collection.length; i++) {
var object = collection[i];
var color = getRandomColor();
var highlight = getRandomColor();
data.push({
value: object.amount,
color: color,
label: object.category
});
}
return data;
}
});
var collection = new Transactions([{
amount: 12,
transactionDate: 1417442176000,
transactionType: "debit",
category: "miscellaneous",
description: ""
}, {
amount: 13,
transactionDate: 1417442176000,
transactionType: "credit",
category: "salary",
description: ""
}]);
var view = new ChartView({
collection: collection
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone.js"></script>
<script src="http://www.chartjs.org/assets/Chart.min.js"></script>
<script id="chart-template" type="text/x-handlebars-template">
<canvas id="expense-chart"></canvas>
</script>
<div class="home-page">
<div class="chart-view-div"></div>
</div>