How to restrict max value on html5 number input on manual entry - javascript

Free jqgrid column is defined to use html5 number input type like
{ name: "amount", width: 62, template: "number",
formatter: "number", formatoptions: {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 4, defaultValue: '0.0000'},
editoptions: {
maxlength; 4
type: "number",
max: 9999
} },
It allows to enter numbers from keyboard greater than 9999.
max: 9999 affects only to entry using spinner.
How to fix this so that keyboard entry cannot exceed 9999 ?
testcase is at
http://jsfiddle.net/jhckz7rr/3/
It allows to manually enter numbers greater that 9999 into Amount column. How to restrict manual entry to 9999 ?
I tried also to use string max value max: '9999' but problem persists.
If input type is text, input respects maxlength value.

Try to use something like the following
{
name: "amount",
width: 62,
template: "number", // formatter: "number"
formatoptions: {
decimalSeparator: ",",
thousandsSeparator: " ",
decimalPlaces: 2,
defaultValue: "0,00"
},
editoptions: {
maxlength: 7,
type: "number",
max: "9999",
dataEvents: [
{
type: "blur",
fn: function (e) {
if (e.target.checkValidity()) {
$(e.target).removeClass("ui-state-error");
} else {
$(e.target).addClass("ui-state-error");
alert(e.target.validationMessage);
$(e.target).focus();
}
}
}
]
}
}
The above code calls checkValidity() method of <input type="number">. Of cause you need to include additional tests in the code like validation that e.target.checkValidity is a function (for the case of executing in old web browser) and some other. The above code just shows the main idea of validation which uses functionality of <input type="number">.
See the demo http://jsfiddle.net/OlegKi/jhckz7rr/8/, which works for both inline editing and form editing.

Create validation on input with jQuery.
Event listeners are attached on edit click, and removed on save click.
I used setTimeout, to be synchronized with free-jqgrid elements manipulation - as the proper solution will be to extend free-jqgrid functionality
function restrictMax(){
var max = parseFloat($(this).attr('max'))
var value = parseFloat($(this).val())
if($(this).val() > max){
$(this).val(max)
}
}
setTimeout(function(){
$('.fa-pencil').click(function(){ //click on edit
var thatParent = $(this).closest('tr')
setTimeout(function(){
thatParent.find('input[type="number"]').on('input',restrictMax)
},0);
})
$('.fa-floppy-o').click(function(){ //click on save
var thatParent = $(this).closest('tr')
setTimeout(function(){
thatParent.find('input[type="number"]').off('input',restrictMax)
},0)
})
},0)
http://jsfiddle.net/jhckz7rr/6/

Related

Vue-form-generator Update Range Slider Attribute

I am currently setting up a multi-step form where the input from one slider needs to effect the max of another. I can manually update the max using this.tabSchema.(tab-id).fields[0].rangeSliderOptions.max, but this doesn't change the UX at all. I can see in the console that max has been correctly updated, but the UX shows the old max.
Digging into the ion.RangeSlider documentation, I see that it has .update, .destroy, and .reset methods. However, these seem to require a function particular to jquery, .data(), in order to properly setup the slider object that you then call .update() upon. I do not see any documentation around this for use in Vue. Is there a known way to do this? If not, does anyone know a way around it?
ETA: With code requested. Here is the relevant bit of tabSchema. There are many more tabs in the tabSchema, but these are the relevant two:
tabSchema: {
"num1" : {
fields: [{
type: "rangeSlider",
rangeSliderOptions: {
type: "single",
grid: false,
min: 0,
max: 2000000,
step: 5000,
// from: 100000,
prettify_enabled: true,
prettify_separator: ",",
prefix: "$",
hide_min_max: false,
},
id: "num1In",
model: "num1Val",
required:true,
styleClasses:'col-xs-12 col-sm-10 slider-bar'
}]
},
"num2" : {
fields: [{
type: "rangeSlider",
rangeSliderOptions: {
type: "single",
grid: false,
min: 0,
// max: ,
step: 5,
// from: 0,
prettify_enabled: true,
prefix: "$",
hide_min_max: false,
},
id: "num2In",
model: "num2Val",
required:true,
styleClasses:'col-xs-12 col-sm-10 slider-bar'
}]
}
}
And here is the bit of code that validates each tab:
validateTab: function(num){
var $valid = false; // assume not valid until checks are passed
this.error = '';
//////////// other validation //////////
else if (num == "num1"){
$valid = (this.model.num1Val != "");
if(!$valid){
this.error = 'Please provide a valid purchase price';
} else {
this.tabSchema.num2.fields[0].rangeSliderOptions.max = this.model.num1Val;
}
}
}
Documentation for ion.RangeSlider (public methods at the bottom): https://github.com/IonDen/ion.rangeSlider
Documentation for Vue-form-generator rangeslider: https://icebob.gitbooks.io/vueformgenerator/content/fields/slider.html

