Hichcharts- hidden series does not show again after updating plots twice - javascript

I have done something like:
Have a check box to change the plot's data
when the check box is checked/unchecked, update the series data array by calling series[i].update() accordingly.
But I have a problem that when a series is hidden by the user and try to check the checkbox and then uncheck, followed by reshow the series, the series does not show again.
Please note that If I only check the box once, no problem occurs, there will be problem only when we check the box more than once after we hide the series.
I have reproduce the problem HERE (JSFiddle)
The code to update the plot is :
if (chart) {
for (var i = 0; i < chart.series.length; i++) {
//chart.series[i].setVisible(true, true); // Note that if I add this code, then no problem
chart.series[i].update({
data: dataArray[i]
});
}
}

The problem is that you base on Highcharts generated points. When series is hidden, then points don't exist and you set empty data for a series. In other words it looks like this: chart.series[i].setData( [] );.
I suggest to use separate arrays for data and use those for your calculations. General idea: http://jsfiddle.net/pGuEv/37/ (I know, it works a bit different, but shows how should be written)
var origData = [
[11, 22, 33, 44, 55, 66, 77, 88],
[10, 20, 30, 40, 50, 60, 70, 80]
];
$('#container').highcharts({
series: [{
data: origData[0].slice()
}, {
data: origData[1].slice()
}]
});
And later:
for (var i = 0; i < origData.length; i++) { // original data
var onePlotData = [];
var sum = 0; //前面点的合计值s
for (var j = 0; j < origData[i].length; j++) { // original data
var value = origData[i][j]; // original data
var point = {
//x: value.x,
y: state ? value + sum : value - sum,
//total: value.total
}
sum = point.y;
onePlotData.push(point);
}
dataArray.push(onePlotData);
}

Related

Javascript - I am trying to build the function passingGrades to filter out low grades (<=70) in an array of grades, but it's not working.

