NoUISlider Tooltip only show integers - javascript

I want that the tooltip on my slider only shows integers like "130" and not "130.00".
I just dont know where i could start.
Here is my code:
$( document ).ready(function() {
var groesseslider = document.getElementById('slider-tooltip');
noUiSlider.create(groesseslider, {
start: [ 145 ],
step: 1,
range: {
'min': 100,
'max': 250
}
});
});
$( document ).ready(function() {
var groesseslider = document.getElementById('slider-tooltip');
var tipHandles = groesseslider.getElementsByClassName('noUi-handle'),
tooltips = [];
// Add divs to the slider handles.
for ( var i = 0; i < tipHandles.length; i++ ){
tooltips[i] = document.createElement('div');
tipHandles[i].appendChild(tooltips[i]);
}
// When the slider changes, write the value to the tooltips.
groesseslider.noUiSlider.on('update', function( values, handle ){
tooltips[handle].innerHTML = values[handle];
});
});
My JS Code:
http://jsfiddle.net/miiauwz/66a5ahm0/

This can work..
var sliderFormat = document.getElementById('slider-format');
noUiSlider.create(sliderFormat, {
start: [ 20 ],
...
format: {
from: function(value) {
return parseInt(value);
},
to: function(value) {
return parseInt(value);
}
}
});

