How to change properties of element in JSXGraph? - javascript

Suppose, I have the following piece of code:
var brd2 = JXG.JSXGraph.initBoard('box2', {boundingbox: [-8.75, 2.5, 8.75, -2.5]});
var ax2 = brd2.create('axis', [[0,0],[1,0]]);
How can I change second point of axis?
Something like ax2.setSecondPoint([2,0])?
In general, how can I set property of any element?
Thank you.

Axis has two properties which names are self-explanatory: point1 and point2.
You can use setPosition method on any of them, e.g.
ax2.point2.setPosition(JXG.COORDS_BY_USER,[2,0])
Now there is one catch: you will not see this change on the chart unless you set needsRegularUpdate property of the axis object to true. Finally, to refresh the chart you should execute fullUpdate() method on the board variable. The whole looks like this:
var brd2 = JXG.JSXGraph.initBoard('box2', {boundingbox: [-8.75, 2.5, 8.75, -2.5]});
var ax2 = brd2.create('axis', [[0,0],[1,0]],{needsRegularUpdate:true});
ax2.point2.setPosition(JXG.COORDS_BY_USER,[2,0]);
brd2.fullUpdate();
References:
http://jsxgraph.uni-bayreuth.de/docs/symbols/JXG.Point.html#setPosition
http://jsxgraph.uni-bayreuth.de/wiki/index.php/Options (search for "special axis options")
Now to change properties like fixed, visible, etc. you should use setAttribute method (setProperty is deprecated). Example:
// Set property directly on creation of an element using the attributes object parameter
var board = JXG.JSXGraph.initBoard('jxgbox', {boundingbox: [-1, 5, 5, 1]};
var p = board.create('point', [2, 2], {visible: false});
// Now make this point visible and fixed:
p.setAttribute({
fixed: true,
visible: true
});
Source:
http://jsxgraph.uni-bayreuth.de/docs/symbols/JXG.GeometryElement.html#setAttribute
Last but not least a simple formula:
a + b = c
where:
a = using JavaScript debugging tools in browsers to investigate object properties
b = checking documentation for products you use
c= success :)

Related

leaflet and chroma.js .domain arguments not working

