I'm using the Zebra Datepicker in one of my forms and I'm trying to validate it with the jzaefferer validate plugin. I want the input field to get a red border and I want a error message beneath the input field. The red border is working, but the error message isn't showing. How can I get the error message to show up?
This is my code (the error message should go into .diverror):
<div class="input-datepicker">
<label>Van:</label>
<input type="text" name="Datum1" class="datepicker" />
</div>
<div class="diverror"></div>
Zebra Datepicker places the <input> inside a <span> and adds a <button> under the <input> inside the <span>.
<div class="input-datepicker">
<label>Van:</label>
<span class="Zebra_DatePicker_Icon_Wrapper" style="display: block; position: relative; float: none; top: auto; right: auto; bottom: auto; left: auto;">
<input class="datepicker error" type="text" name="Datum1" readonly="readonly" style="position: relative; top: auto; right: auto; bottom: auto; left: auto;">
<button class="Zebra_DatePicker_Icon Zebra_DatePicker_Icon_Inside" type="button" style="top: 23px; left: 233px;">Pick a date</button>
</span>
</div>
<div class="diverror"></div>
I'm not that experienced with jquery but could it be the span that is messing up my appendTo in the example below.
Here's my validation.js:
$("#home-verhuur").validate({
errorPlacement: function(error, element) {
error.appendTo( element.parent("div").next("div") );
},
ignore: "input[type='text']:hidden",
onsubmit: true,
onkeyup: true,
onclick: true,
rules: {
Naam: {
required: true,
minlength: 2
},
Email: {
required: true,
email: true
},
Product: {
required: true
},
Personen: {
required: true,
min: 1
},
Datum1: {
required: true,
},
Datum2: {
required: true,
},
},
messages: {
Naam: "Vul je voornaam in (minimaal 2 karakters)",
Email: "Vul een correct Email adres in",
Product: "Kies een product",
Personen: "Vul het aantal personen in",
Datum1: "Kies een begindatum",
Datum2: "Kies een einddatum",
}
});
All the help is welcome!
Given your rendered HTML as constructed by the DOM...
You must change .parent() to .parents(), since the target div is now another level higher...
errorPlacement: function (error, element) {
error.appendTo(element.parents("div").next("div"));
},
DEMO: http://jsfiddle.net/2g953/1/
Related
Owlcarousel-slider works fine when I use below code.
HTML Code:
<div class="banner">
<div class="main-banner owl-carousel" id="homeage-data">
<div class="item" v-for="slider in sliders">
<div v-bind:class="slider.class_type"> <img v-bind:src="slider.image_src" alt="Electrro">
<div class="banner-detail">
<div class="container">
<div class="row">
<div class="col-md-3 col-3" v-if="slider.align_right"></div>
<div class="col-md-9 col-8">
<div class="banner-detail-inner">
<span class="slogan">{{ slider.label }}</span>
<h1 class="banner-title" v-html="slider.banner_title"></h1>
<span class="offer">{{ slider.banner_desc }}</span>
</div>
<a class="btn btn-color big" v-bind:href="slider.button_link" v-if="slider.button_np" target="_blank">{{ slider.button_text }}</a>
<a class="btn btn-color big" v-bind:href="slider.button_link" v-else-if="!slider.button_np">{{ slider.button_text }}</a>
</div>
<div class="col-md-3 col-4" v-if="!slider.align_right"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
JavaScript Code:
<script>
new Vue({
el: '#homeage-data',
data: {
sliders: [
{
"label": "Discover",
"banner_title": "Top Branded for <br>headphone",
"banner_desc": "best selling, and popular.",
"image_src": "images/banner1.jpg",
"button_text": "Shop Now!",
"button_link": "#link",
"class_type" : "banner-1",
"button_np": true,
"align_right": false
},
{
"label": "curved tv",
"banner_title": "Get latest TV models",
"banner_desc": "Get the top brands for TV",
"image_src": "images/banner2.jpg",
"button_text": "Shop Now!",
"button_link": "#link",
"class_type" : "banner-2",
"button_np": false,
"align_right": true
},
{
"label": "Premium",
"banner_title": "drone cameras",
"banner_desc": "The latest camera up to 30% off",
"image_src": "images/banner3.jpg",
"button_text": "Shop Now!",
"button_link": "#link",
"class_type" : "banner-3",
"button_np": true,
"align_right": false
}
]
},
});
</script>
Output Image: (Very Nice!)
But when I call the code remotely with Fetch, the image is broken.
JavaScript Code: (I uploaded the slider array to the api.php file and called it remotely.)
<script>
new Vue({
el: '#homeage-data',
data: {
sliders: [
]
},
created() {
fetch("/api/api.php")
.then((response) => { return response.json() })
.then((response) => {
this.sliders = response.sliders;
});
}
});
</script>
Output Image:
As I understand it, it cannot render JQuery code because it was added later.
No matter what I did, I couldn't find the right way.
I have not tried the code below. It didn't happen :(
<script>
new Vue({
el: '#homeage-data',
data: {
sliders: [
]
},
created() {
fetch("/api/api.php")
.then((response) => { return response.json() })
.then((response) => {
this.sliders = response.sliders;
});
$(".main-banner, #client").owlCarousel({
//navigation : true, Show next and prev buttons
items: 1,
nav: true,
slideSpeed : 300,
paginationSpeed : 400,
loop:true,
autoPlay: false,
dots: true,
singleItem:true,
nav:true
});
}
});
</script>
Demo of using VueOwlCarousel in Vue2, without npm:
Vue.use(VueOwlCarousel);
new Vue({
el: '#app',
data: () => ({
slides: 0,
options: {
autoplay: true,
autoplaySpeed: 800,
autoplayTimeout: 1800,
lazyLoad: true,
autoplayHoverPause: true
}
}),
mounted() {
setTimeout(() => {
this.slides = 7
}, 2000)
},
})
div.owl-carousel {
width: 400px;
height: 180px;
}
.owl-stage-outer {
height: 111px;
}
.loader {
height: 180px;
display: flex;
align-items: center;
width: 400px;
justify-content: center;
}
h2 {
color: #ddd;
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
}
<script src="https://v2.vuejs.org/js/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-owl-carousel#2.0.3/dist/vue-owl-carousel.min.js"></script>
<div id="app">
<vue-owl-carousel :items="1"
v-if="slides"
v-bind="options">
<img v-for="s in slides"
:key="s"
:src="`https://placeimg.com/400/111/any?${s}`">
</vue-owl-carousel>
<div v-else class="loader">
<h2>Loading...</h2>
</div>
</div>
Personal advice: do not mix jQuery with Vue. You only want one source of truth for your DOM manipulations.
That's the underlying cause of your issue.
Note: Owl carousel can't be initialised with empty slides. For this reason, I've placed a v-if="slides" (or, if slides would have been an array, v-if="slides.length").
Also note Owl takes control over the carousel DOM element and, from that moment on, even if you change the slides array, it won't react to the change. If you wanted to update the slides, you'd need the owl instance, change its internal slides (which are built from the original DOM) and then call its internal .refresh() method.
I have designed a login page, but client side validation is not working. I have written JavaScript code for validation. And how to make email extension acceptance only particular comp id. ex: user#example.com. It should accept only example.com email id's. I have tried to to give extension: "example.com" in JavaScript validation, but it's not working.
Code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- This file has been downloaded from Bootsnipp.com. Enjoy! -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
<meta charset="utf-8">
<!-- Font CSS (Via CDN) -->
<link rel='stylesheet' type='text/css' href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700'>
<!-- Favicon -->
<link rel="shortcut icon" href="img/favicon.ico">
<!--Table container---->
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
<link href="css/login.css" rel="stylesheet">
<script src="js/ValidationFormScript.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.min.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<nav class="navbar navbar-light" style="background-color: #e3f2fd;">
<!-- Navbar content -->
</nav>
<!---Body starts here---->
<body>
<br><br><br><br>
<section class="login-block">
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-8 banner-sec">
<div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">
<div class="carousel-inner" role="listbox">
<div class="carousel-item active">
<img class="img-fluid" src="img/logo.jpg" alt="First slide">
</div>
</div>
</div>
</div>
<div class="col-sm-12 col-md-4 login-sec">
<!---Break line after header ---->
<br />
<!--- Form starts here----->
<form class="login-form" method="" action="" id="admin-form">
<!---- Starts the User ID section--->
<div class="form-group">
<label for="exampleInputEmail" class="text-left"><span>User ID</span></label>
<span class="input-status" data-toggle="tooltip" data-placement="top" title="Input your email"></span>
<input type="email" class="form-control" id="email" name="email" placeholder="enter email">
</div>
<!---- Starts the Password section--->
<div class="form-group">
<label for="exampleInputPassword" class="text-left"><span>Password</span></label>
<span class="input-status" data-toggle="tooltip" data-placement="top" title="Input your password"></span>
<input type="password" class="form-control" name="password" id="password" placeholder="enter password">
</div>
<!---- Ends the Password section--->
<!---Submit button--->
<div class="form-group">
<button type="submit" class="btn btn-login float-right">Login</button>
</div>
</form>
</div>
</div>
</section>
<!----- Script for Validation----->
<!-- jQuery Validate Plugin-->
<script src="js/jquery.validate.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
"use strict";
// Init Theme Core
Core.init();
// Init Demo JS
Demo.init();
/* #custom validation method (smartCaptcha)
------------------------------------------------------------------ */
$.validator.methods.smartCaptcha = function(value, element, param) {
return value == param;
};
$("#admin-form").validate({
/* #validation states + elements
------------------------------------------- */
errorClass: "state-error",
validClass: "state-success",
errorElement: "em",
/* #validation rules
------------------------------------------ */
rules: {
firstname: {
required: true
},
lastname: {
required: true
},
email: {
required: true,
email: true,
extension: ""
},
website: {
required: true,
url: true
},
language: {
required: true
},
upload1: {
required: true,
extension: "jpg|png|gif|jpeg|doc|docx|pdf|xls|rar|zip"
},
mobileos: {
required: true
},
comment: {
required: true,
minlength: 30
},
mobile_phone: {
require_from_group: [1, ".phone-group"]
},
home_phone: {
require_from_group: [1, ".phone-group"]
},
password: {
required: true,
},
repeatPassword: {
required: true,
minlength: 6,
maxlength: 16,
equalTo: '#password'
},
gender: {
required: true
},
languages: {
required: true
},
verification: {
required: true,
smartCaptcha: 19
},
applicant_age: {
required: true,
min: 16
},
licence_no: {
required: function(element) {
return $("#applicant_age").val() > 19;
}
},
child_name: {
required: "#parents:checked"
}
},
/* #validation error messages
---------------------------------------------- */
messages: {
firstname: {
required: 'Enter first name'
},
lastname: {
required: 'Enter last name'
},
useremail: {
required: 'Enter email address',
email: 'Enter a VALID email address'
},
website: {
required: 'Enter your website URL',
url: 'URL should start with - http://www'
},
language: {
required: 'Choose a language'
},
upload1: {
required: 'Please browse a file',
extension: 'File format not supported'
},
mobileos: {
required: 'Please select a mobile platform'
},
comment: {
required: 'Oops you forgot to comment',
minlength: 'Enter at least 30 characters or more'
},
mobile_phone: {
require_from_group: 'Fill at least a mobile contact'
},
home_phone: {
require_from_group: 'Fill at least a home contact'
},
password: {
required: 'Please enter a password'
},
repeatPassword: {
required: 'Please repeat the above password',
equalTo: 'Password mismatch detected'
},
gender: {
required: 'Please choose specie'
},
languages: {
required: 'Select laguages spoken'
},
verification: {
required: 'Please enter verification code',
smartCaptcha: 'Oops - enter a correct verification code'
},
applicant_age: {
required: 'Enter applicant age',
min: 'Must be 16 years and above'
},
licence_no: {
required: 'Enter licence number'
},
child_name: {
required: 'Please enter your childs name'
}
},
/* #validation highlighting + error placement
---------------------------------------------------- */
highlight: function(element, errorClass, validClass) {
$(element).closest('.field').addClass(errorClass).removeClass(validClass);
},
unhighlight: function(element, errorClass, validClass) {
$(element).closest('.field').removeClass(errorClass).addClass(validClass);
},
errorPlacement: function(error, element) {
if (element.is(":radio") || element.is(":checkbox")) {
element.closest('.option-group').after(error);
} else {
error.insertAfter(element.parent());
}
}
});
// Cache several DOM elements
var pageHeader = $('.content-header').find('b');
var adminForm = $('.admin-form');
var options = adminForm.find('.option');
var switches = adminForm.find('.switch');
var buttons = adminForm.find('.button');
var Panel = adminForm.find('.panel');
// Form Skin Switcher
$('#skin-switcher a').on('click', function() {
var btnData = $(this).data('form-skin');
$('#skin-switcher a').removeClass('item-active');
$(this).addClass('item-active')
adminForm.each(function(i, e) {
var skins = 'theme-primary theme-info theme-success theme-warning theme-danger theme-alert theme-system theme-dark'
var panelSkins = 'panel-primary panel-info panel-success panel-warning panel-danger panel-alert panel-system panel-dark'
$(e).removeClass(skins).addClass('theme-' + btnData);
Panel.removeClass(panelSkins).addClass('panel-' + btnData);
pageHeader.removeClass().addClass('text-' + btnData);
});
$(options).each(function(i, e) {
if ($(e).hasClass('block')) {
$(e).removeClass().addClass('block mt15 option option-' + btnData);
} else {
$(e).removeClass().addClass('option option-' + btnData);
}
});
// var sliders = $('.ui-timepicker-div', adminForm).find('.ui-slider');
$('body').find('.ui-slider').each(function(i, e) {
$(e).addClass('slider-primary');
});
$(switches).each(function(i, ele) {
if ($(ele).hasClass('switch-round')) {
if ($(ele).hasClass('block')) {
$(ele).removeClass().addClass('block mt15 switch switch-round switch-' + btnData);
} else {
$(ele).removeClass().addClass('switch switch-round switch-' + btnData);
}
} else {
if ($(ele).hasClass('block')) {
$(ele).removeClass().addClass('block mt15 switch switch-' + btnData);
} else {
$(ele).removeClass().addClass('switch switch-' + btnData);
}
}
});
buttons.removeClass().addClass('button btn-' + btnData);
});
setTimeout(function() {
adminForm.addClass('theme-primary');
Panel.addClass('panel-primary');
pageHeader.addClass('text-primary');
$(options).each(function(i, e) {
if ($(e).hasClass('block')) {
$(e).removeClass().addClass('block mt15 option option-primary');
} else {
$(e).removeClass().addClass('option option-primary');
}
});
// var sliders = $('.ui-timepicker-div', adminForm).find('.ui-slider');
$('body').find('.ui-slider').each(function(i, e) {
$(e).addClass('slider-primary');
});
$(switches).each(function(i, ele) {
if ($(ele).hasClass('switch-round')) {
if ($(ele).hasClass('block')) {
$(ele).removeClass().addClass('block mt15 switch switch-round switch-primary');
} else {
$(ele).removeClass().addClass('switch switch-round switch-primary');
}
} else {
if ($(ele).hasClass('block')) {
$(ele).removeClass().addClass('block mt15 switch switch-primary');
} else {
$(ele).removeClass().addClass('switch switch-primary');
}
}
});
buttons.removeClass().addClass('button btn-primary');
}, 800);
});
</script>
</body>
</html>
<style type="text/css">
#import url("//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css");
.login-block{
background: #fff; /* fallback for old browsers */
background: -webkit-linear-gradient(to bottom, #fff, #fff); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to bottom, #fff, #fff); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
float:left;
width:100%;
padding : 50px 0;
}
.banner-sec{background:#fff; no-repeat left bottom; background-size:cover; min-height:0px; border-radius: 0 10px 10px 0; padding:0;}
.carousel-inner{border-radius:10px 10px 10px 10px;}
}
.login-sec{padding: 60px 30px; position:relative;}
.login-sec .copy-text{position:absolute; width:100%; bottom:20px; font-size:13px; text-align:left;}
.login-sec .copy-text i{color:#FEB58A;}
.login-sec .copy-text a{color:#E36262;}
.login-sec h2{margin-bottom:30px; font-weight:400; font-size:30px; color: grey;}
.btn-login{background: #90EE90; color:#000; font-weight:400;}
.banner-text{width:70%; position:absolute; bottom:40px; padding-left:20px;}
.banner-text p{color:#fff;}
.carousel-caption {
position: absolute;
left: 3%;
right: 26%;
bottom: 160px;
z-index: 10;
padding-top: 20px;
padding-bottom: 20px;
color: #ffffff;
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
font: Century Gothic;
font-weight: 400;
}
body {
font-family: "Helvetica Neue",Century Gothic,Century Gothic,Century Gothic;
font-size: 14px;
line-height: 1.428571429;
color: grey;
background-color: #fff;
}
.palel-primary
{
border-color: #bce8f1;
}
.panel-primary>.panel-heading
{
background:#bce8f1;
}
.panel-primary>.panel-body
{
background-color: #EDEDED;
}
input {
margin-top: 5px;
margin-bottom: 5px;
display:inline-block;
*display: inline; /* for IE7*/
zoom:1; /* for IE7*/
vertical-align:middle;
margin-left:20px
}
label {
display:inline-block;
*display: inline; /* for IE7*/
zoom:1; /* for IE7*/
float: left;
padding-top: 5px;
text-align: right;
width: 80px;
}
.form-control {
display: block;
width: 77%;
height: 32px;
}
.label{
color: black;
}
label span { color: black;
font-weight: normal !important;}
a {
text-decoration: none !important;
}
body {
margin-bottom:50px;
}
</style>
JavaScript code for validation, but it's not working.
You need to add an attribute called, 'pattern' (based on regular expressions). It should look like,
<input type="email" class="form-control" id="email" name="email" placeholder="enter email" pattern="[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+"/>
Optionally, you can also publish custom error messages using event handler attributes like oninput, onvalid,... It brings value and helpful to direct the users with more precise & meaningful messages.
If you are only going to use the email input to validate, it is better to use javascript to validate the input and show error messages.
function checkRegistration() {
var email = document.getElementById('login-email').value;
var alertMessage = document.getElementById('alert-email');
var re = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
var isValid = re.test(email);
if (isValid) {
alertMessage.innerHTML = '';
alertMessage.style.opacity = 0;
alertMessage.style.visibility = 'hidden';
} else {
alertMessage.innerHTML = "You have entered an invalid email address!";
alertMessage.style.opacity = 1;
alertMessage.style.visibility = 'visible';
}
return isValid;
}
#alert-email {
visibility:hidden;
opacity:0;
transition:visibility 0s linear,opacity 0.5s linear;
}
<form onsubmit="return checkRegistration()">
<div>
<label>User ID</label>
<input type="email" placeholder="enter email" id="login-email" />
</div>
<span id="alert-email"></span>
<div>
<label>Password</label>
<input type="password" placeholder="enter password" id="login-password" />
</div>
<button type="submit" class="btn btn-login float-right">Login</button>
</form>
Try to add new require for JQuery validate:
$.validator.addMethod("email_domain", function (value, element) {
var regex = /^[a-zA-Z0-9_.+-]+#(?:(?:[a-zA-Z0-9-]+\.)?[a-zA-Z]+\.)?(domain|domain2)\.com$/;
if(!regex.test(value)) {
return false;
}else{
return true;
}
});
Then add "email_domain" to form require validate
I'm using the tooltipster plugin to show fields's hints and also another tooltip at bottom to show errors from jquery validate plugin, but for some reason all the messages updates are happening on the first error tooltip.
What am I missing?
$(document).ready(function () {
// initialize tooltipster on text input elements
$('input').tooltipster();
var tooltipsterErrorMsg = [];
// initialize validate plugin on the form
$('#myform').validate({
showErrors: function(errorMap, errorList) {
// Clean up any tooltips for valid elements
$.each(this.validElements(), function (index, element) {
if (index < tooltipsterErrorMsg.length) {
tooltipsterErrorMsg[index].hide();
}
});
// Create new tooltips for invalid elements
$.each(errorList, function (index, error) {
if (index === tooltipsterErrorMsg.length) {
var tooltipObject = $(error.element).tooltipster({
trigger: 'custom',
multiple: true,
position: 'bottom'
});
tooltipsterErrorMsg.push(tooltipObject[0]);
}
tooltipsterErrorMsg[index].content(errorList[index].message).show();
});
},
rules: {
field1: {
required: true,
email: true
},
field2: {
required: true,
minlength: 5
}
},
submitHandler: function (form) { // for demo
alert('valid form');
return false;
}
});
});
#myform {
margin: 100px;
}
input {
margin: 20px;
}
a {
display: block;
position: absolute;
bottom: 0;
}
.error {
color: #900;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tooltipster/3.3.0/css/tooltipster.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tooltipster/3.3.0/js/jquery.tooltipster.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<form id="myform">
<input type="text" name="field1" title="Tooltip teste 1" />
<input type="text" name="field2" title="Tooltip teste 2" />
<br/>
<input type="submit" />
</form>
Here's the fiddle: http://jsfiddle.net/macmessa/m368ntxw/
Two issues...
You're using the showErrors function improperly. It was only intended for constructing an error list, not for individual error placement. Employ the errorPlacement and success functions for showing & hiding the individual tooltip bubbles.
errorPlacement: function(error, element) {
var lastError = $(element).data('lastError'),
newError = $(error).text(); // current error message
$(element).data('lastError', newError); // keep track of the error
if (newError !== '' && newError !== lastError) { // new error?
$(element).tooltipster('content', newError); // replace message
$(element).tooltipster('show'); // show bubble
}
},
success: function(label, element) {
$(element).tooltipster('hide'); // hide bubble when error clears
},
You're trying to initialize and re-initialize ToolTipster on the same element for showing two different bubbles on the same element at the same time. Although I'm not clearly seeing the described issue in your demo, I can see how it would lead to problems and confusion.
Here's a workaround.
Surround the input elements with a container element.
<div title="Tooltip teste 1">
<input type="text" name="field1" />
</div>
BTW: you don't need the data-rule-required attribute when you've already declared required within .validate().
Then you can initialize ToolTipster on the input[type="text"] elements for validation error messages...
$('input[type="text"]').tooltipster({
trigger: 'custom', // default is 'hover' which is no good here
onlyOne: false, // allow multiple tips to be open on the page
position: 'right'
});
And then separately initialize another ToolTipster instance on the parent container for the hints...
$('input[type="text"]').parent().tooltipster();
(I'm being more specific with the target here. By targeting only input, you would also match the type="submit" element.)
Proof-of-concept DEMO: http://jsfiddle.net/2xgcyg6w/
Well, I achieved exactly what I needed using the errorPlacement and success as Sparky recommended, I kind of mixed what I did with his example:
$(document).ready(function () {
// initialize tooltipster on text input elements
$('input').tooltipster({position: 'top'});
var tooltipsterErrorMsg = [];
// initialize validate plugin on the form
$('#myform').validate({
errorPlacement: function (error, element) {
if ($(element).index() === tooltipsterErrorMsg.length) {
var tooltipObject = $(element).tooltipster({
trigger: 'custom',
multiple: true,
position: 'bottom'
});
tooltipsterErrorMsg.push(tooltipObject[0]);
}
tooltipsterErrorMsg[$(element).index()].content($(error).text()).show();
},
success: function (label, element) {
tooltipsterErrorMsg[$(element).index()].hide();
},
submitHandler: function (form) { // for demo
alert('valid form');
return false;
}
});
});
#myform {
margin: 100px;
}
input {
margin: 20px;
}
a {
display: block;
position: absolute;
bottom: 0;
}
.error {
color: #900;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tooltipster/3.3.0/css/tooltipster.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tooltipster/3.3.0/js/jquery.tooltipster.min.js"></script>
<form id="myform">
<input type="text" name="field1" title="Tooltip teste 1" data-rule-required="true" data-rule-email="true" />
<input type="text" name="field2" title="Tooltip teste 2" data-rule-required="true" data-rule-minlength="5" />
<br/>
<input type="submit" />
</form>
In the jsfiddle link given below, there are 2 buttons and a tooltip is displayed on clicking of any one of them. I want the button inside the tooltip to change the display and other attributes of the "delete" text and "input text"(make the text field editable) The problem is that the value does update but still the text does not become editable" Please suggest a solution to the problem
JSFIDDLE
HTML
<button id="gear">Gear</button>
<button id="gear1">Gear</button>
<div style="display:none;" id="menu">
<button class="menuitem">Rename</button><br>
<input type= "text" id = "try" readonly = "true"><br>
<div id = "delete" style = "display: block">Delete</div><br>
</div>
JavaScript
$(function() {
$("#gear").button({
icons: {
primary: "ui-icon-gear",
secondary: "ui-icon-triangle-1-s"
},
text: false
}).qtip({
content: {
text: $('#menu')
},
show: {
event: 'click',
solo: true,
modal: true
},
style: {
classes: 'ui-tooltip-dark ui-tooltip-shadow'
},
position: {
my: 'top center',
at: 'bottom center',
}
});
$("#gear1").button({
icons: {
primary: "ui-icon-gear",
secondary: "ui-icon-triangle-1-s"
},
text: false
}).qtip({
content: {
text: $('#menu')
},
show: {
event: 'click',
solo: true,
modal: true
},
style: {
classes: 'ui-tooltip-dark ui-tooltip-shadow'
},
position: {
my: 'top center',
at: 'bottom center',
}
});
$(".menuitem").click(function(){
document.getElementbyId("try").readOnly = false;
document.getElementbyId("delete").style.display = none; alert($(this).text());
});
});
CSS
#gear {
margin:100px;
}
.menuitem {
padding-left: 10px;
padding-right: 10px;
font-size: 9px;
margin-bottom: 3px;
width: 75px;
}
I can suggest you to use jquery selectors:
$(".menuitem").click(function(){
$("#try").attr('readonly', false);
$("#delete").hide();
alert($(this).text());
});
I have an odd problem, that I can find no reference to in SO or otherwise. My grid appears to be working great in all ways except for two critical issues, and two things I would like to do. When replying, I don't expect responses for all concerns, even if you have info for one of them, please post it as an answer. Please see images below for visuals on my problem.
First issue:
Whenever data is placed into ANY field of an empty row and tab is clicked a new row is generated. I only want this behaviour if the selected cell is in the last column of this row
Second issue:
Whenever a new row is added that extends past the edge of my defined div, and the vertical scrollbar appears,an additional non-selectable column is added which creates a horizontal scrollbar at the bottom of my grid. This bar hides part of the bottom row. How do I prevent this horizontal bar from appearing.
Third request:
When the grid creates a new row, how to I validate to ensure each cell in the current last row has data in it before allowing the tab effect to add the new row.
Final request:
After clicking a cell and it receives focus, it cannot lose focus unless another cell is selected. I need to lose focus if user clicks on anything outside of the grid.
Showing adding of new row even though not all cells filled, and selector is in first cell
Showing issues presented by bottom scrollbar
HTML
<link type="text/css" rel="stylesheet" href="css/slickGrid/slick.grid.css" />
<link type="text/css" rel="stylesheet" href="css/cupertino/jquery-ui-1.8.20.custom.css" />
<link type="text/css" rel="stylesheet" href="css/slickGrid/slick.grid.darren1.css" />
<form id="myGridForm" action="" method="post">
<div style="position:relative; overflow:visible; margin:25px 0 0 0;">
<div id="loader" style="position:absolute; z-index:997;top: 62px; left:200px;"><img src="images/loading.gif" border="0" /></div>
<div id="dateInput" style="position:relative;z-index:990;visibility:hidden;">
<!-- jQuery DatePicker shows here -->
<p><label for="datepicker">Click to change date:</label><input type="text" id="datepicker" name='datepicker'size="30" readonly="readonly"/></p>
</div>
<div id="myGrid" style="height: 177px; width: 902px; float: left; overflow: hidden; position: relative; visibility: hidden;" >
<!-- #myGrid.slickGrid goes here -->
</div>
</div>
<div class="options-panel" style=" -moz-border-radius: 6px; -webkit-border-radius: 6px; border: 1px solid silver; background: #f0f0f0; padding: 4px; margin: 0 0 220px 0; width: 880px;position: absolute; top: 315px; left: 280px;">
<h2>Instructions:</h2>
<ul>
<li>Select the date by clicking the date image above the table</li>
<li>Enter your event data (you can enter multiple events for that date)</li>
<li>To add another event, hit your <em>TAB</em> key and a new row will be created</li>
<li>When you're all done for this date, click the <em>Commit Changes</em> button to have your events saved to the site</li>
</ul>
<input type="hidden" name="p" id="p" value="<?=$_POST['p']?>" />
<input type="hidden" name="k" id="k" value="<?=$_POST['k']?>" />
<input type="hidden" name="i" id="i" value="<?=$_POST['i']?>" />
<input type="hidden" name="d" id="d" value="<?=$_POST['d']?>" />
<input type="hidden" name="gridData" id="gridData" />
<div id="submitButton" style="visibility:hidden;"> <button type="submit">Commit Changes</button></div>
</div>
</form>
<script>
console.log('json2 Loadstatus: '+json2Loaded);
</script>
<script type="text/javascript" language="javascript" src="js/slickGrid/lib/firebugx.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.20.custom.min.js.php"></script>
<script type="text/javascript" src="js/json2.js.php"></script>
<script src="js/slickGrid/plugins/slick.cellrangedecorator.js"></script>
<script src="js/slickGrid/plugins/slick.cellrangeselector.js"></script>
<script src="js/slickGrid/plugins/slick.cellselectionmodel.js"></script>
<script src="js/slickGrid/slick.formatters.js"></script>
<script src="js/slickGrid/slick.editors.js"></script>
<script src="js/slickGrid/jquery.event.drag-2.0.min.js"></script>
<script src="js/slickGrid/slick.core.js"></script>
<script src="js/slickGrid/slick.grid.js"></script>
<script>
function requiredFieldValidator(value) {
if (value == null || value == undefined || !value.length) {
return {valid: false, msg: "This is a required field"};
} else {
return {valid: true, msg: null};
}
}
var columns = [
{ id: "VisitDate", name: "VisitDate", field: "VisitDate", width: 120, cssClass: "cell-title", editor: Slick.Editors.Text },
{ id: "VisitTime", name: "VisitTime", field: "VisitTime", width: 100, editor: Slick.Editors.Text },
{ id: "PrimaryComplaint", name: "PrimaryComplaint", field: "PrimaryComplaint", width: 100, cssClass: "cell-right", editor: Slick.Editors.Text },
];
var data = [
{
"VisitDate": "11/30/2009",
"VisitTime": "0117",
"PrimaryComplaint": "General malaise "
},
{
"VisitDate": "02/08/2010",
"VisitTime": "0930",
"PrimaryComplaint": "General malaise "
}
];
var options = {
editable: true,
enableAddRow: true,
enableCellNavigation: true,
asyncEditorLoading: false,
forceFitColumns: true
};
var grid = new Slick.Grid("#myGrid", data, columns, options);
grid.onAddNewRow.subscribe(function (e, args) {
var item = args.item;
grid.invalidateRow(data.length);
data.push(item);
grid.updateRowCount();
grid.render();
});
$('#loader').hide();
$('#dateInput').css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0},"slow");
$('#myGrid').css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0},"slow");
$('#submitButton').css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0},"slow");
$.getScript("js/jquery.calendarPicker.js");
$.getScript("js/jquery.json-2.3.min.js");
</script>
<script>
console.log('json2 Loadstatus: '+json2Loaded);
</script>
<? //Instantiate datepicker jQueryUI widget ?>
<script>
$(document).ready(function(){
$(function() {
$( "#datepicker" ).datepicker({ numberOfMonths: [1, 3] });
$( "#datepicker" ).datepicker( "option", "showAnim", "clip");
$( ".selector" ).datepicker( "option", "showOn", "both" );
}); // end function()
}); // end doc.ready
$('#myGridForm').submit(function() {
console.log ( ' myGrid data1: '+ $('grid').data() );
console.log ( ' myGrid data2: '+ $('#myGrid').data() );
var datum = $('#myGrid').data();
console.log ( ' myGrid data3: '+ $('datum').serialize() );
console.log ( ' myGrid data4: '+ JSON.stringify(data) );
$("input[name='gridData']").val(JSON.stringify(data));
// stops submit /ie. return false;
});
</script>