Adding styling to non-input elements during jquery validation - javascript

I am using Jquery validation and a Tag-it plugin that generates UL LIs on the fly for each new tag to be added. If there are no tags, the plugin has only one LI and it is empty. If you create at least one tag, then the plugin creates a second LI. I am using submitHandler and invalidHandler to validate only if there is more than 1 LI, which means there is at least one tag. This works. Here is my fiddle: http://jsfiddle.net/Z3HDh/95/
I need help with two additional things:
When the form fails to validate because no tags have been entered, it writes to the console - "you don't have any tags". It also displays a message, "Add some tags, puhleeeease!" I want it to add the error styling to the background and border of the ul class="tagit ui-widget ui-widget-content ui-corner-all". I have unsuccessfully tried using jquery validation's highlight and addrules functions.
If the field fails to validate (there is no tag, the "Add some tags, puhleeeease!" message appears), and then I put in a tag (which means the field now validates), it will only register the validation and remove the error message if I click submit again. On other fields, the plugin itself validates on the fly and adjusts the styling. So, in this case, as soon as I add the tag, I would like the field to validate successfully and remove the error styling and message, rather than waiting until I re-submit it. I have seen a number of examples of this but also have failed to implement it.
HTML:
<div class="form-group">
<label for="id_title">Add your title here (required)</label>
<input type="text" id="id_title" name="title" maxlength="75" value=""
required data-msg="Please add a title.">
</div><!-- end form-group -->
<div class="form-group">
<label for="id_material">Your tags go here... (required)</label>
<input type="text" id="id_material" name="material" value=""
required data-msg="Add some tags, puhleeeease!">
</div>
<div class="form-group-buttons">
<p class="form_buttons">
Cancel
<button type="submit">Submit</button>
</p>
</div><!-- end form-group-buttons -->
</form>
JS:
$("#id_material").tagit();
$("#add_idea_form").validate({
ignore: "input[name='tags']:hidden",
submitHandler: function (form) {
},
invalidHandler: function(event, validator) {
if($('#id_material + ul').length < 2){
console.log("You don't have any tags");
// return false;
}
}
});
$("li.email > input").rules("add", {
required: true,
email: true
});
CSS:
input.error, td.field input.error, td.field select.error, tr.errorRow td.field, input, tr.errorRow td.field select {
/*background-color: #ffffd5;*/
border:2px solid #d17877;
background: #F2DEDE;
box-shadow: none;
}
#add_idea_form label.error{
color: red;
}

You need to add a delete rule when a tag is entered. The example below will remove the "Add tags please" when a tag is added (after the error was run).
$("#id_material").tagit({
afterTagAdded: function(event, ui) {
$("#id_material-error").remove();
$(".ui-corner-all").removeClass('error');
console.log(ui.tag);
}
});
To add CSS around the tag area, add the following code to your invalid Handler
invalidHandler: function(event, validator) {
if($('#id_material + ul').length < 2){
console.log("You don't have any tags");
$('.ui-corner-all').addClass('error');
}
}
});
It will add a red outline inside the tag input box. If you have multiple tag input boxes, the code may need to be updated to target a specific input.
You'll also need to add the following to your css file
.error{
border:2px solid #d17877;
background: #F2DEDE;
box-shadow: none;
}
.ui-corner-all.error{
background:red;
}
Working example at http://jsfiddle.net/v0jdpkz8/8/

Related

Javascript - Button visible when has content in a input

I would like that when the user inserts information in a specific input text, another element becomes visible. My question looks study, but I'm new on JavaScript world, and I have tried searching on Google and here but I wasn't able to find anything.
Check out my code:
.hide {
display: none;
}
<div>
<label>Password:</label>
<input type="password" id="pwInput">
Show password
</div>
What I want is that the "Show password" anchor only shows when the password input has content inside.
Super simple option... use the input event handler on the <input> to toggle a class on it. You can then use an adjacent-sibling selector in your CSS to show or hide the <a>.
.hide {
display: none;
}
.has-input + .hide {
display: inline;
}
<div>
<label>Password:</label>
<input type="password" id="pwInput"
oninput="this.classList.toggle('has-input', this.value.trim())">
Show password
</div>
If you're not a fan of inline event handlers, this is the unobtrusive equivalent
document.getElementById('pwInput').addEventListener('input', function(e) {
this.classList.toggle('has-input', this.value.trim())
}, false)
Note, the force option on classList.toggle() doesn't work in IE. If you need to support it, try something like
this.classList[this.value.trim() ? 'add' : 'remove']('has-input')
Just do this in JavaScript:
document.addEventListener("keydown", function() {
if (document.getElementById("pwInput").value != "") {
document.querySelector(".hide").style.display = "inline";
}
else {
document.querySelector(".hide").style.display = "none";
}
});
.hide {
display: none;
}
<div>
<label>Password:</label>
<input type="password" id="pwInput">
Show password
</div>
This will check every keydown if the input has any content, plus it'll work both ways e.g. if the user deletes the password then the anchor will go away.

