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);
Related
On my page I have an alert. The desired behavior is that when a user clicks the close button, the element will disappear and a key in the browser's Session Storage will be activated to prevent it from reappearing.
What's happening, however, is that the Session Storage key is placed at all times - regardless if the user clicks the close button. How might I go about having it only placed when the user clicks the button?
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
let dismissed = sessionStorage.getItem("dismissed");
let alertDiv = document.getElementById("alert");
let dismissButton = document.getElementById("dismiss");
if (!dismissed) {
alertDiv.classList.remove("off");
}
dismissButton.addEventListener("click", function() {
alertDiv.classList.add("hide");
});
alertDiv.addEventListener("transitionend", function({
target
}) {
if (target.classList.contains("hide")) {
target.classList.add("off");
}
sessionStorage.setItem("dismissed", true);
});
});
</script>
<div class="ddAlert off" id="alert">
<span class="ddAlertBtn" id="dismiss">×</span>
<h5>Text</h5>
<p>Text</p>
<a class="ddBtn black" href="#" target="_blank">Button</a>
</div>
Per the transitioned event specifications the event will fire whenever a CSS transition completes on the event target. I can't tell from your code but you probably have a transition that's happening when the alert div is loaded.
Either way; you should probably set the sessionStorage key inside the click event handler rather than the transitioned handler. That way you can make sure it's only set on the click like you're wanting.
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.
I'm able to detect a click on a button using jQuery
$('#myButton').click(function(){
// do something
});
but, when the user clicks many times on the button, it fires unnecessary intermediaries events.
I would like to fire the event only on the last click on the button.
Something like:
$('#myButton').lastClickOnASequenceOfClicks(function(){
// ignore the multiple clicks followed
// do something only on the last click of a sequence of clicks
});
With that, if the user clicks 10 times (with a little interval of time), it should fires an event only on the tenth click.
Each click resets the timer.
var timer;
$("#myButton").click(function () {
var timeToWait = 1000;
clearTimeout(timer);
timer = setTimeout(function () {
// do something only on the last click
}, timeToWait);
}
Update
Another way to solve this problem of handling 'multiple click events' generated by the user is to do what was mentioned in the OP comments section. do something on the first click THEN disable the button so the user cannot click it anymore (maybe also set a time for the button to become enabled again)
var timer, timeToWait = 5000, selector ="#myButton";
$(selector).click(function (e) {
$(this).attr("disabled", "disabled");
// do something
// Then wait a certain amount of time then remove the disabled attr on your button
timer = setTimeout(function () {
$(selector).removeAttr("disabled");
}, timeToWait);
})
I would like to display a helpful DIV that basically shows the user how to accomplish something on a particular page, but only if the user has been idle for a period of time, say, 30seconds.
What I mean by "Idle" is:
Not clicking any links
Not right clicking anywhere
Exceptions:
I would like to exclude the following conditions from the Is User Idle rule:
User has scrolled up or down/left or right
User has pressed mouse button on an empty area on the site/ or on an element which has no source/link for example, an image with no hyperlink.
and, Pressing keyboard buttons
Can this be done? Or can we only detect when a particullar event occurs?
Any thoughts/suggestions/resources will be greatly appreciated.
Thank you
fairly basic...
var trigger = 30000
$.(function(){
setInterval('displayInf()',trigger );
$('body').bind('click dblclick keypress mousemove scroll', function(){
clearDisplayInf();
});
});
function displayInf()
{
$('body').append('<div>Your notification div</div>');
}
function clearDisplayInf()
{
trigger = clearInterval(trigger);
trigger = setInterval('displayInf()', 30000 );
}
that should do the trick - you could add some script to make the div removable and start the timer again once its removed but that just polishing up really..
Event in DOM would bubble from leaf to root, thus add a event listener on document would make sense.
But since we are possibiliy stop bubbling for click event in certain element, register click event on document may not work perfectly, in that case, register mousedown and mouseup event would help:
var timer; // create a timer at first
// restart timer on click
function startIdle() {
timer = setTimeout(function() { /* show div */ }, time);
}
if (document.addEventListener) {
document.addEventListener('mouseup', startIdle, false);
}
else {
document.attachEvent('onmouseup', startIdle);
}
// start the first timer
startIdle();
Here is where I am at so far:
http://jsbin.com/ujuqa3/4
So far, I've decided to set a variable to false and to true when the .share-box is open. After it is open, I want the user to be able to click anywhere (except the box) to close it.
Right now it works the first time, but any time after that, it messes up for some reason.
$(document).ready(function() {
// user clicks on report this button
$(".shareThis").click(function() {
// confirmation fades in
$(".share-box").fadeIn("fast"),
// Prevent events from getting pass .share-box
$(".share-box").click(function(e){
e.stopPropagation();
});
});
$(document.body).click(function () {
$("body").click(function(){
// hide the share-box if clicked anywhere aside from the box itself
$(".share-box").fadeOut().removeClass("active");
});
});
});
Add the return false;
// user clicks on report this button
$(".shareThis").click(function() {
// confirmation fades in
$(".share-box").fadeIn(),
// Prevent events from getting pass .share-box
$(".share-box").click(function(e){
e.stopPropagation();
});
return false;
});
When $('.shareThis') click happen its also triggering the $(document.body).click
build a demo at
http://jsbin.com/uyizi4/4