You can either try using the unencoded value like described in noUISlider's documentation about events and their binding
slider.noUiSlider.on("update", function(values, handle, unencoded ) {
// values: Current slider values;
// handle: Handle that caused the event;
// unencoded: Slider values without formatting;
});
or another possibility would be using the format option on slider creation (but haven't tried it myself yet):
noUiSlider.create(slider, {
start: [ 20000 ],
...
format: wNumb({
decimals: 0, // default is 2
thousand: '.', // thousand delimiter
postfix: ' (US $)', // gets appended after the number
})
});
The drawback is you have to download the wNumb-Library separately from here: http://refreshless.com/wnumb/.
Another way without wNumb
After having another look at the examples from noUISlider, I found this way for manually formatting (at the bottom of the page):
var sliderFormat = document.getElementById('slider-format');
noUiSlider.create(sliderFormat, {
start: [ 20 ],
...
format: {
to: function ( value ) {
return value + ',-';
},
from: function ( value ) {
return value.replace(',-', '');
}
}
});

If you don't think you'll ever need to have decimal places on your site, you can search the jquery.nouislider.min.js file for toFixed(2) and replace with toFixed(0).

I you don't want to use wNumb - library , this method might work.
This will give you value without decimals.
Hope this helps.
value.split('.')[0]

Possible way without using any other library. If we want to show only integers there is no need to use additional libraries. Assuming that in the html code there is the element 'slider-fee'.
<div id="slider-fee"></div>
Let's say that we want to give the possibility to choose a range of hours in a day. Something like 7h-19h or 8h-20h and in the tooltip we want to display the integer only.
dragTapSlider = document.getElementById('slider-fee');
// number of decimal places
decimals = 0;
// format object
numberFormat = {
// 'to' the formatted value. Receives a number.
to: function (value) {
return value.toFixed(decimals);
},
// 'from' the formatted value.
// Receives a string, should return a number.
from: function (value) {
return Number(value);;
}
};
noUiSlider.create(dragTapSlider, {
start: [8, 20],
connect: [false, true, false],
step: 1,
behaviour: 'drag',
tooltips: [true, true],
range: {
'min': 1,
'max': 24
},
format: numberFormat
});
noUiSlider - Integer Format
Example for money range
dragTapSlider = document.getElementById('slider-fee');
decimals = 2;
suffix = '€';
numberFormat = {
// 'to' Format the value to currency.
to: function (value) {
return value.toFixed(decimals) + ' ' + suffix;
},
// 'from' Convert currency value to number.
// Receives a string, should return a number.
from: function (value) {
return Number(value.replace(' ' + suffix));
}
};
noUiSlider.create(dragTapSlider, {
start: [25, 40],
connect: [false, true, false],
step: 0.5,
behaviour: 'drag',
tooltips: [true, true],
range: {
'min': 20,
'max': 50
},
format: numberFormat
});
noUiSlider - Currency Format

Figured I'd provide an answer in case someone else comes looking for this. Simply add the following as an option to the noUiSlider creation:
tooltips: [ wNumb({ decimals: 0 }), wNumb({ decimals: 0 }) ],
The following code will create the slider you need with the noUiSlider tooltip displaying only the integer value with no decimal points:
$( document ).ready(function() {
var groesseslider = document.getElementById('slider-tooltip');
noUiSlider.create(groesseslider, {
start: [ 145 ],
step: 1,
tooltips: [ wNumb({ decimals: 0 }), wNumb({ decimals: 0 }) ],
range: {
'min': 100,
'max': 250
}
});

Just use Math for this instead of the library.
Math.round(value)

var skipSlider = document.getElementById('price');
noUiSlider.create(skipSlider, {
start: [47000, 247000],
connect: true,
behaviour: 'drag',
step: 1,
range: {
'min': [47000],
'max': [247000]
},
});
var skipValues = [
document.getElementById('min-price'),
document.getElementById('max-price')
];
skipSlider.noUiSlider.on('update', function (values, handle, unencoded) {
skipValues[handle].innerHTML = unencoded[handle];
});

React example with no external library:
<Nouislider
range={{ min: 0, max: 5 }}
tooltips={true}
step={1}
start={[0, 5]}
connect
format={{
from: (value) => {
return parseInt(value);
},
to: (value) => {
return parseInt(value);
}
}}
onSlide={onUpdate}
/>

Related

Chart.js show negative value in the top half

I am creating a chart.js which has both positive and negative values
but how to make all values be on the top half
(ignore the if it's positive or negative when drawing but keep the label)
var tax_dash = new Chart(ctx_tax_dash, {
type: "bar",
data: {
labels: lable_set,
datasets: [{
label: "Tax in",
data: total_tax_in_t_data__year,
backgroundColor: '#0fd96d',
// borderColor: sales_t_data,
borderWidth: 1,
},
{
label: "Tax out",
data: total_tax_out_t_data__year,
backgroundColor: '#0f81d9',
// borderColor: sales_t_data,
borderWidth: 1,
},
{
label: "Net VAT",
data: total_tax_in_out_t_data__year,
backgroundColor: '#d96a0f',
// borderColor: sales_t_data,
borderWidth: 1,
},
],
},
options: {
legend: {
display: true,
}
},
});
EDIT
what I am trying to do
possible solution: is (multi-axis) dual y axis.multi-axis example
~ issue: how to flip the axis so that the -100 be to the top and 0 be on the bottom
~ issue: how to split the data set base on the (sign)
OR
possible solution 2 : make all variable positive
#Gkiokan> solution: use the popup modifier to the showing values with negative
~ ++ issue: how the function will know if the value is negative
~ issue: the user needs to know that this value is negative in the label
Solution 2
I did it this morning user what Math.abs from #Lawrence comment and "popup modifier" from #Gkiokan comment as well as this jsfiddle
Thank you very much for the help. Chatting with smarter people rubs off on you :)
total_tax_in_t_data_portal_month_year = [Math.abs(12),Math.abs(-234),Math.abs(234)];
total_tax_in_t_data_portal_month_year_sign = [12,-234,234];
var tax_dash_portal = new Chart(ctx_tax_dash_portal, {
type: "bar",
data: {
labels: lable_set,
datasets: [
{
label: "VAT In",
data: total_tax_in_t_data_portal_month_year,
sign: total_tax_in_t_data_portal_month_year_sign,
backgroundColor: "#0fd96d",
// borderColor: sales_t_data,
borderWidth: 1,
},
{
label: "VAT Out",
data: total_tax_out_t_data_portal_month_year,
sign: total_tax_out_t_data_portal_month_year_sign,
backgroundColor: "#0f81d9",
// borderColor: sales_t_data,
borderWidth: 1,
},
{
label: "Net VAT",
data: total_tax_t_data_portal_month_year,
sign: total_tax_t_data_portal_month_year_sign,
backgroundColor: "#d96a0f",
// borderColor: sales_t_data,
borderWidth: 1,
},
],
},
options: {
legend: {
display: true,
},
tooltips: {
enabled: true,
callbacks: {
label: function (tooltipItem, data) {
var label = data.labels[tooltipItem.index];
var val = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var sign = data.datasets[tooltipItem.datasetIndex].sign[tooltipItem.index];
if(sign < 0){
return label + ": -" + val;
}else{
return label + ': ' + val;
}
}
}
}
},
});
total_tax_in_t_data_portal_month_year is an example as the values come from a function
Math.abs is used to remove the negative sign
then I added sign to the datasets for essay access
tooltips callbacks is called on every variable so I added the if statement there
to add - if sign < 0 and do nothing if not
In my opinion you can have a data Set to save the orginal Data and the modified
Data and then use the values as you need. You can not trust the value characters. My solution will work kind cross over as you have control over both values.
I've made a jsfiddle for you which demonstrates the orginal Data vs modified Data usage. Please click first on Modify Data which will then map the data, so you can see the work in progress. In your case you would modify the data before calling the charts.
Actually you will need just a couple of methods as followed:
updateItemValues to modify the negative values and put it to the other object
tooltipCallback callback for the tooltip to use the mapped orginal value
let data = {
modified: false,
orginalData : {
'tax_in' : [10, 20, -30, -40, -100, -50],
'tax_out' : [-10, 10, 20, 10, -40, -70],
'net_vat' : [-50, -9, -40, -20, -10, -90],
},
modifiedData : {
// this modified data will be calculated before putting it in the charts
// for demo purpose we will just copy the values for now.
'tax_in' : [10, 20, -30, -40, -100, -50],
'tax_out' : [-10, 10, 20, 10, -40, -70],
'net_vat' : [-50, -9, -40, -20, -10, -90],
},
updateModifiedData(){
// loop though the orginal Data
Object.keys(this.orginalData).forEach( (item, indexx) => {
console.log('modifying item chart data for: ', item)
this.updateItemValues(item)
})
this.modified = true
document.getElementById('status').innerHTML = 'modified'
},
updateItemValues(dataKey){
let temp = []
this.orginalData[dataKey].forEach( (value, index) => {
console.log('- validating ', dataKey, 'index: ', index, '; value: ', value)
// if we have a negative value, just multiply by -1 so get it positive
if(value <= 0){
value = value * -1
}
// add to the temporary variable
temp.push(value)
})
// put the modified data to some place to have it saved
this.modifiedData[dataKey] = temp
console.log('-- final data modded ', temp)
},
tooltipCallback(tooltipItem, chartData) {
// find reference values
let index = tooltipItem.index
let dataIndex = tooltipItem.datasetIndex
// find the name of dataset
let key = chartData.datasets[dataIndex].name
// validate or whatever with the orginal value
let orginalValueOfItem = data.orginalData[key][index]
let modifiedValueOfItem = data.modifiedData[key][index]
// Modify your final tooltip here
return 'Orginal Value: ' + orginalValueOfItem + ' ; Modified Value: ' + modifiedValueOfItem
}
}
How can you use this solution?
Pretty simple.
Copy that data Object in your code.
Fill the data.orginalData value with your orginal charts data based on key
example data.orginalData.tax_in = [...]
In your datasets add name property with the corresponding key
Extend the Charts options with the tooltipCallback
Call data.updateModifiedData() to get the modified data
Checkout the jsFiddle for reference if you need to.
Have fun.

Is there a stable way to set echarts axis limits from html id value

I'm writing an electron.js app where I'm using echart.js to display a heatmap.
Two html input tags are used to let the user set the axis limits for the heatmap.
<span>
<input type="number" id="min_limit" value= 1>
<input type="number" id="max_limit" value= 2>
</span>
In the javascript code I'm simply using the following to get this content:
data_min = document.getElementById('min_limit').value;
data_max = document.getElementById('max_limit').value;
The problem occurs when I try to use these two variables within the echart option:
option = {
...
visualMap: {
min: data_min,
max: data_max,
...
}
}
I get the following error:
"Uncaught DOMException: Failed to execute 'addColorStop' on 'CanvasGradient': The value provided ('undefined') could not be parsed as a color."
The interesting thing is that the program works when I try any of the following (only one of the input values respectively but not both at the same time):
option = {
...
visualMap: {
min: 0,
max: data_max,
... // No errors
}
}
option = {
...
visualMap: {
min: data_min,
max: 1,
... // No errors
}
}
option = {
...
visualMap: {
min: 0,
max: 1,
... // No errors
}
}
And calling*:
myChart.setOption(option);
To display the chart.
Any suggestions? I'm new to html and JavaScript so there may be an obvious error that I'm missing.
*EDIT: Forgot to mention that I'm using "setOption" to change the appearance.
You can't set echarts option directly. Need to use setOption for add data, see documentation.
Update
Your implementation does not work because Echarts not understand what need do with inputs. Getting value you in fact calling the getter (special built-in function) of input component. The Echarts does't know how to call getter, it's expecting just value.
With regard to the implementation I would have the following way.
Define function that read value for inputs.
Define function that update Echart's min/max.
Attach event listener to body element for listen inputs change event.
And then after receive the event call the update Echarts.
var myChart = echarts.init(document.getElementById('main'));
var hours = ['12a', '1a', '2a', '3a', '4a', '5a', '6a',
'7a', '8a', '9a','10a','11a',
'12p', '1p', '2p', '3p', '4p', '5p',
'6p', '7p', '8p', '9p', '10p', '11p'];
var days = ['Saturday', 'Friday', 'Thursday',
'Wednesday', 'Tuesday', 'Monday', 'Sunday'];
var data = [[0,0,5],[0,1,1],[0,2,0],[0,3,0],[0,4,0],[0,5,0],[0,6,0],[0,7,0],[0,8,0],[0,9,0],[0,10,0],[0,11,2],[0,12,4],[0,13,1],[0,14,1],[0,15,3],[0,16,4],[0,17,6],[0,18,4],[0,19,4],[0,20,3],[0,21,3],[0,22,2],[0,23,5],[1,0,7],[1,1,0],[1,2,0],[1,3,0],[1,4,0],[1,5,0],[1,6,0],[1,7,0],[1,8,0],[1,9,0],[1,10,5],[1,11,2],[1,12,2],[1,13,6],[1,14,9],[1,15,11],[1,16,6],[1,17,7],[1,18,8],[1,19,12],[1,20,5],[1,21,5],[1,22,7],[1,23,2],[2,0,1],[2,1,1],[2,2,0],[2,3,0],[2,4,0],[2,5,0],[2,6,0],[2,7,0],[2,8,0],[2,9,0],[2,10,3],[2,11,2],[2,12,1],[2,13,9],[2,14,8],[2,15,10],[2,16,6],[2,17,5],[2,18,5],[2,19,5],[2,20,7],[2,21,4],[2,22,2],[2,23,4],[3,0,7],[3,1,3],[3,2,0],[3,3,0],[3,4,0],[3,5,0],[3,6,0],[3,7,0],[3,8,1],[3,9,0],[3,10,5],[3,11,4],[3,12,7],[3,13,14],[3,14,13],[3,15,12],[3,16,9],[3,17,5],[3,18,5],[3,19,10],[3,20,6],[3,21,4],[3,22,4],[3,23,1],[4,0,1],[4,1,3],[4,2,0],[4,3,0],[4,4,0],[4,5,1],[4,6,0],[4,7,0],[4,8,0],[4,9,2],[4,10,4],[4,11,4],[4,12,2],[4,13,4],[4,14,4],[4,15,14],[4,16,12],[4,17,1],[4,18,8],[4,19,5],[4,20,3],[4,21,7],[4,22,3],[4,23,0],[5,0,2],[5,1,1],[5,2,0],[5,3,3],[5,4,0],[5,5,0],[5,6,0],[5,7,0],[5,8,2],[5,9,0],[5,10,4],[5,11,1],[5,12,5],[5,13,10],[5,14,5],[5,15,7],[5,16,11],[5,17,6],[5,18,0],[5,19,5],[5,20,3],[5,21,4],[5,22,2],[5,23,0],[6,0,1],[6,1,0],[6,2,0],[6,3,0],[6,4,0],[6,5,0],[6,6,0],[6,7,0],[6,8,0],[6,9,0],[6,10,1],[6,11,0],[6,12,2],[6,13,1],[6,14,3],[6,15,4],[6,16,0],[6,17,0],[6,18,0],[6,19,0],[6,20,1],[6,21,2],[6,22,2],[6,23,6]];
data = data.map(function (item) {
return [item[1], item[0], item[2] || '-'];
});
option = {
tooltip: {
position: 'top'
},
animation: false,
grid: {
height: '50%',
top: '10%'
},
xAxis: {
type: 'category',
data: hours,
splitArea: {
show: true
}
},
yAxis: {
type: 'category',
data: days,
splitArea: {
show: true
}
},
visualMap: {
min: 0,
max: 10,
calculable: true,
orient: 'horizontal',
left: 'center',
bottom: '15%'
},
series: [{
name: 'Punch Card',
type: 'heatmap',
data: data,
label: {
show: true
},
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
};
function updateChart(values){
myChart.setOption({ visualMap: values })
};
document.body.addEventListener('change', (event) => {
var targets = document.querySelectorAll('.changeable');
var new_values = [...targets].map(target => {
var key_name = target.id.split('_')[0];
return { [key_name]: target.value };
});
var new_values = Object.assign(new_values[0], new_values[1]);
updateChart(new_values);
});
myChart.setOption(option);
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.7.0/echarts.min.js"></script>
<span>
<input type="number" class="changeable" id="min_limit" value= 1>
<input type="number" class="changeable" id="max_limit" value= 5>
</span>
<div id="main" style="width: 600px;height:400px;"></div>

noUiSlider get raw value

I'm using noUiSlider and followed the tutorial how to create custom formatting:
noUiSlider.create(sliderFormat, {
start: [ 20 ],
step: 10,
range: {
'min': [ 0 ],
'max': [ 599 ]
},
format: {
to: function ( value ) {
return Math.round(value/60) + ':' + Math.round(value%60);
},
from: function ( value ) {
return value;
}
}
});
When I call
mySlider.get()
it returns a value like 1:10, which is the formatted value. I would like to get the raw value (like 70 in this example), how is that possible?
As Vaibhav Kumar suggestet, I used the update function to read the raw value:
slider.noUiSlider.on('update', function(values,handle,unencoded){
// unencoded contains the raw value
});

Show only the MIN/MAX value on Y-AXIS with C3JS

I would like to have the y-axis only with the min/max values of my data.
I tried to use the d3 directive but without results.
I had a look at google but I didn't find an answer to achieve this behaviour.
Below the code:
$.getJSON('assets/json/chartc3.json', function(data)
{
scene=data;
var chart = c3.generate({
bindto: '#chartc3',
data:
{
json: scene,
keys:
{
x: 'round',
value: ['Marketable', 'Total Requested Capacity', 'Your Bid'],
},
types: {
Marketable: 'area'
},
colors: {
Marketable: '#A09FA2',
'Total Requested Capacity': '#272E80',
'Your Bid': '#8EBF60'
}
},
axis:
{
x: {
tick:
{
culling:
{
max: 10
}
},
type: 'category'
},
y:
{
min: 0,
padding : {
bottom : 0
},
tick:
{
values: [[0], [***d3.max(scene)]***],
format: function (d) { return d3.format(',f')(d) +' kWh/h' }
//or format: function (d) { return '$' + d; }
}
}
}.........
How could I achieve the result described above ? d3.max(scene) returns NaN.
Well the problem is scene is not an array its a json object.
var k = d3.max([1,5,2])
k will be 5
so you will need to pass an array of elements which constitute your y ordinals.
you need to use
d3.max(arr, function(d){return numberic value});
or
var arr = scene.map(function(d){return ...the number value..})
y:{
min:d3.min(arr),
max:d3.max(arr)
},
the function depends on the array element of your data.
I used a little function to calculate the max by myself.
var maxs=0;
for (var j=0; j<scene.length; j++) {
var maxtemp=Math.max(scene[j].Marketable, scene[j]['Your Bid'], scene[j]['Total Requested Capacity']);
maxs=Math.max(maxs, maxtemp);
}

Perform a simple multiplication with jquery after a slider value is set

I need some advice (help) on the most efficient way to implement a form that incorporates a range slider to set a value (in this case annual mileage), then takes that value and multiplies it by a set constant (0.05) and plugs the result into a second form field with a unit of British Pounds (£) and an accuracy of 2 decimal places rounded as appropriate. I am using a slider called No UI Slider (http://refreshless.com/nouislider/) and have set up the basic elements here:
$("#sliderAnnualMileage").noUiSlider({
start: [ 0 ],
step: 1000,
range: {
'min': [ 0 ],
'max': [ 120000 ]
},
connect: "lower",
serialization: {
lower: [
$.Link({
target: $("#mileage"),
format: {
thousand: ',',
decimals: 0,
postfix: ' miles'
}
})
]
}
});
Here is a partially working JS Fiddle: http://jsfiddle.net/highlander/jMA98/1/
Any insight or experience you have would be much appreciated.
You can set another $.Link to the second input box, with a formatting function:
lower: [
// your one
// then this:
$.Link({
target: $("#annualSavings"),
method: function (val) {
$(this).val("£" + (val * 0.05).toFixed(2));
}
})
]
This is the result: http://jsfiddle.net/jMA98/3/
For whatever reason your slider resets the value.
http://jsfiddle.net/jMA98/2/
$('#mileage').on('change',function(){
console.log($(this).val().replace(' miles',''));
$('#annualSavings').val($(this).val().replace(' miles','')*0.05);
});
Other than that this works.

Categories

Resources