How to disable custom validation method on condition - jquery-validate

I use jQuery Validation plugin to ensure what user entered positive cost_of_car in first text field and positive payment_amount in second text field such what *cost_of_car * 0.4 <= payment_amount <= cost_of_car*:
$.validator.addMethod("testMaxAmount", function()
{
return $("#cost_of_car").val() - 0 >= $("#payment_amount").val() - 0;
}, "Can't be more than cost_of_car");
$.validator.addMethod("testMinAmount", function()
{
return $("#cost_of_car").val() * 0.4 <= $("#payment_amount").val() - 0;
}, "Can't be less than cost_of_car * 0.4");
$("#calc_form").validate(
{
rules:
{
cost_of_car:
{
required: true,
number: true,
min: 1,
max: 10000000
},
payment_amount:
{
required: true,
number: true,
testMaxAmount: true,
testMinAmount: true
}
}
});
Now I want to skip testMaxAmount and testMinAmount checks until cost_of_car is valid. Testing
$("#calc_form").validate().element("#cost_of_car")
or even
$("#calc_form").validate({ignore: "#payment_amount"}).element("#cost_of_car")
inside these methods leads to the recursion and hangs browser.
Would you propose some other method to disable validation of payment_amount until cost_of_car is valid, please?

UPDATE: The change has to be in the validator.addMethod() calls:
$.validator.addMethod("testMaxAmount", function()
{
if($("#cost_of_car").valid())
return $("#cost_of_car").val() - 0 >= $("#payment_amount").val() - 0;
else
return true;
}, "Can't be more than cost_of_car");
$.validator.addMethod("testMinAmount", function()
{
if($("#cost_of_car").valid())
return $("#cost_of_car").val() * 0.4 <= $("#payment_amount").val() - 0;
else
return true;
}, "Can't be less than cost_of_car * 0.4");

Related

Kendo Grid Custom Toolbar button Enable/Disable

