I used DROPDOWNHOVER script and i need to make if mouseover two seconds then appear the menu this is the code before my edit:
var Dropdownhover = function (element, options) {
this.options = options
this.$element = $(element)
var that = this
// Defining if navigation tree or single dropdown
this.dropdowns = this.$element.hasClass('dropdown-toggle') ? this.$element.parent().find('.dropdown-menu').parent('.dropdown') : this.$element.find('.dropdown')
this.dropdowns.each(function(){
$(this).on('mouseenter.bs.dropdownhover', function(e) {
that.show($(this).children('a, div'))
})
})
this.dropdowns.each(function(){
$(this).on('mouseleave.bs.dropdownhover', function(e) {
that.hide($(this).children('a, div'))
})
})
}
after my edit:
var Dropdownhover = function (element, options) {
this.options = options
this.$element = $(element)
var that = this
// Defining if navigation tree or single dropdown
this.dropdowns = this.$element.hasClass('dropdown-toggle') ? this.$element.parent().find('.dropdown-menu').parent('.dropdown') : this.$element.find('.dropdown')
var timeout;
this.dropdowns.each(function(){
$(this).on('mouseenter.bs.dropdownhover', function(e) {
timeout = setTimeout(function () {
that.show($(this).children('a, div'))
}, 2000)
})
})
this.dropdowns.each(function(){
$(this).on('mouseleave.bs.dropdownhover', function(e) {
that.hide($(this).children('a, div'))
})
})
}
after my edit it's not working when hover and i must click to open it i try many solutions but failed, What i need when mouseover two seonds then open the dropdown menu.
Any advice ?
I did not read your code and i can only suggest a way to do that yourself. What you want is a setTimeout function and cancel it if needed:
var timeout;
$('.your-Mouse-enter-Menu').mouseenter(function(){
timeout = setTimeout(function(){
//Showing The Sub Menu Code
},2000);
});
$('.your-Mouse-enter-Menu').mouseleave(function(){
clearTimeout(timeout); //cancel opening submenu if mouse leave
});
This should help: https://jsfiddle.net/4eww3pf3/
The JavaScript:
var hovered = false;
$('.my-select').on('mouseenter',function(){
hovered = true;
setTimeout(function(){
if(hovered){
// do your stuff here
$('body').append('2 seconds passed!');
}
},2000);
}).on('mouseleave',function(){
hovered = false;
});
What is it doing?
A hovered variable is defined at the start and set to false. When the <select> is hovered, the variable gets set to true, and back to false when unhovered. When the <select> is hovered, we set a timeout for 2 seconds; once the 2 seconds has passed we check the state of the hovered variable, to find out if we're still hovering on the element or not.
Related
I have a function which will take some time to run on click event.
Following is merely an example and setTimeout is there only to simulate time it may take to run it. How can I ensure when a user click on an item any previous running function(s) is(are) cancelled and only the latest onclick function is fired?
i.e. if a user clicked on it 10 times. I want to only execute the only the 10th click not the 9 clicks before.
I am hoping for a pure/vanilla js solution... NOT jQuery
(function () {
var nav = document.querySelector('.nav__toggle');
var toggleState = function (elem, one, two) {
var elem = document.querySelector(elem);
elem.setAttribute('data-state', elem.getAttribute('data-state') === one ? two : one);
};
nav.onclick = function (e) {
setTimeout(function(){
toggleState('.nav ul', 'closed', 'open');
}, 5000);
e.preventDefault();
};
})();
fiddle: http://jsfiddle.net/6p94p48m/
You need to debounce your click handler.
var button = document.getElementById("debounced");
var clickHandler = function() {
alert('click handler');
}
var debounce = function(f, debounceTimeout) {
var to;
return function() {
clearTimeout(to);
to = setTimeout(f, debounceTimeout);
}
}
button.addEventListener('click', debounce(clickHandler, 5000));
<button id="debounced" href="#">debounced</button>
Or use underscore/lodash https://lodash.com/docs#debounce
I asked this question yesterday hopefully this one is clearer as I've now provided a working example of my store.
I'm developing a Shopify Theme. I've been using Timber as my base and I'm currently having a problem with my Quick Cart and Quick Shop/View drawers.
I have 2 drawers on the right of my site, 1 for the cart and 1 for the product quick view option. The drawers currently slide open - #PageContainer moves to the left on click to reveal each drawer.
As they are currently sitting on top of each other I need to alter the JS so that on click the z-index changes so that the correct drawer being called is highest in the stack.
I'm not great with JS so not sure if this is a simple task?
Here is a link to my Dev Store
JS:
timber.Drawers = (function () {
var Drawer = function (id, position, options) {
var defaults = {
close: '.js-drawer-close',
open: '.js-drawer-open-' + position,
openClass: 'js-drawer-open',
dirOpenClass: 'js-drawer-open-' + position
};
this.$nodes = {
parent: $('body, html'),
page: $('#PageContainer'),
moved: $('.is-moved-by-drawer')
};
this.config = $.extend(defaults, options);
this.position = position;
this.$drawer = $('#' + id);
if (!this.$drawer.length) {
return false;
}
this.drawerIsOpen = false;
this.init();
};
Drawer.prototype.init = function () {
$(this.config.open).on('click', $.proxy(this.open, this));
this.$drawer.find(this.config.close).on('click', $.proxy(this.close, this));
};
Drawer.prototype.open = function (evt) {
// Keep track if drawer was opened from a click, or called by another function
var externalCall = false;
// Prevent following href if link is clicked
if (evt) {
evt.preventDefault();
} else {
externalCall = true;
}
// Without this, the drawer opens, the click event bubbles up to $nodes.page
// which closes the drawer.
if (evt && evt.stopPropagation) {
evt.stopPropagation();
// save the source of the click, we'll focus to this on close
this.$activeSource = $(evt.currentTarget);
}
if (this.drawerIsOpen && !externalCall) {
return this.close();
}
// Add is-transitioning class to moved elements on open so drawer can have
// transition for close animation
this.$nodes.moved.addClass('is-transitioning');
this.$drawer.prepareTransition();
this.$nodes.parent.addClass(this.config.openClass + ' ' + this.config.dirOpenClass);
this.drawerIsOpen = true;
// Run function when draw opens if set
if (this.config.onDrawerOpen && typeof(this.config.onDrawerOpen) == 'function') {
if (!externalCall) {
this.config.onDrawerOpen();
}
}
if (this.$activeSource && this.$activeSource.attr('aria-expanded')) {
this.$activeSource.attr('aria-expanded', 'true');
}
// Lock scrolling on mobile
this.$nodes.page.on('touchmove.drawer', function () {
return false;
});
this.$nodes.page.on('click.drawer', $.proxy(function () {
this.close();
return false;
}, this));
};
Drawer.prototype.close = function () {
if (!this.drawerIsOpen) { // don't close a closed drawer
return;
}
// deselect any focused form elements
$(document.activeElement).trigger('blur');
// Ensure closing transition is applied to moved elements, like the nav
this.$nodes.moved.prepareTransition({ disableExisting: true });
this.$drawer.prepareTransition({ disableExisting: true });
this.$nodes.parent.removeClass(this.config.dirOpenClass + ' ' + this.config.openClass);
this.drawerIsOpen = false;
this.$nodes.page.off('.drawer');
};
return Drawer;
})();
Update
As instructed by Ciprian I have placed the following in my JS which is making the #CartDrawer have a higher z-index. I'm now unsure how I adapt this so that it knows which one to have higher dependant on which button is clicked. This is what I've tried:
...
Drawer.prototype.init = function () {
$(this.config.open).on('click', $.proxy(this.open, this));
$('.js-drawer-open-right-two').click(function(){
$(this).data('clicked', true);
});
if($('.js-drawer-open-right-two').data('clicked')) {
//clicked element, do-some-stuff
$('#QuickShopDrawer').css('z-index', '999');
} else {
//run function 2
$('#CartDrawer').css('z-index', '999');
}
this.$drawer.find(this.config.close).on('click', $.proxy(this.close, this));
};
...
The approach would be like this:
$('.yourselector').css('z-index', '999');
Add it (and adapt it to your needs) inside your onclick() function.
if you need to modify the z-index of your div when clicking a buton, you shoud put in this code on your onclick() function, else if you need to activate it when you looding the page you shoud put it on a $( document ).ready() function , the code is :
$('#yourID').css('z-index', '10');
You can use:
document.getElementById("your-element-id").style.zIndex = 5;
It's pure Javascript and sets the z-index to 5. Just bind this to onClick event!
Based on this script I found on Stack Overflow, I tried adapting it to fade out an editor panel on a HTML page. Fading out works fine, but I'd like limit the fade-out from being triggered.
What I hope to accomplish is to prevent the fade-out whenever the mouse is over the editor panel (and child controls) or when there's keyboard activity in one of the input children.
var i = null;
// this part is working
$("#my-canvas").mousemove(function() {
clearTimeout(i);
$("#panel,#btn-panel-toggle,#fps").fadeIn(200);
var i = setTimeout('$("#panel,#btn-panel-toggle,#fps").fadeOut(800);', 3000);
})
// this part is not working
$("#panel").mouseover(function() {
clearTimeout(i);
})
For a live example, please check out this jsFiddle.
Two independent variables are needed here to indicate, whether the input#sc-url is focused and div#panel is hovered by mouse or not. Then you can handle the timer with these functions:
$(function () {
var t = null; //timer
var is_url_focused = false, is_panel_hovered = false;
var panel = $('#panel');
function hide_panel(){
if (t) {
clearTimeout(t);
}
t = setTimeout(function(){
if (is_url_focused || is_panel_hovered) {
return;
}
panel.stop().animate({
opacity:0
},800, function(){
panel.hide(); // == diplay:none
});
},2000);
}
function show_panel(){
panel.show().stop().animate({
opacity:1
},800);
}
$('#my-canvas').mouseenter(function(){
show_panel();
}).mouseleave(function(){
hide_panel();
});
$('#panel').hover(function(){
is_panel_hovered = true;
show_panel();
}, function(){
is_panel_hovered = false;
hide_panel();
});
$('#sc-url').focus(function(){
is_url_focused = true;
show_panel();
}).blur(function(){
is_url_focused = false;
hide_panel();
});
$('#btn-panel-toggle').click(function(){
if (panel.is(':hidden')) {
panel.css('opacity',1).show();
} else {
panel.css('opacity',0).hide();
}
});
});
http://jsfiddle.net/w9dv4/3/
I have a piece of code that hides an element on mouseout.
The code looks like this:
var myMouseOutFunction = function (event) {
setTimeout(function () {
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
};
This produces a result very close to what I want to do. However, I want to wait the time on the timeout (in this case 200 ms) then check to see if my mouse is still "out" of the element. If it is, I want to do .hide() and .show() on the desired elements.
I want to do this because if a user slightly mouses out then quickly mouses back in, I don't want the elements to flicker (meaning: hide then show real quick) when the user just wants to see the element.
Assign the timeout's return value to a variable, then use clearTimeout in the onmouseover event.
Detailing Kolink answer
DEMO: http://jsfiddle.net/EpMQ2/1/
var timer = null;
element.onmouseout = function () {
timer = setTimeout(function () {
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
}
element.onmouseover = function () {
clearTimeout(timer);
}
You should use mouseenter and mouseleave of jquery. mouseenter and mouseleave will get called only once.and use a flag if to check if mouseenter again called.
var isMouseEnter ;
var mouseLeaveFunction = function (event) {
isMouseEnter = false;
setTimeout(function () {
if(isMouseEnter ){ return;}
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
};
var mouseEnterFunction = function(){
isMouseEnter = true;
}
Use a boolean flag:
var mustWait = true;
var myMouseOutFunction = function (event) {
setTimeout(function () {
if(mustWait){
mustWait = false;
}
else{
$(".classToHide").hide();
$(".classToShow").show();
mustWait = true;
}
}, 200);
};
I've toggled click event to a node and I want to toggle a dbclick event to it as well. However it only triggers the click event when I dbclick on it.
So How do I set both events at the same time?
You have to do your "own" doubleclick detection
Something like that could work:
var clickedOnce = false;
var timer;
$("#test").bind("click", function(){
if (clickedOnce) {
run_on_double_click();
} else {
timer = setTimeout(function() {
run_on_simple_click(parameter);
}, 150);
clickedOnce = true;
}
});
function run_on_simple_click(parameter) {
alert(parameter);
alert("simpleclick");
clickedOnce = false;
}
function run_on_double_click() {
clickedOnce = false;
clearTimeout(timer);
alert("doubleclick");
}
Here is a working JSFiddle
For more information about what delay you should use for your timer, have a look here : How to use both onclick and ondblclick on an element?
$("#test-id").bind("click dblclick", function(){alert("hello")});
Works for both click and dblclick
EDIT --
I think its not possible. I was trying something like this.
$("#test").bind({
dblclick: function(){alert("Hii")},
mousedown: function(){alert("hello")}
});
But its not possible to reach double click without going through single click. I tried mouse down but it does not give any solution.
I pretty much used the same logic as Jeremy D.
However, in my case, it was more neat to solve this thing with anonymous functions, and a little slower double click timeout:
dblclick_timer = false
.on("click", function(d) {
// if double click timer is active, this click is the double click
if ( dblclick_timer )
{
clearTimeout(dblclick_timer)
dblclick_timer = false
// double click code code comes here
console.log("double click fired")
}
// otherwise, what to do after single click (double click has timed out)
else dblclick_timer = setTimeout( function(){
dblclick_timer = false
// single click code code comes here
console.log("single click fired")
}, 250)
})
you need to track double click and if its not a double click perform click action.
Try this
<p id="demo"></p>
<button id='btn'>Click and DoubleClick</button>
<script>
var doubleclick =false;
var clicktimeoutid = 0;
var dblclicktimeoutid = 0;
var clickcheck = function(e){
if(!clicktimeoutid)
clicktimeoutid = setTimeout(function(){
if(!doubleclick)
performclick(e);
clicktimeoutid =0;
},300);
}
var performclick =function(e){
document.getElementById("demo").innerHTML += 'click';
}
var performdblclick = function(e)
{
doubleclick = true;
document.getElementById("demo").innerHTML += 'dblclick';
dblclicktimeoutid = setTimeout(function(){doubleclick = false},800);
};
document.getElementById("btn").ondblclick = performdblclick;
document.getElementById("btn").onclick=clickcheck;
</script>
a slightly different approach - The actual click comparison happens later in the timeOut function, after a preset interval... till then we simply keep tab on the flags.
& with some simple modifications (click-counter instead of flags) it can also be extended to any number of rapid successive clicks (triple click, et al), limited by practicality.
var clicked = false,
dblClicked = false,
clickTimer;
function onClick(param){
console.log('Node clicked. param - ',param);
};
function onDoubleClick(param){
console.log('Node Double clicked. param - ',param);
};
function clickCheck(param){
if (!clicked){
clicked = true;
clickTimer = setTimeout(function(){
if(dblClicked){
onDoubleClick(param);
}
else if(clicked){
onClick(param);
}
clicked = false;
dblClicked = false;
clearTimeout(clickTimer);
},150);
} else {
dblClicked = true;
}
};