Enter password to display content of div

I'd like to enter the word,PASSWORD and for the content inside HIDDENDIV to display.
Can someone show me where I'm going wrong?
#HIDDENDIV {
display: none;
}
<input type="text" id="password" onkeydown="if (event.keyCode == 13) document.getElementById('button').click()" />
<br/>
<input id="button" type="button" value="Login" onclick="if (document.getElementById('password').value == 'PASSWORD') {
document.getElementById('table').classList.toggle('show'); document.getElementById('passw').style.display='none'; }
else { alert('Invalid Password!'); password.setSelectionRange(0, password.value.length); } " />
<div id="HIDDENDIV">bla</div>
Because you hid the content via an id based CSS selector, adding a "show" CSS class to it later won't override the id rule that you already set. (Read this on how different CSS selectors are more specific than others and thus, more difficult to override.)
Here's a quick example:
#d1 { display:none; } /* Will override most other selectors */
div { display:block; } /* Won't work */
.show { display:block; } /* Won't work */
<p>You aren't going to see the div below this paragraph even though it matches two selectors that indicate that it should be shown and even though those two selectors come after the one that hides it. This is because the way it's being hidden is with an id based selector and tag type and class selectors alone are less specific than an id selector and won't override it.</p>
<div id="d1" class="show">Hello?!</div>
So, first, set the content to be hidden with a CSS class instead of an id based selector, then later, you can just remove that class - no extra "show" class is needed.
Next, in your code you have a div with an id of HIDDENDIV, but your code attempts to get and show an element with an id of table. I'm assuming that this was just a typo when posting this question and that, in reality, you really to have a table to show, but you need to correct that.
Also, you should not be using HTML inline event attributes. This was the way we did event handling 20+ years ago before we had standards and unfortunately, is a technique that is so pervasive that it just won't die the death it deserves. There are a variety of reasons not to use them. Instead, use modern standards and best-practices and do all of your event handling in separated JavaScript.
You also need to add an additional line just before you attempt to select all the text in the password field to give that element the focus, otherwise the select code won't work (see code below for this).
// Get references to the elements you'll be working with
var input = document.getElementById("password");
var div = document.getElementById("HIDDENDIV");
var btn = document.getElementById("button");
// Set up event handlers in JavaScript
button.addEventListener("click", validate);
function validate(){
if (input.value == 'PASSWORD') {
// No need to add a "show" class. Just remove the "hidden" class.
div.classList.remove('hidden');
// Or, add it:
input.classList.add("hidden");
} else {
password.focus(); // <-- If you don't do this first, your select code won't work
password.setSelectionRange(0, password.value.length);
alert('Invalid Password!');
}
}
input.addEventListener("keydown", function(event){
if (event.keyCode === 13){
// No reason to simulate a button click. Just call the code that needs to be run.
validate();
}
});
/* You only need to apply this to elements that should be hidden and
then simply remove this class from hidden elements to show them. */
.hidden { display: none; }
<input type="text" id="password">
<br>
<input id="button" type="button" value="Login">
<div id="HIDDENDIV" class="hidden">bla</div>
NOTES:
Keep in mind that although this code can "work", anyone can defeat
this code quite easily simply by looking at your source code. To
truly protect content from being consumed without the correct
credentials being provided, you need to implement a server-side
solution.
Just like inline scripting should no longer be done, the same can be
said for using XHTML self-terminating tag syntax (i.e. <br />,
<input />). That is also an old syntax that just won't go away.
Here's why you don't need and shouldn't use this syntax.
I modified and cleaned your code to get to this working snippet:
(See my comments in the code)
// Scripts belongs in tag scripts or in separate files, inline scripts shouldn't be that long.
function verify() { // I created the function, which is called onclick on the button
if (document.getElementById('password').value === 'PASSWORD') {
document.getElementById('HIDDENDIV').classList.remove("hidden"); // Using class instead of inline CSS
document.getElementById('credentials').classList.add("hidden"); // Hide the div containing the credentials
} else {
alert('Invalid Password!');
password.setSelectionRange(0, password.value.length);
}
return false;
}
.hidden { /* Changed id selector to a class */
display: none;
}
<div id="credentials">
<!-- Added the parent div to be able to hide both the password, the button and even the <br> tag easily -->
<input type="text" id="password" onkeydown="if (event.keyCode == 13) verify()" />
<br/>
<input id="button" type="button" value="Login" onclick="verify()" />
</div>
<div id="HIDDENDIV" class="hidden">bla</div><!-- Added class -->
Note that this is NOT a way to secure anything.
Just open the code viewer on any browser and you will see the “hidden” div.
changed
document.getElementById('table').classList.toggle('show')
to
document.getElementById('HIDDENDIV').style.display = 'block';
Seems like you have a lot of uneccesary code though
<input type="text" id="password" onkeydown="if (event.keyCode == 13) document.getElementById('button').click()" />
<br/>
<input id="button" type="button" value="Login" onclick="if (document.getElementById('password').value == 'PASSWORD') {
document.getElementById('HIDDENDIV').style.display = 'block'; document.getElementById('passw').style.display='none'; }
else { alert('Invalid Password!'); password.setSelectionRange(0, password.value.length); } " />
<div id="HIDDENDIV">bla</div>

