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...
Related
i am working on react-flow, and my task is to transform the following data => `
`const configObj = {
name: "Dataset",
nodeChild: {
type: "schema",
nodeConfiguration: {
sid1: {
name: "Schema 1",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did1: {
name: "Dashboard 1"
}
}
}
},
sid2: {
name: "Schema 2",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did2: {
name: "Dashboard s1",
},
did3: {
name: "Dashboard 3"
}
}
}
}
}
}
}` to this ->
const elements = [
{
id: '1',
type: 'input', // input node
data: { label: 'Input Node' },
position: { x: 250, y: 25 },
},
// default node
{
id: '2',
// you can also pass a React component as a label
data: { label: <div>Default Node</div> },
position: { x: 100, y: 125 },
},
{
id: '3',
type: 'output', // output node
data: { label: 'Output Node' },
position: { x: 250, y: 250 },
},
// animated edge
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e2-3', source: '2', target: '3' },
];
`
not exactly but according to data1 so i prepare a code for it and it is working well in node environment but the moment i try it on react it shows some errorenter image description here here is my code
const configObj = {
name: "Dataset",
onClick: true,
nodeChild: {
type: "schema",
nodeConfiguration: {
sid1: {
name: "Schema 1",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did1: {
name: "Dashboard 1"
}
}
}
},
sid2: {
name: "Schema 2",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did2: {
name: "Dashboard s1",
nodeChild: {
type: "ritik",
nodeConfiguration: {
ri1: {
name: "Ritik",
}
}
}
},
did3: {
name: "Dashboard 3"
}
}
}
}
}
},
}
let count =1;
let dataConfig = []
const recursion = (obj, level,type) => {
let objData = {}
for(let j in obj){
if(j !== 'nodeChild' && j !== 'nodeParent'){
if(j === 'name'){
objData= {
...objData,
label: obj[j]
}
}else {
objData= {
...objData,
[j]: obj[j]
}
}
}
}
let idd = count
dataConfig = [...dataConfig, {id: count, data: objData, type, level, parentID}]
count++;
if('nodeChild' in obj){
const {nodeConfiguration, type} = obj.nodeChild
for(let val in nodeConfiguration){
recursion(nodeConfiguration[val], level+1, type, parentID = idd)
}
}
if('nodeParent' in obj){
const {nodeConfiguration, type} = obj.nodeParent
for(let val in nodeConfiguration){
recursion(nodeConfiguration[val], level-1, type)
}
}
}
recursion(configObj, level=0, type='root', parentID=1)
let edges = []
for(let i=1; i<dataConfig.length; i++){
let e = {
id: `e${dataConfig[i].id}-${dataConfig[i].parentID}`,
source: `${dataConfig[i].parentID}`, target: `${dataConfig[i].id}`, animated: true
}
edges = [
...edges,
e
]
}
let finalDataSet = []
let x=650, y=25;
let flag = false;
for(let i in dataConfig){
let element = {}
for(let key in dataConfig[i]){
if(key !== 'parentID'){
if(key === 'type'){
let k = dataConfig[i][key]
if(k === 'schema' || k === 'root'){
element = {
...element,
[key]: 'input'
}
}else {
element = {
...element,
[key]: 'output'
}
}
}else {
element = {
...element,
[key]: dataConfig[i][key]
}
}
}
}
element = {
...element,
position: { x, y }
}
// console.log(i)
finalDataSet = [
...finalDataSet,
element
]
y += 75;
if(!flag){
x = 25;
}
x = flag ? x+155 : x
flag = true
}
for(let i =0; i<edges.length; i++){
finalDataSet = [
...finalDataSet,
edges[i]
]
}
const DataSET = finalDataSet
export default DataSET
this code is perfectly working on local nodejs but the same code pops errors on react.js can any one help me on this
It's the recursion(configObj, level=0, type='root', parentID=1) calls that are causing trouble. You think that level=0 is saying to pass 0 to the level parameter but javascript doesn't recognize that syntax. It thinks that level is some variable you forgot to define. Hence the is not defined error.
To fix the issue, just do something like recursion(configObj, 0, 'root', 1) instead.
I am trying to use High-charts in reactjs and I am new to both these. In the beginning, everything was fine but now I am unable to solve this error.
The following is my code:
Array.prototype.contains = function (v) {
for (var i = 0; i < this.length; i++) {
if (this[i] === v) return true;
}
return false;
};
Array.prototype.unique = function () {
var arr = [];
for (var i = 0; i < this.length; i++) {
if (!arr.contains(this[i])) {
arr.push(this[i]);
}
}
return arr;
}
export default class Chart extends React.Component {
constructor(props) {
super(props);
this.state = {
installs: [],
isLoaded: false,
}
this.state = {
filteredData: [],
isLoadedFilteredData: false,
showChart: true
}
this.state = {
options: {}
}
}
componentDidMount() {
// setInterval(() => {
fetch('xyz)
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
installs: json,
});
});
}
getFilteredData = async (operatingSystem, applicationServer, database, cloud, serverRelease) => {
fetch(`xyz`)
.then(res => res.json())
.then(json => {
// console.log(json);
this.setState({
isLoadedFilteredData: true,
filteredData: json,
}, console.log("getFilteredData called ... "));
});
}
handleChange = ({ altered, name, text, value }) => {
const nextFormValue = {
[name]: {
text,
value,
altered
}
};
this.setState({ ...this.state, ...nextFormValue }, () =>
console.log("handleChange()", this.state),
);
};
render() {
const { isLoaded, installs } = this.state;
const { isLoadedFilteredData, filteredData } = this.state;
if (!isLoaded) {
return <p>Loading...</p>;
}
else {
var arrayOS = []
var arrayApp = []
var arrayDB = []
var arrayCloud = []
var arrayServerRelease = []
for (var i = 0; i < installs.length; i++) {
arrayOS.push(this.state.installs[i].object.hardwareStackDetails.operatingSystem)
arrayApp.push(this.state.installs[i].object.hardwareStackDetails.applicationServer)
arrayDB.push(this.state.installs[i].object.hardwareStackDetails.database)
arrayCloud.push(this.state.installs[i].object.cloud)
arrayServerRelease.push(this.state.installs[i].object.serverRelease)
}
var operatingSystemTemp = arrayOS.unique();
var applicationServerTemp = arrayApp.unique();
var dataBaseTemp = arrayDB.unique();
var cloudTemp = arrayCloud.unique();
var serverReleaseTemp = arrayServerRelease.unique();
arrayOS = []
arrayApp = []
arrayDB = []
arrayCloud = []
arrayServerRelease = []
for (var i = 0; i < operatingSystemTemp.length; i++) {
arrayOS.push({
text: operatingSystemTemp[i],
value: operatingSystemTemp[i]
})
}
for (var i = 0; i < applicationServerTemp.length; i++) {
arrayApp.push({
text: applicationServerTemp[i],
value: applicationServerTemp[i]
})
}
for (var i = 0; i < dataBaseTemp.length; i++) {
arrayDB.push({
text: dataBaseTemp[i],
value: dataBaseTemp[i],
})
}
for (var i = 0; i < cloudTemp.length; i++) {
arrayCloud.push({
text: cloudTemp[i],
value: cloudTemp[i]
})
}
for (var i = 0; i < serverReleaseTemp.length; i++) {
arrayServerRelease.push({
text: serverReleaseTemp[i],
value: serverReleaseTemp[i]
})
}
if (isLoadedFilteredData){
if(filteredData.length === 0) {
console.log("filteredData")
mapNew = new Map();
labelMap = {};
xlabels = []
seriesDataValue = []
Highcharts.chart('container', {
title: {
text: ''
},
subtitle: {
// text: 'Source: thesolarfoundation.com'
},
xAxis: {
categories: xlabels
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
series: seriesDataValue,
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
}
);
}
else {
console.log(filteredData)
var mapNew = new Map();
var labelMap = {};
var xlabels = []
var seriesDataValue = []
for (var j = 0; j < filteredData.length; j++) {
if (filteredData[j].object.status === "PASS") {
var date1 = moment(filteredData[j].object.creationTime);
var date2 = moment(filteredData[j].object.updationTime);
var ms = moment(date2, "DD/MM/YYYY HH:mm:ss").diff(moment(date1, "DD/MM/YYYY HH:mm:ss"));
var d = moment.duration(ms);
// var s = d.format("hh:mm:ss");
console.log(ms)
console.log(d.hours())
var timeInhrs = d.hours()
if (mapNew.has(filteredData[j].object.clientBuild)) {
// timeInhrs = ((timeInhrs + mapNewInnerTemp.get(this.state.kuch[j].object.clientBuild)));
console.log(this.state.filteredData[j].object.clientBuild + " " + timeInhrs);
mapNew.set(this.state.filteredData[j].object.clientBuild, timeInhrs);
} else {
console.log(this.state.filteredData[j].object.clientBuild + " " + timeInhrs);
mapNew.set(this.state.filteredData[j].object.clientBuild, timeInhrs);
labelMap[this.state.filteredData[j].object.clientBuild] = 0; ///
//count = count + 1;
}
}
}
console.log(mapNew)
for (var key in labelMap) {
xlabels.push(key);
}
console.log(xlabels)
var dataValue = [] // array
for (const entry of mapNew.entries()) {
console.log(entry)
for (var key in labelMap) {
if (key === entry[0]) {
dataValue.push(entry[1])
}
}
}
console.log(dataValue)
seriesDataValue.push(
{
data: dataValue,
})
console.log(seriesDataValue)
var elementExists = document.getElementById("container");
if(elementExists === null){
let div = document.createElement("div");
div.id="container";
div.id="select"
document.body.appendChild(div);
}
Highcharts.chart('container',
xAxis: {
categories: xlabels
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
series: seriesDataValue,
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
}
);
}
}
return (
<div>
<div id="container"> </div>
</div>
);
}
}
}
The above error gets vanished after the page gets refreshed .
The error results from the fact that you create a chart before a div element with the 'container' id is created.
However, to avoid such problems I recommend you to use officially supported Highcharts wrapper for React: https://www.npmjs.com/package/highcharts-react-official
I need a create an one excel file with 3 worksheets. For now I wrote a function which create worksheet and workbook. I have problem because I need write data into workshet in some executed async function. Maybe some code will describe what I have to do.
var Excel = require('exceljs');
const workbook = new Excel.Workbook({
useStyles: true
})
const headers = [
{ header: 'Plik', key: 'path', width: 40 },
{ header: 'Zwierze', key: 'name', width: 12 },
{ header: 'Prawdopodobienstwo(%)', key: 'confidence', width: 24 },
{ header: 'Czas odpowiedzi(s)', key: 'responseTime', width: 20 }
];
workbook.xlsx.writeFile("./excel/Wyniki.xlsx");
setWorkSheet = (name, responses, filename) => {
workbook.xlsx.readFile(filename)
.then(function () {
const worksheet = workbook.addWorksheet(name);
worksheet.columns = headers;
for (let i = 0; i < responses.length; i++) {
worksheet.addRow(responses[i]);
}
worksheet.getRow(1).style.font = { size: 12, name: 'Bahnschrift SemiBold SemiConden' }
worksheet.getRow(1).eachCell((cell) => {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: '993399' }
},
cell.style.font = {
color: {
argb: 'ffffff'
},
size: 14,
}
})
worksheet.eachRow((Row, rowNumber) => {
Row.alignment = {
horizontal: 'center',
}
Row.eachCell((Cell, cellNumber) => {
Cell.alignment = {
vertical: 'middle',
horizontal: 'center'
},
Cell.border = {
top: { style: 'double', color: { argb: 'black' } },
left: { style: 'double', color: { argb: 'black' } },
bottom: { style: 'double', color: { argb: 'black' } },
right: { style: 'double', color: { argb: 'black' } }
}
})
})
worksheet.views = [
{ state: 'frozen', xSplit: 1, ySplit: 1, activeCell: 'B2' },
];
return workbook.xlsx.writeFile(`${filename}`)
})
.then(function () {
console.log("Done");
})
.catch(function (err) {
console.log(err)
});
}
And this function for now create a new file with special defined name worksheet. I need execute this function 3 times and after this operations I need to have one file and 3 worksheets. Here are places where I executed this function:
async function Cognitive() {
let tab = [];
for (let i = 0; i < arrayOfFiles.length; i++) {
let x = await cognitive.cognitiveDetectLabels(arrayOfFiles[i]);
tab.push(x)
}
setWorkSheet('Cognitive', tab, "./excel/Wyniki.xlsx");
}
exports.Cognitive = Cognitive;
async function Rekognition() {
let tab = [];
const path = "./csv/Rekognition.csv";
for (let i = 0; i < arrayOfFiles.length; i++) {
let x = await rekognitionFile.callaws(arrayOfFiles[i]);
tab.push(x)
}
setWorkSheet("Rekognition", tab, "./excel/Wyniki.xlsx");
}
exports.Rekognition = Rekognition;
async function Vision() {
let tab = [];
for (let i = 0; i < arrayOfFiles.length; i++) {
let x = await vision.callVision(arrayOfFiles[i]);
tab.push(x)
}
setWorkSheet("Vision", tab, "./excel/Wyniki.xlsx");
}
exports.Vision = Vision;
When I execute one of this async function. File with worksheet always is overwritten.
However, I need to add sheets to one file (3 sheets). Anyone have some ideas about this problem ? Thank you
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>
Can anyone show me how to parse an array of URL-like data to json?
Array ["a.b.c.d","a.c.e.f","a.b.c.g"] to this kind of json:
items:{
text: "a",
items:[
{
text:"b",
items:[
{
text:"c",
items:[
{
text:"d",
leaf:true
},
{
text:"g",
leaf:true
}
]
}
]
},
{
text:"c",
items:[
{
text:"e",
items:[
{
text:"f",
leaf:true
}
]
}
]
}
]
}
The following should work:
// ['a', 'b'] -> { text: 'a', items: [{ text: 'b', leaf: true }] }
function buildTree(components) {
if (components.length === 0) {
throw new Error('Can\'t parse: empty components');
} else if (components.length === 1) {
return { text: components[0], leaf: true };
} else {
return {
text: components[0],
items: [buildTree(components.slice(1))]
}
}
}
// 'a.b' -> { text: 'a', items: [{ text: 'b', leaf: true }] }
function parseString(str) {
return buildTree(str.split('.'));
}
// Merge nodes with a same text.
function mergeSame(left, right) {
if (left.text !== right.text) {
throw new Error('Can\'t merge: different text ' + left.text + ', ' + right.text);
}
// Same text
if (left.leaf && right.leaf) {
return left;
} else if (left.leaf && !right.leaf) {
return right;
} else if (!left.leat && right.leaf) {
return left;
} else {
var concat = left.items.concat(right.items);
return { text: left.text, items: merge(concat) };
}
}
// Merge multiple nodes.
function merge(items) {
var textToItem = {};
var keys = [];
for (var i = 0; i < items.length; i++) {
var text = items[i].text;
if (textToItem[text]) {
textToItem[text] = mergeSame(textToItem[text], items[i]);
} else {
textToItem[text] = items[i];
keys.push(text);
}
}
keys.sort();
var merged = [];
for (i = 0; i < keys.length; i++) {
merged.push(textToItem[keys[i]]);
}
return merged;
}
function parse(strs) {
var nodes = [];
for (var i = 0; i < strs.length; i++) {
nodes.push(parseString(strs[i]));
}
return { items: merge(nodes) };
}
console.log(parseString('a.b.c.d'));
console.log(parse(["a.b.c.d","a.c.e.f","a.b.c.g"]));
It may look messy. I was not sure about your environment and didn't use map or reduce.
You can use this demo.
Just remove unnecessary formatting ;) and change to local variables as you want.
I have written just parsing logic for you.
function parceArrayToExtJSTreeNodes(arr) {
for(i in arr) {
addNodesToTree(arr[i].split('.'));
}
createExtJSString(root, 0, true);
}
http://jsfiddle.net/HxFL6/