The code below does not work and I can't figure out why. Can anyone help?
var grades = [];
var passingGrades = function(grades) {
for (i=0; i < grades.length; i++){
console.log(grades.filter(function(grades[i]) {
return grades[i] >= 70;
}));
}
};
passingGrades([63, 75, 39, 88, 94, 100, 24]);
You just need to return the filtered array, a new one is created by the filter method.
Side note: Don't use a global variable with the same name as a local variable!
var passingGrades = function(grades) {
return grades.filter((grade) => grade >= 70);
};
console.log(passingGrades([63, 75, 39, 88, 94, 100, 24]));
Array methods like filter and map automatically iterate over every item within them(that's what makes them so powerful) and, when called, they return a new array. This means there's no need for a for loop as well. What you have currently would be roughly the equivalent of:
for(i = 0; i < grades.length; i++) {
for(i = 0; i < grades.length; i++) {
if(grades[i] > 70) {
...
}
}
}
That's unnecessary.
Furthermore since you're simply filtering an array that you are already passing into the function you might as well just return the filtered array immediately. To do this we just return the grades.filter result.
Lastly the function that you're placing within .filter is what will be called on each item within the array you passed in. The parameter you provide is a reference to each individual item as this iteration occurs. This is why grades[i] makes no sense, it's a pointer to the referenced item, so you can simply call it grade.
In simpler terms we are saying hey, grades, filter everything within yourself and for each grade determine if it's greater than 70. Return an array only containing these filtered items
var passingGrades = function(grades) {
return grades.filter(function(grade) {
return grade >= 70;
});
}
console.log( passingGrades([63, 75, 39, 88, 94, 100, 24]) );

Dynamic width for each column if value is 0 in highcharts

I'm new to highcharts plugin and I need to set different width for each column if the value is empty.
series: [{
name: 'Jane',
data: [1, 0, 4]
}, {
name: 'John',
data: [5, 7, 3]
}]
And i need to display it this way
I need this
I have been searching the documentation but i don't find anything that does it, without a lot of code.
I achieved this, but it doesn't upload/resize dynamically.
http://jsfiddle.net/5vgjztk0/
Thanks
You can use something like merimekko chart.
(function(H) {
var each = H.each;
var xStart = 0;
var rememberX = 0;
H.wrap(H.seriesTypes.column.prototype, 'drawPoints', function(proceed) {
var series = this;
if(series.data.length > 0 ){
each(this.data, function(point) {
point.shapeArgs.width = series.xAxis.translate(point.x) - series.xAxis.translate(xStart);
point.shapeArgs.x = series.xAxis.translate(point.x) - point.shapeArgs.width;
xStart = point.x;
});
xStart = 0;
}
proceed.call(this);
})
})(Highcharts)
Demo:
http://jsfiddle.net/js55fuo1/24

Handsontable Sequence word creation

Thanks for this wonderful plugin.
I am using this plugin for grid functionality. For this I am trying to use sequence word creation on drag down.
I have implemented upto my knowledge. But I am facing one problem while select and drag multiple column.
I have created jsfiddle for this sample
var myData = [
["WIRE-001", 10, 11, 12, 13],
["WIRE-002", 20, 11, 14, 13],
["WIRE-003", 30, 15, 12, 13]
];
$("#exampleGrid").handsontable({
data: myData,
startRows: 5,
startCols: 5,
//minSpareCols: 1, //always keep at least 1 spare row at the right
minSpareRows: 10, //always keep at least 1 spare row at the bottom,
rowHeaders: true,
colHeaders: true,
contextMenu: true,
currentRowClassName: 'currentRow',
currentColClassName: 'currentCol',
outsideClickDeselects: false,
fillHandle: true,
beforeAutofill: function(start, end, data) {
console.log(arguments);
console.log(start);
console.log(end);
console.log(data);
var selectedVal = this.getSelected();
var selectedData = this.getData(selectedVal[0], selectedVal[1], selectedVal[2], selectedVal[3]);
var sequenceNum = [];
var sequenceWord = [];
var numberFormat = 1;
if (start.col == 0) {
for (var j = 0; j < selectedData.length; j++) {
var numbers = selectedData[j][0].match(/[0-9]+$/g);
if (numbers && !isNaN(numbers[0])) {
numberFormat = numbers[0].length;
sequenceNum.push(Number(numbers[0]));
}
var words = selectedData[j][0].match(/[A-Za-z\-]+/g);
if (words && isNaN(words[0])) {
sequenceWord.push(words[0]);
}
}
var prefix = sequenceWord.length > 0 ? sequenceWord[0] : "";
var lastValue = sequenceNum[sequenceNum.length - 1]
var diff = sequenceNum.length > 1 ? (sequenceNum[sequenceNum.length - 1] - sequenceNum[sequenceNum.length - 2]) : 1;
for (var i = 0; i < end.row; i++) {
if (!data[i]) { data[i] = []; }
data[i][0] = prefix + pad((lastValue + diff), numberFormat);
diff++;
}
}
},
afterChange: function(changes, source) {
}
});
Appreciate for helping to solve this.
I recommend opening the console and checking the errors since it becomes very clear what your problem is if you do so. The example that leads to the bug that you mentioned on your comment uses an empty row. In your code you are doing
var words = selectedData[j][0].match(/[A-Za-z\-]+/g);
However, selectedData[j][0] will be null. I would simply add a check for empty rows and handle it appropriately (toss it or default to some value)

How can I style highchart select to look like hover?

Highcharts is an amazing library, however I need to programatically scroll through the chart as if the cursor itself was hovering across the x-axis. The only way I can think of doing this is by selecting points, unfortunately I could not find options in highcharts api documentation that allows me to put crosshairs/ playheader on selected points.
How can I do this?
This is not part of the API, but you can use point.onMouseOver() to fire mouseover event: http://jsfiddle.net/15dzo23n/1/
Example:
var index = 0;
$('#container').highcharts({
chart: {
events: {
load: hoverAnim
}
},
tooltip: {
crosshairs: true
},
series: [{
name: 'AAPL',
data: [5, 10, 15, 12, 13, 14, 12, 1, 12, 1, 12, 12, 12, 1]
}]
});
function hoverAnim(e) {
var chart = this,
points = chart.series[0].points,
len = points.length;
if (index < len) {
chart.hoverSeries = chart.series[0];
chart.hoverPoint = points[index];
chart.pointer.runPointActions(e); //display crosshair
points[index].onMouseOver(e); // display tooltip and set hover state
index++;
setTimeout(function () {
hoverAnim.call(chart, e);
}, 100);
}
}
Pawel Fus had a good answer, however I found an even better solution which doesn't have the buggy lag behavior when switching to different time points. Also events are not needed in this solution.
var chart = myElement.highcharts();
function select(value) {
// Scroll to some time.
var axes = chart.axes;
for (var i = 0; i < axes.length; i ++) {
var axis = axes[i];
axis.drawCrosshair(null, chart.series[0].points[value])
}
for (i = 0; i < chart.series.length; i++) {
var series = chart.series[i];
// Unset last value
series.points[oldValue].setState('');
// Set new value
series.points[value].setState('hover');
}
oldValue = value;
});

