How to close navigation with outside click? - javascript

I would like to detect a click outside of the menu class .tab-nav-menu, on the rest of the window and add an event to close the menu with similar animation of closing.
// Menu
jQuery(function($) {
$('.header-menu-toggle').on('click', function(e){
e.preventDefault();
$('.tab-nav-menu >ul >li').animate({
opacity: 0
}, 200).animate({
bottom: '-25px'
}, 50);
if($('.tab-nav-menu').hasClass('tab-invisible') ){
$('.tab-nav-menu').css({'right':'-1em'});
$('.tab-nav-menu').removeClass('tab-invisible').addClass('tab-visible');
$(this).find('.burg').addClass('activeBurg');
}
else{
$('.tab-nav-menu').css({'right':'-100%'});
$('.tab-nav-menu').removeClass('tab-visible').addClass('tab-invisible');
$(this).find('.burg').removeClass('activeBurg');
}
var delay = 600;
var duration = 400;
if( $(".header-navigation-menu").hasClass("strip-header-menu") ){
delay = 250;
}
$('.tab-nav-menu >ul >li').each(function(){
$(this).delay(delay).animate({
opacity: 1,
bottom: 0,
}, duration);
delay += 150;
});
})
});
Thanks for your help

A simplified "on outside click" jQuery script:
$(document).ready(function () {
$(document).on('click', function (e) {
var clickedEl = $(e.target);
var outsideClicker = $('#clicker');
if ( !(clickedEl.is(outsideClicker)
|| outsideClicker.has(clickedEl).length > 0) ) { // I flipped this so you can just omit the else
console.log('I clicked outside the target!'); // do whatever you need to do here-- maybe call a function that closes the menu...
} else {
console.log('all good'); // if you don't have an else just get rid of this
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h1> A title </h1>
<p> A paragraph and a <b id="clicker">thing <span>to</span> click </b></p>
</div>
You can extrapolate this for your purposes.

Related

How could I make this active onclick?

var span = document.getElementById('loading_dots');
var int = setInterval(function() {
if ((span.innerHTML += '●').length == 4)
span.innerHTML = '';
}, 400);
(function(){
var loading_dots = document.getElementById("loading_dots"),
show = function(){
loading_dots.style.display = "block";
setTimeout(hide, 5000); // 5 seconds
},
hide = function(){
loading_dots.style.display = "none";
};
show();
})();
How can I make it so loading_dots start on the click of a button, and re-activates everytime I click the button? the bottom function is to stop it after 5 seconds, maybe could merge it into one function?
Needs to work for 3 seperate buttons and relaunch on click of each, also needs to display inside of <span class="loading_dots" id="loading_dots"></span> any method is fine, css, jquery, or javascript
here is a jQuery version:
(function ( $ ) {
$.fn.loader = function( options ) {
var settings = $.extend({
text:"●",
spn: undefined
}, options );
$.each(this, function(){
var btn = this;
var int;
var spn;
if (settings.spn === undefined) {
spn = $("<span/>" , { "class":"loading_dots" });
$(btn).append(spn);
} else {
spn= $(settings.spn);
}
var show = function(){
btn.setAttribute("disabled", "disabled")
clearInterval(int);
spn.show();
int = setInterval(function() {
if ((spn[0].innerHTML += settings.text).length == 4)
spn.html("");
}, 400);
setTimeout(hide, 5000); // 5 seconds
}
var hide = function (){
spn.hide();
btn.removeAttribute("disabled", "disabled")
clearInterval(int);
}
btn.addEventListener("click", show);
});
};
}( jQuery ));
// now bind it by its class, this only need to be run once every time new button is added to the html
$(".btn").loader({spn:".loading_dots"});
// and you could also specify the text by
// $(".btn").loader({text: "*"});
.loading_dots {
color:red;
display:none;
width:100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<span class="loading_dots"></span>
<button class="btn" type="button" >
submit
</button>
<button class="btn" type="button" >
submit
</button>
</div>
If you want to add an event listener for a button click, just select the buttons, and add the listeners in a loop:
document.querySelectorAll("button").forEach(e => e.addEventListener("click", myFunc));
Alternatively, listen for any click, then check if the event's target is a button:
document.addEventListener("click", (e) => if (e.target.tagName == "BUTTON") myFunc());
You could use CSS for the most part of your code, and than simply toggle a show class on the parent #loading element:
const Loading = () => {
let tOut = null;
const el = document.querySelector("#loading");
const show = () => {
el.classList.add('show');
tOut = setTimeout(hide, 5000);
};
const hide = () => {
el.classList.remove('show');
clearTimeout(tOut);
};
return {
show,
hide
};
};
const loadingDots = Loading();
const loadBtns = document.querySelectorAll('.load');
[...loadBtns].forEach(el => el.addEventListener('click', loadingDots.show));
// you can always use loadingDots.hide() to hide when needed (before the 5sec ticks out)
#loading {
position: fixed;
z-index: 100;
top:0;
left: 0;
width:100vw;
height:100vh;
display:flex;
background: rgba(0,0,0,0.5);
color: #fff;
font-size: 3em;
align-items: center;
justify-content:center;
visibility: hidden;
opacity: 0;
transition: 0.4s;
}
#loading.show {
opacity: 1;
visibility: visible;
}
#keyframes blink {
50% {opacity: 1;}
}
#loading i:after {content: "\25cf";}
#loading i { opacity: 0; animation: blink 1.2s infinite; }
#loading i:nth-child(2) { animation-delay: .2s; }
#loading i:nth-child(3) { animation-delay: .4s; }
<div id="loading"><i></i><i></i><i></i></div>
<button class="load">LOAD</button>
<button class="load">LOAD</button>
<button class="load">LOAD</button>
A plain javascript version with the option to programmatically/manually stop displaying the loading dots. Just pass the id of the parent element you want the loading to be attached to. By default the loading will be appended to the parent but you can optionally pass an object as the last parameter with a position property.
function removeLoading(id) {
var parent = document.getElementById(id);
var spans = parent.getElementsByClassName("loading_dots");
while (spans.length > 0) {
var span = spans[0];
if (span.dataset.timerId) {
clearTimeout(span.dataset.timerId);
}
span.remove();
}
}
function addLoading(id, options) {
options = options || {};
var parent = document.getElementById(id);
var existingSpans = parent.getElementsByClassName("loading_dots");
if (existingSpans.length > 0) {
removeLoading(id);
}
var span = document.createElement("span");
span.setAttribute("class", "loading_dots");
if (options.timerId) {
span.dataset.timerId = options.timerId;
}
parent.insertAdjacentElement(options.position || "beforeend", span);
setInterval(function () {
if ((span.innerHTML += '●').length == 4)
span.innerHTML = '';
}, 400)
}
function addLoadingWithTimeout(id, ms, options) {
options = options || {};
var timerId = setTimeout(function () { removeLoading(id) }, ms);
options.timerId = timerId;
addLoading(id, options);
}
<p id="load1">Load 1 - Will stop automatically in 3 seconds after starting. </p>
<button onclick="addLoadingWithTimeout('load1', 3000)">Start Load 1</button>
<button onclick="removeLoading('load1')">Stop Load 1</button>
<p id="load2">Load 2 - Only manual Stop </p>
<button onclick="addLoading('load2')">Start Load 2</button>
<button onclick="removeLoading('load2')">Stop Load 2</button>
Here you go. on the HTML side, you just pass the event to the button that you want and then the id, as a string, of the span/div where you want the load icons to appear.
HTML:
<button id="btn" onclick="load(event, 'loadDiv')">Load</button>
<div>
<span id="loadDiv"></span>
</div>
Below, we are getting the btn id from event so you don't have to manually pass it everytime. Then we are defining function for the innerhtml icons. Lastly, we are running the showIcon function every .4s and then clearing the interval after 5 seconds.
JS:
function load(e, location) {
var btn = document.getElementById(e.srcElement.id)
var loadDiv = document.getElementById(location)
function showLoad() {
if (loadDiv.innerHTML.length < 3) {
return loadDiv.innerHTML += '●'
}
loadDiv.innerHTML = ''
}
(function() {
var loadIcons = setInterval(function() {
showLoad()
}, 400)
var clear = setTimeout(function() {
clearInterval(loadIcons)
}, 5000)
})()
}
Hope this helps!
You can define your code in a function and add click handler to the button.
function myFunc() {
var span = document.getElementById('loading_dots');
var int = setInterval(function() {
if ((span.innerHTML += '●').length == 4)
span.innerHTML = '';
}, 400);
(function(){
var loading_dots = document.getElementById("loading_dots"),
show = function(){
loading_dots.style.display = "block";
setTimeout(hide, 5000); // 5 seconds
},
hide = function(){
loading_dots.style.display = "none";
};
show();
})();
}
document.getElementById("myBtn1").addEventListener("click", myFunc);
document.getElementById("myBtn2").addEventListener("click", myFunc);

Stop timeout when user click and hold the picture

I have a gallery, that will show pictures to user for 5 to 5 seconds.
function slideSwitch() {
var current = $('#slideshow .active');
current.removeClass('active');
if (current.next().length) {
current.next().addClass('active');
myInterval = setTimeout(slideSwitch, 5000);
bar();
}
}
http://jsfiddle.net/6hcste51/
I'd like to pause the timeout when user click and hold the click on div holder.
For example, the timeout is in 3 seconds, if user click and hold the holder div I'd like to stop in 3 seconds until the hold ends, and then go to 4 and 5 seconds to call the function again.
I saw this function but I don't know how to add it in my slideSwitch(). any ideas?
selector.addEventListener('mousedown', function(event) {
// simulating hold event
setTimeout(function() {
// You are now in a `hold` state, you can do whatever you like!
}, 500);
}
you need to set timer function it can support pause and resume
need to set anmatin can support pause and resume and reset (i use jquery queue &
animations)
At last the code will be :
jsfiddle Link
//--------------------------global variables----------------
var isfirst= true;
var cycle_remaining = null;
var anim_time = 5000;//in mil sec
var downtime = null;
var myTimer = null;
var is_down = false;//is down event
var is_SpeedClick_getnext = false;//set to true you want to set click to get next image
//---------------------------timer-------------------------
function Timer(callback, delay) {
var timerId, start, remaining = delay;
cycle_remaining = remaining;
this.pause = function() {
window.clearTimeout(timerId);
remaining -= new Date() - start;
cycle_remaining = remaining;
};
this.resume = function() {
start = new Date();
window.clearTimeout(timerId);
timerId = window.setTimeout(callback, remaining);
cycle_remaining = remaining;
};
this.resume();
}
function slideSwitch() {
var current = $('#slideshow .active');
if (current.next().length) {
current.removeClass('active');
current.next().addClass('active');
myTimer = new Timer(slideSwitch, 5000);
resetanim();
startanim();
}
}
//--------------------- mouse control functions----------------------
$(document).on( "click", ".holder", function() {
if(isfirst){
isfirst = false;
slideSwitch();
}
});
$('.holder').on('mouseout mouseup', function(e) {
if(is_down && !isfirst){
is_down = false;
//set this if if you want to set click to get next image
if(downtime > new Date() - 100 && is_SpeedClick_getnext){
slideSwitch();
}else{
myTimer.resume();
startanim();
}
}
});
$(".holder").mousedown(function() {
if(!isfirst){
downtime = new Date();
is_down = true;
myTimer.pause();
puseanim();
}
});
//--------------------- animation control functions----------------------
//start or resume animation
function startanim() {
var myDiv = $( ".bottom_status" );
myDiv.show( "slow" );
myDiv.animate({
width:"100%"
},cycle_remaining );
myDiv.queue(function() {
var that = $( this );
//that.addClass( "newcolor" );
that.dequeue();
});
}
function rutanim() {
var myDiv = $( ".bottom_status" );
myDiv.show( "slow" );
myDiv.animate({
width:"100%"
}, anim_time );
myDiv.queue(function() {
var that = $( this );
//that.addClass( "newcolor" );
that.dequeue();
});
}
//to puse animation
function puseanim() {
var myDiv = $( ".bottom_status" );
myDiv.clearQueue();
myDiv.stop();
}
// to reset animation
function resetanim() {
var myDiv = $( ".bottom_status" );
myDiv.animate({
width:"1%"
}, 200 );
myDiv.queue(function() {
var that = $( this );
that.dequeue();
});
}
.holder{
display:none;
}
.active{
display:block;
}
.bottom_status{
position:absolute;
bottom:0;
background:blue;
width:0%;
height:10px;
left: 0;
margin-left: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id=slideshow>
<div class='holder active'>
Click here to start counting and click and hold to stop.
</div>
<div class='holder'>
text 2
</div>
<div class='holder'>
text 3
</div>
<div class='holder'>
text 4
</div>
</div>
<div class=bottom_status></div>
There is a Var called is_SpeedClick_getnext set to true you want to set click to get next
Note : the explanation in code comment
As mentioned you cant pause a setTimeout, but I have a solution which I think you might find useful.
I've created a second timer function that effectively stores the remaining time before a slide in the #slideshow element as an attribute every 500ms. If the user clicks on an image then it will cancel the original setTimeout and pauses the changing of the #slideshow attribute until the mouseup event. After the mouseup event is fired a new setTimeout is started using the remaining time stored in the attribute.
I also added a line of code to restart from the first image at the end of the slideshow (not sure if that's what you planned).
Hope this helps
// Start slider
slideSwitch();
// Start independent timer
timer();
function slideSwitch() {
// Select active slide and remove active status
var current = $('#slideshow .active');
current.removeClass('active');
// Check if there is a 'next' element and give active class, or return to first
if (current.next().length) {
current.next().addClass('active');
} else {
$("#slideshow img").first().addClass("active");
}
// Reset timer for the slide, store time and reset timer stop
myInterval = setTimeout(slideSwitch, 3000);
$("#slideshow").attr("time", "3000");
$("#slideshow").attr("timeStop", "false");
}
function timer() {
// Check if the slide countdown has been stopped
if ($("#slideshow").attr("timeStop") != "true") {
// Get last saved time and reduce by 500ms
tempTime = parseInt($("#slideshow").attr("time") - 500);
// Save time to slideshow attribute
$("#slideshow").attr("time", tempTime)
// Show countdown on label
$("#timerLabel").text(tempTime);
}
// Continue timer
myTimer = setTimeout(timer, 500);
}
// Add event for mousedown which cancels timer
$("#slideshow img").mousedown(function() {
// Stop timer and clear countdown for slide
$("#slideshow").attr("timeStop", "true");
window.clearTimeout(myInterval);
});
// Start timer on mouse up
$("#slideshow img").mouseup(function() {
// Restart a new countdown for slide using stored time remaining value
tempTime = parseInt($("#slideshow").attr("time"));
myInterval = setTimeout(slideSwitch, tempTime);
$("#slideshow").attr("timeStop", "false");
});
img {
display: none;
border: 5px solid black;
}
img.active {
display: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="slideshow" time="">
<img src="https://via.placeholder.com/150/fff">
<img src="https://via.placeholder.com/150/000" class="active">
<img src="https://via.placeholder.com/150/f00">
<img src="https://via.placeholder.com/150/0f0">
<img src="https://via.placeholder.com/150/00f">
</div>
<p>Remaining: <span id="timerLabel"></span> ms</p>

Function compared width element

I am trying to retrieve the width of an element sidebar to compare it to an absolute value 250px to adapt my menu, but I'm not sure how to continue.
I need to know when my menu is open or close to delete items when it's closed.
Sorry for the little information given at the start.
Full Code JS
$(document).ready(function() {
function toggleSidebar() {
$(".button").toggleClass("active");
$(".sidebar").toggleClass("widthSidebarJs");
$(".sidebar-item").toggleClass("active");
}
$(".button").on("click tap", function() {
toggleSidebar();
});
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").innerwidth();
function displayForXsSidebar(){
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").toggleClass("displayXs");
}
}
$(document).keyup(function(e) {
if (e.keyCode === 27) {
toggleSidebar();
}
});
});
As I can guess, you need to add/remove displayXs-class on resize.
You can try to add resize() event listener.
Something like this:
$(window).on('resize', function(){
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
} else {
$(".displayForXs").removeClass("displayXs");
}
})
But the better way is #media-queries in your css.
In you currently code, your function displayForXsSidebar() not will be run. but easily, try this, remove the function..
$(document).ready(function() { // when document ready, we calculate the width, is better.
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").outerWidth();
alert('you widthSidebar value right now is ' + widthSidebar );
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
} else {
$(".displayForXs").removeClass("displayXs");
}
});
live demo..
$(document).ready(function() {
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").outerWidth();
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
alert('you widthSidebar value right now is ' + widthSidebar + ' so we add class displayXs');
} else {
$(".displayForXs").removeClass("displayXs");
alert('you widthSidebar value right now is ' + widthSidebar + ' so we remove class displayXs');
}
});
.sidebar {
width: 240px; /* Change width here to 260px if you want */
}
.displayXs { background: #000; color: #fff; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="sidebar">
MY SIDEBAR</div>
<div class="displayForXs">
My displayForXs element
</div>

toggle the mousemove mousestop event

My question is simple. When my mouse moves, I would like to execute a function which would print "you are moving" in a div tag. When my mouse is not moving, I would like the text function to go away.
Below is a pseudo code that i can think of. So for example, the text function will be called every 50/1000 of a second and check if the mouse is moving. if it is moving, the text will show. if the mouse is not moving, the text will not show. How can i achieve this since there is no mousestop event?
$(function() { setInterval(text, 50);
});
function text() {
/*Do something to check if mouse is moving*/
/*if mouse is moving*/
if{
$("#shu").text("You are moving");
} else {
$("#shu").remove();
}
}
Pure javascript solution:
var shu = document.getElementById("shu");
var timeout;
document.addEventListener("mousemove", function() {
shu.innerHTML = "You are moving";
if (timeout) clearTimeout(timeout);
timeout = setTimeout(mouseStop, 150);
});
function mouseStop() {
shu.innerHTML = "";
}
jsFiddle
You can use jQuery .mousemove function along with set interval to check the mouse movement.
Here is an example code.
var lastTimeMouseMoved = "";
jQuery(document).ready(function(){
$(document).mousemove(function(e){
$(".text").show();
lastTimeMouseMoved = new Date().getTime();
var t=setTimeout(function(){
var currentTime = new Date().getTime();
if(currentTime - lastTimeMouseMoved > 1000){
$('.text').fadeOut('fast');
}
},1000)
});
});
body{
background-color:#333;
}
.text{
display:none;
color:white;
font-size:25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="text">Your are moving!!</div>
$(window).mousemove(
function() {
$("#shu").text("You are moving");
}, function() {
$("#shu").remove();
}
);
With jquery
var lastMove = new Date().getTime() ,currentTime;
$(window).mousemove(function(){
lastMove = new Date().getTime();
});
setInterval(function(){
currentTime = new Date().getTime();
if(currentTime - lastMove > 400)
$("#shu").empty();
else
$("#shu").text("moving");
},20);
function mouseStop(callback) {
$(window).mousemove((function() {
var t;
return function() {
if(typeof t !='undefined')
clearTimeout(t); //we should check that `t` is not null
t = setTimeout(function() {
callback();
}, 200)//change to 200 so it will not trigger on mouse move
}
})())
}
mouseStop(function() {
console.log("stop!!!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

jQuery click event

In the following code, the click event is added explicitly to the body, so that even if click outside the button say on the body the div with ID tip1 should close with a fade effect.
The problem here is that the the div closes even if we click on the div itself.
Any idea on this would help ..
$(document).ready(function(){
$('.button').getit({speed: 150, delay: 300});
});
$.fn.getit = function(options){
var defaults = {
speed: 200,
delay: 300
};
var options = $.extend(defaults, options);
$(this).each(function(){
var $this = $(this);
var tip = $('.tip');
this.title = "";
var offset = $(this).offset();
var tLeft = offset.left;
var tTop = offset.top;
var tWidth = $this.width();
var tHeight = $this.height();
$this.click(
function() {
if($('.tip').hasClass('.active101')) {
$('.tip').fadeOut("slow");
$('.tip').removeClass('.active101').addClass('.inactive101');
}
else {
setTip(tTop, tLeft);
$('body').bind('click',function(e) {
var parentElement = "button1";
var parentElement2 = "tip1"
if( e.target.id != parentElement) {
$('.tip').fadeOut("slow");
$('.tip').removeClass('.active101').addClass('.inactive101');
}
});
$('.tip').removeClass('.inactive101').addClass('.active101');
setTimer();
}
},
function() {
if($('.tip').hasClass('.inactive101')) {
stopTimer();
tip.hide();
}
}
);
setTimer = function() {
$this.showTipTimer = setInterval("showTip()", defaults.delay);
}
stopTimer = function() {
clearInterval($this.showTipTimer);
}
setTip = function(top, left){
var topOffset = tip.height();
var xTip = (left-440)+"px";
var yTip = (top-topOffset+100)+"px";
tip.css({'top' : yTip, 'left' : xTip});
}
showTip = function(){
stopTimer();
tip.animate({"top": "+=20px", "opacity": "toggle"}, defaults.speed);
}
});
};
<div class="main">
<a href="#" class="button" id="button1">
Click Me!
</a>
<div class="tip" id="tip1">Hello again</div>
</div>
Set the click event on your div to 'stopPropagation'
http://api.jquery.com/event.stopPropagation/
Perhaps you can bind a click event to the div itself and prevent the click event from bubbling up?
$("#div").click(function(e) {
e.stopPropagation();
});
Rick.
you should stop the event's propagation
you should check if any of the element's children are clicked (if you click a child of that element, the element would close)
you should probably be more careful with your selectors(if you intend to use this only on one element - because you are verifying with an id ('#button1' which is unique), you shouldn't bind the getit function to all the elements with class '.button')
if( e.target.id != parentElement
&& $(e.target).parents('#'+parentElement).length == 0) {
$('.tip').fadeOut("slow");
$('.tip').removeClass('.active101').addClass('.inactive101');
e.stopPropagation();
}
thanks for your answers. Tried with all of them and each worked. But I also found another solution to this by just adding another condition:
if (e.target.id != parentElement && e.target.id != parentElement2) {
$('.tip').fadeOut("slow");
$('.tip').removeClass('.active101').addClass('.inactive101');
}

Categories