How to pass custom data into Highcharts graph click event - javascript

Is possible to pass custom data when rendering a Highcharts graph (funnel, in this case), so that when I bind a click event, I can use this custom data point?
Currently, all that I can get is the "name" event.point.name, which I provide for the Label, but I also want to pass a song_id too.
http://jsfiddle.net/y4a2end3/1/
Is there a place in the graph code that I can add another data point, like "song_id"?
series: [{
name: 'Song Plays',
data: [
['song_name1',123, 'song_id_1'], /* song_id_1 would be the custom data */
['song_name2',234, 'song_id_2']
]
}]

If you want to attach additional data to points in a series you can initialize the points that need additional data as objects instead of arrays/ints. For example, with your code you could do:
series: [{
name: 'Song Plays',
data: [
{x:'song_name1', y:123, songid:'song_id_1'},
{x:'song_name2', y:234, songid:'song_id_2'}
]
}]
You can then get it from the point on click as event.point.songid. See this JSFiddle demo using point click and tooltip.
Note that in many cases x in the object will not be required. It is often automatic and sequential.

You can try
alert(event.point.series.userOptions.data[event.point.x][2])
Updated fiddle: http://jsfiddle.net/y4a2end3/2/
Or this:
alert(event.point.series.userOptions.data[event.point.series.data.indexOf(event.point)][2]);

Related

Apostrophe CMS: filtering apostrophe-events based on a field from the (extended) widget definition

We have locations (and location-pages) as the primary page type on our site.
We use the apostrophe-events module to contain basic event (day, time, location, etc.) information which is then presented via widgets within the associated location page. Our events/event-pages definitions have a required 'location' field to associate a location, and work as expected. We have a 'featured-event-widgets' defined that presents a single, selected, event.
I am trying to implement the events modules standard 'events-widgets', which presents multiple events, however I want to filter the returned events by associated location and am running into a problem.
The default implementation works as expected - it finds x upcoming events (i.e. events that haven't happened/finished yet), where x is an arbitrary number specified in the widget, and passes the collection of events to the widget.html template for expression.
My issue is that the default widget provides the next events regardless of which location they are associated with i.e. while there may be 5 upcoming events defined in location A, if there are also upcoming events in locations C and B then the widget will return 2 events from A, and 2 events from B, and 1 event from C rather then the 5 events from location A as I desire.
I have updated the events-widget index.js to include the required selection of a location.
module.exports = {
label: 'Events Widget',
addFields: [
{
name: 'title',
label: 'Title',
type: 'string',
required: true
},
{
name: '_location',
label: 'Location',
required: true,
withType: 'location',
type: 'joinByOne',
filters: {
projection: {
title: 1,
slug: 1,
}
}
}
]
So my widget definition has an associated location object, and all of my events pieces have an associated location, but I am running into a brick wall in trying to use that information to filter what the underlying cursor is returning to the widget.html template.
While I can/could filter within the template, by returning an arbitrarily large number of events in order to (mostly) ensure that I obtain the required number of events for the desired location, that seems like a broken approach.
I thought adding the addFilters: [...] definition to index.js functionality would give me what I need, but I have been unable to get that approach to work e.g.
addFilters: [
{
name: '_location',
label: 'Location'
}
]
After spending a bunch of time on Google and StackOverflow it seems like I might be able to do something by overriding and expanding the default construct definition in index.js, and using self.widgetCursor to achieve this, however I'm unable to determine where to find the location specified in the widget definition (presumably somewhere buried in req) to do this.
construct: function(self, options) {
// Append upcoming flag by extending widgetCursor.
var superWidgetCursor = self.widgetCursor;
self.widgetCursor = function(req, criteria) {
return superWidgetCursor(req, criteria).upcoming(true);
};
}
I'm hoping I'm missing something glaringly obvious that someone can point out to me :)
Many thanks,
Shaun

Directly update mapbox source features

I'm drawing orders on the map using layers with symbols, this orders has status. Whenever the status changes I'd like to change de color of the symbol.
My layer has this configuration:
map.addLayer({
id: "orders",
type: "symbol",
source: "order-markers",
layout: {
"icon-image": [
"match",
["get", "orderStatus"],
"UNASSIGNED",
"unassigned-marker",
"ASSIGNED",
"assigned-marker",
"IN_TRANSIT",
"intransit-marker",
"CONCLUDED",
"concluded-marker",
"UNASSIGNED-marker",
],
},
});
});
Is there a recommended way to directly access the source and update the status in the properties object ? Or is it right to always overwrite the whole data object with setData ?
I tried to create a state in React with the features but it seems that the features object dont react to the state changes.
Thanks.
I haven't found a way to update a single property on a single feature. What I've always done is to overwrite the data as you've mentioned (i.e. map.getSource('order-markers').setData(/*...*/)) with the whole data object where a feature's property was changed. This is the method mapbox uses in their example for updating with live data: live-update-feature
As an alternative however, you can update a single feature's state. If that's a possibility you can use map.setFeatureState.
for example:
map.setFeatureState(
{
source: 'order-markers',
id: feature.id,
}, {
status: "IN_TRANSIT"
}
);
You'll then have to update your layer style/expressions to use the state instead of property to properly reflect the data as they are slightly different in how you get the values.