Removing item from array based on id

I have two array's. One of id's of elements that I need to show and then another of the elements in a drop down. If the id's match then then show. It sounds simple, but I'm having trouble slicing out the elements that do not need to show.
So it kind of looks like this
var option = //Ton of objects with values that match with the id that look like this, there are about 70 of them. I need to loop through these to get the value of each one. Please see screen shot, I don't know how else to show that they are objects.
var ids = [16, 15, 17, 18, 5];
and then I was trying to loop through each option and see if the value is equal to the Id. For some reason this is removing everything instead of just the once that need to be removed.
for(var i=0 ; i<option.length; i++){
if (option[i].value !== ids) {
option.splice(i);
}
}
Try out the filter function:
var newOptions = options.filter(function(option, index) {
return ids.indexOf(option.value) >= 0;
});
var values = newOptions.map(function(option) {
return option.value;
});
If you want to remove items from the option array:
var option = [
{display:'opt50', value:50 },
{display:'opt16', value:16 },
{display:'opt10', value:10 },
{display:'opt17', value:17 },
{display:'opt43', value:43 },
{display:'opt5', value:5 }
]
var ids = [16, 15, 17, 18, 5];
for(var i = option.length - 1; i > -1; i--) {
if(ids.indexOf(option[i].value) == -1) {
option.splice(i,1);
}
}
// logs [{"display":"opt16","value":16},{"display":"opt17","value":17},{"display":"opt5","value":5}]
console.dir(JSON.stringify(option));
If you want to just find matching items and keep option intact:
// fill in options with some elements
var option = [
{display:'opt50', value:50 },
{display:'opt16', value:16 },
{display:'opt10', value:10 },
{display:'opt17', value:17 },
{display:'opt43', value:43 },
{display:'opt5', value:5 }
]
var ids = [16, 15, 17, 18, 5];
var filteredOption = option.filter(function(o) {
return ids.indexOf(o.value) > -1;
});
// logs [{"display":"opt16","value":16},{"display":"opt17","value":17},{"display":"opt5","value":5}]
console.dir(JSON.stringify(filteredOption));
The !== operator is always going to return true.
12 !== [12,34,45]
true
13 !== [12,34,45]
true
As a result, if (option[i].value !== ids) { will always execute option.splice(i); since the compared values are always different types.
Mozilla's Sameness documentation has a great explanation and useful chart.
var option = [{display: "Member Form",value: 2}, {display: "Member Form",value: 5}];
var ids = [16, 15, 17, 18, 5];
var optionKey = Object.keys(option);
for(var i = optionKey.length - 1; i >= 0 ; i--){
if (ids.indexOf(option[optionKey[i]].value) == -1) {
option.splice(i, 1) //second argument allows splice to only delete one element.
}
}
console.log(option);
document.write(JSON.stringify(option)); //result!

Categories