Changing a Highcharts theme (partially working) - javascript

I have a problem with changing the theme for highcharts. I have created an array to hold all the themes and am trying to change them via a select list onChange event.
var highcharts_theme = [];
/* Default theme */
highcharts_theme.push({});
/* Dark Blue theme */
highcharts_theme.push({
colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
chart: {
backgroundColor: {
linearGradient: [0, 0, 250, 500],
stops: [
[0, 'rgb(48, 48, 96)'],
[1, 'rgb(0, 0, 0)']
]
},
.... Shortened for brevity.....
My code to change the theme is :
$('#theme-type').selectmenu({ width: 200 }).change(function (e) {
var themeIndex = parseInt($('#theme-type').val());
Highcharts.theme = highcharts_theme[themeIndex];
// Apply the theme
highchartsOptions = Highcharts.setOptions(Highcharts.theme);
});
The problem I am having is that if for example I switch to the Skies theme it is fine, but then changing to any other theme, the skies background remains along with other elements of the theme.
Does anyone know of a proper way to reset the theme entirely?
Thanks

Every time you set a theme, it merges with the existing theme, and hence any option that is not present in the new theme it will pick from the existing theme. This may not be desired always.
Unfortunately, Highcharts does not give an option to go back to the very defaults that are set at the time of first load. The following code can be used to get that functionality
// Make a copy of the defaults, call this line before any other setOptions call
var HCDefaults = $.extend(true, {}, Highcharts.getOptions(), {});
function ResetOptions() {
// Fortunately, Highcharts returns the reference to defaultOptions itself
// We can manipulate this and delete all the properties
var defaultOptions = Highcharts.getOptions();
for (var prop in defaultOptions) {
if (typeof defaultOptions[prop] !== 'function') delete defaultOptions[prop];
}
// Fall back to the defaults that we captured initially, this resets the theme
Highcharts.setOptions(HCDefaults);
}
After resetting the theme, applying a new theme would work as if that's the first theme being applied.
Demo # jsFiddle

If you remove all of the color options and reload the Highcharts object it will default back to the default basic theme. If you set the below to null it should not show a back ground image once reloaded.
plotBackgroundImage: null

Related

How can I update the background color of my div or any element by using Color Picker

I'm using ([mdbassit/Coloris][1]) as my website's color picker. I'm trying to change any div or elements color by using that color picker using JavaScript but it's not working.
I thing the problem is with my JavaScript Code.
My Code:
Coloris({
// The default behavior is to append the color picker's dialog to the end of the document's
// body. but it is possible to append it to a custom parent instead. This is especially useful
// if the color fields are in a scrollable container and you want color picker' dialog to stay
// anchored to them. You will need to set the position of the container to relative or absolute.
// Note: This should be a scrollable container with enough space to display the picker.
parent: '.container',
// A custom selector to bind the color picker to. This must point to input fields.
el: '.color-field',
// The bound input fields are wrapped in a div that adds a thumbnail showing the current color
// and a button to open the color picker (for accessibility only). If you wish to keep your
// fields unaltered, set this to false, in which case you will lose the color thumbnail and
// the accessible button (not recommended).
wrap: true,
// Available themes: default, large, polaroid.
// More themes might be added in the future.
theme: 'default',
// Set the theme to light or dark mode:
// * light: light mode (default).
// * dark: dark mode.
// * auto: automatically enables dark mode when the user prefers a dark color scheme.
themeMode: 'light',
// The margin in pixels between the input fields and the color picker's dialog.
margin: 2,
// Set the preferred color string format:
// * hex: outputs #RRGGBB or #RRGGBBAA (default).
// * rgb: outputs rgb(R, G, B) or rgba(R, G, B, A).
// * hsl: outputs hsl(H, S, L) or hsla(H, S, L, A).
// * auto: guesses the format from the active input field. Defaults to hex if it fails.
// * mixed: outputs #RRGGBB when alpha is 1; otherwise rgba(R, G, B, A).
format: 'hex',
// Set to true to enable format toggle buttons in the color picker dialog.
// This will also force the format (above) to auto.
formatToggle: true,
// Enable or disable alpha support.
// When disabled, it will strip the alpha value from the existing color value in all formats.
alpha: true,
// Show an optional clear button and set its label
clearButton: {
show: true,
label: 'Done'
},
// An array of the desired color swatches to display. If omitted or the array is empty,
// the color swatches will be disabled.
swatches: [
'#264653',
'#2a9d8f',
'#e9c46a',
'rgb(244,162,97)',
'#e76f51',
'#d62828',
'navy',
'#07b',
'#0096c7',
'#00b4d880',
'rgba(0,119,182,0.8)'
]
});
var inputBox = document.getElementById('colorBackground');
inputBox.onkeyup = function(){
document.body.style.backgroundColor = inputBox.value;
}
body{
background-color: black;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/mdbassit/Coloris#latest/dist/coloris.min.css"/>
<script src="https://cdn.jsdelivr.net/gh/mdbassit/Coloris#latest/dist/coloris.min.js"></script>
<body>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<input class="color-field" type='text' id='colorBackground'>
</body>
Please tell me the correct JavaScript code, by which I can change the background color or any color property of any element or div.
Thank You
[1]: https://github.com/mdbassit/Coloris
If i understood your problem correctly, to fix this you need to use the addEventListener method and get the value from the target directly.
const inputBox = document.getElementById('colorBackground');
inputBox.addEventListener('change', ev => {
document.body.style.backgroundColor = ev.target.value;
});
inputBox.addEventListener('keyup', ev => {
document.body.style.backgroundColor = ev.target.value;
});
// inputBox.onkeyup = function () {
// document.body.style.backgroundColor = inputBox.value;
// };
Coloris({
// The default behavior is to append the color picker's dialog to the end of the document's
// body. but it is possible to append it to a custom parent instead. This is especially useful
// if the color fields are in a scrollable container and you want color picker' dialog to stay
// anchored to them. You will need to set the position of the container to relative or absolute.
// Note: This should be a scrollable container with enough space to display the picker.
parent: '.container',
// A custom selector to bind the color picker to. This must point to input fields.
el: '.color-field',
// The bound input fields are wrapped in a div that adds a thumbnail showing the current color
// and a button to open the color picker (for accessibility only). If you wish to keep your
// fields unaltered, set this to false, in which case you will lose the color thumbnail and
// the accessible button (not recommended).
wrap: true,
// Available themes: default, large, polaroid.
// More themes might be added in the future.
theme: 'default',
// Set the theme to light or dark mode:
// * light: light mode (default).
// * dark: dark mode.
// * auto: automatically enables dark mode when the user prefers a dark color scheme.
themeMode: 'light',
// The margin in pixels between the input fields and the color picker's dialog.
margin: 2,
// Set the preferred color string format:
// * hex: outputs #RRGGBB or #RRGGBBAA (default).
// * rgb: outputs rgb(R, G, B) or rgba(R, G, B, A).
// * hsl: outputs hsl(H, S, L) or hsla(H, S, L, A).
// * auto: guesses the format from the active input field. Defaults to hex if it fails.
// * mixed: outputs #RRGGBB when alpha is 1; otherwise rgba(R, G, B, A).
format: 'hex',
// Set to true to enable format toggle buttons in the color picker dialog.
// This will also force the format (above) to auto.
formatToggle: true,
// Enable or disable alpha support.
// When disabled, it will strip the alpha value from the existing color value in all formats.
alpha: true,
// Show an optional clear button and set its label
clearButton: {
show: true,
label: 'Done',
},
// An array of the desired color swatches to display. If omitted or the array is empty,
// the color swatches will be disabled.
swatches: [
'#264653',
'#2a9d8f',
'#e9c46a',
'rgb(244,162,97)',
'#e76f51',
'#d62828',
'navy',
'#07b',
'#0096c7',
'#00b4d880',
'rgba(0,119,182,0.8)',
],
});
const inputBox = document.getElementById('colorBackground');
inputBox.addEventListener('change', ev => {
document.body.style.backgroundColor = ev.target.value;
});
inputBox.addEventListener('keyup', ev => {
document.body.style.backgroundColor = ev.target.value;
});
// inputBox.onkeyup = function () {
// document.body.style.backgroundColor = inputBox.value;
// };
body {
background-color: black;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/mdbassit/Coloris#latest/dist/coloris.min.css" />
<script src="https://cdn.jsdelivr.net/gh/mdbassit/Coloris#latest/dist/coloris.min.js"></script>
<br /><br /><br /><br /><br /><br /><br />
<input class="color-field" type="text" id="colorBackground" />

How to give a single line serie multiple colors with Tradingview Lightweight charts in Javascript?

This image below is what I have at this moment.
This image below is what I want. (1st image from my code, second from tradingview).
To be clear: I want a single line to have multiple colors. For my situation I need only two colors. I need each new line I create changable in color. Its a nice to have if the price tag on the right also changes to the color of the line that hits the right part of the chart.
This is my code:
var chart = LightweightCharts.createChart(document.getElementById("Chart"), {width: 1500, height: 700});
/**
* Creates startline and adds extra options to the lineSeries.
*/
function initChartSettings() {
// Init lines
priceArea = chart.addAreaSeries();
buySellLine = chart.addLineSeries(); //LINE THAT NEEDS TWO COLORS
// Set start position of lines
priceArea.setData([{time: '2019-04-11', value: startPrice}]);
buySellLine.setData([{time: '2019-04-11', value: startPrice}]);
// Visualization edits
priceArea.applyOptions({
topColor: 'rgba(70, 130, 180, 0.5)',
bottomColor: 'rgba(70, 130, 180, 0.1)',
lineColor: '#4682B4'
});
// Buy sell line
buySellLine.applyOptions({
color: '#42f54b', //CHANGES COLOR OF THE COMPLETE LINE, FROM BEGIN TO END.
priceLineVisible: true,
lastValueVisible: true
});
updateChartStatic();
}
/**
* Updates the chart its lines.
*/
function updateChartStatic() {
setTimeout(() => {
priceArea.update({
time: yearMonthDay, //How this works should not matter for question
value: newPrice, //Same as above
});
// Updates the price line of the chart.
buySellLine.update({
time: yearMonthDay,
value: currentMovingAverage //Even though it would be nice to do the below commented thing...
// color: 'red or green (example)'
});
buySellLine.applyOptions({
color: changeLineColor(currentMovingAverage, lastMovingAverage) // CHANGES COMPLETE LINE :(
});
}, 1);
}
the changeLineColor() function is doing an if statement, which has nothing to do with setting a color to a line.
EDIT: As this feature was landed in v3.8 you can simply add color properties to any of your data items by using the following properties in the data:
LineData.color to change a color of line data item
CandlestickData.color to change a body color of a candlestick item
CandlestickData.borderColor to change a border color of a candlestick item
CandlestickData.wickColor to change a wick color of a candlestick item
Note that you don't need to provide all the colors and you can provide only necessary ones (e.g. only body color for some candlestick items).
Original answer:
It's impossible right now, but there is issue for this feature https://github.com/tradingview/lightweight-charts/issues/195. You can subscribe on it to being notified when it'll be fixed (or even make a proposal and/or provide a PR with changed).

Highcharts | Heatmap | Legend filters not working when updating data

I have an issue with how the setData function works with a series of kind 'HEATMAP', when updating the data, and when one or more legend filters have been disabled.
I use 3 colors to fill the Heatmap chart according to the value represented by the data (which works fine) , each color is shown as an item in the legend :
options.colorAxis = {
dataClasses: [
{
color: GREEN,
from: 0,
to: 50,
},
{
color: ORANGE,
from: 50,
to: 100,
},
{
color: RED,
from: 100,
to: 1e6,
}]
};
When I want to update the chart with new data coming from a server, I use :
this.chart.series[0].setData(newData, true, false, false);
This works fine as well, except when colors have been disabled by clicking on the legend items.
The problem is that all the colors that were filtered out by the filter reappear on the chart when data is updated ( image below , part 3 )
However, the legend is ok (what was disabled remains disabled).
Can you please help me find a solution ?
Thank you.
Please find below the visual description of what I explained :
FWIW, this is how I solved my problem.
Right after updating with
this.chart.series[0].setData(newData, true, false, false);
I just added the lines below ( toggle programmatically twice the visibility of the data groups ) :
const allItems = (<any>this.chart.legend).allItems as Array<any> ;
allItems.forEach( item => {
item.setVisible();
item.setVisible();
});

Add custom parameter to info.contentsFunction

I need to be able to add some custom info to the pie.info.contentsFunction in Zoomcharts. I have multiple charts on the page, each one created like so...
var pc = new PieChart({
pie: {
innerRadius: 0.5,
},
container: chartContainer1,
area: { height: 500 },
data:chartData,
toolbar: {
"fullscreen": true,
"enabled": true
},
info: {
contentsFunction: boomChartTT
}
});
In the "boomChartTT" function I need to know what chart is being hovered upon. I'd like to be able to do something like this...
info: {
contentsFunction: boomChartTT(i)
}
...where 'i' is the index of the chart.
The reason I need to know the chart index is because I have some other data saved in an indexed array for each chart. The index of the chart matches the index of the data.
EXAMPLE: if user hovers on a slice in chart2 I'd want to pass '2' to the boomChartTT function so I can access the totals data for that chart (say, totalsData[2]).
I've done this in the past with other chart libraries by simply adding a data attribute to the chart container to give me the index like so...
<div id="chartContainer1" data-index="1"></div>
...and then I'm able to access the chartContainer from the hover function (contentsFunction) and then get that index.
I don't want to add the totals data to the actual chart data because I'd have to add it to each slice which is redundant.
Is there a way to do this?
Please let me know if my post is unclear.
EDITED TO ADD:
I don't think it matters but here is the boomChartTT function:
function boomChartTT(data,slice){
var tt="<div class=\"charttooltip\">";
if(data.name==="Others" || data.name==="Previous"){return tt+=data.name+"</div>";}
//var thisData=dataSearch(totalsData[i],"REFERRINGSITE",data.id);
tt+="<h5 class=\"strong\">"+data.id+"</h5>"+oHoverTable.render(thisData)+"</div>";
return tt;
}
The commented line is where I would need the index (i) to to get the correct totalsData.
SOLVED. I simply added "chartIndex" to the data like so...
for(var i=0;i<r.length;i++){
var thisDataObj ={
id:r[i].REFERRINGSITE,
value:r[i].PCTOFSALES,
name:r[i].REFERRINGSITE,
chartIndex: arguments[1],//<----- arguments[1] is the chart index
style: { expandable: false, fillColor: dataSearch(dataRSList,"REFERRINGSITE",r[i].REFERRINGSITE)[0].COLOR }
};
chartData.preloaded.subvalues.push(thisDataObj);
}
Then in the boomChartTT function...
function boomChartTT(data,slice){
var tt="<div class=\"charttooltip\">";
if(data.name==="Others" || data.name==="Previous"){return tt+=data.name+"</div>";}
var thisData=dataSearch(totalsData[data.chartIndex-1],"REFERRINGSITE",data.id);
tt+="<h5 class=\"strong\">"+data.id+"</h5>"+oHoverTable.render(thisData)+"</div>";
return tt;
}
I feared that adding custom fields to the chart data would break the chart (which I believe I've experienced with other libraries). So, there you go.

How to disable Stacking on an individual series using Primefaces jQplot implementation

I am using Primefaces 6 for my companys charting needs, which relies on jQplot.
For a project, I am trying to overlay a line chart on a stacked bar chart with negative values, to obtain something like this:
The problem is that when I try to add a linechartseries to the same model as the two barchartseries , the linechart becomes a part of the stack when setting setStacked(true); on the model, because Primefaces seems to not allow individual disabling of stacking on series, only per model. So I end up with this when rendering the chart with
<p:chart type="bar" model="#{backingBean.cartesianChartModel}"/>
After some investigation I have notoced that jQplot is capable of disabling Stacking on individual series by passing disableStack : true in the JS options, so the question is if it's posssible to override this in some way on the rendered page,either via PF or via some JS hack? I feel that using the extender only apples to the entire model?
Related issues: Disable individual stacking
By pouring through the documentation I found a solution to the problem, if not the question:
It seems that Primefaces allows for individual series to be excempt from the stack in the series creation in this version, by passing
LineChartSeries.setDisableStack(true);
Simple as that.
I guess it may be possible. I used the extender functionality for some jqPlot hacks in the past.
In my case, for example, I had a Donut Chart defined with an extender function as follows:
private void createDonutModel() {
donutModel = new DonutChartModel();
donutModel.setLegendPosition("s");
donutModel.setLegendPlacement(LegendPlacement.OUTSIDE);
donutModel.setSliceMargin(4);
donutModel.setDataFormat("value");
donutModel.setShadow(false);
donutModel.setExtender("donutExtender");
donutModel.setSeriesColors("B81C40, FFA600, 79B54A");
}
The corresponding javascript was doing some changes to the jqPlot:
/**
* Customized jqPlot JQuery layout of the Donut Chart for Status Dashboard.
*/
function donutExtender() {
this.cfg.seriesDefaults = {
// make this a donut chart.
renderer:$.jqplot.DonutRenderer,
rendererOptions:{
thickness: 26,
ringMargin: 0,
fill: true,
padding: 0,
sliceMargin: 4,
// Pies and donuts can start at any arbitrary angle.
startAngle: -90,
showDataLabels: false,
// By default, data labels show the percentage of the donut/pie.
// You can show the data 'value' or data 'label' instead, or 'percent'
dataLabels: 'value',
shadow: false
}
}
this.cfg.gridPadding = {
top: 0, right: 0, bottom: 0, left: 0
}
this.cfg.legend = {
show: false
}
this.cfg.grid = { drawBorder: false,
shadow: false,
background: "transparent"
};
}
So you may try something like this in your case ?
Leave the extension configuration of your series empty, except for the one you are interested in...
function chartExtender() {
this.cfg.series = [
{ //...
},
{ // ...
},
{
disableStack: true
}
]
}
Worth having a shot ...

Categories