Related
I would like to have the built-in functionality of having a text input (in the middle of other text inputs) be checked and flagged (i.e. the default red marquee applied around the text box) to make sure it is populated before the user clicks the form submit button, without including that value in the form submission. Basically, I don't want to send the retyped password with the form, but it of course needs to be filled in (and will be checked client-side). Is there a "simple" way to do this?
Here is a very minimal example of what you want.
You can do this type of logic using JavaScript events like onblur, onfocus, onchange, etc.
Here is an example showing you how you can validate that a field has a value in it.
var validate = function(element) {
// element is HTMLInputElement
if (element.value == "") {
element.className = "border-red";
} else {
element.className = "";
}
}
.red {
color: red;
}
.border-red {
border: 2px solid red;
}
<form>
Required: <input type="text" name="required_field" onblur="validate(this)" />
Optional: <input type="text" name="optional" />
</form>
I have a main div (parent) with a input (child) and 2 other child div (clickable).
I want to capture focus out event for the main div - not when input or other 2 clickable div are clicked or focused. I have set up an event handler using jQuery to capture focusin focusout events on all the elements.
What I see is when I click on the input:
first input is focused
then the main div.
If I click on any other clickable divs
event fires first focusout for input
then main div and then other div gets focus in and main div get focusin.
I don't want main div to loose focus when clicked on other clickable divs.
How can I achieve this? I want to validate the input on lose focus but not when clicked other divs.
So far this is what I have : Fiddle
HTML :
<div id="main">
<input id="i" type="text" />
<div id="Div2" class="icons" style="background-color:blue; right: 25px;" onclick="log('Clear Clicked');"></div>
<div id="Div1" class="icons" style="background-color:red;" onclick="log('DD Clicked');"></div>
</div>
CSS :
* {
-webkit-box-sizing: border-box;
/* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box;
/* Firefox, other Gecko */
box-sizing: border-box;
/* Opera/IE 8+ */
}
#main {
top: 50px;
left: 200px;
position: absolute;
border: 1px solid #00bfff;
width: 250px;
height: 27px;
}
input {
border: none;
width: 248px;
height: 25px;
position: absolute;
z-index: 200;
}
.icons {
text-align:center;
border:1px solid blue;
height: 23px;
width: 23px;
position: absolute;
top: 2px;
right: 2px;
z-index: 99999999999999999999999;
background-position: center;
background-repeat: no-repeat;
}
jQuery :
$("#main").focusin(function () {
log("Main div got focused");
});
$("#i").focusin(function () {
log("input got focused");
});
$("#Div2").focusin(function () {
log("dropdown div got focused");
});
$("#Div1").focusin(function () {
log("clear div got focused");
});
$("#main").focusout(function () {
log("Main div lost focused");
});
$("#i").focusout(function () {
log("input lost focused");
});
$("#Div2").focusout(function () {
log("dropdown div lost focused");
});
$("#Div1").focusout(function () {
log("clear div lost focused");
});
function log(msg) {
//window.console.log(msg);
$("body").append("<p>" + msg + "</p>");
}
Any help or guidance appreciated
Here is a best way to solve, because I had the same problem too ^_^
There is a attr of event: "relatedTarget"
relatedTarget will provide the next element of this event
So, if next element is not your box OR anything inside your box, trigger focus out.
But FIRST you have to let your <div> element focusable, you have to add tabindex='-1' on div like this
<div id="main" tabindex='-1'>
the script is short:
$("#main, #main *").blur(function(e){
if(!$(e.relatedTarget).is("#main, #main *")){
//focus out.
}
});
The focus will lost and get inside #main, but you can do anything when the focus is lost from #main area.
This is a little different to your request, but I guess this may be what you want.
If this is, the code would be very clean.
Based on this accepted answer Is there a way to use event.preventDefault with focusOut? If not, why?
$(document).on('mousedown', function (event) {
target = event.target;
main = document.getElementById("main");
input = document.getElementById("i");
if (target == input) return true;
parent = event.target.parentNode;
if (parent == main) {
event.preventDefault(); //prevent default DOM action
event.stopPropagation(); //stop bubbling
return false; // return
}
});
OK, so it looks like you are constructing some sort of input widget. I see that the #main div is the outer container of the widget, the input is for entering text, and then you have two other divs serving as buttons or something. You want to validate the value of the input when the user tries to exit the widget, and you are trying to capture this event by listening for focusout on #main. This won't work because a div isn't an element that can receive focus. See the answer here for more.
I can prove to you that your div isn't focusable with a little experiment:
If you put e.stopPropagation() in both your focusin and focusout listeners for your input, you'll see that your main div is never actually focused or unfocused itself; it was just receiving the focusin and focusup events as they bubbled up the DOM tree from your input.
So, this means we have to tackle your problem from another angle.
Let's describe what it means for your widget to lose focus with a short user story:
User clicks on the input/#main/#Div1/#Div2 -- widget gains focus
User clicks on input (if he/she hasn't already) and types some text -- widget focus is not lost
User clicks somewhere on #main -- widget focus is not lost
User clicks #Div1 and then #Div2 -- widget focus is not lost
User clicks somewhere else on the page -- widget focus is lost -> validation runs
We now know exactly which events during which states should cause validation to run.
First, let's keep track of the 'focus' state of the widget with a boolean variable:
var isFocused = false;
The widget starts out in the unfocused state and becomes focused when there is a click anywhere in #main or its children OR when the input is somehow focused (could be via tabbed-into with the keyboard):
$("#main").on('click',function(){
isFocused = true;
});
$("#i").on('focus',function(){
isFocused = true;
});
The only time the widget becomes unfocused is when a) it's focused and b) the user clicks somewhere else on the page:
$(document).on('click',function(){
if(isFocused){
isFocused = false;
//kick-off the validation check!
}
});
But since all events bubble-up the DOM tree by default, multiple clicks within #main will bubble up to document.body and trigger a validation check. To prevent this, we call stopPropagation on the click event in the #main's click handler:
$("#main").on('click',function(e){
isFocused = true;
e.stopPropagation();
});
That's it!
I hope I was correct about what you're after.
Here's a working fiddle with above code.
Here is simple way to do it (As far as i understood)
$('#Div1').click(function(){
log('Clear Clicked');
//$('#main').focusin();
$('#i').focus();
});
$('#Div2').click(function(){
log('DD Clicked');
//$('#main').focusin();
$('#i').focus();
});
here is fiddle
The other way to workaround is to add a small setTimeout before running focusout handler.
You can easily whitelist a list of elements to exclude with and clearTimeout when they get focusin.
I am doing a phonegap app. When I am trying type="date" input field as shown below, it shows date picker in iPhone as I expected but it doesn't show the placeholder I have given. I found the same issue here in SO, but no solution anywhere.
<input placeholder="Date" class="textbox-n" type="date" id="date">
It may not be appropriate... but it helped me.
What I did is start with a text input field, then change the type to a date input when the input is in focus.
<input
placeholder="Date"
class="textbox-n"
type="text"
onfocus="(this.type='date')"
id="date" />
If you use mvp's method but add the onblur event to change it back to a text field so the placeholder text appears again when the input field looses focus. It just makes the hack a little bit nicer.
<input placeholder="Date" class="textbox-n" type="text" onfocus="(this.type='date')" onblur="(this.type='text')" id="date" />
I ended up using the following.
Regarding Firefox comment(s): Generally, Firefox will not show any text placeholder for inputs type date.
But as this is a Cordova/PhoneGap question this should be of no concern (Unless you want to develop against FirefoxOS).
input[type="date"]:not(.has-value):before{
color: lightgray;
content: attr(placeholder);
}
<input type="date" placeholder="MY PLACEHOLDER" onchange="this.className=(this.value!=''?'has-value':'')">
As of today (2016), I have successfully used those 2 snippets (plus they work great with Bootstrap4).
Input data on the left, placeholder on the left
input[type=date] {
text-align: right;
}
input[type="date"]:before {
color: lightgrey;
content: attr(placeholder) !important;
margin-right: 0.5em;
}
Placeholder disappear when clicking
input[type="date"]:before {
color: lightgrey;
content: attr(placeholder) !important;
margin-right: 0.5em;
}
input[type="date"]:focus:before {
content: '' !important;
}
I used this in my css:
input[type="date"]:before{
color:lightgray;
content:attr(placeholder);
}
input[type="date"].full:before {
color:black;
content:""!important;
}
and put somenthing like this into javascript:
$("#myel").on("input",function(){
if($(this).val().length>0){
$(this).addClass("full");
}
else{
$(this).removeClass("full");
}
});
it works for me for mobile devices (Ios8 and android). But I used jquery inputmask for desktop with input text type. This solution it's a nice way if your code run on ie8.
Based on deadproxor and Alessio answers, I would try only using CSS:
input[type="date"]::before{
color: #999;
content: attr(placeholder) ": ";
}
input[type="date"]:focus::before {
content: "" !important;
}
And if you need to make the placeholder invisible after writing something in the input, we could try using the :valid and :invalid selectors, if your input is a required one.
EDIT
Here the code if you are using required in your input:
input[type="date"]::before {
color: #999999;
content: attr(placeholder);
}
input[type="date"] {
color: #ffffff;
}
input[type="date"]:focus,
input[type="date"]:valid {
color: #666666;
}
input[type="date"]:focus::before,
input[type="date"]:valid::before {
content: "" !important;
}
<input type="date" placeholder="Date" required>
I took jbarlow idea, but I added an if in the onblur function so the fields only change its type if the value is empty
<input placeholder="Date" class="textbox-n" type="text" onfocus="(this.type='date')" onblur="(this.value == '' ? this.type='text' : this.type='date')" id="date">
According to the HTML standard:
The following content attributes must not be specified and do not apply to the element: accept, alt, checked, dirname, formaction, formenctype, formmethod, formnovalidate, formtarget, height, inputmode, maxlength, minlength, multiple, pattern, placeholder, size, src, and width.
It works for me:
input[type='date']:after {
content: attr(placeholder)
}
I used this whit jQuery:
http://jsfiddle.net/daviderussoabram/65w1qhLz/
$('input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="time"], input[type="week"]').each(function() {
var el = this, type = $(el).attr('type');
if ($(el).val() == '') $(el).attr('type', 'text');
$(el).focus(function() {
$(el).attr('type', type);
el.click();
});
$(el).blur(function() {
if ($(el).val() == '') $(el).attr('type', 'text');
});
});
Found a better way to solve your problem.
I think this will help you. when focused out, the box will change type into text so it will show your placeholder. when focused in, its type changes into date so the calendar view will be shown.
<input placeholder="Date" class="textbox-n" type="text" onfocusin="(this.type='date')" onfocusout="(this.type='text')" id="date">
<input placeholder="01-01-2021" class="textbox-n" type="text" onfocus="(this.type='date')" onblur="(this.type='text')" id="date" />
Adressing the problem in the current correct answer "clicking the field shows the onscreen keyboard instead of the datepicker":
The problem is caused by the Browser behaving according to the type of input when clicking (=text). Therefore it is necessary to stop from focussing on the input element (blur) and then restart focus programmatically on the input element which was defined as type=date by JS in the first step. Keyboard displays in phonenumber-mode.
<input placeholder="Date" type="text" onfocus="this.type='date';
this.setAttribute('onfocus','');this.blur();this.focus();">
To summarize the date inputs problem:
You have to display them (i.e. avoid display:none) otherwise the input UI will not be triggered ;
a placeholder is contradictory with them (as per the spec, and because they have to display a specific UI) ;
converting them to another input type for the unfocused time do allows placeholders, but focus then triggers the wrong input UI (keyboard), at least for a small time, because focus events cannot be cancelled.
inserting (before) or adding (after) content doesn't prevent the date input value to be displayed.
The solution I found to meet those requirements is to use the usual trick to style native form elements : ensure the element is displayed but not visible, and display its expected style through its associated label. Typically, the label will display as the input (including a placeholder), but over it.
So, an HTML like:
<div class="date-input>
<input id="myInput" type="date">
<label for="myInput">
<span class="place-holder">Enter a date</span>
</label>
</div>
Could be styled as:
.date-input {
display: inline-block;
position: relative;
}
/* Fields overriding */
input[type=date] + label {
position: absolute; /* Same origin as the input, to display over it */
background: white; /* Opaque background to hide the input behind */
left: 0; /* Start at same x coordinate */
}
/* Common input styling */
input[type=date], label {
/* Must share same size to display properly (focus, etc.) */
width: 15em;
height: 1em;
font-size: 1em;
}
Any event (click, focus) on such an associated label will be reflected on the field itself, and so trigger the date input UI.
Should you want to test such a solution live, you can run this Angular version from your tablet or mobile.
try my solution. I use 'required' attribute to get know whether input is filled and if not I show the text from attribute 'placeholder'
//HTML
<input required placeholder="Date" class="textbox-n" type="date" id="date">
//CSS
input[type="date"]:not(:valid):before {
content: attr(placeholder);
// style it like it real placeholder
}
Took me a while figuring this one out, leave it as type="text", and add onfocus="(this.type='date')", just as shown above.
I even like the onBlur idea mentioned above
<input placeholder="Date" class="textbox-n" type="text" onfocus="(this.type='date')" onblur="(this.type='text')" id="date">
Hope this helps anyone who didn't quite gather whats going on above
SO what i have decided to do finally is here and its working fine on all mobile browsers including iPhones and Androids.
$(document).ready(function(){
$('input[type="date"]').each(function(e) {
var $el = $(this),
$this_placeholder = $(this).closest('label').find('.custom-placeholder');
$el.on('change',function(){
if($el.val()){
$this_placeholder.text('');
}else {
$this_placeholder.text($el.attr('placeholder'));
}
});
});
});
label {
position: relative;
}
.custom-placeholder {
#font > .proxima-nova-light(26px,40px);
position: absolute;
top: 0;
left: 0;
z-index: 10;
color: #999;
}
<label>
<input type="date" placeholder="Date">
<span class="custom-placeholder">Date</span>
</label>
Date
Im working with ionicframework and solution provided by #Mumthezir is almost perfect. In case if somebody would have same problem as me(after change, input is still focused and when scrolling, value simply dissapears) So I added onchange to make input.blur()
<input placeholder="Date" class="textbox-n" type="text" onfocus=" (this.type='date')" onchange="this.blur();" id="date">
You can
set it as type text
convert to date on focus
make click on it
...let user check date
on change store the value
set input to type text
set text type input value to the stored value
like this...
$("#dateplaceholder").change(function(evt) {
var date = new Date($("#dateplaceholder").val());
$("#dateplaceholder").attr("type", "text");
$("#dateplaceholder").val(date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear());
});
$("#dateplaceholder").focus(function(evt) {
$("#dateplaceholder").attr("type", "date");
setTimeout('$("#dateplaceholder").click();', 500);
});
$("#dateplaceholder").attr("type", "text");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<input type="date" id="dateplaceholder" placeholder="Set the date" />
Found a better way to handle user basic comprehension with mouseover and opening datepicker on click :
<input type="text" onfocus="(this.type='date')" onmouseover="(this.type = 'date')" onblur="(this.value ? this.type = 'date' : this.type = 'text')" id="date_start" placeholder="Date">
Also hide webkit arrow and make it 100% wide to cover the click :
input[type="date"] {
position: relative;
}
input[type="date"]::-webkit-calendar-picker-indicator {
position: absolute;
height: 100%;
width: 100%;
opacity: 0;
left: 0;
right: 0;
top:0;
bottom: 0;
}
Expanding on #mvp's solution with unobtrusive javascript in mind, here's the approach:
HTML:
<input type="text" placeholder="Date" class="js-text-date-toggle">
Javascript:
$('.js-text-date-toggle').on('focus', function() {
$(this).attr('type', 'date');
}).on('blur', function() {
$(this).attr('type', 'text');
});
I think all you have to do is change the model to say the date field is nullable and then put [Required] on it if it is required. If you do this the placeholder text does appear.
Hey so I ran into the same issue last night and figured out a combination of all of your answer and some sparkling magic are doing a good job:
The HTML:
<input type="date" name="flb5" placeholder="Datum" class="datePickerPlaceHolder"/>
The CSS:
#media(max-width: 1024px) {
input.datePickerPlaceHolder:before {
color: #A5A5A5; //here you have to match the placeholder color of other inputs
content: attr(placeholder) !important;
}
}
The jQuery:
$(document).ready(function() {
$('input[type="date"]').change(function(){
if($(this).val().length < 1) {
$(this).addClass('datePickerPlaceHolder');
} else {
$(this).removeClass('datePickerPlaceHolder');
}
});
});
Explanation:
So, what is happening here, first of all in the HTML, this is pretty straight forward just doing a basic HMTL5-date-input and set a placeholder.
Next stop: CSS, we are setting a :before-pseudo-element to fake our placeholder, it just takes the placeholder's attribute from the input itself. I made this only available down from a viewport width of 1024px - why im going to tell later.
And now the jQuery, after refactoring a couple of times I came up with this bit of code which will check on every change if there is a value set or not, if its not it will (re-)add the class, vice-versa.
KNOW ISSUES:
there is a problem in chrome with its default date-picker, thats what the media-query is for. It will add the placeholder infront of the default 'dd.mm.yyyy'-thing. You could also set the placeholder of the date-input to 'date: ' and adjust the color incase of no value inside the input...for me this resulted in some other smaller issues so i went with just not showing it on 'bigger' screens
hope that helps!
cheerio!
From Angular point of view I managed to put a placeholder in input type date element.
First of all I defined the following css:
.placeholder {
color: $text-grey;
}
input[type='date']::before {
content: attr(placeholder);
}
input::-webkit-input-placeholder {
color: $text-grey;
}
The reason why this is neccessary is that if css3 content has different color that the normal placeholder, so I had to use a common one.
<input #birthDate
class="birthDate placeholder"
type="date"
formControlName="birthDate"
placeholder="{{getBirthDatePlaceholder() | translate}}"
[class.error]="!onboardingForm.controls.birthDate.valid && onboardingForm.controls.birthDate.dirty"
autocomplete="off"
>
Then in the template used a viewchild birthDate attribute, to be able to access this input from the component. And defined an angular expression on the placeholder attribute, which will decide if we show the placeholder or not. This is the major drawback of the solution, is that you have to manage the visibility of the placeholder.
#ViewChild('birthDate') birthDate;
getBirthDatePlaceholder() {
if (!this.birthDate) {
return;
} else {
return this.birthDate.nativeElement.value === '' ?
'ONBOARDING_FORM_COMPONENT.HINT_BIRTH_DATE' :
'';
}
}
<input placeholder="Date" type="text" onMouseOver="(this.type='date')" onMouseOut="(this.type='text')" id="date" class="form-control">
Revised code of mumthezir
If you're only concerned with mobile:
input[type="date"]:invalid:before{
color: rgb(117, 117, 117);
content: attr(placeholder);
}
I'm surprised there's only one answer with an approach similar to the one I used.
I got the inspiration from #Dtipson's comment on #Mumthezir VP's answer.
I use two inputs for this, one is a fake input with type="text" on which I set the placeholder, the other one is the real field with type="date".
On the mouseenter event on their container, I hide the fake input and show the real one, and I do the opposite on the mouseleave event. Obviously, I leave the real input visibile if it has a value set on it.
I wrote the code to use pure Javascript but if you use jQuery (I do) it's very easy to "convert" it.
// "isMobile" function taken from this reply:
// https://stackoverflow.com/a/20293441/3514976
function isMobile() {
try { document.createEvent("TouchEvent"); return true; }
catch(e) { return false; }
}
var deviceIsMobile = isMobile();
function mouseEnterListener(event) {
var realDate = this.querySelector('.real-date');
// if it has a value it's already visible.
if(!realDate.value) {
this.querySelector('.fake-date').style.display = 'none';
realDate.style.display = 'block';
}
}
function mouseLeaveListener(event) {
var realDate = this.querySelector('.real-date');
// hide it if it doesn't have focus (except
// on mobile devices) and has no value.
if((deviceIsMobile || document.activeElement !== realDate) && !realDate.value) {
realDate.style.display = 'none';
this.querySelector('.fake-date').style.display = 'block';
}
}
function fakeFieldActionListener(event) {
event.preventDefault();
this.parentElement.dispatchEvent(new Event('mouseenter'));
var realDate = this.parentElement.querySelector('.real-date');
// to open the datepicker on mobile devices
// I need to focus and then click on the field.
realDate.focus();
realDate.click();
}
var containers = document.getElementsByClassName('date-container');
for(var i = 0; i < containers.length; ++i) {
var container = containers[i];
container.addEventListener('mouseenter', mouseEnterListener);
container.addEventListener('mouseleave', mouseLeaveListener);
var fakeDate = container.querySelector('.fake-date');
// for mobile devices, clicking (tapping)
// on the fake input must show the real one.
fakeDate.addEventListener('click', fakeFieldActionListener);
// let's also listen to the "focus" event
// in case it's selected using a keyboard.
fakeDate.addEventListener('focus', fakeFieldActionListener);
var realDate = container.querySelector('.real-date');
// trigger the "mouseleave" event on the
// container when the value changes.
realDate.addEventListener('change', function() {
container.dispatchEvent(new Event('mouseleave'));
});
// also trigger the "mouseleave" event on
// the container when the input loses focus.
realDate.addEventListener('blur', function() {
container.dispatchEvent(new Event('mouseleave'));
});
}
.real-date {
display: none;
}
/* a simple example of css to make
them look like it's the same element */
.real-date,
.fake-date {
width: 200px;
height: 20px;
padding: 0px;
}
<div class="date-container">
<input type="text" class="fake-date" placeholder="Insert date">
<input type="date" class="real-date">
</div>
I tested this also on an Android phone and it works, when the user taps on the field the datepicker is shown. The only thing is, if the real input had no value and the user closes the datepicker without choosing a date, the input will remain visible until they tap outside of it. There's no event to listen to to know when the datepicker closes so I don't know how to solve that.
I don't have an iOS device to test it on.
This might help in some situation.
<input type="text" id="date" onclick="this.type='date'" onblur="this.type='text'" placeholder="Date" class="textbox-n" name="myDate" />
HTML:
<div>
<input class="ui-btn ui-btn-icon-right ui-corner-all ui-icon-calendar ui-shadow" id="inputDate" type="date"/>
<h3 id="placeholder-inputDate">Date Text</h3>
</div>
JavaScript:
$('#inputDate').ready(function () {
$('#placeholder-inputDate').attr('style'
, 'top: ' + ($('#placeholder-inputDate').parent().position().top + 10)
+ 'px; left: ' + ($('#placeholder-inputDate').parent().position().left + 0) + 'px; position: absolute;');
$('#inputDate').attr('style'
, 'width: ' + ($('#placeholder-inputDate').width() + 32) + 'px;');
});
Here is another possible hack not using js and still using css content. Note that as :after is not supported on some browser for inputs, we need to select the input in another way, same for content attr('')
input[type=date]:invalid+span:after {
content:"Birthday";
position:absolute;
left:0;
top:0;
}
input[type=date]:focus:invalid+span:after {
display:none;
}
input:not(:focus):invalid {
color:transparent;
}
label.wrapper {
position:relative;
}
<label class="wrapper">
<input
type="date"
required="required"
/>
<span></span>
</label>
I have no idea what this is even called so not sure where to start, hoping you all are able to point me in the right direction. I am trying to create something like this:
The idea being that when a user types something in and then separates with a comma, their input into this form field will turn into a little tag-like box that they can then delete with the x.
Any ideas on where to start?
Thanks!
Here is simple example: http://jsfiddle.net/9tzb4/
HTML:
<form>
Tags:
<div class="tag_field">
<input type="text">
<input type="hidden" name="tags">
</div>
<br>
<input type="submit" value="Submit">
</form>
CSS:
.tag_buttons {
position: absolute;
}
.tag_buttons div {
display:inline-block;
margin: 2px;
border: 1px solid #666;
padding: 1px;
}
.tag_field input[type=text] {
padding: 5px;
width: 300px;
border: 1px solid #666;
}
JavaScript:
$(".tag_field").each(function() {
var buttons = $("<div/>");
var input = $(this).find("input[type=text]");
var output = $(this).find("input[type=hidden]");
var update_padding = function() {
input.css("padding-left", buttons.width() + 2);
};
setInterval(update_padding, 300);
$(this).prepend(buttons);
buttons.addClass("tag_buttons");
buttons.css({ left: input.offset().left + 1,
top: input.offset().top + 2 });
input.bind("keyup change paste", function() {
var i = input.val().indexOf(",");
if (i >= 0) {
var new_tag = input.val().substr(0, i);
input.val(input.val().substr(i+1));
buttons.append("<div id='button'><span class='value'>"+new_tag+"</span> <span class='close'>(x)</span></div>");
}
});
var form = $(this).closest("form");
if (form.length > 0) {
form.submit(function() {
var v = [];
form.find(".tag_buttons div").each(function() {
v.push($(this).find(".value").html());
});
output.val(v.join(","));
return false;
});
}
});
$(document).on("click", ".tag_buttons span.close", {}, function(e) {
$(e.target).closest("div").detach();
});
Check this out. http://davidwalsh.name/dw-content/jquery-chosen.php This is the things I guess will perfectly suite your application.
Check out the amazing jQuery chosen, which - among other things - does exactly what you're looking for.
select2 is a similar plugin, and it also allows you to add your own tags (as well as use an AJAX source).
Update from the select2 docs:
Note that when tagging is enabled the user can select from pre-existing tags or create a new tag by picking the first choice which is what the user has typed into the search box so far.
You may find the jQuery Tags Input Library helpful. It gives you something like this
I recently discovered that the :invalid pseudo-class applies to required form elements as soon as the page loads. For example, if you have this code:
<style>
input:invalid { background-color: pink; color: white; }
input:valid { background-color: white; color: black; }
</style>
…
<input name="foo" required />
Then your page will load with an empty pink input element on it. Having validation built in to HTML5 is great, but I don't think most users expect the form to validate before they've had a chance to enter any values at all. Is there any way to delay the application of the pseudo-class until the first event affecting that element (form submit, blur, change, whatever's appropriate)? Is it possible to do this without JavaScript?
http://www.alistapart.com/articles/forward-thinking-form-validation/
Since we only want to denote that a field is invalid once it has
focus, we use the focus pseudo-class to trigger the invalid styling.
(Naturally, flagging all required fields as invalid from the start
would be a poor design choice.)
Following this logic, your code would look something like this...
<style>
input:focus:required:invalid {background-color: pink; color: white;}
input:required:valid {background-color: white; color: black; }
</style>
Created a fiddle here: http://jsfiddle.net/tbERP/
As you'd guess, and as you'll see from the fiddle, this technique only shows the validation styling when the element has focus. As soon as you move focus off, the styling is dropped, regardless of whether it is valid or not. Not ideal by any means.
These answers are out of date. Now you can do this by checking for a placeholder pseudo-class with CSS.
input:not(:placeholder-shown):invalid {
background-color: salmon;
}
form:invalid button {
background-color: salmon;
pointer-events: none;
}
<form>
<input type="email" placeholder="me#example.com" required>
<button type="submit">Submit</button>
</form>
It starts with a normal background and turns pink as you enter you incomplete email address into it.
This is not possible in pure CSS, but can be done with JavaScript. This is a jQuery example:
// use $.fn.one here to fire the event only once.
$(':required').one('blur keydown', function() {
console.log('touched', this);
$(this).addClass('touched');
});
/**
* All required inputs initially are yellow.
*/
:required {
background-color: lightyellow;
}
/**
* If a required input has been touched and is valid, it should be white.
*/
.touched:required:valid {
background-color: white;
}
/**
* If a required input has been touched and is invalid, it should be pink.
*/
.touched:required:invalid {
background-color: pink;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
<label>
Name:
<input type="text" required> *required
</label>
</p>
<p>
<label>Age:
<input type="text">
</label>
</p>
This is a VanillaJS (no jQuery) version of kzh's answer
{
let f = function() {
this.classList.add('touched')
}
document
.querySelectorAll('input')
.forEach((e) => {
e.addEventListener('blur', f, false)
e.addEventListener('keydown', f, false)
})
}
/**
* All required inputs initially are yellow.
*/
:required {
background-color: lightyellow;
}
/**
* If a required input has been touched and is valid, it should be white.
*/
.touched:required:valid {
background-color: white;
}
/**
* If a required input has been touched and is invalid, it should be pink.
*/
.touched:required:invalid {
background-color: pink;
}
<p><label>
Name:
<input type="text" required> *required
</label></p>
<p><label>Age:
<input type="text">
</label></p>
Mozilla takes care of this with its own :-moz-ui-invalid pseudoclass that only applies to forms after they've been interacted with. MDN does not recommend using this due to a lack of support. However, you can modify it for Firefox.
There's a level 4 spec for a :user-invalid spec on the horizon that will offer similar behavior.
I created a small shim to deal with this in my codebase. I just start off with my <form/> element having the novalidate property along with a data-validate-on="blur" attribute. This watches for the first event of that type. This way you can still use the native :invalid css selectors for the form styling.
$(function () {
$('[data-validate-on]').each(function () {
var $form = $(this);
var event_name = $form.data('validate-on');
$form.one(event_name, ':input', function (event) {
$form.removeAttr('novalidate');
});
});
});
There is a html5 invalid event that fires on form elements before the submit event occurs for each element that does not pass checkValidity. You can use this event to apply a class for example to the surrounding form and display :invalid styles only after this event occurs.
$("form input, form select, form textarea").on("invalid", function() {
$(this).closest('form').addClass('invalid');
});
Your CSS would then look something like this:
:invalid { box-shadow: none; }
.invalid input:invalid,
.invalid textarea:invalid,
.invalid select:invalid { border: 1px solid #A90909 !important; background-color: #EEC2C2; }
The first line removes the default styling, so form elements look neutral at page load. As soon as the invalid event fires (when a user tries to submit the form), the elements are visibly rendered invalid.
You could make it so that only elements that have a certain class on them and are required, are pink. Add an event handler to each required element that adds that class when you leave the element.
Something like:
<style>
input.touched:invalid { background-color: pink; color: white; }
input.touched:valid { background-color: white; color: black; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
var required = document.querySelectorAll('input:required');
for (var i = 0; i < required.length; ++i) {
(function(elem) {
function removeClass(name) {
if (elem.classList) elem.classList.remove(name);
else
elem.className = elem.className.replace(
RegExp('(^|\\s)\\s*' + name + '(?:\\s+|$)'),
function (match, leading) {return leading;}
);
}
function addClass(name) {
removeClass(name);
if (elem.classList) elem.classList.add(name);
else elem.className += ' ' + name;
}
// If you require a class, and you use JS to add it, you end up
// not showing pink at all if JS is disabled.
// One workaround is to have the class on all your elements anyway,
// and remove it when you set up proper validation.
// The main problem with that is that without JS, you see what you're
// already seeing, and stuff looks hideous.
// Unfortunately, you kinda have to pick one or the other.
// Let non-blank elements stay "touched", if they are already,
// so other stuff can make the element :invalid if need be
if (elem.value == '') addClass('touched');
elem.addEventListener('blur', function() {
addClass('touched');
});
// Oh, and when the form submits, they need to know about everything
if (elem.form) {
elem.form.addEventListener('submit', function() {
addClass('touched');
});
};
})(required[i]);
}
});
</script>
And of course, it won't work as is in IE8 or below, as (a) DOMContentLoaded is relatively new and wasn't standard when IE8 came out, (b) IE8 uses attachEvent rather than the DOM-standard addEventListener, and (c) IE8 isn't going to care about :required anyway, as it doesn't technically support HTML 5.
While using HTML5 form validation, try to use the browser to detect for invalid submissions/fields, rather than re-inventing the wheel.
Listen for the invalid event to add a class of 'invalid' to your form. With the 'invalid' class added, you can go to town with styling your form using CSS3 :pseudo selectors.
For example:
// where myformid is the ID of your form
var myForm = document.forms.myformid;
var checkCustomValidity = function(field, msg) {
if('setCustomValidity' in field) {
field.setCustomValidity(msg);
} else {
field.validationMessage = msg;
}
};
var validateForm = function() {
// here, we're testing the field with an ID of 'name'
checkCustomValidity(myForm.name, '');
if(myForm.name.value.length < 4) {
checkCustomValidity(
// alerts fields error message response
myForm.name, 'Please enter a valid Full Name, here.'
);
}
};
/* here, we are handling your question above, by adding an invalid
class to the form if it returns invalid. Below, you'll notice
our attached listener for a form state of invalid */
var styleInvalidForm = function() {
myForm.className = myForm.className += ' invalid';
}
myForm.addEventListener('input', validateForm, false);
myForm.addEventListener('keyup', validateForm, false);
myForm.addEventListener('invalid', styleInvalidForm, true);
Now, simply style your form as you see fit based on the 'invalid' class we've attached.
For example:
form.invalid input:invalid,
form.invalid textarea:invalid {
background: rgba(255, 0, 0, .05);
border-color: #ff6d6d;
-webkit-box-shadow: 0 0 6px rgba(255, 0, 0, .35);
box-shadow: 0 0 6px rgba(255, 0, 0, .35);
}
A good way is to abstract :invalid, :valid with a CSS classes and then some JavaScript to check if the input field was focused or not.
CSS:
input.dirty:invalid{ color: red; }
input.dirty:valid{ color: green; }
JS:
// Function to add class to target element
function makeDirty(e){
e.target.classList.toggle('dirty');
}
// get form inputs
var inputs = document.forms[0].elements;
// bind events to all inputs
for(let input of inputs){
input.addEventListener('invalid', makeDirty);
input.addEventListener('blur', makeDirty);
input.addEventListener('valid', makeDirty);
}
DEMO
Following on from agouseh's idea, you can have a bit of javascript to tell when the submit button has been focussed, and have validation show up at that time.
The javascript will add a class (eg. submit-focussed) to the form field when the submit button is focussed or clicked, which then allows the CSS to style invalid inputs.
This follows the best practice of showing validation feedback after the user has finished filling in the fields, as according to research there is no additional benefit to showing it during the process.
document
.querySelector('input[type=submit]')
.onfocus = function() {
this
.closest('form')
.classList
.add('submit-focussed');
};
form.submit-focussed input:invalid {
border: thin solid red;
}
<form>
<label>Email <input type="email" required="" /></label>
<input type="submit" />
</form>
jQuery alternative
(function($) {
$('input[type=submit]').on('focus', function() {
$(this)
.parent('form')
.addClass('submit-focussed');
});
})(jQuery); /* WordPress compatible */
Here is my method to avoid the default styling of any unfocused input as invalid, you just have to add a simple js command onFocus to let the webpage to identify focused and unfocused inputs, so all the input will not appear in the style of invalid at first place.
<style>
input.focused:required:invalid { background-color: pink; color: white; }
input:valid { background-color: white; color: black; }
</style>
…
<input name="foo" class="notfocused" onFocus="document.activeElement.className='focused';" required />
Try it yourself below:
input.focused:required:invalid {
background-color: pink;
color: white;
}
input:required:valid {
background-color: darkseagreen;
color: black;
}
<label>At least 1 charater:</label><br />
<input type="text" name="foo" class="notfocused" onFocus="document.activeElement.className='focused';" required />
I can't comment, but to go with #Carl's very useful answer regarding using :not(:placeholder-shown). As another comment mentioned, this will still show the invalid state if you have NO placeholder (as some form designs call for).
To solve this, simply add an empty placeholder like so
<input type="text" name="username" placeholder=" " required>
Then your CSS, something like
:not(:placeholder-shown):invalid{ background-color: #ff000038; }
Worked for me!