form validation with valid and invalid notification and symbol - html

I have the following set of code where I'm trying to make it work in such a way that by default it will have no pop-over notification and no X symbol. It should appear if the input is invalid stating the format of input (red box) and the Red-X. The rest is fine that as soon as someone make some input, it gives a green-tick symbol but in that case I don't want the pop-over notification at all.
Fiddle Demo
HTML:
<form action="#" method="GET" id="subscribe" name="subscribe">
<div class="NameForm">
<input class="inputName" type="text" placeholder="Your Name" name="query" aria-describedby="name-format" required >
<span id="name-format" class="helpName">Format: firstname lastname</span>
</input>
</div>
</form>
CSS:
.inputName {
border: 2px solid #306b88;
color: #383838;
font: 14px/14px 'focobold';
height: 40px;
margin: 2px 0;
padding: 0 16px;
text-transform: uppercase;
width:248px;
}
.helpName {
display:none;
font-size:90%;
}
input:focus + .helpName {
display:inline-block;
background-color:#26ae56;
height:38px;
width:240px;
position:absolute;
color:#fff;
left:30px;
top:70px;
text-align:center;
line-height:40px;
}
input:required:invalid, input:focus:invalid {
background-image: url(http://s27.postimg.org/ttonbaj5b/invalid.png);
background-position: 260px center;
background-repeat: no-repeat;
}
input:required:valid {
background-image: url(http://s14.postimg.org/gaechg2e5/valid.png);
background-position: 254px center;
background-repeat: no-repeat;
}
More or less, this is the Required Format:

I'm glad I was able to solve the quest...
Here's the Fiddle if you would like to know more about the solution.
It required
function validate_all_forms(){
jQuery.validator.setDefaults({
debug: true,
success: "valid"
});
jQuery.validator.addMethod("notEqual", function(value, element, param) {
return this.optional(element) || value != param;
}, "Please specify a different (non-default) value");
$( "#registration-form" ).validate({
rules: {
myname: {
required: true,
minlength: 3
},
email: {
required: true,
minlength: 6,
email: true
},
},
focusInvalid: false,
onkeyup: false,
submitHandler: function(form) {
$(form).ajaxSubmit({
target: '.optional'
});
},
messages: {
myname: {
required: "Enter Your name",
minlength: jQuery.format("atleast 2 char"),
notEqual: "except the default value please!"
},
email:{
required: "Enter Your E-MAIL",
minlength: jQuery.format("atleast 6 char"),
email: "incorrect e-mail id"
}
}
});
$( "#contact-form" ).validate({
rules: {
your_name: {
required: true,
minlength: 2
},
},
onkeyup: false,
focusInvalid: false,
submitHandler: function(form) {
$(form).ajaxSubmit();
},
});
}

Related

CSS Show div, detect if end of screen

I am implementing a customized dropdown becuase of the requirements we have, using Vue 2 and typescript (jquery is not an option).
It is working fine, when you click on the main box, it opens the options list downwards.
An improvement I am looking for is that, when at the end of the screen, the options list adds to the page height and thus causing the scrollbar to appear or increase scroll height.
What I am looking for is that, when popping up the div, if there's not enough space at the bottom of the screen, open it upwards instead. How do I achieve this?
(classes are using bootstrat 5)
Opened dropdown &
Closed dropdown
My code:
import Vue, {
PropType
} from 'vue';
import {
Validation
} from 'vuelidate';
let uidc = 0;
export default Vue.extend({
name: 'BaseDropdown',
props: {
value: {
type: [Number, String, Object],
default: () => ''
as string,
},
target: {
type: String,
default: '',
},
label: {
type: String,
default: '',
},
valueIsNumber: {
type: Boolean,
default: false,
},
options: {
type: Array,
default: null,
},
placeholder: {
type: String,
default: '',
},
required: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
validations: {
type: Object as PropType < Validation > ,
default: () => ({
$error: false,
$touch: () => undefined,
$params: {},
}) as Validation,
},
error: {
type: Boolean,
default: false,
},
trackEvent: {
type: String,
default: '',
},
trackField: {
type: String,
default: '',
},
trackPublic: {
type: Boolean,
default: false,
},
padLeft: {
type: Boolean,
default: false,
},
enforceBlackColour: {
type: Boolean,
default: false,
},
customStyled: {
type: Boolean,
default: false,
},
borderBottomWarning: {
type: Boolean,
default: false,
},
},
data(): {
selectedItem: any | null;
menuOpen: boolean;
searchText: string | null;
} {
return {
selectedItem: null,
menuOpen: false,
searchText: null,
};
},
mounted() {
const appElement = document.getElementById('app_home');
(appElement as any).addEventListener('click', this.handleDropdownClickOutside);
this.$nextTick(() => {
if (this.value) {
if (this.valueIsNumber) {
this.selectedItem = this.options.find((x: any) => x.value === Number(this.value)) || null;
} else {
this.selectedItem = this.options.find((x: any) => x.value.toString().toLowerCase() === this.value.toString().toLowerCase()) || null;
}
}
});
},
computed: {
v(): Validation | {} {
return this.validations;
},
errorMessage(): string {
// Validation must be cast to any to access validators
return Object.entries((this.v as Validation).$params).find(([k]) => !(this.v as any)[k]) ? .[1].message;
},
optgroups(): any {
return this.options.reduce((acc: any, o: any) => ({ ...acc,
[o.optgroup]: [...(acc[o.optgroup] || []), o]
}), {});
},
isRequired(): boolean {
return this.required !== false;
},
getSelectedItemText(): string | null {
return this.selectedItem ? this.selectedItem.text : this.placeholder || 'Please select an item';
},
filteredItems(): any[] {
const list: any[] = [];
for (let c = 0; c < 10; c += 1) {
list.push({
text: c,
value: c
});
}
// return this.searchText && this.searchText.length > 0 ? this.options.filter((x: any) => x.text.toLowerCase().indexOf(this.searchText!.toLowerCase()) > -1) : this.options;
return list;
},
},
methods: {
openMenu() {
this.menuOpen = !this.menuOpen;
if (this.menuOpen) {
this.searchText = null;
}
},
selectItem(item: any) {
this.selectedItem = item;
this.$emit('input', item.value);
this.menuOpen = false;
},
setSuppliedSelectedItem() {
this.$nextTick(() => {
if (this.value) {
this.selectedItem = this.options.find((x: any) => x.value === this.value) || null;
}
});
},
handleDropdownClickOutside(event: any): void {
const parent = document.getElementById(`select-${(this as any).uid}`);
const isParent = parent !== event.target && parent ? .contains(event.target);
if (!isParent) {
this.menuOpen = false;
// this.closeOpenendMenu();
// this.searchText = '';
}
},
},
beforeCreate() {
// eslint-disable-next-line no-plusplus
(this as any).uid = uidc++;
},
});
.dropdown {
font-size: 0.7rem;
img {
// float: right;
// padding-right: 10px;
// padding-top: 5px;
position: absolute;
top: 40%;
right: 10px;
}
.fade {
opacity: 0.5;
}
.search-box {
.form-control {
font-size: 12px !important;
height: 30px !important;
margin: 0 10px 5px 10px !important;
width: 95% !important;
}
}
.selected-item {
border-radius: 3px;
border: 1px solid #ced4da;
padding: 10px;
.selected-item-text {
text-overflow: ellipsis;
overflow: hidden;
width: 93%;
/* height: 1.2em; */
white-space: nowrap;
}
}
.items {
border: 1px solid rgb(236, 236, 236);
width: 100%;
z-index: 15;
max-height: 300px;
overflow-y: auto;
overflow-x: hidden;
background-color: white;
}
.item {
padding: 10px;
background-color: rgb(240, 240, 240);
cursor: pointer;
&:hover {
background-color: rgb(216, 216, 216);
}
}
}
.hidden {
opacity: 0.2;
}
.disabled {
background-color: #e9ecef;
opacity: 1;
pointer-events: none;
}
<template>
<div class="mt-2" :id="`select-${uid}`">
<label v-show="label" class="mb-2 label-grey" :class="{ 'required': isRequired }" :for="`select-${uid}`">{{ label }}</label>
<div class="dropdown noselect position-relative" :class="{'disabled': disabled}">
<div class="selected-item cursor-pointer" #click="openMenu">
<div class="selected-item-text" :class="{'fade': !selectedItem}">{{getSelectedItemText}}</div>
<img v-if="menuOpen" :src="constants.icons.arrowTop" />
<img v-else :src="constants.icons.arrowDown" />
</div>
<div class="items position-absolute" v-show="menuOpen">
<div v-if="filteredItems && filteredItems.length > 5 || searchText" class="search-box">
<input :size="'sm'" v-model="searchText" />
</div>
<div v-for="item in filteredItems" :key="item.value" #click="selectItem(item)">
<div class="item">
{{item.text}}
</div>
</div>
</div>
</div>
<span v-if="v.$error" class="text-error text-xs font-light">{{ errorMessage }}</span>
</div>
</template>
Suggest to use Floating-ui (well known as Poper)
Floating UI is a low-level library for positioning "floating" elements...intelligently keeping them in view
It's been using widely and cover a lot of edge cases you might encounter when try to create dropdown yourself
You can try with references here
creating-vue-component-dropdown-with-popper-js
floating-vue/dropdown

How to validate email addresses using vuelidate?

How to validate emails?
Would you please show an example with an error message?
Documentation does not give enough details.
It seems there is nothing like v-if="!$v.user.email.email"
Following code does not work either
validations: {
user: {
email: {
required,
email: email(),
},
}
}
Actualy, I was wrong and there was something like v-if="!$v.user.email.email"
You do not need any details for email validator.
All you need is
email: {
email,
},
If you had any Vetur errors just uninstall Vetur and reinstall it.
Vue.use(window.vuelidate.default)
const { email } = window.validators
new Vue({
el: "#app",
data: {
user: {
email: ""
}
},
validations: {
user:{
email: {
email
}
}
},
methods: {
status(validation) {
return {
error: validation.$error,
dirty: validation.$dirty
}
}
}
})
input {
border: 1px solid silver;
border-radius: 4px;
background: white;
padding: 5px 10px;
}
.dirty {
border-color: #5A5;
background: #EFE;
}
.error {
border-color: red;
background: #FDD;
}
<script src="https://cdn.jsdelivr.net/combine/npm/vuelidate#0.7.5/dist/validators.min.js,npm/vuelidate#0.7.5/dist/vuelidate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="$v.user.email.$model" :class="status($v.user.email)">
<div class="error" v-if="!$v.user.email.email">this must be an email</div>
<pre>{{ $v }}</pre>
</div>
Answer https://stackoverflow.com/a/61359412/11993949 shows off how to use on blur functionality too
you can use this regex validation pattern to validate your email.
[a-zA-Z0-9]+#[a-z]+\.[a-z]{2,3}
If you are getting as json format you can try this
[a-zA-Z0-9]+#[a-z]+\\.[a-z]{2,}

how to call ajax function to update the Highcharts graph dynamically?

I am using Highcharts to plot the graph of temperature vs time. I am having a JSON file wherein data from the backend keep updates the JSON file. I want to call ajax function such that the graphs automatically generates with respect to time. How to do that? I am new to high charts, please help me.
You can use Series.addPoint method.
http://api.highcharts.com/highcharts/Series.addPoint
Here is a example of using Highcharts with live data with GET HTTP requests.
const options = {
chart: {
type: 'spline'
},
title: {
text: 'Live Bitcoin Price'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'Price (USD)'
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Live Bitcoint Price [USD]',
data: []
}]
}
const chart = Highcharts.chart('container', options)
// Data
const getData = () => {
setInterval(() => {
window.fetch('https://api.cryptonator.com/api/ticker/btc-usd').then((response) => {
return response.json()
}).then((data) => {
chart.series[0].addPoint({ x: data.timestamp * 1000, y: Number(data.ticker.price) })
})
}, 3000)
}
getData()
#import 'https://code.highcharts.com/css/highcharts.css';
.highcharts-background {
fill: #222;
}
.highcharts-title,
.highcharts-axis-title {
fill: #DDD;
}
.highcharts-credits,
.highcharts-credits:hover {
fill: #222;
}
body {
background-color: #222;
margin 0 !important;
}
#container {
margin: 0;
padding: 0;
border: 0;
background-color: #222;
min-height: 400px;
height:95%;
width:95%;
position:absolute;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Live example:
https://jsfiddle.net/xpfkx91w/

Bootstrap span change width after submit

I'm using a register form with a jquery to validate this form
My problem is with the design after submit the form and the error appear the span change her height
I'm using a bootstrap for my css
/*validation css*/
#import url('../assets/css/bootstrap.min.css');
#import url('../assets/css/bootstrap-responsive.min.css');
label.valid {width: 24px;height: 24px;background: url(../assets/img/valid.png) center center no-repeat;display: inline-block;text-indent: -9999px;}
label.error {font-weight: bold;color: red;padding: 2px 8px;margin-top: 2px;}
.form-group{
margin-bottom: 15px;
}
label{
margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder {
font-size: 11px;
padding-top: 3px;
}
.main-login{
background-color: #fff;
/* shadows and rounded borders */
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
}
.main-center{
margin-top: 30px;
margin: 0 auto;
max-width: 500px;
padding: 40px 40px;}
Html Form
<div class="main-login main-center">
<form class="form-horizontal" method="post" action="#" id="registration-form" name="form">
<div class="form-group">
<label for="name" class="cols-sm-2 control-label">Your Name</label>
<div class="cols-sm-10">
<div class="input-group">
<span class="input-group-addon "><i class="fa fa-user fa" aria-hidden="true"></i></span>
<input type="text" class="form-control label.error" name="name" id="name" placeholder="Enter your Name"/>
</div>
</div>
</div>
Before submit
After submit
$(document).ready(function(){
$('#registration-form').validate({
rules: {
name: {
required: true,
required: true
},
username: {
minlength: 6,
required: true
},
phone: {
minlength: 8,
required: true
},
password: {
required: true,
minlength: 6
},
confirm_password: {
required: true,
minlength: 6,
equalTo: "#password"
},
email: {
required: true,
email: true
},
address: {
minlength: 10,
required: true
},
agree: "required"
},
highlight: function(element) {
$(element).closest('.control-group').removeClass('success').addClass('error');
},
success: function(element) {
element
.text('OK!').addClass('valid')
.closest('.control-group').removeClass('error').addClass('success');
}
});
}); // end document.ready
Updated
You need to wrap your script in $(document).ready(function(){...});
Check Demo HERE
JS:
$(document).ready(function(){
$('#registration-form').validate({
rules: {
name: {
required: true,
required: true
},
username: {
minlength: 6,
required: true
},
phone: {
minlength: 8,
required: true
},
password: {
required: true,
minlength: 6
},
confirm_password: {
required: true,
minlength: 6,
equalTo: "#password"
},
email: {
required: true,
email: true
},
address: {
minlength: 10,
required: true
},
agree: "required"
},
highlight: function(element) {
$(element).closest('.form-group').addClass('has-error');
},
unhighlight: function(element) {
$(element).closest('.form-group').removeClass('has-error');
},
errorElement: 'span',
errorClass: 'help-block',
errorPlacement: function(error, element) {
if (element.parent('.input-group').length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
},
success: function(label) {
label.addClass("valid").text("Ok!")
}
});
});

kendo treeview change datasource on the fly

I have a kendoTreeView connected to OData source as given in the demo on official site. I need to change the dataSource of the kendoTreeView to something else. Here is the html with the script.
When I click on the change button the tree changes but shows all the nodes as undefined. It is not able to show the new dataTextField values. When I revert it back it works even without setting the dataTextField.
I need to either change the dataSource of the tree or destroy the tree, remove it from DOM and then add a new one. Any help or pointers?
<body>
<input type="button" id="expandAllNodes" value="expandAllNodes" />
<input type="button" id="changedatasource" value="changedatasource" />
<input type="button" id="revert" value="revert" />
<span>First Tree</span>
<div id="treeview"></div>
<br/>
<span>Second Tree</span>
<div id="treeview2"></div>
<!--<div id="example" class="k-content">
<div id="treeview" class="demo-section"></div>-->
<script>
</script>
<style scoped>
#example {
text-align: center;
}
.demo-section {
display: inline-block;
vertical-align: top;
width: 320px;
height: 300px;
text-align: left;
margin: 0 2em;
}
</style>
<!--</div>-->
</body>
$(document).ready(function () {
// TreeView bound to Categories > Products > OrderDetails
var viewModel = {
self: this,
OrderDetails: {
type: "odata",
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products({0})/Order_Details", options.ProductID);
}
}
},
schema: {
model: {
hasChildren: function () {
return false;
}
}
}
},
Products: new kendo.data.HierarchicalDataSource({
type: "odata",
transport: {
read: {
url: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products"
}
},
schema: {
model: {
id: "ProductID",
hasChildren: "Order_Details",
children: {
type: "odata",
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products({0})/Order_Details", options.ProductID);
}
}
},
schema: {
model: {
hasChildren: function () {
return false;
}
}
}
}
}
}
}),
Categories: new kendo.data.HierarchicalDataSource({
type: "odata",
transport: {
read: {
url: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"
}
},
schema: {
model: {
hasChildren: "Products",
id: "CategoryID",
children: {
type: "odata",
schema: {
model: {
id: "ProductID",
hasChildren: "Order_Details",
children: {
type: "odata",
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products({0})/Order_Details", options.ProductID);
}
}
},
schema: {
model: {
hasChildren: function () {
return false;
}
}
}
}
}
},
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories({0})/Products", options.CategoryID);
}
}
}
}
}
}
})
}
$("#treeview").kendoTreeView({
dataSource: viewModel.Categories,
dataTextField: ["CategoryName", "ProductName", "OrderID"],
checkboxes: {
checkChildren: true
}
});
$("#treeview2").kendoTreeView({
dataSource: viewModel.Products,
dataTextField: ["ProductName", "OrderID"],
checkboxes: {
checkChildren: true
}
});
ko.applyBindings(viewModel);
$("#expandAllNodes").click(function () {
var treeView = $("#kendoTreeView").data("kendoTreeView");
treeView.expand(".k-item");
});
$("#changedatasource").click(function () {
var treeview: kendo.ui.TreeView = $("#treeview").data("kendoTreeView");
//treeview.destroy();
treeview.setOptions({ dataTextField: ["ProductName", "OrderID"] });
treeview.setDataSource(viewModel.Products);
});
$("#revert").click(function () {
var treeview: kendo.ui.TreeView = $("#treeview").data("kendoTreeView");
//treeview.setOptions({ dataTextField: ["CategoryName", "ProductName", "OrderID"] });
treeview.setDataSource(viewModel.Categories);
});
});
Set the datasource to a new instance of a HierarchicalDataSource, see here: http://d585tldpucybw.cloudfront.net/forums/datasource-property-update-and-refresh. Direct link to Dojo by Alex Gyoshev: http://dojo.telerik.com/#gyoshev/iJIhI.