I am trying to incorporate chroma.js into my leaflet map so that i can toggle between quantiles, equal interval, and k-means, but the second and third argument for the domain function does not change anything
var colorScale = chroma.scale('YlGnBu').domain(voterList, 3, 'quantiles');
Here is the full code for the function
this.getRegionItemColor = function(item) {
var regionData = Mapbook.getRegionData();
var voterList = Mapbook.getColorScheme();
var colorScale = chroma.scale('YlGnBu').domain(voterList, 3, 'quantiles');
if (!_.isUndefined(item)) {
var voters = item.voters,
minVoters = regionData.min_voters,
maxVoters = regionData.max_voters;
var alpha = colorScale(voters);
return alpha;
}
else {
return 0;
}
}
Does anyone know why changing the number of buckets or classification method does not change anything?
Strange... I looked into it and I do think there is a problem with the library. Let's consider a very simple and documented example.
If you look at the documentation on github, here is what is written (https://github.com/gka/chroma.js/wiki/Color-Scales):
// Calling .domain() with no arguments will return the current domain.
chroma.scale(['white', 'red']).domain([0, 100], 4).domain() // [0, 25, 50, 75, 100]
When I do the same, however, this returns [0,100] (and not [0, 25, 50, 75, 100]); as you said, the second argument has not changed anything. You may want to flag that behavior as a bug on the plugin github page. Unless someone has a good explanation?
I was having the same problem, then I realized that at the time I defined 'ColorScale', my domain was not yet populated. are you certain that 'voterList' had your dataset in it at the time you defined ColorScale?

Changing the function in the text box is not changing the graph

I am attempting to create a fiddle which can allow me to change the graph through and input text showing below the graph. I am using jsxgraph library for that.
http://jsxgraph.uni-bayreuth.de/wiki/index.php/Change_Equation_of_a_Graph#JavaScript_Part
Above is the example which is working when you change the function in the text shown graph also changes.
Same example I am trying with the fiddle. But it is not working.
https://jsfiddle.net/me55dw4h/30/
initial code:
board = JXG.JSXGraph.initBoard('box', {boundingbox: [-6, 12, 8, -6], axis: true});
eval("function f(x){ return "+document.getElementById("eingabe").value+";}");
graph = board.create('functiongraph', [function(x){ return f(x); },-10, 10]);
How do I make it work?
This is a jsfiddle-specific problem. If the declaration of the function doIt is changed to
doIt = function (){
//redefine function f according to the current text field value
eval("function f(x){ return "+document.getElementById("eingabe").value+";}");
//change the Y attribute of the graph to the new function
graph.Y = function(x){ return f(x); };
//update the graph
graph.updateCurve();
//update the whole board
board.update();
};
instead of
function doIt() {
...
}
then the example runs.
But let me emphasize that meanwhile JSXGraph comes with it's own parser JessieCode (see https://github.com/jsxgraph/JessieCode), which allows the input of common math syntax instead of JavaScript syntax. That means, instead of Math.sin(x) the user may just input sin(x). Additionally, there is the power operator ^, i.e. instead of Math.pow(x,2) it is possible to type x^2.
A minimal example using JessieCode for function plotting looks like this, see https://jsfiddle.net/eLs83cs6/
board = JXG.JSXGraph.initBoard('box', {boundingbox: [-6, 12, 8, -6], axis: true});
doPlot = function() {
var txtraw = document.getElementById('input').value, // Read user input
f = board.jc.snippet(txtraw, true, 'x', true), // Parse input with JessieCode
curve;
board.removeObject('f'); // Remove element with name f
curve = board.create('functiongraph', [f, -10, 10], {name:'f'});
};
doPlot();
Ann additional side effect is that the parsing of the math syntax with JessieCode prevents XSS attacks which would be easily possible if the users are allowed to supply arbitrary JavaScript code as input.

Square Line Chart / Step Chart jqplot

I need to plot 3 series of data, the first is a line and the other 2 are just dots. However the line should be a step chart (instead of the line drawing from point to point, it should draw the line horizontal and then up to the value
I am stuck as to how to get this with JQPlot.
$(document).ready(function(){
var plot1 = $.jqplot ('chart1', [[3,7,9,1,4,6,8,2,5]]);
});
The above code would produce the blue line on the below graph, instead I need the green line.
Unfortunately, I am not allowed to make comments. Therefore I have to write a new answer.
The already given answer suggests to subtract a small amount from the x value (0.001 in this example) to prevent the triangle effect. But this is not quite accurate and can only be seen as workaround.
The triangle effect is caused by the sorting performed by jqPlot. Sorting is required by most chart types, including line charts. If the data is already sorted before feeding it to jqPlot, sorting can be disabled for jqPlot by setting the sortData attribute to false, see jqPlot.sortData
This will prevent the sorting issues and therefore no triangle effect occurs!
You may also want to hide the point markers as jqPlot doesn't know the difference between the real points and our injected artificial points.
var data = [3, 7, 9, 1, 4, 6, 8, 2, 5];
var points = [[1, data[0]]];
for (var i = 1; i < data.length; i++) {
points.push([i + 1, data[i - 1]]);
points.push([i + 1, data[i]]);
}
var plot1 = $.jqplot('chart1', [points], {
sortData: false,
seriesDefaults: {
showMarker: false
}
});
Try it in a fiddle
If you want to get also the point markers right, the only option I see is changing the rendering logic, e.g. writing a step chart plugin.
For reference, see also the answers in the following post: jqPlot step chart not plotting in series order
You need to specify both the x and y value for each point on the graph. The tricky thing is, if two points have the same x value, jqplot may reverse them, which winds up looking like a triangle plot rather than a square. So, the solution is to take each point after the first, subtract a small amount from the x value (in my example, 0.001), and make that the x value for a new point that has the same y value as the point before it. Here's a hard-coded example:
var plot1 = $.jqplot ('chart1', [[
[1,3], [1.999,3],
[2,7], [2.999,7],
[3,9], [3.999,9],
//...
]]);
Try it in a fiddle.
To create such a list in code, just loop over the original data set and add the necessary extra steps:
var data = [3,7,9,1,4,6,8,2,5];
var points = [[1, data[0]]], len = data.length;
for (var i = 1; i < len; i++) {
points.push([i + .999, data[i - 1]]);
points.push([i + 1, data[i]]);
}
var plot1 = $.jqplot ('chart1', [points]);
Try it in an updated fiddle.

Calling value in the same object returns undefined

So I'm making this small little application that allows users to enter a command to resize their div.
When doing this I want to make it easier by making a shorthand option that simply calls the same value from the full name, but this returns undefined.
Changing this.small to sizes.small returns the error:
Uncaught TypeError: Cannot read property 'small' of undefined
Here is my code:
var sizes = {
// Full names for sizes
small : [200, 150],
medium : [500, 350],
large : [1000, 700],
fullscreen : [window.innerWidth, window.innerHeight],
// Shorthand for sizes
s : this.small,
m : this.medium,
l : this.large,
f : this.fullscreen
}
// The following two calls should return the exact same result
console.log(sizes.small); // array[200, 150]
console.log(sizes.s); // undefined
Could anyone tell me what I'm doing wrong?
An object literal doesn’t change any contexts; it’s not a function. It’s more like an expression. sizes.small won’t work either, since although sizes is declared, it hasn’t been assigned a value at the time you’re reading it (which is to create the object that gives it a value).
You can assign the properties afterwards:
var sizes = {
// Full names for sizes
small : [200, 150],
medium : [500, 350],
large : [1000, 700],
fullscreen : [window.innerWidth, window.innerHeight]
};
// Shorthand for sizes
sizes.s = sizes.small;
sizes.m = sizes.medium;
sizes.l = sizes.large;
sizes.f = sizes.fullscreen;
make "s" be a function that returns "this.small"
That is,
var sizes = {
small : [200, 150],
s : function() {return this.small}
}
You can't reference properties that way. Here is one way to achieve what you want:
var sizes = new (function() {
this.small = [200, 150];
this.s = this.small;
})();
console.log(sizes.small);
console.log(sizes.s);
See on JSFiddle.
It is impossible to access other values in object before it is created.
You can try with:
var sizes = {
// Full names for sizes
small : [200, 150],
medium : [500, 350],
large : [1000, 700],
fullscreen : [window.innerWidth, window.innerHeight],
}
sizes.s = sizes.small;
sizes.m = sizes.medium;
sizes.l = sizes.large;
sizes.f = sizes.fullscreen;
In JavaScript
this
always refers to the “owner” of the function we're executing, or rather, to the object that a function is a method of. When we define, for example, a function in a page, its owner is the page, or rather, the window object (or global object) of JavaScript.

Adding data to a highchart chart using an array with IDs

I want to add a series to a highchart scatterplot where I am naming each point in the series. I create a chart in the following way:
var chart; // globally available
makeCharts = function(){
chart = new Highcharts.Chart({
chart: {
renderTo: 'container1',
type: 'scatter'
},
series: [{
name: 'a',
data: [{
'id': 'point1',
'x': 1,
'y': 2
}, {
'id': 'point2',
'x': 2,
'y': 5
}]
}]
});
}
I would like to be able to update the points on the chart using something like:
chart.series[0].setData([{id:['point3', 'point4', 'point5'], y:[0,1,2], x:[1,2,3]}])
but this is not correct. Is it possible to update a chart using this approach where each point has an ID?
EDIT:
Just to clarify, I would like to be able to pass the arrays directly, rather than adding the data point by point using addPoint(). I could loop through an array and use addPoint() doing something like this:
id:['point3', 'point4', 'point5'];
y:[0,1,2];
x:[1,2,3];
for (i=0; i<x.length; i++)
{
chart.series[0].addPoint({
x: x[[i],
y: y[i],
id: id[i]
});
}
However, this is very slow. It's much quicker to add data using the following approach:
chart.series[0].setData([[1,0],[2,1],[3,2]]);
I have found that I can add data like this:
chart.series[0].setData([[1,0, 'point3'],[2,1, 'point4'],[3,2, 'point5']]);
but then the only way that I can access the id when the point is selected, is through this.point.config[2]. With the following approach I am unable to use chart.get('pointID') to identify a point as I did not set the ID. I want to be able to identify the point using just the ID.
Well broadly speaking there are two ways in which you can modify the chart data dynamically
Series.setData() Use this approach when you want to completely replace the existing data with some new data
Series.addPoint() Use this approach when you want to add a subset of the points dynamically. This method is not just for adding one point at a time, if you read the documentation carefully again you will find that this method takes a boolean redraw argument, and the argument detail is as following
redraw: Boolean
Defaults to true. Whether to redraw the chart after
the point is added. When adding more than one point, it is highly
recommended that the redraw option beset to false, and instead
chart.redraw() is explicitly called after the adding of points is
finished.
In your case, since you want to add a few points dynamically, but retaining the existing points, you should go with approach 2. But you need to use it inside a loop, with the redraw being set to false (hence solving the problem of being slow) and then after the loop, call the redraw method explicitly
Code
var id = ['point3', 'point4', 'point5'],
y = [0, 1, 2],
x = [1, 2, 3];
for (var i = 0; i < x.length; i++) {
chart.series[0].addPoint({
x: x[i],
y: y[i],
id: id[i]
},false);
}
chart.redraw();
Adding multiple points dynamically | Highcharts and Highstock # jsFiddle
Try using series.addPoint.
chart.series[0].addPoint({
x: 0,
y: 0,
id: 'anything'
});
But if you need to set data for series, use
chart.series[0].setData([{
x: 0,
y: 0,
id: 'anything'
},{
x: 2,
y: 2,
id: 'another'
}]);
As soon as you can pass your data like this:
chart.series[0].setData([[1,0, 'point3'],[2,1, 'point4'],[3,2, 'point5']]);
(as you stated in question), I can suggest you to use a little hack.
We'll need to add another statement to method applyOptions of Highcharts.Point prototype.
if (typeof options[0] === 'number' && options[2] && typeof options[2] === 'string') this.id = options[2];
Here you can see it in action.

Categories