I'm trying to keep the current div visible if I click inside it. I want to hide the div only if I click anywhere on the page but the current div.
I already tried e.stopPropagation(); but that breaks other click handlers I have inside the function.
jsFiddle
var filterContainer = $(".js-filter-container");
var pageDocument = $(document);
$(document).on('click', '.js-show-filter', function(e) {
e.preventDefault();
var currentFilter = $(this).next(filterContainer);
currentFilter.toggle().css("z-index", 99);
filterContainer.not(currentFilter).hide();
pageDocument.click(function(){
filterContainer.hide();
});
return false;
});
If you don't want to change the event propagation, you can check whether the click was within the element by traversing upwards from the event.target, i.e. $(e.target).closest(). (Checking just the event target itself would not work with sub-elements.) The sample shown here binds to a specific element rather than a delegated document event, but it would work exactly the same:
$('.catch').click(function(e) {
if ($(e.target).closest('.prevent').length) {
// The click was somewhere inside .prevent, so do nothing
} else {
alert("Hide the element");
}
});
.prevent {
border: 1px solid
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="catch">
Clicks here should fire the event.
<div class="prevent">
Clicks here should not fire the event.
<div class="whatever">Neither should <b>clicks</b> on <i>child nodes</i>.</div>
And not here.
</div>
But here, yes.
</div>
there is two way:
The simplest: when clicking the div, call e.stopPropagation(), and copy all click handler you want (not the proper way, because you duplicate code...)
Or on your onclick function, get the cursor position, and close the div only if it is not inside the div:
pageDocument.click(function(e)
{
//we get element position
var startX = $(filterContainer).offset().left;
var startY = $(filterContainer).offset().top;
var endX = startX + $(filterContainer).outerWidth();
var endY = startY + $(filterContainer).outerHeight();
//mouse pose relative to page (not window)
var mouseX = e.pageX;
var mouseY = e.pageY;
if (!((mouseX > startX || mouseX < endX) && (mouseY > startY || mouseY < endY))) filterContainer.hide(); //if not on the container: remove it
});
You can try this approach
$(document).on('click', '.js-show-filter', function(e) {
$('.currentFilter').removeClass('currentFilter');
var currentFilter = $(this).next('.js-filter-container');
$('.js-filter-container:visible').hide();
currentFilter.addClass('currentFilter');
currentFilter.slideDown(500);
});
$('body').on('click', ':not(.currentFilter)', function(){
$('.currentFilter').removeClass('currentFilter');
$('.js-filter-container:visible').hide();
});
Fiddle here
Check this W3Schools How to about accordions
I end up using with this solution:
$(document).mouseup(function (e) {
if (!filterContainer.is(e.target) && filterContainer.has(e.target).length === 0) {
filterContainer.hide();
}
});
jsFiddle
Related
I want to use an if statement to check if the mouse is inside a certain div, something like this:
if ( mouse is inside #element ) {
// do something
} else {
return;
}
This will result in the function to start when the mouse is inside #element, and stops when the mouse is outside #element.
you can register jQuery handlers:
var isOnDiv = false;
$(yourDiv).mouseenter(function(){isOnDiv=true;});
$(yourDiv).mouseleave(function(){isOnDiv=false;});
no jQuery alternative:
document.getElementById("element").addEventListener("mouseenter", function( ) {isOnDiv=true;});
document.getElementById("element").addEventListener("mouseout", function( ) {isOnDiv=false;});
and somewhereelse:
if ( isOnDiv===true ) {
// do something
} else {
return;
}
Well, that's kinda of what events are for. Simply attach an event listener to the div you want to monitor.
var div = document.getElementById('myDiv');
div.addEventListener('mouseenter', function(){
// stuff to do when the mouse enters this div
}, false);
If you want to do it using math, you still need to have an event on a parent element or something, to be able to get the mouse coordinates, which will then be stored in an event object, which is passed to the callback.
var body = document.getElementsByTagName('body');
var divRect = document.getElementById('myDiv').getBoundingClientRect();
body.addEventListener('mousemove', function(event){
if (event.clientX >= divRect.left && event.clientX <= divRect.right &&
event.clientY >= divRect.top && event.clientY <= divRect.bottom) {
// Mouse is inside element.
}
}, false);
But it's best to use the above method.
simply you can use this:
var element = document.getElementById("myId");
if (element.parentNode.querySelector(":hover") == element) {
//Mouse is inside element
} else {
//Mouse is outside element
}
Improving using the comments
const element = document.getElementById("myId");
if (element.parentNode.matches(":hover")) {
//Mouse is inside element
} else {
//Mouse is outside element
}
$("div").mouseover(function(){
//here your stuff so simple..
});
You can do something like this
var flag = false;
$("div").mouseover(function(){
flag = true;
testing();
});
$("div").mouseout(function(){
flag = false;
testing();
});
function testing(){
if(flag){
//mouse hover
}else{
//mouse out
}
}
I have a draggable function in jquery to make it so I can drag and move elements on a div. Sometimes, when dragging the mouse comes off the div and I am not able to put back down the element.
I'm trying to add a keydown event for the escape button or something so that when pressed, the same thing happens on .on("mouseup", function(event) {
I've tried doing .on("mouseup keydown", function(event) { but it doesn't catch any keys that are being pressed.
Does anyone have any ideas on how I can cancel the drag? Either by a keydown or even on a mouseup regardless of if the mouse is on the div or not that is being dragged?
Just to be clear, the problem I am having is sometimes I will be dragging the element, I will mouseup but the mouse wasn't on the element when mouseup was called. Therefore, the element is still dragging and I no longer have my finger on the mouse and I have no way to stop the element from dragging to get it back on the document.
EDIT: Here is a jsfiddle, notice I am trying to get this to work on a scaled container. youtube video showing drag glitch
(function($) {
$.fn.drags = function(opt, callback) {
opt = $.extend({
handle: "",
cursor: "move"
}, opt);
if (opt.handle === "") {
var $el = this;
} else {
var $el = this.find(opt.handle);
}
return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
if (opt.handle === "") {
var $drag = $(this).addClass('draggable');
} else {
var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
}
var z_idx = $drag.css('z-index'),
drg_h = $drag.outerHeight(),
drg_w = $drag.outerWidth(),
pos_y = $drag.offset().top + drg_h - e.pageY,
pos_x = $drag.offset().left + drg_w - e.pageX;
$drag.css('z-index', 1000).parents().on("mousemove", function(e) {
$('.draggable').offset({
top: e.pageY + pos_y - drg_h,
left: e.pageX + pos_x - drg_w
}).on("mouseup", function() {
$(this).removeClass('draggable').css('z-index', z_idx);
});
});
e.preventDefault();
}).on("mouseup", function(event) {
if (opt.handle === "") {
$(this).removeClass('draggable');
} else {
$(this).removeClass('active-handle').parent().removeClass('draggable');
}
if (typeof callback == 'function') {
alert("this is a callback");
}
});
}
})(jQuery);
Here are a few things that might work:
Instead of listening for mouseup on the target element, listen for it on document.body. That way it will fire regardless of if the cursor is over the dragged element.
If you want to cancel the drag when the cursor wanders out of the page, add an event listener for mouseleave on document.body and use it to cancel the drag.
If you make a code-pen (or similar) test case, I will be happy to dig into the code.
Edit__
Handling mouseleave on the document prevents it from getting stuck in a draggable state. It also fixes the multiplied movement that you were seeing.
$(document.body).on('mouseleave', function(){
$el.removeClass('draggable').css('z-index', z_idx);
});
Edit2__
Previous JSFiddle was incorrect.
https://jsfiddle.net/spk4523t/6/
I am making a slider and I detect the position of the mouse to define click event. I create a $(document).on('mousemove') event and when I am on the position I want a click, I add a on('click') event, but in this case, the event it's called so many time, and not just one time.
Let's see this code. Here is a quick example : jsFiddle
var widthScreen = $(window).width();
$(document).on('mousemove', function(e) {
console.log(e.pageX);
if (e.pageX > (widthScreen - 120) && e.pageX < widthScreen) {
$('ul').addClass('right-show');
$('li').eq(2).on('click', function() {
console.log('too much click');
});
} else {
$('ul').removeClass('right-show');
}
});
How can I solve this issue ?
When ever you do the mousemove, it is checking the condition and attaching the click event. So the click event is attached many times. To avoid this, first remove the click event using off('click') and attach it. Here is the updated fiddle.
var widthScreen = $(window).width();
$(document).on('mousemove', function(e) {
console.log(e.pageX);
if (e.pageX > (widthScreen - 120) && e.pageX < widthScreen) {
$('ul').addClass('right-show');
$('li').eq(2).off('click').on('click', function() {
console.log('too much click');
});
} else {
$('ul').removeClass('right-show');
}
});
Remove the event attachment from mousemove handler, and create a flag to check, if the cursor is on correct position:
var widthScreen = $(window).width(),
onArea = false;
$(document).on('mousemove', function(e) {
if (e.pageX > (widthScreen - 120) && e.pageX < widthScreen) {
$('ul').addClass('right-show');
onArea = true;
} else {
$('ul').removeClass('right-show');
onArea = false;
}
});
$('li').eq(2).on('click', function(e) {
if (onArea) {
console.log('Not too much clicks.');
}
});
A live demo at jsFiddle.
Have a look at underscore.js throttle function:
_.throttle(function, wait, [options])
Creates and returns a new, throttled version of the passed function, that, when invoked repeatedly, will only actually call the original function at most once per every wait milliseconds. Useful for rate-limiting events that occur faster than you can keep up with
Use .one() instead of .on() Here
I would like to catch some events for a specific div if the user clicked on the div (focus the div), keyboard events are catch (not if the last click was out of the div (unfocus the div)
I tried some things, but haven't succeeded : JSFiddle
document.getElementById("box").onkeydown = function(event) {
if (event.keyCode == 13) { // ENTER
alert("Key ENTER pressed");
}
}
This code doesn't work even if I click on the div.
Pure JS solution please
The div element isn't interactive content by default. This means that there isn't a case where the return key will ever trigger on it. If you want your div element to be interactive you can give it the contenteditable attribute:
<div id="box" contenteditable></div>
In order to now fire the event you need to first focus the div element (by clicking or tabbing into it). Now any key you press will be handled by your onkeydown event.
JSFiddle demo.
Giving the 'div' a tabindex should do the trick, so the div can have the focus:
<div id="box" tabindex="-1"></div>
If you click on the div it gets the focus and you can catch the event.
JSFIDDEL
If you set 'tabindex' > 0 you can also select the div using TAB.
You could catch all the click events, then check if the event target was inside the div:
var focus_on_div = false;
document.onclick = function(event) {
if(event.target.getAttribute('id') == 'mydiv') {
focus_on_div = true;
} else {
focus_on_div = false;
}
}
document.onkeyup = function(event) {
if (focus_on_div) {
// do stuff
}
}
try this code i hope this work
var mousePosition = {x:0, y:0};
document.addEventListener('mousemove', function(mouseMoveEvent){
mousePosition.x = mouseMoveEvent.pageX;
mousePosition.y = mouseMoveEvent.pageY;
}, false);
window.onkeydown = function(event) {
var x = mousePosition.x;
var y = mousePosition.y;
var elementMouseIsOver = document.elementFromPoint(x, y);
if(elementMouseIsOver.id == "box" && event.keyCode == "13") {
alert("You Hate Enter Dont You?");
}
}
DEMO
I created a Fiddle to demonstrate my situation.
I want to not fire the click event when the user is panning--only if it's just a simple click. I've experimented with different placements of .off() and .on() to no avail.
Thanks in advance for your help.
http://jsfiddle.net/Waxen/syTKq/3/
Updated your fiddle to do what you want. I put the re-binding of the event in a timeout so it wouldn't trigger immediately, and adjusted the mousemove to
In on click event, you can detect whether mouse was pressed DOWN or UP. So let's analyse:
DRAG:
mouse down
mosue position changes
mouse up
CLICK:
mouse down
mouse up
You see - the difference is changed mouse position. You can record click coordinate in mouse down and then compare it when muse goes back up. If it is within some treshold, the action was a click.
The only way to tell between a "click" and a "pan" would be the time the mouse has spent held down. You could create a Date in the mousedown, then another in the mouseup, and only fire your click (zoom) event if the difference between the two dates is greater than some threshold (i would guess 1/10 of a second, but you may want to experiment)
I added a "panning" bool for a solution to your problem:
see http://jsfiddle.net/syTKq/4/
Basically, if the user has mousedown and mousemove, then panning is true. once mouseup panning is false. if just mousedown, panning is false, therefore zoom.
This solution solves your problem:
var bClicking = false,
moved = false;;
var previousX, previousY;
var $slider = $('#slider'),
$wrapper = $slider.find('li.wrapper'),
$img = $slider.find('img.foo');
$img.on('click', function()
{
if(!moved)
{
doZoom();
}
});
$wrapper.mousedown(function(e) {
e.preventDefault();
previousX = e.clientX;
previousY = e.clientY;
bClicking = true;
moved = false;
});
$(document).mouseup(function(e) {
bClicking = false;
});
$wrapper.mousemove(function(e) {
if (bClicking)
{
moved = true;
var directionX = (previousX - e.clientX) > 0 ? 1 : -1;
var directionY = (previousY - e.clientY) > 0 ? 1 : -1;
$(this).scrollLeft($(this).scrollLeft() + 10 * directionX);
$(this).scrollTop($(this).scrollTop() + 10 * directionY);
previousX = e.clientX;
previousY = e.clientY;
}
});
function doZoom() {
$img.animate({
height: '+=300',
width: '+=300'
}, 500, function() {
//animation complete
});
}
Basically, it calls doZoom() only when the mouse has not moved between the mousedown and the mouseup events.
You can use the mousemove/mousedown events to set a flag that can be used in the click event handler to determine if the user was clicking or panning. Something like:
//set a flag for the click event to check
var isClick = false;
//bind to `mousedown` event to set the `isClick` flag to true
$(document).on('mousedown', function (event) {
isClick = true;
//bind to `mousemove` event to set the `isClick` flag to false (since it's not a drag
}).on('mousemove', function () {
isClick = false;
//bind to `click` event, check to see if the `isClick` flag is set to true, if so then this is a click, otherwise this is a drag
}).on('click', function () {
if (isClick) {
console.log('click');
} else {
console.log('drag');
}
});
Here is a demo: http://jsfiddle.net/SU7Ef/