Calculate sum of object array field - node.js

Working on a Node App with Express as the web framework and Mongo as the backend. Currently, I have a Mongoose data schema with players and associated statistics. Here's an anonymized example of the structure:
name: 'Player Name',
image: 'image-location',
position: 'Guard',
description: 'Player Detail',
__v: 6,
weight: 200,
dob: 1993-08-03T05:00:00.000Z,
hometown: 'town-name',
country: 'country-name',
height_feet: 6,
height_inches: 4,
season: [
{
year: '2012-2013',
grade: 'Freshman',
gp: 18,
gs: 0,
mpg: 6.9,
fg: 0.348,
tp: 0.278,
ft: 1,
rpg: 0.8,
apg: 1,
spg: 0.3,
bpg: 0,
ppg: 1.4
},
{
year: '2013-2014',
grade: 'Sophomore',
gp: 36,
gs: 7,
mpg: 20.3,
fg: 0.432,
tp: 0.4,
ft: 0.643,
rpg: 1.6,
apg: 1.1,
spg: 0.2,
bpg: 0.1,
ppg: 7.1
},
{
year: '2014-2015',
grade: 'Junior',
gp: 34,
gs: 33,
mpg: 27.5,
fg: 0.449,
tp: 0.391,
ft: 0.755,
rpg: 2.9,
apg: 2,
spg: 0.8,
bpg: 0.1,
ppg: 10.1
},
{
year: '2015-2016',
grade: 'R. Senior',
gp: 8,
gs: 8,
mpg: 31.6,
fg: 0.425,
tp: 0.291,
ft: 0.6,
rpg: 2.9,
apg: 1.9,
spg: 0.6,
bpg: 0.3,
ppg: 12
},
{
year: '2016-2017',
grade: 'Senior',
gp: 35,
gs: 35,
mpg: 33.3,
fg: 0.473,
tp: 0.384,
ft: 0.795,
rpg: 4.6,
apg: 2.7,
spg: 1.2,
bpg: 0,
ppg: 15.1
}
]
}
I'm still fairly new to Mongo and Node as a whole, so pardon the elementary question. How would I be able to calculate the average of a particular statistic for the total number of seasons (e.g. 4 year average of points per game)?
The goal here is to calculate the value and have it available and passed on the GET route for the player page. Here's the route I have for the player page:
router.get("/:id", function(req, res){
Player.findById(req.params.id).populate("comments").exec(function(err, foundPlayer){
if(err){
console.log(err);
} else {
console.log(foundPlayer)
res.render("players/show", {player: foundPlayer});
}
});
});
What can I do to both calculate this value and have it available for use on the player page?

You have to iterate over seasons array and find the average. For example:
const { season } = <.........your MongoDB response>
let average = 0;
if(season.length){
let total = 0
season.map(({ gp }) => (total += gp))
average = total / season.length
}
The variable average will give you the answer. I've shown an example to calculate average of gp

we can use aggregate pipeline to calculate the average directly within the query
db.collection.aggregate([
{
$match: {
_id: "playerId1" // this needs to be of type ObjectId, it should be something like mongoose.Types.ObjectId(req.params.id) in your case
}
},
{
$unwind: "$season" // unwind the season array to get a stream of documents, and to be able to calculate the average of ppg
},
{
$group: { // then group them again
_id: "$_id",
averagePointsPerGame: {
$avg: "$season.ppg"
},
season: {
$push: "$season"
}
}
}
])
you can test it here Mongo Playground
hope it helps

Related

default rows per page is overriding items-per-page attribute in v-data-iterator in Vuetify 1.5.2

