Slider NoUiSlider value keep range - javascript

I'm having troubles to keep the values from a range slider of NoUiSlider visible when submitting a form.
So people can set a range and then hit a submit button. The values from that range slider are nicely submitted via the form however the range of the slider changes to the new set value.
So I have set the range to eg. 0 - 500. When somebody sets the range to eg. 100-400 and then submit the form then the range changes to 100-400. So people can't change the range back to 0 - 500.
So my question:
How can I keep the range as is(so 0 -500) but move the handles to the set values (so 100 - 400)?
So what I have is this:
<form>
<input type="hidden" name="max" value="0" id="filter_form_max" />
<input type="hidden" name="min" value="500" id="filter_form_min" />
<div id="slider-handles"></div>
<input type="submit" class="price-btn" />{{ 'Set price' | t }}
</form>
And JS:
$(function() {
var handlesSlider = document.getElementById('slider-handles');
noUiSlider.create(handlesSlider, {
start: [ 0, 500 ],
format: wNumb({
decimals:0,
thousand: '.'
}),
range: {
'min': [ 0 ],
'max': [ 500 ]
},
tooltips: true,
});
handlesSlider.noUiSlider.on('update', function( values, handle ) {
var minVal = document.getElementById('filter_form_min');
var maxVal = document.getElementById('filter_form_max');
minVal.value = values[0]
maxVal.value = values[1]
});
});