How to set the decimal places of a number in Kendo UI model defenition?

I'm using a kendo ui editable grid with NumericTextBox. Usually in NumericTextBox the decimal places are limited to two i.e, if I enter 10.135 the value will be formatted to 10.14. But what I need is to get 10.135 itself. What is to be done here.
My model definition.
var GridViewModel = new kendo.data.Model.define({
fields: {
Name: { type: "string", editable: false },
Weight: { type: "number", editable: true, validation: { required: true } },
}
});
and in my view model I have set the Grid as.
$("#DryingBinItemsAddedGrid").kendoGrid({
dataSource: {
data: DataDetails,
schema: {
model: GridViewModel
},
},
editable: true,
dataBound: function () {
},
columns: [
{
field: "Name",
title: "Name"
},
{
field: "Weight",
title: "Total Weight"
}
]
});
I have not mentioned my failed attempts in this example. Currently my Weight field is a numeric text box with two fields. What is to be done here to make my Weight field a NumericTextBox with 3 decimal point.
In order to control the configuration of the NumericTextBox used by the grid as the editor, you need to implement a custom editor, otherwise, the default configuration for the NumericTextBox will be used(which is 2 decimal places).
Try changing your "Weight" column definition to:
{
field: "Weight",
title: "Total Weight",
editor: weightEditor
}
and add a weightEditor function that implements the custom editor:
function weightEditor(container, options) {
$('<input name="' + options.field + '"/>')
.appendTo(container)
.kendoNumericTextBox({
decimals: 3,
})
};
Demo: http://dojo.telerik.com/#Stephen/uviLO

How to validate an editor field in a dojo OnDemandGrid

I have built a dojo OnDemandGrid that has a couple columns that have editors (NumberTextBox, and FilteringSelect) so I can modify values in the grid. I have also added some validation on these columns to help make sure the values that are entered are correct. This all appears to be working fine and when I enter an invalid value I get an indication that the value is incorrect.
My problem is when I try to send this data back to the server. When I get the grid data with a ui.searchResultGrid.collection.data, any of the fields that are invalid have not been updated in the collection and still have their original values. My guess is that when the cell is updated and does a save it does its validation, and if that validation fails it doesn't update the collection. How can I tell that some cells have failed validation and have issues?
Here's how I'm defining my grid if it helps:
require(["dojo/_base/declare", "dgrid/OnDemandGrid", "dgrid/Keyboard", "dgrid/Selection", "dgrid/Editor",
"dgrid/extensions/ColumnResizer", "dgrid/extensions/DijitRegistry", "dijit/form/NumberTextBox",
"dijit/form/FilteringSelect", "dojo/_base/lang", "dojo/domReady!"],
function (declare, OnDemandGrid, Keyboard, Selection, Editor, ColumnResizer, DijitRegistry, NumberTextBox, FilteringSelect, lang) {
var CustomGrid = declare([OnDemandGrid, Keyboard, Selection, Editor, ColumnResizer, DijitRegistry]);
ui.searchResultGrid = new CustomGrid({
columns: {
newItemAmount: {
label: "# of New Item",
editor: NumberTextBox,
editorArgs: {
constraints: {
min: 0.0001,
max: 999.9999,
allowNegative: false,
places: 4
},
style: "width:90px;",
required: true
},
autoSave: true,
resizable: false,
sortable: false,
width: 100
},
newItemUnitId: {
label: "Unit of New Item",
editor: FilteringSelect,
editorArgs: {
style: "width:130px",
searchAttr: "name",
labelAttr: "name",
required: true
},
autoSave: true,
resizable: false,
sortable: false,
width: 140
}
},
selectionMode: "none",
cellNavigation: false,
}, "searchResultGrid");
});
From what I was able to find, you have to look at each cell you want to validate and check .element.widget.isValid() to see if that widget passes validation. I wrote a function to validate a grid with parameters:
grid - the grid to validate
cols - an array of strings of the column names to validate
function gridValid(grid, cols) {
for (var i = 0; i < grid.collection.data.length; i++) {
var rowId = grid.collection.getIdentity(grid.collection.data[i])
for (var c = 0; c < cols.length; c++) {
if (!grid.cell(rowId, cols[c]).element.widget.isValid()) {
return false;
}
};
}
return true;
}
and I called the function like this:
if (gridValid(ui.searchResultGrid, ["newItemAmount", "newItemUnitId"])) {
var toSave = ui.searchResultGrid.collection.data;
//TODO: save the grid data
}
This may not be the best way to validate the grid, but it appears to be working.

