Fadeout form on focusout - javascript

How can I make a form fade out when focus is lost entirely? Or another way of putting it: How do I prevent the form from fading when the focus is just shifted from one input to another?
My failing approach is:
form.focusout(function(){
form.fadeout();
});
I have tied to add an if statement counting the number of inputs with focus but to no benefit since the lostfocus fires before the new focus is set.

try setting a timeout, and then if another input has focus, clear the time out to avoid the fadeout:
var timeout;
form.find('input').on('focusout', function(){
timeout = setTimeout(function() {form.fadeout();}, 2000);
});
form.find('input').on('focusin', function(){
clearTimeout(timeout);
});

Related

jquery hide element when no interaction occurs

I have an element pop up in the screen on page load and it hides after 5 seconds. I'm trying to create logic where it'll hide if the user doesn't interact with the pop up, and if user does interact, it'll keep it shown, and if user leaves the element, the timer starts again to hide.
<div id="popup">
Some popup
<input type="email" placeholder="enter email" />
</div>
<div id="popup-button" style="display:none;">
button to open the popup
</div>
// on load, 5 seconds starts
var goTimeout = setTimeout(function(){
$('#popup').css("display","none");
$('#popup-button').css("display","block");
}, 5000);
goTimeout;
// when mouse enter's popup element and/or user types in input
// should turn off the setTimeout
$(document).on("touchstart click mouseenter keyup", "#popup", function(e){
e.stopPropagation();
e.preventDefault();
console.log(e);
clearTimeout(goTimeout);
});
// when user mouse leave's the popup the timer starts again, but
// if user is still focused within input field, don't start until
// user clicks outside of the element
$(document).on("mouseleave", "#popup", function(e){
e.stopPropagation();
e.preventDefault();
console.log(e);
clearTimeout(goTimeout);
goTimeout;
});
Was wondering if someone can help me with the logic, not getting it to work the way I like to
goTimer isn't a function but you're trying to call it like it is one at the end of your mouseleave section. Make a function that creates / starts the timer and you'll be good to go. Like this:
var goTimeout;
function myTimer() {
goTimeout = setTimeout(function() {
$('#popup').css("display", "none");
$('#popup-button').css("display", "block");
}, 5000);
}
myTimer();
Then just change the last line of your mouseleave section to be:
myTimer(); instead of goTimeout;
Here's a JSFiddle to check out.
You can use DOM elements like onmouseover, onmousedown, etc.
Also, the timeout declared at the end seems to be the error, it's more of a variable or count, than a function.
You can have something like,
Gotimeout=5;
clearTimeout(goTimeout);

When using blur with timeout to achieve click-outside-close - the time interval sometimes too short

