Kendo Numeric text box custom validation for percentage value - kendonumerictextbox

We are trying to display a validation error message by overriding the default behavior of Kendo numerictextbox for displaying percentage value.
our expectation is to provide a custom message when user type in any value more than 100.
By default Kendo NumericTextbox for percentage auto corrects the value if the user type in anything more than 100 (we don't want this behavior)
Please find a jsfiddle reference URL for the same to understand it better
https://jsfiddle.net/6uyp825h/57/
<!DOCTYPE html>
<html>
<head>
<base href="https://demos.telerik.com/kendo-ui/numerictextbox/index">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.material.mobile.min.css" />
<script src="https://kendo.cdn.telerik.com/2018.2.620/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2018.2.620/js/kendo.all.min.js"></script>
</head>
<body>
<div id="example">
<div id="add-product" class="demo-section k-content">
<p class="title">Add new product</p>
<ul id="fieldlist">
<li>
<label>
Price Discount:
<input id="percentage" value="5" title="percentage" style="width: 100%;" />
</label>
</li>
</ul>
</div>
<script>
$(document).ready(function() {
// create Percentage NumericTextBox from input HTML element
$("#percentage").kendoNumericTextBox({
format: "##.00 \\%",
min: 0,
spinner: false
});
var container = root;
kendo.init(container);
container.kendoValidator({
rules: {
checkPercentageMaxValue: function (input) {
var maxAllowedValue = 100;
var currentValue = parseInt($("#percentage").val());
if (currentValue > maxAllowedValue)
{
return false;
}
else {
return true;
}
return true;
}
},
messages: {
checkPercentageMaxValue: "Percentage value cannot be greater than 100."
}
});
});
</script>
<style>
.demo-section {
padding: 0;
}
#add-product .title {
font-size: 16px;
color: #fff;
background-color: #1e88e5;
padding: 20px 30px;
margin: 0;
}
#fieldlist {
margin: 0 0 -1.5em;
padding: 30px;
}
#fieldlist li {
list-style: none;
padding-bottom: 1.5em;
}
#fieldlist label {
display: block;
padding-bottom: .6em;
font-weight: bold;
text-transform: uppercase;
font-size: 12px;
}
#fieldlist label .k-numerictextbox {
font-size: 14px;
}
</style>
</div>
Here is the html which I gets in real scenario
<div class="col-sm-8">
<span class="k-widget k-numerictextbox single-line text-box form-control">
<span class="k-numeric-wrap k-state-default k-expand-padding">
<input tabindex="0" title="112.00 %" class="k-formatted-value single-line text-box form-control k-input k-valid" role="spinbutton" aria-disabled="false" aria-valuenow="112" style="display: inline-block;" type="text">
<input name="PercentHeld3" class="single-line text-box form-control k-input k-valid" id="PercentHeld3" role="spinbutton" aria-disabled="false" aria-valuenow="112" style="display: none; border-color:black; " type="text" maxlength="16" data-role="numerictextbox" data-bind="value: PercentHeld" data-spinners="false" data-numberformat="percentage" data-decimals="2" data-validate="true" data-maxallowedvalue="100" data-max-msg="Percentage value cannot be greater than 100.">
<span class="k-select" style="display: none;">
<span title="Increase value" class="k-link k-link-increase" style="touch-action: none;" aria-label="Increase value" unselectable="on">
<span class="k-icon k-i-arrow-60-up" unselectable="on"></span>
</span>
<span title="Decrease value" class="k-link k-link-decrease" style="touch-action: none;" aria-label="Decrease value" unselectable="on">
<span class="k-icon k-i-arrow-60-down" unselectable="on"></span>
</span>
</span>
</span>
</span>
</div>
Rule used in real scenario
checkPercentageMaxValue: function (input) {
$('input[data-maxallowedvalue][data-validate="true"]').each(function (index, item) {
var maxAllowedValue = parseInt($(item).attr('data-maxallowedvalue'));
var currentValue = parseInt($(item).val().replace(/%?$/, ''));
if (currentValue > maxAllowedValue) {
return false;
}
else {
return true;
}
});
return true;
}