I have a kendo grid with save button in the Tool bar panel. I have a proposed discount column which is editable and if the user enters whole numbers between 0 and 100(excluding decimals) , the save button should be visible or enabled otherwise invisible or disabled. I was able to achieve making the button invisible or disable but when they enter correct value, the button was not getting visible or enabled. Please help me. I just started working on Kendo UI recently.
function setEnabled(enabled) {
if (enabled) {
// $(".k-grid-nstToolbarBtn").removeClass("k-state-disabled");
$(".k-grid-nstToolbarBtn").show();
}
else {
// $(".k-grid-nstToolbarBtn").addClass("k-state-disabled");
$(".k-grid-nstToolbarBtn").removeAttr("href");
$(".k-grid-nstToolbarBtn").hide();
}
}
$('#NSTGrid').kendoGrid({
toolbar: [{ type: "button", text: "Save", name: "nstToolbarBtn", className: "k-grid-saveData" }],
dataSource: {
data: data.ReportData,
schema: {
model: {
fields: {
ProposedDiscount: {
validation: {
required: true,
proposeddiscountvalidationcvalidation: function (input) {
if (input.val() != "" && input.is("[name='ProposedDiscount']")) {
input.attr("data-proposeddiscountvalidationcvalidation-msg", "Proposed Discount should be whole number");
setEnabled(false);
return input.val() >= 0 && input.val() < 101 && input.val() % 1 == 0;
} else {
setEnabled(true);
return true;
}
}
}
},
ProductApprovedDiscount: { type: "decimal", editable: false },
BAN: { type: "string", editable: false },
I think the value passed to your setEnabled function needs to be the same as what you return as the validation result. Please try the following change:
proposeddiscountvalidationcvalidation: function (input) {
if (input.val() != "" && input.is("[name='ProposedDiscount']")) {
input.attr("data-proposeddiscountvalidationcvalidation-msg", "Proposed Discount should be whole number");
var valid = input.val() >= 0 && input.val() < 101 && input.val() % 1 == 0;
setEnabled(valid);
return valid;
} else {
return true;
}
}

kendo grid cell validation for 2 decimal places

I have a kendo grid that needs to display discounts.I have to implement the validation that it should accept numbers between 0.00 and 100. I have written code for accepting numbers between 0 and 100, now i need to implement the 2 decimal place validation as well. Please help.
$(gridname).kendoGrid({
dataSource: {
data: data.ReportData,
schema: {
model: {
fields: {
ProposedDiscountNST: {format: "{0:n2}",
validation: {
required: true,
proposeddiscountNSTvalidation: function (input) {
if (input.val() != "" && input.is("[name='ProposedDiscountNST']")) {
input.attr("data-proposeddiscountNSTvalidation-msg", "Should be between 0.00 & 100");
// return input.val() >= 0 && input.val() < 101 && input.val() % 1 == 0;
return input.val() >= 0 && input.val() < 101 ; // Accepts max 2 decimal digits
} else {
return true;
}
}
}
}
I need to display the validation message that this field accepts 2 decimal places only. Please help.
How to obtain the number of decimals is described in multiple places, e.g. Simplest way of getting the number of decimals in a number in JavaScript Get this number and check if is okay or not.
One remark: You are checking if input.val() < 101 This includes 100.7 and does not seem match your requirement "between 0.00 and 100".
You can get the number of decimals by comparing the number and the fixed number (number.toFixed(x) rounds the given number to x decimals):
$(gridname).kendoGrid({
dataSource: {
data: data.ReportData,
schema: {
model: {
fields: {
ProposedDiscountNST: {format: "{0:n2}",
validation: {
required: true,
proposeddiscountNSTvalidation: function (input) {
if (input.val() != "" && input.is("[name='ProposedDiscountNST']")) {
input.attr(
"data-proposeddiscountNSTvalidation-msg",
"Value should be between 0.00 & 100 and have a maximum of 2 decimals"
);
return
input.val() >= 0 &&
input.val() <= 100 &&
input.val() == input.val().toFixed(2)
;
} else {
return true;
}
}
}
}
}
}
}
}
});
Actually I tried the above solution by Stephan T. but unfortunately it did not work. so I tried this method and it worked. So posting it so that it will help some one.
$(gridname).kendoGrid({
dataSource: {
data: data.ReportData,
schema: {
model: {
fields: {
ProposedDiscountNST: {format: "{0:n2}",
validation: {
required: true,
proposeddiscountNSTvalidation: function (input) {
if (input.val() != "" && input.is("[name='ProposedDiscountNST']")) {
input.attr("data-proposeddiscountNSTvalidation-msg", "Should be between 0.00 & 100");
// return input.val() >= 0 && input.val() < 101 && input.val() % 1 == 0;
return input.val() >= 0 && input.val() <= 100 && ((parseFloat(input.val()) / (parseFloat(input.val()).toFixed(2))) == 1 ); // Accepts max 2 decimal digits
} else {
return true;
}
}
}
}

Custom function only for edit mode, not add mode, in jqGrid

I have a jqGrid custom function as editrules: { custom: true, custom_func: checkforduplicates, required:true }
However, I want this function to be run only in add mode, not in edit mode. Is this possible ?
EDIT:- After answer below from Oleg, I changed code to below. However, the alert does not print. Not sure where I am going wrong.
colModel: [
{ key: true, name: 'id', editable: false, formatter: 'integer', viewable: false, hidden: true },
{
key: false,
name: 'name',
editable: true,
editrules: {
required: true,
custom: function (options) {
// options have the following properties
// cmName
// cm
// iCol
// iRow
// rowid
// mode - "editForm", "addForm", "edit", "add", "cell" and so on
// newValue - the value which need be validated
// oldValue - the old value
// some additional properties depends on the editing mode
alert("mode is " + options.mode);
if (options.mode === "add") { // "add" for inline editing
var grid = $("#grid");
var textsLength = grid.jqGrid("getRowData");
var textsLength2 = JSON.stringify(textsLength);
alert("i am here");
var myAttrib = $.map(textsLength,
function (item) { return item.name });
var count = 0;
for (var k in textsLength) {
if (textsLength.hasOwnProperty(k)) {
++count;
}
}
var text, i;
for (i = 0; i < count; i++) {
text = myAttrib[i];
if (value === text) {
return [false, " - Duplicate category name."];
}
}
return [true, ""];
}
return true;
}
}
},
Free jqGrid supports old style custom_func with the options value, name and iCol and the new style validation. To use new style validation one don't need to specify any custom_func callback, but to define custom as the calback function with one parameter:
editrules: {
required: true,
custom: function (options) {
// options have the following properties
// cmName
// cm
// iCol
// iRow
// rowid
// mode - "editForm", "addForm", "edit", "add", "cell" and so on
// newValue - the value which need be validated
// oldValue - the old value
// some additional properties depends on the editing mode
if (options.mode === "addForm") { // "add" for inline editing
// do the validation
}
return true;
}
}
In case of validation of Add form the mode property is equal to "addForm", options.iRow === -1, options.oldValue === null, options.rowid === "_empty". It's recommended to use options.mode to detect the editing (or searching mode) in free jqGrid because the values of other properties (iRow, oldValue and rowid) depends on the editing mode.
For version 4.7 I use this method. Form for adding data class for the table. After that, special actions verified by the user are performed.
{
name : "LOGIN",
index : "LOGIN", editrules: {
required:true,
custom:true,
custom_func: dublicateUser
}
...
{
closeAfterAdd : true,
width : 500,
recreateForm : true,
afterShowForm : function () {
jQuery("#TblGrid_list_users").addClass('addMode');
}
...
function dublicateUser() {
var a;
var login = jQuery('#LOGIN').val();
var checkMode = jQuery('#TblGrid_list_users').hasClass('addMode');
jQuery.ajax({
type: 'POST',
data: {login:login, mode:checkMode},
url: 'code/validate_user.php',
async: false,
success: function(data) {
if (data == 'err') {
a = 1;
}
else {
a=0;
}
}
});
if (a==1) {
return[false,"error"];
}
else {
return[true];
}
}

ZoomRange Highstock works not correct?

I made a Highstock diagramm and got aproblem with zooming on the yAxis.
I have a Button and 2 textfield to get the wanted min/max values for the axis. With min:0, max: 100 it works well. With min:0, max:80 it doesn't (max will still be 100 in the Diagramm).
If I use the mouse for zooming it works well (even a min of: 3.7 and a max of 3.894 is possible). But using the mouse is not an Option, because in the later Diagramm there will be 3 yAxes with individual zoom.
$(function () {
var seriesOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'];
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createChart() {
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 4
},
chart:{
zoomType: 'xy'
},
yAxis: [
{
labels: {
format: '{value}',
},
height: '100%',
opposite: false,
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
],
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: seriesOptions
},
function(chart){
$('#btn').click(function(){
var min = temp_min.value,
max = temp_max.value;
chart.yAxis[0].setExtremes((min),(max));
});
});
}
$.each(names, function (i, name) {
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function (data) {
if(seriesCounter==0){
seriesOptions[i] = {
name: name,
data: data,
yAxis: 0
};
} else {
seriesOptions[i] = {
name: name,
data: data,
yAxis: 0
};
}
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter += 1;
if (seriesCounter === names.length) {
createChart();
}
});
});
});
JSFiddle
Another Question: Is it possible to set up a scrollbar for the yAxis as well?
Thanks for your help, Patrick
This is related with fact that tickInterval is not regular, so is rounded to value (like 100). The solution is using tickPositioner which calculates ticks, based on extremes which you define.
tickPositioner: function (min,max) {
var positions = [],
tick = Math.floor(min),
increment = Math.ceil((max - min) / 5);
for (tick; tick - increment <= max; tick += increment) {
positions.push(tick);
}
return positions;
},
http://jsfiddle.net/6s11kcwd/
The scrollbar is supported only for xAxis.

How can I optimize datasource for Kendo UI Combobox with 5000 items?

In my test -> http://jsfiddle.net/olragon/642c4/12/, KendoUI Combobox cannot run with 5000 items, how can I make it work without calling severside data source or this is limit of KendoUI?
HTML
<h3>T-shirt Fabric</h3>
<input id="fabric" placeholder="Select fabric..." />
JS
/**
* Returns a random integer between min and max
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
$(document).ready(function() {
var superData = []
, data = [
{ text: "Cotton", value: "1" },
{ text: "Polyester", value: "2" },
{ text: "Cotton/Polyester", value: "3" },
{ text: "Rib Knit", value: "4" }
];
for(var _i=0; _i<5000; _i++) {
var randomEntry = data[getRandomInt(0,data.length-1)];
randomEntry.text += '-' + _i;
randomEntry.value += _i;
superData.push(randomEntry);
}
// create ComboBox from input HTML element
$("#fabric").kendoComboBox({
dataTextField: "text",
dataValueField: "value",
dataSource: superData,
filter: "contains",
suggest: true,
index: 3
});
});
Update
Fiddle link was updated.
Virtual scrolling and paging for Combobox was not yet supported by KendoUI
The problem is not in Kendo UI ComboBox but in your loop. Did you check what it does (not what you want it to do)? I would say that there is an error since data[getRandomInt(0,data.length-1)] does not return a new element but a reference so you are appending "_i" to the same 5 elements many times building up a very long string.
Try this instead:
for (var _i = 0; _i < 5000; _i++) {
var randomEntry = data[getRandomInt(0, data.length - 1)];
var newEntry = {
text: randomEntry.text + '-' + _i,
value : randomEntry.value += _i
};
superData.push(newEntry);
}
Check the modified version of the Fiddle here: http://jsfiddle.net/OnaBai/642c4/14/

Resources