You just need to change values of start array.
Try to change those with following. It worked for me.
//---- some code ---
noUiSlider.create(handlesSlider, {
start: [ 100, 400 ],
//-----

Related

Best way to bind this slider control to an MVC model property?

Question background:
I'm using noUiSlider to allow users to select prices between a maximum and minimum value (0 - 5000). The selected Maximum and Minimum values then need to be bound to a my views maximum and minimum properties and posted to a relevant controller method.
The Issue:
I'm not sure how I should go about binding this control. I have a form group that used HTML Helpers such as TextBoxFor which allow me to easily bind an input to a property but this is different as there is no user input instead the values are set through the nouislider javascript.
I have two labels - as shown - that display the selected values from the controller.
Note: As I need to post the values to the controller I have included the Html.HiddenFor helpers to bind the models but these are always null.
How can I bind the values within the labels to a model in my view?
The following code will show the situation.
The Code:
nouislider setup:
var snapSlider = document.getElementById('slider-snap');
var snapValues = [
document.getElementById('slider-snap-value-lower'),
document.getElementById('slider-snap-value-upper')
];
var range = {
'min': 0,
'10%': 100,
'20%': 200,
'30%': 400,
'40%': 600,
'50%': 800,
'60%': 1000,
'70%': 2000,
'80%': 3000,
'90%': 4000,
'max': 5000
};
noUiSlider.create(snapSlider, {
start: [ 0, 5000 ],
snap: true,
connect: true,
tooltips: true,
range: range,
format: wNumb({
decimals: 0,
prefix: '$',
})
});
snapSlider.noUiSlider.on('update', function( values, handle ) {
snapValues[handle].innerHTML = values[handle];
});
Form:
<div class="form-group">
<div class="maxPricePad height dropWidth">
<div class="pricePad">
<label for="formGroupExampleInput">Min. Price:</label>
<span id="slider-snap-value-lower"></span>
</div>
<div>
<label for="formGroupExampleInput">Max. Price:</label>
<span id="slider-snap-value-upper"></span>
</div>
#Html.HiddenFor(m => m.maxPrice)
#Html.HiddenFor(m => m.minPrice)
</div>
</div>
Controller:
[HttpGet]
public JsonResult UpdateResults(HomePageVM homePageSearch)
{
//Data logic
//return JsonResult(data);
}
HomePageVM Model:
public class HomePageVM
{
public string maxPrice { set; get; }
public string minPrice { set; get; }
}
As per their documentation, values (the first param on the callback on the update event) will be an array with the range values. Read the first and second values from this array and use that to set the input field values.
snapSlider.noUiSlider.on('update', function( values, handle ) {
var min=values[0];
var max=values[1];
$("#maxPrice").val(max);
$("#minPrice").val(min);
});
Also you need to make sure that your input fields(the #Html.HiddenFor calls) are inside a form tag so that when you submit the form the values will be also submitted and can be available in your action method.
Here is a working js bin sample.

Changing series visibility of multiple dygraphs charts

UPDATED 7-10-15
I'm trying to control the visibility of data series across multiple plots using a set of check boxes. I have looked at a couple of the examples using the visibility option on the dygraphs website and other questions here but what I have found so far either focuses on a single chart or is limited in the details I need.
My first thought was to have the check boxes change the visibility values and then re-draw the charts, however I quickly realized that the visibility just reverts back to the initial conditions I set when creating the charts.
Now I'm wondering if I can create a function using the 'setVisibility' within its own loop to change the visibility of each chart as desired. Below is what I have recently tried, however it is not working. I'm not sure if this is the right way to accomplish this or not.
function change(el) {
for (i=0; i<23; i++) {
chart[i].setVisibility(el.id, el.checked);
}
}
My HTML code for check boxes:
<input type=checkbox id="0" checked onClick="change(this)"> <label for="0"> data1</label>
<input type=checkbox id="1" checked onClick="change(this)"> <label for="1"> data2</label>
<input type=checkbox id="2" checked onClick="change(this)"> <label for="2"> data3</label>
JS code to create plots:
var chart = [];
for (i=0; i<23; i++){
chart.push(
new Dygraph(
document.getElementById("div"+i),
csv[i],{
rollPeriod: 1, errorBars: true,
colors: ['#006600', '#993300', '#003399'],
title: name, connectSeparatedPoints: true,
drawPoints: true, sigFigs: 4, legend: 'always',
labelsSeparateLines: true, labelsDivWidth: 250,
visibility: [true, true, true]
}
)
);
}
I don't have much Javascript experience so I apologize if this is a simple problem, but it has been giving me fits.
I was able to find a solution to my problem. The issue was primarily rooted in the scope of my 'chart' variable, as it needed to be a global variable, which was not evident in my original post. By moving it outside of the containing function which fixed that issue.
<input type=checkbox id="acheck" index=0 checked onClick="change('acheck',0)"> <label for="0"> data1</label>
<input type=checkbox id="bcheck" index=1 checked onClick="change('bcheck',1)"> <label for="1"> data2</label>
<input type=checkbox id="ccheck" index=2 checked onClick="change('ccheck',2)"> <label for="2"> data3</label>
and the Javascript code I used:
for (i=0; i<23; i++) {
chart[i] = new Dygraph(
document.getElementById("div"+i), csv[i], {
rollPeriod: 1,
errorBars: true,
colors: ['#006600', '#993300', '#003399'],
connectSeparatedPoints: true,
drawPoints: true,
sigFigs: 4,
legend: 'always',
labelsSeparateLines: true,
labelsDivWidth: 250,
animatedZooms: false,
visibility: [vis2[0], vis2[1], vis2[2]],
}
);
}
function change(element,ind) {
var x=document.getElementById(element);
for (i=0; i<=22; i++) {
chart[i].setVisibility(ind, x.checked);
}
}

How to define a Kendo grid Column filter between two dates?

In our application we want the filter on a date column to prompt the user for a start date and an end date, with the filter returning rows where the field in question falls between (or on) those two dates.
Initial Approach
Our initial approach was to restrict date types to use gte and lte operators, and add the "extra : true" filterable option on the column. This came close, but presented the following problems: A) Each date input could use either the gte (Start) or lte (End) operator, providing undesired flexibility and the option for the user to create a filter that would never return results, and B) Presented a logical comparison (And / Or) that we don't want.
Better Approach
This question has an answer by Matthew Erwin that gets us very close: it allows us to completely re-style the filter entirely, so we can present simply a Start Date input and an End date input. However, what I can't get working is associating the right filter operation with the right input (gte for the Start date, lte for the End date). My custom filter is as follows:
$scope.dateFilter = {
extra: true,
operators: {},
ui: function (element) {
var parent = element.parent();
while (parent.children().length > 1)
$(parent.children()[0]).remove();
parent.prepend(
"Start Date:<br/><span class=\"k-widget k-datepicker k-header\">" +
"<span class=\"k-picker-wrap k-state-default\">" +
"<input data-bind=\"value: filters[0].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
" style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" aria-disabled=\"false\" " +
" aria-readonly=\"false\" aria-label=\"Choose a date\">" +
"<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
"<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>" +
"<br/>End Date:<br/>" +
"<span class=\"k-widget k-datepicker k-header\"><span class=\"k-picker-wrap k-state-default\">" +
"<input data-bind=\"value: filters[1].value\" class=\"k-input\" type=\"text\" data-role=\"datepicker\"" +
" style=\"width: 100%\" role=\"textbox\" aria-haspopup=\"true\" aria-expanded=\"false\" " +
" aria-disabled=\"false\" aria-readonly=\"false\" aria-label=\"Choose a date\">" +
"<span unselectable=\"on\" class=\"k-select\" role=\"button\">" +
"<span unselectable=\"on\" class=\"k-icon k-i-calendar\">select</span></span></span></span>"
);
}
};
With this approach, the Odata filter option is generated for each of the dates, however it uses the eq Equal To operator, so no values are ever returned. We aren't building filters specifically on the data source.
Is there a simple way I can associate each of those date inputs with a specific filter operator? Is there a better way to approach this subject? It seems like filtering dates based on a Start - End range would be commonly desired.
Other Details
We are using AngularJS, and WebAPI with Odata.
After working with Telerik, I came to an answer. The thread that I opened can be found here, but I'll also summarize in this answer.
The ultimate solution was to:
Use the "Messages" option of the column "filterable" option to customize the filter display message.
Use the "Extra" option of the column "filterable" option to get the extra Date selector in the filter menu.
Configure the "Operators" option in the grid filterable option to set what operators can be used for dates (gte, lte) and what text is displayed for each (Begin Date, End Date).
Use the filterMenuInit event to configure the filter controls.
End Result
Column Filterable
The following filterable options were used:
filterable: { "extra": "true", "messages": { "info": "Show items between dates:" }}
Extra gives us the second date selector, and the "info" message customizes the text displayed at the top of the filter menu.
Grid Filterable
I used the "operators" option in the grid-level "filterable" option to make date filters only provide the gte and lte operators, and to customize the text for those operators. This is what the operators configuration object wound up looking like:
"date": {
"gte": "Begin Date",
"lte": "End Date"
}
Because we want this to apply for all dates, we put that in a factory and reuse it in each angular controller / view.
filterMenuInit Event
By providing a handler for the filterMenuInit event, you can access and configure the individual controls in the filter menu as it is created. The handler function that I created looks like this:
function (e) {
if (e.sender.dataSource.options.schema.model.fields[e.field].type == "date") {
var beginOperator = e.container.find("[data-role=dropdownlist]:eq(0)").data("kendoDropDownList");
beginOperator.value("gte");
beginOperator.trigger("change");
beginOperator.readonly();
var logicOperator = e.container.find("[data-role=dropdownlist]:eq(1)").data("kendoDropDownList");
logicOperator.readonly();
var endOperator = e.container.find("[data-role=dropdownlist]:eq(2)").data("kendoDropDownList");
endOperator.value("lte");
endOperator.trigger("change");
beginOperator.readonly();
}
Specifically, for any date field, this function sets the first and last dropdown operators to "gte" and "lte" respectfully (Those are the dropdowns for the first date operator and the second date operator), and sets all of the dropdowns to read-only so the user can't change them (the only other dropdown, which is at index 1, is the logical comparison - only And makes sense, so we don't let users change it.)
This function applies this configuration for any fields that are of "date" type. I did it this way so that I could create this function once, put it in an Angular factory, and then reuse it for any grid that I needed. If you don't want to apply this as a blanket configuration across all of your date columns, you can change the conditional to check for fields by name. Example:
if (e.field == "fieldName")
Hopefully this will be helpful to someone else. This doesn't give you ultimate customization of the UI in the filter menu, but it does let you simply set up a filter between two dates. I'm sure someone clever could merge this with my original strategy (replacing the markup for the filter menu entirely) to come up with something completely customized.
You can try the following method that gives two option for filtering: With two filtering fields and with the grid column.
<div>
From: <input id="from" /> To: <input id="to" />
<br />
<br />
<button id="filter" class="k-button">Filter</button>
</div>
<br />
<br />
<div id="grid"></div>
<script>
var grid = $("#grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: "/Controller/Action"
},
pageSize: 10,
schema: {
model: {
fields: {
OrderId: { type: 'number' },
OrderItem: { type: 'string' },
OrderDate: { type: 'date' }
}
}
}
},
pageable: true,
filterable: true,
navigatable: true,
selectable: true,
columns:
[
{ field: "OrderID", width: 100, title: "Order ID", filterable: false },
{ field: "OrderItem", width: 100, title: "Order Item", filterable: false },
{
field: "OrderDate", type: "date", width: 125, title: "Order Date",
template: "#= kendo.toString(kendo.parseDate(EventTime, 'dd.MM.yyyy hh:mm tt'), 'dd.MM.yyyy hh:mm tt') #",
filterable: {
ui: "datetimepicker"
}
},
]
}).data("kendoGrid");
$("#from, #to").kendoDatePicker({
});
$("#filter").on("click", function () {
//var from = $("#from").data("kendoDatePicker").value();
//var to = $("#to").data("kendoDatePicker").value();
//If there is a problem regarding to the two lines above, you can also try this:
var from = $("#from").val();
var to = $("#to").val();
var filter = [
{ field: "OrderDate", operator: "gte", value: from },
{ field: "OrderDate", operator: "lte", value: to }
];
grid.dataSource.filter(filter);
});
</script>
For more information Date Range Filtering in Kendo Grid Using WEB API and Entity Framework.