Input type="text" with select functionality after clicking on Input type="text"

I have this piece of code:
input type="text" name="email" id="email" value="" placeholder="" class="txt"
This is a simple input.
What I need.
Click on this input type="text" -> a drop-down select menu with several options appears (but it is still possible to write something manually into this input type="text") -> click on any option -> one of the options is inserted into the input type="text" -> click again on the input type="text" -> the same drop-down select menu with several options appears.
Please help to do this.
This can't be done with the standard form controls alone, but you can make your own. See the comments below for explanation.
// Get references to elements used
var input = document.getElementById("selectedBrowser");
var list = document.getElementById("list");
// Get all the list items into an array
var listItems = Array.prototype.slice.call(document.querySelectorAll("#list > div"));
// Make the "drop down" list the same width as the input
list.style.width = getComputedStyle(input).width;
// Set up click handler on the input
input.addEventListener("click", function(){
list.classList.remove("hidden"); // Show the list
});
// Set up input event handler on input
input.addEventListener("input", function(){
list.classList.add("hidden"); // Hide the list
});
// Loop over the list items
listItems.forEach(function(item){
// Set up a click event handler
item.addEventListener("click", function(){
input.value = item.textContent; // Copy the value into the input
list.classList.add("hidden"); // Hide the list
});
// Set up a mouseover event handler
item.addEventListener("mouseover", function(){
item.classList.add("highlight"); // Hide the list
});
// Set up a mouseout event handler
item.addEventListener("mouseout", function(){
item.classList.remove("highlight"); // Hide the list
});
});
/* Applied to the drop down list by default to hide it and
removed when the list needs to be shown. */
.hidden {
display:none;
}
#container {
display:inline-block;
vertical-align:top;
}
/* Ensures that the input will be positioned at the top-left of its parent */
#selectedBrowser {
position:absolute;
}
#list {
position:absolute; /* Position at top-left of parent */
top:1.85em; /* But, then move down to be below the input */
border:1px solid #e0e0e0;
height:5em; /* Limit height of list */
overflow-y:scroll; /* Add vertical scroll bar when list won't fit in height */
}
#list > div {
cursor:pointer;
user-select:none;
margin:2px 0;
}
.highlight {
background-color:rgba(255, 255, 0, .5);
}
<label for="selectedBrowser">Choose a browser from this list:</label>
<div id="container">
<input id="selectedBrowser" name="browser">
<div id="list" class="hidden">
<div>Chrome</div>
<div>Firefox</div>
<div>Internet Explorer</div>
<div>Opera</div>
<div>Safari</div>
<div>Microsoft Edge</div>
</div>
</div>
HTML5 has a built-in input and a datalist that renders as a combo box. You add a list attribute to the input that matches the value of the id in the datalist. An example is shown below.
<input type="text" list="items" />
<datalist id="items">
<option>Item1</option>
<option>Item2</option>
<option>Item3</option>
<option>Item4</option>
</datalist>
An issue with this solution is that it is not supported by the Apple Safari browser. W3Schools has the latest compatibility info.
If compatibility is an issue, a number of jQuery or javascript solutions are out there that may solve the problem. Here is a link to a Javascript solution that may work for you.

jQuery taking control over label's border color