I'm working on a vue.js application which uses Vuetify 1.5.2. I'm having trouble setting the items-per-page attribute of the v-data-iterator:
<v-data-iterator
:items="facilities"
:items-per-page.sync="facilitiesPerPage"
content-tag="v-layout"
rows-per-page-text="Facilities per page"
row
wrap
>
<v-flex slot="item" slot-scope="props" xs12 sm6 md4 lg3 x12>
<facility :facility="props.item"></facility>
</v-flex>
</v-data-iterator>
data: () => ({
facilitiesPerPage: 4,
facilities: [],
...
})
According to this, I would think the data-iterator would display 4 items per page. But that's not what's happening. It seems to be defaulting to the number of items per page set in the footer by default. Since we don't set the rows-per-page-items explicitely, it default to [5, 10, 25, 'All'], and 5 is selected by default:
This seems to be overriding the items-per-page value.
What we want to do is make the items-per-page value dynamic, changing based on the screen width. We lay our items out horizontally, wrapping to multiple rows if necessary, so we want as many items per row as can fit within the screen width. Then facilitiesPerPage is to be calculated based on this number multiplied by the number of rows.
We want something like this:
https://www.codeply.com/p/bFrSEsnq4L
But this only works in Vuetify 2.0, and we have to deal with Vuetify 1.5.2. So we're trying to customize our own design.
What's blocking us now is that the default number of items per page seems to be overriding what we set for items-per-page. Is there any way to prevent this in Vuetify 1.5.2?
Thanks.
It is possible to change the items-per page dynamically in Vuetify 1.5.2 version.
Here is the working codepen:
https://codepen.io/chansv/pen/oNjqNoG?editors=1010
You have to use the following props to achieve this:
In the version 1.5.2 it is not items-per-page instead it should be :rows-per-page-items
To set the rows per page text, you can use this props :rows-per-page-text="'Facilities per page'"
Dynamically select the value for rows-per-page, you can use this props :pagination.sync="paginationSync" and set the value in object as {rowsPerPage: 30} // 10, 20, or any
<div id="app">
<v-app id="inspire">
<v-data-table
:headers="headers"
:items="desserts"
class="elevation-1"
:rows-per-page-items="rowsPerPage"
:rows-per-page-text="'Facilities per page'"
:pagination.sync="paginationSync"
>
<template v-slot:items="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.calories }}</td>
<td class="text-xs-right">{{ props.item.fat }}</td>
<td class="text-xs-right">{{ props.item.carbs }}</td>
<td class="text-xs-right">{{ props.item.protein }}</td>
<td class="text-xs-right">{{ props.item.iron }}</td>
</template>
</v-data-table>
</v-app>
</div>
new Vue({
el: '#app',
data () {
return {
paginationSync: {rowsPerPage: 30},
rowsPerPage: [10, 20, 30, 40, 50],
headers: [
{
text: 'Dessert (100g serving)',
align: 'left',
sortable: false,
value: 'name'
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' }
],
desserts: [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%'
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%'
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%'
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
iron: '8%'
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
iron: '16%'
},
{
name: 'Jelly bean',
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
iron: '0%'
},
{
name: 'Lollipop',
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
iron: '2%'
},
{
name: 'Honeycomb',
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
iron: '45%'
},
{
name: 'Donut',
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
iron: '22%'
},
{
name: 'KitKat',
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
iron: '6%'
}
]
}
}
})

Angular4 and Devextreme scheduler