Right after some trial and error and finally understanding what it is you want. I think you have misunderstood how the validator rules work.
http://dojo.telerik.com/UHIhACOh
The rules:
checkPercentageMaxValue: function(input) {
var valid = true;
singlerule += 1;
if ($(input).is('[data-maxallowed-value][data-validate="true"]')) {
var maxAllowedValue = parseFloat($(input).attr('data-maxallowed-value'));
var currentValue = parseFloat($(input).val());
if (isNaN(currentValue)) {
currentValue = 0;
}
valid = (currentValue <= maxAllowedValue);
$('#control1').html('Max Allowed Value::' + maxAllowedValue + ',Current Parsed Value::' + currentValue);
} else {
$('#control1').html('<pre><code>' + JSON.stringify($(input), null, 4) + '</code></pre>');
}
$('#control1').append('I ran <b>checkPercentageMaxValue</b> rule: ' + singlerule + 'time(s)<br/>');
singlerule = 0;
return valid;
},
yourrule: function(input) {
$('input[data-maxallowed-value][data-validate="true"]').each(function(index, item) {
multirule += 1;
$('#control1').append('I ran <b>yourrule</b> rule: ' + multirule + 'time(s)<br/>');
var maxAllowedValue = parseFloat($(item).attr('data-maxallowed-value'));
var currentValue = parseFloat($(item).val());
if (isNaN(currentValue)) {
currentValue = 0;
}
if (currentValue > maxAllowedValue) {
return false;
} else {
return true;
}
});
multirule = 0;
return true;
}
}
Each rule listed in the custom rules list is ran on every control that is being validated.
So your current rule is checking each input control and then any other input controls of that type again assuming they meet the approved condition.
So you are running the checks multiple times and if one passes then your rule assumes all have passed if it hits a true condition and the same is true for an error'd item which is why you are getting the issues you are currently getting. Obviously if this is what you want (checking multiple items are the same time) then you need to hold the true/false value in a variable so that it will return back the message (but this message will only be displayed next the control that kicked off the initial validation/focus)
Hopefully adding the second control will show you what is happening clearer.
As you can see the first time you enter a control your rule will run twice until one of the input boxes states that is in an error state and then you rule will only run when one of the controls is in a invalid state, if you put a value incorrectly in the second box then your rule states that it has exited successfully and is valid.
I added a button so you can see if the validator thinks it is in a valid/invalid state based on the rules provided.
If anything isn't clear or you need more info let me know and I will update the answer accordingly.

Related

Nuxt.js Scroll to bottom of div element

