I'm trying to make floating labels dynamically resize themselves when you click on an input like more forms do today. I'm working with vanilla JS and exclusively going to use vanilla JS for this problem.
I have it set up currently so that it works with the tag. However, for my tag, it does not. For some reason, every time I've looked into this problem across a day or two or looking and then stepping away to reset myself, I cannot see why my element comes up null when I try to add the .active class to it, so as to make the font and animation play properly. Here is the JS script as it functions right now
// add active class
const handleFocus = (e) => {
const target = e.target;
target.parentNode.classList.add('active');
target.setAttribute('placeholder', target.getAttribute('data-placeholder'));
};
// remove active class
const handleBlur = (e) => {
const target = e.target;
if(!target.value) {
target.parentNode.classList.remove('active');
}
target.removeAttribute('placeholder');
};
// register events
const bindEvents = (element) => {
const floatField = element.querySelector('input');
floatField.addEventListener('focus', handleFocus);
floatField.addEventListener('blur', handleBlur);
};
// get DOM elements
const init = () => {
const floatContainers = document.querySelectorAll('.float-container');
//I can see the textarea element in this list.
console.log(document.querySelectorAll('.float-container'));
floatContainers.forEach((element) => {
if (element.querySelector('input').value) {
element.classList.add('active');
}
//The commented section below causes a "TypeError querySeclector is null"
/*
if (element.querySelector('textarea').value) {
element.classList.add('active');
}
*/
bindEvents(element);
});
};
return {
init: init
};
})();
window.onload=FloatLabel.init();
As mentioned in the commented part of the script, when I check the console.log for the list of elements it grabs, I can see the in that list. However, when I try to add the active class for when checking if text is inside the textarea, it comes up null and breaks the script.
I'm not sure if there's something I'm not seeing, or if I fundamentally don't know/understand part of what's going on. I have also checked to make sure the TypeError I'm getting is not related to the DOM not being ready. I've also made sure that the script is at the bottom of the php file and and for good measure added the defer keyword too it. Though, from what I understand about JS, putting defer on a script that's at the bottom of the document doesn't do anything, but I digress. Here is the CSS classes involved.
{
width: 66%;
position: relative;
}
.float-container.small input
{
width: 50%;
outline-offset: 1px;
font-size: 16px;
padding: 16px 4px 10px 4px;
border-radius: 4px;
}
.float-container.small textarea
{
width: 100%;
outline-offset: 1px;
font-size: 16px;
padding: 16px 4px 10px 4px;
border-radius: 4px;
color: red;
}
.float-container.large input
{
width: 100%;
outline-offset: 1px;
font-size: 16px;
padding: 16px 4px 10px 4px;
border-radius: 4px;
}
.float-container.active
{
border: 2px solid #1A57FF;
outline: 2px solid rgba(26, 87, 255, 0.3);
border-radius: 4px;
}
.float-container.active label
{
transform: translate(0, 4px) scale(.75);
}
.floating-text
{
position: absolute;
font-size: 16px;
text-decoration: underline;
color: rgb(100, 100, 100);
transform: translate(0, 16px) scale(1);
transform-origin: top left;
transition: all .1s ease-in-out;
}
Finally, here is the portion of the form from the document
<div id="floatContainer" class="float-container small">
<label for="fName" class="floating-text">First Name</label>
<input type="text" id="fName" name="fName" data-placeholder="First name"><br>
</div>
<p id="fName-validate" class="form-validate-text"><p>
<div id="floatContainer" class="float-container small">
<label for="lName" class="floating-text">Last Name</label>
<input type="text" id="lName" name="lName" data-placeholder="Last name"><br>
</div>
<p id="lName-validate" class="form-validate-text"><p>
<div id="floatContainer" class="float-container small">
<label for="email" class="floating-text">Email</label>
<input type="text" id="email" name="email" data-placeholder="Email"><br>
</div>
<p id="email-validate" class="form-validate-text"><p>
<div id="floatContainer" class="float-container small active">
<label for="phoneNumber" class="floating-text">Phone Number</label>
<input type="tel" id="phoneNumber" name="phoneNumber" data-placeholder="Phone"><br>
</div>
<p id="phoneNumber-validate" class="form-validate-text"><p>
<div id="floatContainer" class="float-container small">
<label for="problemDesc" class="floating-text">Description of problem</label>
<textarea id="problemDesc" name="problemDesc"></textarea><br>
</div>