i try to use the devexpress's scheduler plugin into my project.
After creating a project using angular Cli and installing the devexpress plugin using this command :
npm install --save devextreme devextreme-angular
Here is what i've get in my project :
calendrier.component.css
/deep/ .options {
padding: 20px;
background-color: #f5f5f5;
margin-top: 20px;
}
/deep/ .caption {
font-size: 18px;
font-weight: 500;
}
/deep/ .option {
margin-top: 10px;
display: inline-block;
width: 19%;
}
/deep/ .switcher-mode {
width: 100%;
}
/deep/ .option > span {
margin-right: 10px;
}
/deep/ .option > .dx-selectbox {
display: inline-block;
vertical-align: middle;
}
calendrier.component.html
<dx-scheduler
style="height: 100%; display: block"
[dataSource]="appointmentsData"
[currentDate]="currentDate"
startDateExpr="StartDate"
endDateExpr="EndDate"
textExpr="Text"
[views]="['agenda','workWeek']"
currentView="workWeek"
[firstDayOfWeek]="1"
[startDayHour]="9"
[endDayHour]="19"
[resources]="resourcesData"
></dx-scheduler>
calendrier.component.ts
import { NgModule, Component, enableProdMode } from '#angular/core';
import {BrowserModule} from '#angular/platform-browser';
import {platformBrowserDynamic} from '#angular/platform-browser-dynamic';
import {Appointment, Resource, Service} from './calendrier.service';
import {DxSchedulerModule, DxCheckBoxModule, DxSelectBoxModule} from 'devextreme-angular';
if(!/localhost/.test(document.location.host)) {
enableProdMode();
}
#Component({
selector: 'calendrier',
templateUrl: './calendrier.component.html',
styleUrls: ['./calendrier.component.css'],
providers: [Service]
})
export class CalendrierComponent {
appointmentsData: Appointment[];
currentDate: Date = new Date(2015, 4, 25);
resourcesData: Resource[];
switchModeNames: string[];
constructor(service: Service) {
this.switchModeNames = ["Tabs", "Drop-Down Menu"];
this.appointmentsData = service.getAppointments();
this.resourcesData = service.getResources();
}
}
#NgModule({
imports: [
BrowserModule,
DxSchedulerModule,
DxCheckBoxModule,
DxSelectBoxModule
],
declarations: [CalendrierComponent],
bootstrap: [CalendrierComponent]
})
export class CalendrierModule {}
platformBrowserDynamic().bootstrapModule(CalendrierModule)
calendrier.component.service
import { Injectable } from "#angular/core";
export class Appointment {
text: string;
ownerId: number[];
startDate: Date;
endDate: Date;
allDay?: boolean;
recurrenceRule?: string;
}
export class Resource {
text: string;
id: number;
color: string;
}
let appointments: Appointment[] = [
{
text: "Website Re-Design Plan",
ownerId: [4],
startDate: new Date(2015, 4, 25, 9, 30),
endDate: new Date(2015, 4, 25, 11, 30)
}, {
text: "Book Flights to San Fran for Sales Trip",
ownerId: [2],
startDate: new Date(2015, 4, 25, 12, 0),
endDate: new Date(2015, 4, 25, 13, 0),
allDay: true
}, {
text: "Install New Router in Dev Room",
ownerId: [1],
startDate: new Date(2015, 4, 25, 14, 30),
endDate: new Date(2015, 4, 25, 15, 30)
}, {
text: "Approve Personal Computer Upgrade Plan",
ownerId: [3],
startDate: new Date(2015, 4, 26, 10, 0),
endDate: new Date(2015, 4, 26, 11, 0)
}, {
text: "Final Budget Review",
ownerId: [1],
startDate: new Date(2015, 4, 26, 12, 0),
endDate: new Date(2015, 4, 26, 13, 35)
}, {
text: "New Brochures",
ownerId: [4],
startDate: new Date(2015, 4, 26, 14, 30),
endDate: new Date(2015, 4, 26, 15, 45)
}, {
text: "Install New Database",
ownerId: [2],
startDate: new Date(2015, 4, 27, 9, 45),
endDate: new Date(2015, 4, 27, 11, 15)
}, {
text: "Approve New Online Marketing Strategy",
ownerId: [3, 4],
startDate: new Date(2015, 4, 27, 12, 0),
endDate: new Date(2015, 4, 27, 14, 0)
}, {
text: "Upgrade Personal Computers",
ownerId: [2],
startDate: new Date(2015, 4, 27, 15, 15),
endDate: new Date(2015, 4, 27, 16, 30)
}, {
text: "Customer Workshop",
ownerId: [3],
startDate: new Date(2015, 4, 28, 11, 0),
endDate: new Date(2015, 4, 28, 12, 0),
allDay: true
}, {
text: "Prepare 2015 Marketing Plan",
ownerId: [1, 3],
startDate: new Date(2015, 4, 28, 11, 0),
endDate: new Date(2015, 4, 28, 13, 30)
}, {
text: "Brochure Design Review",
ownerId: [4],
startDate: new Date(2015, 4, 28, 14, 0),
endDate: new Date(2015, 4, 28, 15, 30)
}, {
text: "Create Icons for Website",
ownerId: [3],
startDate: new Date(2015, 4, 29, 10, 0),
endDate: new Date(2015, 4, 29, 11, 30)
}, {
text: "Upgrade Server Hardware",
ownerId: [4],
startDate: new Date(2015, 4, 29, 14, 30),
endDate: new Date(2015, 4, 29, 16, 0)
}, {
text: "Submit New Website Design",
ownerId: [1],
startDate: new Date(2015, 4, 29, 16, 30),
endDate: new Date(2015, 4, 29, 18, 0)
}, {
text: "Launch New Website",
ownerId: [2],
startDate: new Date(2015, 4, 29, 12, 20),
endDate: new Date(2015, 4, 29, 14, 0)
}, {
text: "Stand-up meeting",
ownerId: [1, 2, 3, 4],
startDate: new Date(2015, 4, 25, 9, 0),
endDate: new Date(2015, 4, 25, 9, 15),
recurrenceRule: "FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR;UNTIL=20150530"
}
];
let resources: Resource[] = [
{
text: "Samantha Bright",
id: 1,
color: "#cb6bb2"
}, {
text: "John Heart",
id: 2,
color: "#56ca85"
}, {
text: "Todd Hoffman",
id: 3,
color: "#1e90ff"
}, {
text: "Sandra Johnson",
id: 4,
color: "#ff9747"
}
];
#Injectable()
export class Service {
getAppointments(): Appointment[] {
return appointments;
}
getResources(): Resource[] {
return resources;
}
}
index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CroissantBoard</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/17.1.4/css/dx.spa.css" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/17.1.4/css/dx.common.css" />
<link rel="dx-theme" data-theme="generic.light" href="https://cdn3.devexpress.com/jslib/17.1.4/css/dx.light.css" />
<script src="https://unpkg.com/core-js#2.4.1/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js#0.6.25/dist/zone.js"></script>
<script src="https://unpkg.com/reflect-metadata#0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs#0.19.31/dist/system.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<calendrier>Loading...</calendrier>
</div>
</body>
</html>
when i launch the project using
ng serve
But i have a problem... my calendar is blank ... did you have an idea of how can i see the events who's on the "calendrier.service.ts"
Here is what i've got on my console :
compiler.es5.js:1689 Uncaught Error: Template parse errors:
Can't bind to 'dataSource' since it isn't a known property of 'dx-scheduler'.
1. If 'dx-scheduler' is an Angular component and it has 'dataSource' input, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("<dx-scheduler
style="height: 100%; display: block"
[ERROR ->][dataSource]="appointmentsData"
[currentDate]="currentDate"
startDateExpr="StartDate"
"): ng:///AppModule/CalendrierComponent.html#2:4
Can't bind to 'currentDate' since it isn't a known property of 'dx-scheduler'.
1. If 'dx-scheduler' is an Angular component and it has 'currentDate' input, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
style="height: 100%; display: block"
[dataSource]="appointmentsData"
[ERROR ->][currentDate]="currentDate"
startDateExpr="StartDate"
endDateExpr="EndDate"
"): ng:///AppModule/CalendrierComponent.html#3:4
Can't bind to 'views' since it isn't a known property of 'dx-scheduler'.
1. If 'dx-scheduler' is an Angular component and it has 'views' input, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
endDateExpr="EndDate"
textExpr="Text"
[ERROR ->][views]="['agenda','workWeek']"
currentView="workWeek"
[firstDayOfWeek]="1"
"): ng:///AppModule/CalendrierComponent.html#7:4
Can't bind to 'firstDayOfWeek' since it isn't a known property of 'dx-scheduler'.
1. If 'dx-scheduler' is an Angular component and it has 'firstDayOfWeek' input, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
[views]="['agenda','workWeek']"
currentView="workWeek"
[ERROR ->][firstDayOfWeek]="1"
[startDayHour]="9"
[endDayHour]="19"
"): ng:///AppModule/CalendrierComponent.html#9:4
Can't bind to 'startDayHour' since it isn't a known property of 'dx-scheduler'.
1. If 'dx-scheduler' is an Angular component and it has 'startDayHour' input, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
currentView="workWeek"
[firstDayOfWeek]="1"
[ERROR ->][startDayHour]="9"
[endDayHour]="19"
[resources]="resourcesData"
"): ng:///AppModule/CalendrierComponent.html#10:4
Can't bind to 'endDayHour' since it isn't a known property of 'dx-scheduler'.
1. If 'dx-scheduler' is an Angular component and it has 'endDayHour' input, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
[firstDayOfWeek]="1"
[startDayHour]="9"
[ERROR ->][endDayHour]="19"
[resources]="resourcesData"
></dx-scheduler>
"): ng:///AppModule/CalendrierComponent.html#11:4
Can't bind to 'resources' since it isn't a known property of 'dx-scheduler'.
1. If 'dx-scheduler' is an Angular component and it has 'resources' input, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
[startDayHour]="9"
[endDayHour]="19"
[ERROR ->][resources]="resourcesData"
></dx-scheduler>
"): ng:///AppModule/CalendrierComponent.html#12:4
'dx-scheduler' is not a known element:
1. If 'dx-scheduler' is an Angular component, then verify that it is part of this module.
2. If 'dx-scheduler' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message. ("[ERROR ->]<dx-scheduler
style="height: 100%; display: block"
[dataSource]="appointmentsData"
"): ng:///AppModule/CalendrierComponent.html#0:0
at syntaxError (http://localhost:4200/vendor.bundle.js:260856:34)
at TemplateParser.webpackJsonp.../../../compiler/#angular/compiler.es5.js.TemplateParser.parse (http://localhost:4200/vendor.bundle.js:271969:19)
at JitCompiler.webpackJsonp.../../../compiler/#angular/compiler.es5.js.JitCompiler._compileTemplate (http://localhost:4200/vendor.bundle.js:286019:39)
at http://localhost:4200/vendor.bundle.js:285939:62
at Set.forEach (native)
at JitCompiler.webpackJsonp.../../../compiler/#angular/compiler.es5.js.JitCompiler._compileComponents (http://localhost:4200/vendor.bundle.js:285939:19)
at http://localhost:4200/vendor.bundle.js:285826:19
at Object.then (http://localhost:4200/vendor.bundle.js:260846:148)
at JitCompiler.webpackJsonp.../../../compiler/#angular/compiler.es5.js.JitCompiler._compileModuleAndComponents (http://localhost:4200/vendor.bundle.js:285825:26)
at JitCompiler.webpackJsonp.../../../compiler/#angular/compiler.es5.js.JitCompiler.compileModuleAsync (http://localhost:4200/vendor.bundle.js:285754:37)
could you take a look please ?
You are using the wrong field names from your class, they are appointmentsData and resourcesData:
<dx-scheduler
style="height: 100%; display: block"
[currentDate]="currentDate"
startDateExpr="StartDate"
endDateExpr="EndDate"
textExpr="Text"
[views]="['agenda','workWeek']"
currentView="workWeek"
[firstDayOfWeek]="1"
[startDayHour]="9"
[endDayHour]="19"
[dataSource]="appointmentsData" // <-- here
[resources]="resourcesData" // <-- and here
></dx-scheduler>
You need to import the DxDataGrid module into your module:
#NgModule({
imports: [
CommonModule,
DxDataGridModule
],
...

Flot displaying dates from timestamps incorrect

This is what is on my x axis on Flot. The below are not typos, it's duplicates dates in proper format, but just plain wrong.
E.g. 1262188800.0 == 12/31/2009
Why is Flot doing this?
1970/01/15 1970/01/15 1970/01/16 1970/01/16 1970/01/16 1970/01/16 1970/01/16
tsPlot(data_ts){
let dataset = [
{
label: "Mean",
data: data_ts["mean_1"],
points: { fillColor: "#FF0000", show: true },
lines: { show: true }
},
{
label: "Var",
data: data_ts["var_1"],
points: { fillColor: "#FF0000", show: true },
lines: { show: true }
}
];
let options = {
grid: { hoverable: true, clickable: true },
xaxis: { mode: "time",
timeformat: "%Y/%m/%d"
}
};
this.plot = $.plot($("#placeholder_ts"),dataset,options);
this.plot.setupGrid();
this.plot.draw();
}
data_ts = { "mean_1": [
[1262188800.0, 500],
[1264867200.0, 500],
[1267286400.0, 500],
[1269964800.0, 492],
[1272556800.0, 484],
[1275235200.0, 484],
[1277827200.0, 477],
[1280505600.0, 477],
[1283184000.0, 470],
[1285776000.0, 475],
[1288454400.0, 471],
[1291046400.0, 480],
[1293724800.0, 480],
[1296403200.0, 489],
[1298822400.0, 489],
[1301500800.0, 489],
[1304092800.0, 490],
[1306771200.0, 500],
[1309363200.0, 500],
[1312041600.0, 500],
[1314720000.0, 500],
[1317312000.0, 490],
[1319990400.0, 484],
[1322582400.0, 492],
[1325260800.0, 492],
[1327939200.0, 488],
[1330444800.0, 498],
[1333123200.0, 498],
[1335715200.0, 499],
[1338393600.0, 493],
[1340985600.0, 485],
[1343664000.0, 493],
[1346342400.0, 493],
[1348934400.0, 493],
[1351612800.0, 498],
[1354204800.0, 498],
[1356883200.0, 506],
[1359561600.0, 510],
[1361980800.0, 510],
[1364659200.0, 510],
[1367251200.0, 514],
[1369929600.0, 516],
[1372521600.0, 516],
[1375200000.0, 513],
[1377878400.0, 513],
[1380470400.0, 517],
[1383148800.0, 517]
],
"var_1": [
[1262188800.0, 300],
[1264867200.0, 300],
[1267286400.0, 300],
[1269964800.0, 292],
[1272556800.0, 284],
[1275235200.0, 284],
[1277827200.0, 277],
[1280505600.0, 277],
[1283184000.0, 270],
[1285776000.0, 275],
[1288454400.0, 271],
[1291046400.0, 280],
[1293724800.0, 280],
[1296403200.0, 289],
[1298822400.0, 289],
[1301500800.0, 289],
[1304092800.0, 290],
[1306771200.0, 300],
[1309363200.0, 300],
[1312041600.0, 300],
[1314720000.0, 300],
[1317312000.0, 290],
[1319990400.0, 284],
[1322582400.0, 292],
[1325260800.0, 292],
[1327939200.0, 288],
[1330444800.0, 298],
[1333123200.0, 298],
[1335715200.0, 299],
[1338393600.0, 293],
[1340985600.0, 285],
[1343664000.0, 293],
[1346342400.0, 293],
[1348934400.0, 293],
[1351612800.0, 298],
[1354204800.0, 298],
[1356883200.0, 306],
[1359561600.0, 310],
[1361980800.0, 310],
[1364659200.0, 310],
[1367251200.0, 314],
[1369929600.0, 316],
[1372521600.0, 316],
[1375200000.0, 313],
[1377878400.0, 313],
[1380470400.0, 317],
[1383148800.0, 317]
]
}
Flot is correct, your timestamps are wrong, see the documentation:
The time series support in Flot is based on Javascript timestamps, i.e. everywhere a time value is expected or handed over, a Javascript timestamp number is used. This is a number, not a Date object. A Javascript timestamp is the number of milliseconds since January 1, 1970 00:00:00 UTC. This is almost the same as Unix timestamps, except it's in milliseconds, so remember to multiply by 1000!

Change color of JointJS Rappid object (via modifying different instance in the left-nav menu and also modify via Rappid Inspector color picker)?

I basically want to change the color of a JointJS shape in their RAPPID environment I'm trialing.
Here is some background on what I have so far and what I want to achieve:
I have a JointJS shape called ChristmasTree that extends joint.dia.Element.
Basically the svg string that builds this ChristmasTree object is a path of the tree (svg path element), and multiple ornaments on it (4 svg circles/ellipses which have id's and classes that I would assume I can use to modify the colors).
I set some initial values for the ornaments via the style attr inside the svg string.
Once I place that in the left RAPPID menu, the user can drag that one Christmas Tree with red balls on it, yay.
Question ###1:
But I would like to place a 2nd ChristmasTree shape in the left menu without creating another main object that has Green balls... How would I achieve this?
In my below code, christmas_tree_style_2 should override the .ornament class with
'fill': "#00ff00", but doesn't (in the left menu, its still red)?
In fact, christmas_tree_style_1, i also tried to override with a Blue ball 'fill': "#0000ff", but its still red.
How can I achieve a left-nav override of the shape?
Question ###2:
Pretend you help me resolve previous issue. You can drag and drop 2 multiple color ChristmasTree's from the left-menu nav into the main RAPPID content area.
I'd like to now change the colors dynamically through the inspector.
I added a color inspector that shows up in the RAPPID right-nav menu for every element with:
'ornament_fill': { label: 'Color of christmas-tree-ornament's fill', type: 'color', group: 'generalinfo', index: 2 }
But not sure how to create an event to dynamically change the color of the ornaments. Any idea? Thanks!
Here is the important part's of the code below.
And also here is an actual working example (but the left-nav initial override and right-nav Inspector color override dont work, hence my 2 questions):
http://armyofda12mnkeys.kissr.com/rappid_christmastree/index.html
(sorry i couldnt find a CDN for rappid.js to add to JSFiddle so it was easier to upload the folder to a site). The applicable files to my question are app.js and rappid-custom-shapes.js.
#
//svg for Christmas Tree + its ornaments... will be added to ChristmasTree shape/obj below
var ChristmasTreeSVGstr = "<g class="rotatable"><g class="scalable">
...
<path id="christmastreestrokeid" class="christmastreestroke" ... />
<circle id="ornament1" class="ornament" r="24" cy="350" cx="120"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament2" class="ornament" rx="30" ry="25" cy="83" cx="231"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament3" class="ornament" rx="28" ry="38" cy="343" cx="331"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament4" class="ornament" rx="63" ry="54" cy="238" cx="230"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
</g></g>";
#
//default Christmas Tree
joint.shapes.basic.ChristmasTree = joint.dia.Element.extend({
markup: ChristmasTreeSVGstr,
defaults: joint.util.deepSupplement({
type: "basic",
name: 'Initial Christmas Tree label text',
size: {
width: 20,
height: 20
},
attrs: {
".christmastreestroke": {
stroke: 'green',
'stroke-width': '100px',
'fill-opacity': 1,
width: 10,
height: 15
},
".ornament": {
'fill': "#00ff00",
'fill-opacity': 1
},
"#ornament3": {
'fill': "#0000FF",
'stroke': "green",
'stroke-width': '5px',
'fill-opacity': .5
}
}
}, joint.dia.Element.prototype.defaults)
});
#
//RAPPID left menu christmas trees (2 variations of the initial ChristmasTree object, so I need to override some of the colors)
var christmas_tree_style_1 = new joint.shapes.basic.ChristmasTree({
position: { x: 0, y: 0 },
size: {
width: 40,
height: 50
},
attr: {
".christmastreestroke": {
stroke: 'green',
'stroke-width': '100px',
'fill-opacity': 1,
},
".ornament": {
'fill': "#0000ff",
'fill-opacity': 1
},
"#ornament3": {
'fill': "#0000FF",
'stroke': "green",
'stroke-width': '5px',
'fill-opacity': .5
}
}
});
var christmas_tree_style_2 = new joint.shapes.basic.ChristmasTree({
position: { x: 0, y: 0 },
size: {
width: 40,
height: 50
},
attr: {
".christmastreestroke": {
stroke: 'blue',
'stroke-width': '100px',
'fill-opacity': 1,
},
".ornament": {
'fill': "#00ff00",
'fill-opacity': 1
},
"#ornament3": {
'fill': "yellow",
'stroke': "yellow",
'stroke-width': '5px',
'fill-opacity': 1
}
}
});
//add to left menu
stencil.load([christmas_tree_style_1, christmas_tree_style_2], 'customchristmastrees');
#
//add it to the inspector
function createInspector(cellView) {
if (!inspector || inspector.options.cellView !== cellView) {
if (inspector) {
// Set unsaved changes to the model and clean up the old inspector if there was one.
inspector.updateCell();
inspector.remove();
}
//if(cellView.$el.hasClass('class')) // certain element should get certain things more in inspector?
//how to determine different shapes?
inspector = new joint.ui.Inspector({
inputs: {
'name': { label: 'Name of Christmas Tree', type: 'text', group: 'generalinfo', index: 1 },
'ornament_fill': { label: 'Color of christmas-tree-ornaments fill', type: 'color', group: 'generalinfo', index: 2 },
},
groups: {
generalinfo: { label: 'General Info', index: 1 },
},
cellView: cellView
});
$('.inspector-container').html(inspector.render().el);
}
}
Question #1: you need to remove style properties from the markup if you want to change them through the attr property on the element. I removed the fill, stroke, stroke-width from the markup:
var ChristmasTreeSVGstr = "<g class="rotatable"><g class="scalable">
...
<path id="christmastreestrokeid" class="christmastreestroke" ... />
<circle id="ornament1" class="ornament" r="24" cy="350" cx="120"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament2" class="ornament" rx="30" ry="25" cy="83" cx="231"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament3" class="ornament" rx="28" ry="38" cy="343" cx="331"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament4" class="ornament" rx="63" ry="54" cy="238" cx="230"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
</g></g>";
then you can customize the shape as follows:
var rb = new joint.shapes.basic.ChristmasTree({
position: { x: 50, y: 50 },
size: { width: 100, height: 150 },
attrs: {
".ornament": {
'fill-opacity': 1,
stroke: 'pink',
'stroke-width': 5,
fill: 'blue'
}
}
});
Question #2:
in case you sorted out the issue #1 you can simply sync the values directly with the attrs:
inspector = new joint.ui.Inspector({
inputs: {
'name': { label: 'Name of Christmas Tree', type: 'text', group: 'generalinfo', index: 1 },
attrs: {
'.ornament': {
fill: {
label: 'Color of christmas-tree-ornaments fill',
type: 'color',
group: 'generalinfo',
index: 2
}
}
},
},
groups: {
generalinfo: { label: 'General Info', index: 1 },
},
cellView: cellView
});

No UiSlider remove decimal?

How to remove decimals digit from linked output
I am using this code
$("#slider_01").noUiSlider({
start: [2000, 24000],
connect: true,
step: 0.01,
range: {
'min': 0,
'max': 28500
},
format: wNumb({
decimals: false,
thousand: ',',
prefix: '$ ',
})
});
$('#slider_01').Link('lower').to($('#value-lower_1'));
$('#slider_01').Link('upper').to($('#value-upper_1'));
I didn't have access to the wNumb library in the environment I was working with.
Had a look under the hood in the library and this also works:
$("#slider_01").noUiSlider({
...
format: {
to: (v) => parseFloat(v).toFixed(0),
from: (v) => parseFloat(v).toFixed(0)
}
});
Decimals decimals: false is invalid, use decimals: 0. Also, you are setting formatting for the .val() method. Use it like this:
$('#slider_01').Link('lower').to($('#value-lower_1'), null, wNumb({
decimals: 0,
thousand: ',',
prefix: '$ ',
}));
Change the step from 0.01 to 1.
I know it's a very old question, but I did not want to include another library Wnumb just to remove the decimal from one place. Here is my solution without using the wnumb.
var slider = document.getElementById('prcsldr');
noUiSlider.create(slider, {
start: [10000],
range: {
min: 1000,
max: 50000
},
step: 1000,
format:{
to: (v) => v | 0,
from: (v) => v | 0
}
});

Resources