What`s wrong with this code? After render div element scroll has to be in the bottom of div element. scrollTop not saving the value after func
<main>
<div v-if="messages">
<ul ref="messagesContainer">
<li v-for="message in messages" :key="`${message.text}.${message.username}`">
<Message :message="message" :username="username" />
</li>
</ul>
</div>
</main>
mounted() {
this.scrollToEnd();
},
methods: {
scrollToEnd() {
const height = this.$refs.messagesContainer.scrollHeight;
this.$refs.messagesContainer.scrollTo(0,height)
// doesnt work
// this.$refs.messagesContainer.scrollTop = height
}
}
main {
background-color: #fff;
height: 56vh;
ul {
height: 100%;
overflow: auto;
flex: auto;
}
}
you can get the y position of the element via the offsetHeight property like this:
var offsetTop = this.$refs.messagesContainer.offsetHeight;
You can find more information regarding offsetHeight, clientHeight and scrollHeight properties here
Note you need to call the scrollTo method on the window element:
example:
methods: {
scrollToEnd() {
var scrollHeight = this.$refs.messagesContainer.offsetHeight;
this.$refs.messagesContainer.scrollTop = scrollHeight;
}
}
Hope this helps :)
<main>
<ul v-if="messages" id="messagesContainer">
<li v-for="message in messages" :key="`${message.text}.${message.username}`">
<Message :message="message" :username="username" />
</li>
</ul>
</main>
scrollToEnd() {
const element = document.getElementById('messagesContainer')
element.scrollTop = element.offsetHeight + element.scrollHeight
}
This seems to work on Nuxt. This also provides a smooth scrolling as well.
const element = this.$refs.messagesContainer;
element.scrollIntoView({ behavior: "smooth", block: "start" });

Vaadin flow: grid conditional background color

I want to color grid lines, depending on a condition.
I try this:
Java:
gridEtudiant.setClassNameGenerator(t -> {
if (t.getEtud_numero().startsWith("2")) {
return "error_row";
}
return "";
});
Css:
td.error_row {
background-color: red;
}
HTML
<td id="vaadin-grid-cell-1" tabindex="0" role="gridcell" part="cell body-cell" first-column="" reorder-status="undefined" aria-selected="false" class="error_row" style="width: 100px; flex-grow: 1; order: 10000000;"><slot name="vaadin-grid-cell-content-1"></slot></td>
We can see the 'class="error_row"' but it's not colored in red.
Vaadin version is 13.0.1
Your java code looks good.
Make sure you have a html file like webapp/frontend/styles/shared-styles.html containing something like:
<dom-module id="my-grid-theme" theme-for="vaadin-grid">
<template>
<style>
[part~="cell"].error_row {
background: red;
}
</style>
</template>
</dom-module>
If you then have your Layout containing the grid annotated with #HtmlImport("frontend://styles/shared-styles.html") (which you already seem to have as your custom css class is already applied) it should work.
Example:
grid.addColumn(Customer::getFirstname).setHeader("Firstname");
grid.addColumn(Customer::getLastname).setHeader("Lastname");
grid.addColumn(Customer::getEmail).setHeader("Email");
grid.setClassNameGenerator(customer -> {
if (customer.getFirstname().equals("Marco")) {
return "error_row";
} else {
return "";
}
});
becomes:

validating a user's value length (javascript)

I am practicing my javascript beginners knowledge on a simple form. I want the user to enter a 10 digits phone number (in case it's less than 10 or more than 10 I have created the invalid style class so the user will only be allowed to enter 10 digits for his phone number). Also, once they entered the phone number of 10 digits, the user should be able to click "+" and get a second box for a second phone number (the second box will appear when you click + only if the user entered 10 digits for his first phone number).
I used an if() for validating the phone number, but it doesn't seem to work. Below is my code, any ideas maybe?
<!DOCTYPE html>
<html>
<head>
<title>Numere de telefon</title>
<style>
.invalid {
background-color: rgb(139,0,0,0.2);
color: darkgreen;
border: 1px green solid;
}
</style>
<script>
function minL(elem,event,nr){
var v = elem.value;
if(v.length < nr ){
elem.classList.add("invalid");
} else if (v.length > nr) {
elem.classList.add("invalid");
} else {
elem.classList.remove("invalid");
}
}
function addInput(elem,event){
event.preventDefault();
var container = document.querySelector("#containerNrTel");
if(minL(document.querySelector("[name=numarTelefon]"))){
container.innerHTML += '<input type="text" placeholder="nr telefon" />';
}
}
</script>
</head>
<body>
<form>
<fieldset>
<legend>Cont nou</legend>
<input type="text" placeholder="nume">
<input type="text" placeholder="prenume">
<input type="text" placeholder="nr telefon" name="numarTelefon" oninput="" onchange="minL(this,event,10);">
<input type="button" value="+" onclick="addInput(this,event);">
<div id="containerNrTel"></div>
<input type="button" value="Submit">
</fieldset>
</form>
</body>
</html>
Thanks in advance,
Ioana
There are two main issues.
The call to minL in the addInput function doesn't have the right number of parameters.
minL doesn't return a boolean value when addInput expects it to.
function minL(elem,event,nr){
var v = elem.value;
if(v.length < nr ){
elem.classList.add("invalid");
} else if (v.length > nr) {
elem.classList.add("invalid");
} else {
elem.classList.remove("invalid");
return true;
}
}
function addInput(elem,event){
event.preventDefault();
var container = document.querySelector("#containerNrTel");
if(minL(document.querySelector("[name=numarTelefon]"), event, 10)){
container.innerHTML += '<input type="text" placeholder="nr telefon" />';
}
}

Slick slider animate back to first slide

I am trying to make a Slick slider jump back to the first slide after the last slide. The closest answer to this topic I have found is this:
Slick slider goto first slide
But unfortunately it uses the fade animation so it does not have the effect I'm after. What I want is that the slideshow will play until the end and then scroll back to the beginning after the last slide is shown.
There are only three slides in my use case, and I can easily fire a message in the console when the last one is reached, but the slickslider method slickGoTo doesn't work.
(function($) {
var slider = $('.sightbox__slideshow');
slider.slick({
arrows: false,
autoplay: true,
infinite: true,
});
function jumpBack() {
slider.slick('slickGoTo', 0);
}
slider.on('beforeChange', function(event, slick, currentSlide, nextSlide) {
console.log(currentSlide);
if (currentSlide === 2 ) {
console.log('last slide');
jumpBack();
}
});
})(jQuery);
.sightbox__slideshow {
width: 250px;
padding: 50px;
}
.sightbox__slide--1 {
background-color: pink;
}
.sightbox__slide--2 {
background-color: green;
}
.sightbox__slide--3 {
background-color: yellow;
}
<link href="https://kenwheeler.github.io/slick/slick/slick.css" rel="stylesheet"/>
<div class="sightbox__slideshow">
<div class="sightbox__slide sightbox__slide--1" id="sightbox__slide--1">
<div alt="" class="sightbox__slide-img"></div>
<p class="sightbox__slide-txt">1. first</p>
</div>
<div class="sightbox__slide sightbox__slide--2" id="sightbox__slide--2">
<div alt="" class="sightbox__slide-img"></div>
<p class="sightbox__slide-txt">2. second</p>
</div>
<div class="sightbox__slide sightbox__slide--3" id="sightbox__slide--3">
<div alt="" class="sightbox__slide-img"></div>
<p class="sightbox__slide-txt">3. third</p>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://kenwheeler.github.io/slick/slick/slick.js"></script>
You may change the trigger event to afterChange and resort to setTimeout function to stay on the last slide for a while (3 seconds approx).
The slick-slider preventing a custom action on its events can also be overridden using the setTimeout function.
function jumpBack() {
setTimeout(function() {
slider.slick("slickGoTo", 0);
},3000);
}
CODEPEN
Hope this helps.

how to make custom line break in my code

I have following code in C# which is printing images from db.And through this code images and radio button shows single time in single line.Here is My code
foreach (DataRow item in ds.Tables[0].Rows)
{
divs += #" <div style="" position:relative; height:100px; width:400px; margin:10px auto;"">
<div style=""position:absolute; width:80px; height:80px; top: 10px; left: 130px;"">
<a href=""#"" class=""screenshot"" rel=""images/"+item["namee"].ToString()+#".jpg"" ><img src=""images/" + item["namee"].ToString() + #".jpg"" width=""80px"" height=""80px"" /></a>
</div>";
if(id < 1){
divs += #" <div style=""position:absolute; width:231px; left:240px; top:35px; height: 40px;"">
<p style="" margin-top:10px; margin-left:20px; ""><input type=""radio"" name=""SSRI"" value=""" + item["namee"].ToString() + #""" /></p>
</div>";
}
divs += #"<div style=""position:absolute; width:231px; left:100px; bottom:10px; height: 40px;"">
</div>
</div>";
}
Response.Write(divs);
By this Code Out Put is like this
Images '' radio
Images '' radio
But i want that out put should b like this
Images '' radio Images '' radio
Images '' radio Images '' radio
Is there any one can help me to do this. Please Help !
I'm not sure how your current code attempts to do what you want, but you should use floating divs. Remove all the top left and position:absolute you have, and just use float, height and width. Then use the clear:left; to a new line.
For example, in your code:
int currLine = 0;
foreach (DataRow item in ds.Tables[0].Rows)
{
if (currLine % 2 == 0)
{
// Every second item, move to a new line
divs += #"<div style=""clear:float;"" />"
}
divs += #" <div style=""float:left; width:400px; margin:10px auto;background:yellow;">
<div style=""width:80px; height:80px;background:red;""
<a href=""#"" class=""screenshot"" rel=""images/"+item["namee"].ToString()+#".jpg"" ><img src=""images/" + item["namee"].ToString() + #".jpg"" width=""80px"" height=""80px"" /></a>
</div>";
if(id < 1){
divs += #" <div style=""width:231px;height: 40px;background:blue;"">
<p style="" margin-top:10px; margin-left:20px; ""><input type=""radio"" name=""SSRI"" value=""" + item["namee"].ToString() + #""" /></p>
</div>";
}
divs += #"<div style=""width:231px; height: 40px;background:green;"">
</div>
</div>";
}
Response.Write(divs);
I took the liberty of adding different colored backgrounds so you can better learn what does what..

Resources