I have small widget that has a list of links, which can open and close:
<div class="widget">
<input class="focuser">
View options
<ul>
<li>Option 1</li>
<li>Option 1</li>
</ul>
</div>
So, when I click on View options - list appears, and when click on any option - do stuff and close list of options.
And I need to have click-outside-close functionality - when user clicks anywhere outside just close the list.
I achieved this by focusing an invisible input when showing the options, and on blur of the input - hide the options after some timeout. This way:
when user clicks outside - the blur timeout runs out - hide the options.
if user clicks any option - clear the timeout, hide options & do
stuff.
And the problem now is that sometimes the timeout ends before the click. I increased the timeout interval to 200ms, but it's still not 100% sure, and also - this way user sees delay before the options list close.
Any idea how to fix and/or improve this?
EDIT:
This is simplified version of the JavaScript code:
CartSidebar.DwCustomSelect = Ember.View.extend({
blurTimeout: false,
focusOut: function(e) {
if (e.target.className == 'focuser') {
var self = this;
this.blurTimeout = setTimeout(function() {
clearTimeout(self.blurTimeout);
$(self.element).removeClass('opened'); // hide options ..
}, 180);
}
},
click: function(e) {
var clickedElement = e.target;
clearTimeout(this.blurTimeout);
if (clickedElement.tagName.toLowerCase() == 'li') {
$(this.element).removeClass('opened'); // hide options ..
doStuff();
}
}
}
EDIT 2:
I created a plunker, so you can see it in action:
https://plnkr.co/edit/boA6yC0sEbLAZU9tjyso?p=preview
(I did the timeout too small, so you see the problem. But even if you increase the interval - you'll see that the focusOut triggers before the click.)
If you want a functionality where you need to hide your div when user clicks anywhere except that div then you can add a click listener to whole document with the code to hide div.
var a = document.querySelector("a");
var ul = document.querySelector("ul");
a.addEventListener('click', function(e){
e.stopPropagation();
if(ul.classList.contains('show')){
ul.classList.remove('show');
ul.classList.add('hide');
}else{
ul.classList.remove('hide');
ul.classList.add('show');
}
});
document.addEventListener('click', function(){
ul.classList.remove('show');
ul.classList.add('hide');
});
For detail example check the jsbin below
http://jsbin.com/mamexev/edit?html,css,js,output
The timeout thing is one option. But you must define a large interval because it will depend on how fast the browser processes everything. It will work 99.99% of the times, but it's not bulletproof, as you said.
Other trick is to listen to the blur of the whole thing. If you assing a tabindex attribute to an element, it will receive focus events. If you set tabindex="0" it will get an automatic index and you won't have to worry about it.
So, instead of listening to the blur of the input, listen to the blur of the div .widget. When the focus goes from the input to the link or the lis, it will be still within the focus of widget and the blur event won't fire.

Auto refresh a Div without scrolling to the top of Div

I have a script that refreshes a Div on my website every 20 seconds. The problem is, once it refreshes, it scrolls to the to of the Div. I want it to stay at the last position and not scroll to the top after a refresh. Could someone please look at this script and maybe point out what I'm doing wrong? Thanks in advance!
var time = new Date().getTime();
var refreshTime = 20*1000;
$(document).bind("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error hover change", function(e) {
time = new Date().getTime();
});
var lastScrollPos = 0;
$('#feed1').on('scroll', function() {
lastScrollPos = this.scrollTop;
});
function refresh() {
if(new Date().getTime() - time >= refreshTime)
$('#feed1').load(location.href="/dashboard" , function () {
$(this).scrollTop(lastScrollPos);
});
else
setTimeout(refresh, refreshTime);
}
setTimeout(refresh, refreshTime);
Why don't you use feed1 div only for loading your dashboard contents and handle its position using style.
#feed1 {
height: 150px;
overflow: auto;
}
Add other data outside feed1 div because load method will overwrite feed1's content.
See this example if you are looking for something similar otherwise you can modify this example so that other can understand your requirement/scenario.
If you do location.href="/dashboard", the browser will discard all the page's state (including scripting variables) and load "/dashboard" (assigning a value to location.href is identical to calling location.assign("/dashboard")).
The jQuery load function will probably not even require you to reposition the scroll offset, if you gave it chance to execute!
Try:
$('#feed1').load("/dashboard #feed1");
UPDATE:
It seems the HTTP request fired by jQuery's load mechanism is receiving a truncated response in your case (content-length: 0).
You would have to put the scroll position you want to keep into localStorage. Try:
var time = new Date().getTime();
var refreshTime = 20*1000;
$(document).bind("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error hover change", function(e) {
time = new Date().getTime();
});
var previousScrollPos = localStorage.getItem("lastScrollPos");
if(previousScrollPos)
{
$('#feed1').scrollTop(previousScrollPos);
localStorage.removeItem("lastScrollPos");
}
function refresh() {
if(new Date().getTime() - time >= refreshTime)
{
localStorage.setItem("lastScrollPos", $('#feed1').scrollTop());
location.reload();
}
}
setInterval(refresh, refreshTime);
I'm not 100% sure that you want to bind to the scroll event of #feed1 or just of body, I haven't seen your page. If anybody clicks "load more" on the news feed, those additional items will be hidden again since you're reloading the page. Not ideal at all.
Many users will hate having the page periodically reload, it's also an accessibility failure since this will interfere with screen reading software. It might be a simpler idea to just put a refresh newsfeed icon on the page, which just reloads the whole page, when the user wants to (instead of periodically).

manage an onBlur event in JavaScript?

I want to set up an onBlur event for an input element that validates the value and, if invalid, "cancels" the blur and refocusses(or focus never loss) the current input.
i have this peace of code already
document.getElementById('my_input_id1').onblur = function() {
var self = this;
setTimeout(function() { self.focus(); }, 10);
}
Suppose my next focused element is'my_input_id2' which also has an "onblur" event.as focus is already moved to 'my_input_id2'.When i set focus back to 'my_input_id1' the second elment 'my_input_id2' "onblur event is fried.I want to cancel onblur event of second element.i have many other element with "onlur" for Validation.
Can i stop elemnt not to lost focus?
Is there another function that can do it without lost focus??
Should i use some other function that does not lose focus??
Is there another way to get out of this problem??
Many many thanks in advance.
Try it
$('#my_input_id1').on('blur',function(){
if(SOME CONDITION){
setTimeout(function(){
$('#my_input_id1').focus();
},100);
return false;
}
});
This is quite straight forward to do with JavaScript:
document.getElementById('id1').onblur = function(e) {
if(this.value.length == 0) {
this.focus();
e.preventDefault();
return false;
}
}
Essentially just refocusing the element based on a criteria, of course this can be anything you want it to be.
and here is the fiddle: http://jsfiddle.net/m4cZ2/1/

Call a function after specified amount of time without changes to the DOM

Suppose you want to display an alert 3 seconds after there no changes in the DOM just after pressing a button that triggers a lot of changes.
An example with a button gotten via jQuery:
$someButton.on('click',function(){
setInterval(function(){
if( noChangesSinceLastTime()){
time += 100;
}
else{
time = 0;
}
if( time == 3000){
alert("3 seconds without changes!");
}
},100);
});
Assume that the click event on that button has some other binding that excecutes a series of functions for DOM manipulation.
How could I achieve something as the noChangesSinceLastTime()function?
More on my specific problem
I have an HTML+JS+CSS slideshow which works with many simultaneous clients in a network.
When a new client joins, he is automatically sent to the start of the current slide being watched by others.
What I want to do is that, just after it finishes loading the current slide, trigger the clicks necessary to sync the new client with others (since every click inside a slide triggers an animation step, and most slides have multiple steps).
I cannot add a callback in the JS slideware, since it's an obfuscated JS not made by me.
This is just pseudo code, but you could try something like this:
timer = setTimeout(function(){
alert("3 seconds without changes!");
}, 3000);
if(/*some change happens*/) {
clearTimeout(timer);
}
You could listen to all of the DOM Mutatation events and set a flag if any of those are were triggered.
Then in you interval function, you could check that flag and do whatever logic you want. =).
Regards,

Categories

Resources