set value in javascript from a jsf value

In this javascript function I am trying to set max from the backingbean's max value. This is using jsf.
Using the value as I do. Will result in the chart being empty. So I assume Max is null/0. Instead of the expected value of 6100.
max: #{teamChart.maxResult}
Edit: Added the complete code for the Chart. Note that setting max inside the barChart will not give the correct functionality.
<p:commandButton value="Visa diagram" update="chart" oncomplete="PF('dlg').show()" />
<p:dialog header="Selected Values" modal="true" showEffect="fade" hideEffect="fade" widgetVar="dlg">
<p:barChart id="chart" value="#{teamChart.CreateChart(serviceTeam.teamLists)}"
rendered="#{not empty serviceTeam.teamLists}" legendPosition="ne"
title="Lagresultat" animate="true" zoom="true" min="0" max="#{teamChart.maxResult}" xaxisLabel="År och vecka"
style="height:500px;width:900px;" extender="ext">
<script type="text/javascript">
function ext(){
this.cfg.legend = {
show:true,
placement: 'outsideGrid'
};
this.cfg.axes.yaxis = {
tickInterval: 500,
markSize: 40,
max: #{teamChart.maxResult},
min: 0,
tickOptions: {
formatString: '%d'
}
};
}
</script>
</p:barChart>
</p:dialog>

