I'm developing a little function for my site where a sign in form is automatically shown in the navbar when the site is opened up, but only if a certain cookie has not been set. Then, after 10 seconds has passed, the form will disappear.
It is also supposed to stay open if the user has selected one of the form inputs OR if one of the inputs contain contents. (#user-pest
or #pass-pest
).
Most of it is working the way it is supposed to, however, even when one of the inputs is selected or contains contents, once 10 seconds has passed, the form will disappear from the page.
The following is the JavaScript (and jQuery) code that I am using (updated).
$(document).ready(function(){
// hide sign in form
function hideForm(){ // function for updating elements
$("#darknet-login-nav").css("display", "none");
$(".index-outer").css("height", "100px");
$(".index-inner").css("width", "438px");
$(".index-inner").css("top", "-10px");
$("#darknet-mast").css("font-size", "97px");
}
function hideFormSet(){ // function used for updating elements and setting cookie
hideForm();
document.cookie = "signinNav=set";
}
var checkDisplayed = getCookie("signinNav"); // get cookie contents
if(checkDisplayed == "set"){
hideForm(); // if cookie is set, hide the form
} else { // if it isn't
var hideInterval = setInterval(hideFormSet, 10000); // after 10 seconds, call hideFormSet function
if($("#user-pest").is(':focus') || $("#pass-pest").is(':focus')){
clearInterval(hideInterval); // if one of the inputs are focused on, stop the interval
} else {
hideInterval; // if they aren't focused, start the interval
}
}
});
and this is my simplified markup.
<div class="darknet-nav-login-form" id="darknet-login-nav">
<form action="" method="post">
<input type="text" name="username" id="user-pest" placeholder="Username" autocomplete="off"><br>
<input type="password" name="password" id="pass-pest" placeholder="Password" autocomplete="off"><br>
</form>
</div>
I'm still very new to JavaScript, so any pointers and fixes will be greatly appreciated.
EDIT: please check my above updated code.
Even when on of the inputs are focused, the interval will still continue, rather than stopping.
Thanks
If I understand your goal correctly, you also want to hide the form 10 seconds after the inputs lose focus. In that case it's easier to bind to the focusin/focusout events to restart the timeout, otherwise when leaving an input just before the interval fires it is hidden much earlier than the timeout.
var inputs = $('#user-pest, #pass-pest'),
hideTimeout,
checkFocus = function(){
var hide = !inputs.is(':focus');
if(hide===!!hideTimeout)return;
if(hide)
hideTimeout = setTimeout(hideFormSet, 10000);
else
hideTimeout = clearTimeout(hideTimeout);
};
inputs.focusin(checkFocus).focusout(checkFocus);
checkFocus();
Sidenote, jQuery's is
method checks if any of the elements in the jq array corresponds to the selector, so instead of a separate and/or, you can do: $('#user-pest, #pass-pest').is(':focus')
example Fiddle
Sidenote2, the (re)binding will occur twice because one input loses focus before the next one gains focus. This is not a problem in itself, but if the form only contains those 2 inputs, using event bubbling to check focus on the form itself might be one little step further optimized: inputs.parent().focusin(checkFocus).focusout(checkFocus);
You need an && in this line.
if(!$("#user-pest").is(':focus') || !$("#pass-pest").is(':focus')){
What you had before was
if( user-pest is not focused OR pass-pest is not focused)
A user can't focus both of them at once, thus this will always evaluate to true and hide will be set to true. Use the following:
if(!$("#user-pest").is(':focus') && !$("#pass-pest").is(':focus')){
Alternatively you could also use the following
if($("#user-pest").is(':focus') || $("#pass-pest").is(':focus')){
var hide = false;
} else {
var hide = true;
}
As pointed out in your comment there is also another problem, which I missed the first time.
The hide variable is set on page load, which happens instantly, and you most likely won't have had the time to focus either object yet. You should move the code that checks if it's focused to inside the timeout callback.
See this jsFiddle for the full code of a working example. Basically your timeout should check if the inputs are focused when run, not on page load, as seen in the following snippet.
setTimeout(function() {
if (!$("#user-pest").is(':focus') && !$("#pass-pest").is(':focus')) {
$("#darknet-login-nav").css("display", "none");
$(".index-outer").css("height", "100px");
$(".index-inner").css("width", "438px");
$(".index-inner").css("top", "-10px");
$("#darknet-mast").css("font-size", "97px");
document.cookie = "signinNav=set"; // set the cookie so the form doesn't appear when they come back later
}
}, 2000);
Here's a solution which ensures that the inputs are each empty and that they're not focused. Behaviour beyond the initial 10s timeout wasn't specified, so I've left the interval active - the hide behaviour will be invoked any time the timeout elapses and the conditions for hiding the header are met.
If you wish to make it a 'one-shot' timer, simply clearInterval
in the intervalHandler
function.
window.addEventListener('load', onDocLoaded, false);
var intervalHandle;
function onDocLoaded(evt)
{
intervalHandle = setInterval(intervalHandler, 2000);
}
function hideHeader()
{
document.getElementById('darknet-login-nav').classList.add('hidden');
}
// returns true/false
// true if the header should be hidden, false otherwise.
// Things that will prevent the header from being hidden area
// 0) content in the #user-pest input
// 1) content in the #pass-pest input
// 2) focus of either #user-pest or #pass-pest elements
function shouldHideHeader()
{
if (document.getElementById('user-pest').value != '')
return false;
if (document.getElementById('pass-pest').value != '')
return false;
if (document.activeElement == document.getElementById('user-pest'))
return false;
if (document.activeElement == document.getElementById('pass-pest'))
return false;
return true;
}
function intervalHandler()
{
if (shouldHideHeader())
hideHeader();
}
.darknet-nav-login-form
{
height: 42px;
}
.hidden
{
height: 0px;
overflow: hidden;
transition: height 2s;
}
<div class="darknet-nav-login-form" id="darknet-login-nav">
<form action="" method="post">
<input type="text" name="username" id="user-pest" placeholder="Username" autocomplete="off"/><br>
<input type="password" name="password" id="pass-pest" placeholder="Password" autocomplete="off"/><br>
</form>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With