Extjs multiple representations of data

I have a Rest endpoint, that sends and receives objects of the form
[
{id: 1, Name: "Type"},
{id: 2, Name: "Type:Subtype"},
...
]
I want to display this in an editable tree, using Sencha Extjs 6. I am confused as to where and when to transform the data, and how to keep changes synchronized without side effects. My current (not nice) method is to reload the data and then reset the tree's store using the converted values, but that collapses all of the expanded nodes
I can get and save entries using a model and a store
I can convert the data into a form suitable for use in a treepanel
I do not know the "right" way to do so, and to have changes in either store reflected in the other.
For clarity, the converted tree store has a data stucture:
[
{
text: "Type",
children: [
{
text: "Subtype",
isLeaf: true
}
]
}
]
Came up with the answer: a save button.
Bound the Load event of the Rest Store to the controller, and in that method copied the values into the TreeStore.
Edits are made to the TreeStore - kept purely client side
Save button copies new data back into Rest Store and calls sync(). Easy to follow. Code is kept mostly declarative. And I can provide default values in the VM's data field. Easy to do - shame it's not made clear in the documentation somewhere

highcharts series update in javascript

I am creating 5 separate charts and try to update them every few seconds with new series data.
If I define just one function that creates new chart and add series data in constructor, it works, but the downside is that every page refresh with setInterval() destroys charts and rebuilds them, which looks terrible.
So I created two functions, CreateChart() called once, and UpdateChart() called on every setInterval() refresh. Now charts are empty and I get error on UpdateChart():
TypeError: FlightCharts[Index].series[0] is undefined
Link to javascript code
Link to example json series data
Any tips (I'm new to javascript)
thanks
The problem is that you defined empty series:
series: []
Next you are trying to set data for a first series:
FlightCharts[Index].series[0]
Instead you should create that one series at least:
series: [{
name: "MyName",
data: []
}]

ExtJS 5 - Dynamically add items to split button menu from store

I want to associate a store to split button menu. I am using extjs version 5. I have searched on the web and even went through sencha documentation but I couldn't figure out a way to achieve this.
Currently i'm holding the menu details in variable and assigning it to the splitbutton xtyoe menu property.I want to achieve the same using store, your help is much appreciated!
Program Code:-
var menuJSON = [{
text:'Menu1',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
},{
text:'Menu2',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
},{
text:'Menu3',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
},{
text:'Menu4'
},{
text:'Menu5',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
}];
{
region: 'south',
fbar: [{
xtype:'splitbutton',
id: 'app-starterMenu',
text:'Start',
scale:'small',
iconCls:'icon-start',
menuAlign: 'bl-tl',
menu: menuJSON
}]
}
Thanks in advance!
It would be helpful if you can provide example code for the store or relative controller, however this is still easier than you might think. Of course, it's nothing that comes out of the box, but it's a perfect case of using listeners.
Whenever the store changes data, you want to update your button configuration. Therefore just add the relevant listener to your store - maybe using the refresh or update event (depending on your specific use case). Then whenever the store data changes, you need to grab a reference to your button (or associated menu) and update the items. In it's most simplistic form, an example might be as follows:
store: {
listeners: {
refresh: function(store) {
// Get all the raw data from records and use it to set items on the menu
var rawData = Ext.Array.pluck(store.getRange(),'data');
Ext.getCmp('app-starterMenu').setMenu({
items: rawData
});
// *OR* Loop through the store data conditionally and include what you need
Ext.getCmp('app-starterMenu').getMenu().removeAll();
store.each(function(record){
Ext.getCmp('app-starterMenu').getMenu().add(record.getData());
});
}
}
}

Categories