Bind event to right-click - event-handling

How do I bind to or recognize a right-click event?
I have a scatter plot where left-click adds a point at the clicked location; I would like right-click to remove the point (if present).
This is my current code:
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
events: {
click: function(event) {
var cs = [Math.floor(event.xAxis[0].value),
Math.floor(event.yAxis[0].value)];
this.series[0].addPoint(cs);
}
},
type: 'scatter',
},
... etc. ...
});

This should help:Making Highcharts support right click context menu

This is not a full solution: I did not figure out how to capture right-click events.
But here's a workaround for clicking on the chart background:
have the user do a shift-click
supply a callback as before
in the callback, inspect the event. If shift was pressed, do something different
Here's what the callback might look like:
function clickChart(event) {
var isShiftPressed = event.shiftKey;
if(isShiftPressed) {
// do something
} else {
// do something different
}
The event object has boolean attributes shiftKey (and altKey).
Here's a workaround for removing points: (actually, it's not a workaround -- I just didn't realize there was an easier way!)
points have their own events
just set up a callback that removes points when they're clicked
Example:
function clickPoint(event) {
this.remove();
}
var chart = new Highcharts.Chart({
chart: {
type: 'scatter',
renderTo: 'chart',
},
series: [{
point: {
events: {
click: clickPoint
}
}
}]
});
Note: the documentation is misleading, at the least, but the jsfiddle examples seem to be correct. It seems to show that the point options are not in series.

Currently, there are only a few events supported by Highcharts.
for ref : https://www.highcharts.com/blog/tutorials/introduction-to-highcharts-events/
To add custom events, such as
double click (including mobile devices)
right click (context menu)
mouse over
mouse out
mouse down
mouse move
we can add a plugin
highcharts-custom-events
https://www.npmjs.com/package/highcharts-custom-events
hope you find this helpful and solves your problem.

Related

Highchart Gantt chart Navigator color

I am rendering a Gantt chart with different series color. The colors are somehow not reflected on the navigator at the bottom. How can I display the same colors in both series and navigator?
Fiddle link : Fiddle
Note: These colors are going to be dynamic which will be based on different cases. So I want them to reflect in the navigator too, dynamically.
I am changing color of the series like so :
chart: {
events: {
load: function() {
Highcharts.each(this.series[0].points, function(p) {
p.color = 'grey'
});
}
}
},
As you can see series color is grey but in the navigator below, I see different colors.
As per highcharts-gantt documentation:
Update the series with a new set of options. For a clean and precise handling of new options, all methods and elements from the series are removed, and it is initialized from scratch.
On event, you should then go through given serie points and change its options (in your case 'color').
The changes will be applied in the timeline below - example code changes the color after 1,5sec.
//Updating the color
setTimeout(function() {
for (var i = 0; i < chart.series[0].points.length; i++) {
chart.series[0].points[i].update({
color: "grey"
});
}
}, 1500);
Working example
In your code it would be:
events: {
load: function() {
Highcharts.each(this.series[0].points, function(p) {
p.update({color: "grey"});
});
}
}
To avoid shrink of timeline - launch setExtremes() after chart update.
Fires when the minimum and maximum is set for the axis, either by calling the .setExtremes() method or by selecting an area in the chart.
//Fully selected timeline
this.xAxis[0].setExtremes();
Working example - timeline selection
You can also set options for series of navigator, like below:
navigator: {
series: {
...,
colorByPoint: false,
color: 'grey'
},
...
}
Live demo: https://jsfiddle.net/BlackLabel/c4j9dvqx/
API Reference: https://api.highcharts.com/gantt/navigator.series.color

How to link zoom in different charts in echarts

We have multiple charts with zoom. Is there a way to link all this charts so they always have the same zoom factor when the user zoom in one of the charts?
When having multiple grids in the same chart is not a possibility, I use this trick to do the job:
myChart.on('datazoom', function (evt) {
var zoom = myChart.getOption().dataZoom[0];
myOtherChart.dispatchAction({
type: 'dataZoom',
dataZoomIndex: 0,
startValue: zoom.startValue,
endValue: zoom.endValue
});
});
Both charts have dataZoom, in my case I hide the one in myOtherChart.
If you've got more events to track, creating the action can be simplified by letting echarts create it:
["datazoom", "legendselectchanged", /* more events*/].forEach((eventType: string) => {
this.chartInstance1.on(eventType, (event) => {
// Automatically create an action from the event
let newEvent = this.chartInstance1.makeActionFromEvent(event);
// Dispatch it directly
this.chartInstance2.dispatchAction(newEvent);
});
})
For everyone who wants to go further, also synchronizing mouse, legend and magic events, its easier to use the connect function.
Template:
// chart 1
<div echarts (chartInit)="onChartInit($event)"></div>
// chart 2
<div echarts (chartInit)="onChartInit($event)"></div>
Typescript:
import { connect, ECharts } from "echarts";
// ...
onChartInit(chart: ECharts) {
this.charts.push(chart);
if (this.charts.length === 2)
// This will do the magic out of the box
connect([charts[0], charts[1]]);
}

Kendo line chart - switch between series

I am making simple line chart in kendo. Something like this demo http://demos.telerik.com/kendo-ui/dataviz/line-charts/index.html.
I also have mulitple series as on example(India,World etc...).
My question is, is there way to allow that only one serie is active on chart.
Series behave like checkbox button(I can have one or more active) and I want them to behave as radio button so only one serie can be active.
The short answer is No. You cannot modify the legend in anyway to achieve such behavior. However you can use radio buttons separately and update the options of the chart - such as the series.
Here is a small JsBin example:
$("input[type=radio]").click(function(){
var clickedOn = $(this).val();
var data = $.grep(series, function(val){
return val.name == clickedOn;
})[0];
chart.setOptions({series:[
{
name: clickedOn,
data: data.data
}
]})
})
You can do this with a button. Haven't tried it with a radio button.
$("#ButtonName").kendoButton({
click: function (e) {
var varname = $("#chartName").data("kendoChart")
kendodatasourcename.filter(
{ field: "fieldName", operator: "eq", value: "filteredvaluefromyourdataset" })

Dynamically updating a TinyMCE 4 ListBox

I'm trying to modify the TinyMCE 4 "link" plugin to allow users to select content from ListBox elements that are dynamically updated by AJAX requests.
I'm creating the ListBox elements in advance of editor.windowManager.open(), so they are initially rendered properly. I have an onselect handler that performs the AJAX request, and gets a response in JSON format.
What I need to do with the JSON response is to have it update another ListBox element, replacing the existing items with the new results.
I'm baffled, and the documentation is terribly unclear. I don't know if I should replace the entire control, or delete items and then add new ones. I don't know if I need to instantiate a new ListBox control, or render it to HTML, etc.
Basically, I have access to the original rendered ListBox (name: "module"} with
win.find('#module');
I have the new values from the AJAX request:
var data = tinymce.util.JSON.parse(text).data;
And I've tried creating a new Control configuration object, like
newCtrlconfig = {
type: 'listbox',
label: 'Class',
values: data
};
but I wouldn't know how to render it, much less have it replace the existing one.
I tried
var newList = tinymce.ui.Factory.create(newCtrlconfig);
and then
newList.renderHtml()
but even then, the rendered HTML did not contain any markup for the items. And examining these objects is just frustrating: there are "settings", "values", "_values", "items" all of which will happily store my values, but it isn't even clear which of them will work.
Since it's a ListBox and not a simple SELECT menu, I can't even easily use the DOM to manipulate the values.
Has anyone conquered the TinyMCE ListBox in 4.x?
I found this on the TinyMCE forum and I have confirmed that it works:
tinymce.PluginManager.add('myexample', function(editor, url) {
var self = this, button;
function getValues() {
return editor.settings.myKeyValueList;
}
// Add a button that opens a window
editor.addButton('myexample', {
type: 'listbox',
text: 'My Example',
values: getValues(),
onselect: function() {
//insert key
editor.insertContent(this.value());
//reset selected value
this.value(null);
},
onPostRender: function() {
//this is a hack to get button refrence.
//there may be a better way to do this
button = this;
},
});
self.refresh = function() {
//remove existing menu if it is already rendered
if(button.menu){
button.menu.remove();
button.menu = null;
}
button.settings.values = button.settings.menu = getValues();
};
});
Call following code block from ajax success method
//Set new values to myKeyValueList
tinyMCE.activeEditor.settings.myKeyValueList = [{text: 'newtext', value: 'newvalue'}];
//Call plugin method to reload the dropdown
tinyMCE.activeEditor.plugins.myexample.refresh();
The key here is that you need to do the following:
Get the 'button' reference by taking it from 'this' in the onPostRender method
Update the button.settings.values and button.settings.menu with the values you want
To update the existing list, call button.menu.remove() and button.menu = null
I tried the solution from TinyMCE forum, but I found it buggy. For example, when I tried to alter the first ListBox multiple times, only the first time took effect. Also first change to that box right after dialogue popped up didn't take any effect.
But to the solution:
Do not call button.menu.remove();
Also, the "hack" for getting button reference is quite unnecessary. Your job can be done simply using:
var button = win.find("#button")[0];
With these modification, my ListBoxes work just right.
Whole dialogue function:
function ShowDialog() {
var val;
win = editor.windowManager.open({
title: 'title',
body: {type: 'form',
items: [
{type: 'listbox',
name: 'categorybox',
text: 'pick one',
value: 0,
label: 'Section: ',
values: categories,
onselect: setValuebox(this.value())
},
{type: 'listbox',
name: 'valuebox',
text:'pick one',
value: '',
label: 'Page: ',
values: pagelist[0],
onselect: function(e) {
val = this.value();
}
}
]
},
onsubmit: function(e) {
//do whatever
}
});
var valbox = win.find("#valuebox")[0];
function setValuebox(i){
//feel free to call ajax
valbox.value(null);
valbox.menu = null;
valbox.settings.menu = pagelist[i];
// you can also set a value from pagelist[i]["values"][0]
}
}
categories and pagelist are JSONs generated from DB before TinyMCE load. pagelist[category] = data for ListBox for selected category. category=0 means all.
Hope I helped somebody, because I've been struggling this for hours.
It looks like the tinyMCE version that is included in wordpress 4.3 changed some things, and added a state object that caches the initial menu, so changing the menu is not enough anymore.
One will probably have to update the state object as well. Here is an example of updating the menu with data coming from an ajax request:
editor.addButton('shortcodes', {
icon: 'icon_shortcodes',
tooltip: 'Your tooltip',
type: 'menubutton',
onPostRender: function() {
var ctrl = this;
$.getJSON( ajaxurl , function( menu) {
// menu is the array containing your menu items
ctrl.state.data.menu = ctrl.settings.menu = menu;
});
}
});
As far as I can tell, these other approaches are broken in TinyMCE 4.9.
After spending most of the day tinkering to fix my own usage of these approaches, this is the working function I've found:
function updateListbox(win, data) { // win is a tinymce.ui.Window
listbox = win.find('#listbox'); // Substitute your listbox 'name'
formItem = listbox.parent();
listbox.remove();
formItem.append({
label: 'Dynamic Listbox',
type: 'listbox',
name: 'listbox',
values: data
});
}

How to show different popups on click and on mouseover?

The SelectFeature method in Control class provides a way of adding and removing popups on the Vector layer by listening to events featureselected and featureunselected respectively. Below shows a sample code that I obtained from an example in the openlayers website:
// create the layer with listeners to create and destroy popups
var vector = new OpenLayers.Layer.Vector("Points",{
eventListeners:{
'featureselected':function(evt){
var feature = evt.feature;
var popup = new OpenLayers.Popup.FramedCloud("popup",
OpenLayers.LonLat.fromString(feature.geometry.toShortString()),
null,
"<div style='font-size:.8em'>Feature: " + feature.id +"<br>Foo: </div>",
null,
true
);
feature.popup = popup;
map.addPopup(popup);
},
'featureunselected':function(evt){
var feature = evt.feature;
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
}
});
vector.addFeatures(features);
// create the select feature control
var selector = new OpenLayers.Control.SelectFeature(vector,{
hover:true, # this line
autoActivate:true
});
The code above will allow a popup to be shown upon mouseover on the Geometry object (icon or marker on the map). If the line hover:true is removed, the popup will be shown only upon a mouse click on the Geometry object.
What I want, is to be able to display one type of popup (example, an image plus a title) upon mouseover and another type (example, detailed description) upon a mouse click. I am not sure how this could be done. Some help would be much appreciated. Thanks.
Also, there another way, it's rather hack than correct usage of API, but seems to work. You can overwrite over and out callbacks.
var selectControl = new OpenLayers.Control.SelectFeature(vectorLayer, {
callbacks: {
over: function(feat) {
console.log('Show popup type 1');
},
out: function(feat) {
console.log('Hide popup type 1');
}
},
eventListeners: {
featurehighlighted: function(feat) {
console.log('Show popup type 2');
},
featureunhighlighted: function(feat) {
console.log('Hide popup type 2');
}
}
});
Here's working example: http://jsfiddle.net/eW8DV/1/
Take a look on select control's source to understand details.