Format Kendo grid column filter for percentages

I have a kendo grid and my datasource data returns number with unknown decimal places. So I'm using a parse function on the datasource to compensate for that.
DefaultMonoCPP: {
editable: false,
type: "number",
parse: function(e) {
return kendo.parseFloat(kendo.toString(e,"p4"));
}
}
Now when I filter, I don't want it to automatically multiply the percentage by 100. So I have filterable set on the columns.
{
field: "DefaultMonoCPP",
title: "Mono Cost",
format: '{0:p4}',
filterable: {
ui: function(e) {
e.kendoNumericTextBox({
//format: "{0:p4}",
//format: "p4",
format: "##.0000 \\%",
decimals: 4
});
}
}
}
But this messes up the filtered number (1.2700% => 1.27). So filtering fails.
JSFiddle for clarification: http://jsfiddle.net/dmathisen/mecny50f/
Is there any way to have both the parse and filterable work correctly together?
My suggestion would be to format the numeric textbox as a percentage and set the step to 0.01 so that it increments/decrements 1% at a time. If you're worried about the user typing in a percentage as a whole number, handle it in the change event.
e.kendoNumericTextBox({
format: '{0:p4}',
step: 0.01,
decimals: 4,
change: function () {
var val = this.value();
if (val > 1) {
this.value(val / 100);
this.trigger("change");
}
}
});
JSFiddle

Highstock setExtremes with a custom range selector button

In highstock range selector I added a custom range selector button (named: my dates) and would like to set a custom extremes when this button is called. I know it works if you put simple button outside the chart and call: chart.xAxis[0].setExtremes(30,80);.
But my scenario is different I want to add a button beside "1m 1y All" range selector buttons, and want that new button to set a custom extremes dates. Using xAxis events setExtremes, does not seems to work unless I am missing something. http://jsfiddle.net/Aeaz3/1/
$(function() {
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-c.json&callback=?', function(data) {
// Create the chart
$('#container').highcharts('StockChart', {
rangeSelector: {
buttons: [{
type: '',
count: 2,
text: 'My dates'
},{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1d'
}, {
type: 'month',
count: 1,
text: '1m'
}, {
type: 'year',
count: 1,
text: '1y'
}, {
type: 'all',
text: 'All'
}],
},
title : {
text : 'AAPL Stock Price'
},
xAxis: {
events:{
setExtremes: function(e) {
var xMin = e.min;
var xMax = e.max;
var zmRange = computeTickInterval(xMin, xMax);
this.chart.xAxis[0].options.tickInterval =zmRange;
this.chart.xAxis[0].isDirty = true;
},
}
},
series : [{
name : 'AAPL',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});
});
The setExtremes callback:
Fires when the minimum and maximum is set for the axis, either by
calling the .setExtremes() method or by selecting an area in the
chart. The this keyword refers to the axis object itself. One
parameter, event, is passed to the function. This contains common
event information based on jQuery or MooTools depending on which
library is used as the base for Highcharts.
So it's not really meant to be used to set extremes but is rather a notification when something else does some extreme setting.
That said, I still think it is possible to leverage it for your use case by catching the call when your button is clicked and then resetting it to your custom range:
xAxis: {
events:{
if (e.trigger == "rangeSelectorButton" &&
e.rangeSelectorButton.text == "My dates"){
// it is your button that caused this,
// so setExtrememes to your custom
// have to do in timeout to let
// highcharts finish processing events...
setTimeout(function(){
Highcharts.charts[0].xAxis[0].setExtremes(1198681756385,1368144000000)
}, 1);
}
}
},
Updated Fiddle here.
One approach would be to modify highstock to use the values of e.min and e.max if they are changed in your event handler. This can be done by modifying 3 lines of code.
in highstock.src.js line 7447 (in version 2.0.4). The method is called setExtremes.
Change:
fireEvent(axis, 'setExtremes', eventArguments, function () { // the default event handler
axis.userMin = newMin;
axis.userMax = newMax;
To:
fireEvent(axis, 'setExtremes', eventArguments, function (event) { // the default event handler
axis.userMin = event.min;
axis.userMax = event.max;
And now changing e.min or e.max in the xAxis.setExtremes event will work. (Don't call setExtremes())

Categories