Using Variable Within JavaScript Object Literal

Basically, I'm having trouble getting information from an input box and using that variable within an object literal.
Here is my code:
$("document").ready(function() {
function updateEvent(){
render();
}
function render() {
//get values from input
var gallons = $("#gallons").val();
var electricity = $("#electricity").val();
var energy = $("#energy").val();
var figure = new Highcharts.Chart({
series: [{
name: 'Throttle',
data: [0, 0, 30 , 0, energy, 30, 0, 0] //Variables will not work in here, no specific error but data doesn't show
}, {
name: 'Power',
data: [30, 30 , 30, 30, 30, 30, 30, 30]
}]
});
I've tried embedding a function and doing other tricks but nothing has worked, I could be doing it wrong, I'm not sure. Is there any way to use a variable within an object literal without completely re-coding the structure.
Any help would be greatly appreciated.
How to get a value from an input box and use that value within an object literal?
function doStuff(){
var realIncome = document.getElementById("income").value;
var objLit= { realIncome: realIncome,
desiredIncome: realIncome * 4 };
console.log(objLit);
document.getElementById("out").innerText =
objLit.realIncome + " " + objLit.desiredIncome;
}
And the HTML
Big Number
<input id="income" name="income" type="number"
placeholder="please enter your desired income">
<button name="calculate" onclick="doStuff()">click me </button>​
Your income <span id="out"></span><br />
Please take a look at my demo code: http://jsfiddle.net/mppAM/2/

Categories

Resources