My jQuery function looks like that
$('input[type="text"]').focus(function() {
$("label").css("border-bottom-color", "red");
});
$('input[type="text"]').blur(function() {
$("label").css("border-bottom-color", "#e6e6e6");
});
1) I have a bunch of text inputs in my form. What I want to do is to change bottom border color of focused text boxes label (there is one label for every text box. And I want to change only focused text boxes label's border color). But my functions changes all labels' border colors at once. How to fix that problem?
2) I have 2 forms. with id's form1 and form2. I want to do same things to second form but color will be another. How to modify this func?
My forms are looking like that
<form id="form1">
...
<label for="fname">First Name</label>
<input name="fname" placeholder="please enter your first name" type="text" />
...
</form>
<form id="form2">
...
<label for="job">Your Job</label>
...
<input name="job" placeholder="please enter your job" type="text" />
</form>
How about this fiddle?
http://jsfiddle.net/RvYca/3/
label tag's for attribute references to an input's id attribute, not its name.
I moved the styles to css too.
Use both CSS and JavaScript:
$('input:text, input:password, textarea').focus(
function(){
$(this).prev('label').addClass('focused');
}).blur(
function(){
$(this).prev('label').removeClass('focused');
});
And, in the CSS:
#form1 label.focused {
border-bottom: 1px solid red;
}
#form2 label.focused {
border-bottom: 1px solid green;
}
JS Fiddle demo.
For question 1, use $(this) as your selector:
$('input[type="text"]').focus(function() {
$(this).css("border-bottom-color", "red");
});
$('input[type="text"]').blur(function() {
$(this).css("border-bottom-color", "#e6e6e6");
});
For question 2, do you mean, after the user has selected both items, in either order? They can't both be in focus at the same time.
your selector is not specific enough for manipulating the css. You must be specific about which label you want to update. Something like this:
$('input[type="text"],textarea,input[type="password"]').focus(function() {
$("label[for='" + $(this).attr('id') + "']").css("border-bottom-color", "red");
});

How to bind to browser change of input field? (jQuery)

Please take a look at this:
http://jsfiddle.net/sduBQ/1/
Html:
<form action="login.php" method="post" id="login-form">
<div class="field">
<input name="email" id="email" type="text" class="text-input" value="E-mail" />
</div>
<div class="field">
<input name="code" id="code" type="password" class="text-input" />
<div id='codetip'>Access Code</div>
<label class="error" for="code" id="code_error"></label>
</div>
<br />
<div class="container">
<a id="submit" class="link-2">Access</a>
</div>
</form>
CSS:
a {
border: solid 1px #777;
padding:5px;
}
#codetip {
position:absolute;
margin-top:-20px;
margin-left:5px;
}
Javascript:
$('#email').focus(function(){
if($(this).val()=='E-mail'){$(this).val('');}
});
$('#email').blur(function(){
if($(this).val()==''){$(this).val('E-mail');}
});
$('#code').focus(function(){
$('#codetip').hide();
});
$('#code').blur(function(){
if($(this).val()==''){$('#codetip').show();}
});
$('#codetip').click(function(){
$(this).hide();
$('#code').focus();
});
$('#submit').click(function(){
$(this).submit();
});
The problem is that at least in Chrome(haven't tried other browsers yet) when the Chrome Password Manager saves your password and prefills the password for you when you pick the email. I use jquery to hide/show a div over the top of the password input field as a label, hiding that div when the user clicks into the password field (as can be seen in the above jsfiddle code). I need to know how to hide that div when Chrome prefills the password field...
I've haven't run into this myself, but it appears to be a common issue, based on a few quick Google Searches.
FireFox capture autocomplete input change event
http://bugs.jquery.com/ticket/7830
One easy hack you could do is set up some code that runs every second or two via setInterval, and checks to see if the field has a value.
Something like this...
var code = $('#code');
var codeTip = $('#codetip');
var interval = setInterval(function(){
if (code.val()!=''){
codeTip.hide();
clearInterval(interval);
}
}, 1000);
I had the same issue. None of the solutions I found worked nicely enough. I ended up with this:
If it doesn't matter that your input fields have a background, I handled it just in CSS.
jsfiddle
I just gave the .inputPlaceholder { z-index: -1; } so that it aligned behind the input field and then set the input { background: transparent; } so you could see the div behind it.
Google's default -webkit-autofill style has a yellow background, so that just covers up your placeholder behind it all. No need to mess around with custom plugins/events/setIntervals.

Categories

Resources