Combining DOM-events in pure JavaScript - javascript

I have a webpage with pseudo-canvas (see https://jsfiddle.net/memeladon/vff01jq6/). Circles randomly change their color when a user hovers a cursor over them (mouseover event). How can I modify a program so that colors change only when both left mouse is clicked and a cursor is over a circle (click + mouseover events)? Currently I create cells with such a function:
function createCell() {
var new_cell = document.createElement("DIV"),
cell_circle = document.createElement("DIV");
new_cell.classList.add("paint-cell");
cell_circle.classList.add("paint-cell__circle");
new_cell.appendChild(cell_circle);
new_cell.addEventListener("mouseover", function () { changeColor(cell_circle); });
return new_cell;
}

you can use mouse event object in your callback function and see if a mouse button is clicked
new_cell.addEventListener("mouseover", function (e) {
if(e.buttons !== 0)
{
//do cool stuff
}
});

Related

Bootstrap 5.2, prevent closing tooltip if cursor is back on triggering element

TLDR: moving the cursor from tooltip back to triggering element closes, shows and closes the tooltip (flickers).
I need to make the tooltips open on hover and make their content clickable. I have found a working example here on SO.
As you hover over the element it shows you a tooltip which can be interacted with, once you move the cursor away from the tooltip it closes.
There is a problem though.
If you leave the tooltip and move the cursor back on the element which triggered the tooltip, the tooltip pops back up, but dissapears after a moment ("flickering"). You need to move the cursor away from the element and back on the element for the tooltip to show again.
What I am trying to do, is check if the cursor is back on the triggering element and if that is the case not run the closing function (tooltip.hide()).
I have tried to do this by imitating the existing process from the example found on SO. That is, check if the tooltip has lost :hover, setTimout (300ms) and check if cursor is now positioned on the triggering element or back on the tooltip.
Here is a jsFiddle example.
This is the code. The problematic code is between the two looong comment lines.
Note: Moving the cursor away from the triggering element and back on the triggering element also triggers the flickering.
//https://stackoverflow.com/questions/67993080/bootstrap-5-make-tooltip-hoverable-and-link-clickable
var tooltipTriggerList = [].slice.call(document.querySelectorAll('button'))
for (let tt of tooltipTriggerList){
tt.setAttribute("data-bs-placement","top")
}
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
const tooltip = new bootstrap.Tooltip(tooltipTriggerEl, {
trigger: "manual",
'customClass': 'custom-tooltip'
})
let tooltipElTimeout;
let currentToolTip;
let currentTooltipTimeout;
tooltipTriggerEl.addEventListener("mouseenter", function () {
let toolTipID;
// Clear Set Timeout
clearTimeout(currentTooltipTimeout);
// Show Tooltip
tooltip.show();
// Assign current tooltip ID to toolTipID variable
toolTipID = tooltipTriggerEl.getAttribute("aria-describedby");
// Assign current tooltip to currentToolTip variable
currentToolTip = document.querySelector(`#${toolTipID}`);
/*******************************************************************/
// Hide tooltip on tooltip mouse leave
currentToolTip.addEventListener("mouseleave", function () {
currentTooltipTimeout = setTimeout(()=>{
console.log("!currentToolTip.matches(':hover')");
console.log(!currentToolTip.matches(":hover"));
if(!tooltipTriggerEl.matches(":hover")){
console.log("!tooltipTriggerEl.matches(':hover')");
console.log(!tooltipTriggerEl.matches(":hover"));
if (!currentToolTip.matches(":hover")) {
tooltip.hide();
}
}
}, 300)
});
/***********************************************************************/
});
tooltipTriggerEl.addEventListener("mouseleave", function () {
// SetTimeout before tooltip disappears
tooltipTimeout = setTimeout(function () {
// Hide tooltip if not hovered.
if (!currentToolTip.matches(":hover")) {
tooltip.hide();
}
}, 100);
});
return tooltip;
})
Thank you
Edit:
Amine Ramouls answer is correct. isHidden also needs to bet set to false on the 2cnd eventListener, otherwise the tooltips no longer work (problem with aria-describedby).
in your code you have an event listener wich add an event listner and that's a big mistake because it add an infinit number of eveneent listner to your element.
so you juste have to organize your code like this :
//https://stackoverflow.com/questions/67993080/bootstrap-5-make-tooltip-hoverable-and-link-clickable
var tooltipTriggerList = [].slice.call(document.querySelectorAll('button'))
for (let tt of tooltipTriggerList){
tt.setAttribute("data-bs-placement","top")
}
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
const tooltip = new bootstrap.Tooltip(tooltipTriggerEl, {
trigger: "manual",
'customClass': 'custom-tooltip'
})
let isHidden = true;
let currentTooltipTimeout;
tooltipTriggerEl.addEventListener("mouseenter", function () {
let toolTipID;
// Clear Set Timeout
clearTimeout(tooltipElTimeout);
clearTimeout(currentTooltipTimeout);
if (isHidden)
{
tooltip.show();
isHidden=false;
}
});
// Hide tooltip on tooltip mouse leave
tooltipTriggerEl.addEventListener("mouseleave", function () {
console.log("!currentToolTip.matches(':hover')");
if(!tooltipTriggerEl.matches(":hover")){
currentTooltipTimeout=setTimeout(()=>{
if (!isHidden && !tooltipTriggerEl.matches(":hover")){
tooltip.hide();
isHidden=true;
}
console.log("!tooltipTriggerEl.matches(':hover')");
console.log(!tooltipTriggerEl.matches(":hover"));
}, 3000)
}
});
return tooltip;
})
now as you can see i juste added the isHidden var to check if the popup info is hidden or not, you can do that with the element if you can get it by a query selector request. that's it. enjoy your life.
Edit: i forget to tell you that i have put 3 seconde before checking the if the popup is hidden or not.

detect mouse position over image

On an image (slideshow) I would like to detect on which side the courser is placed. e.g the left-half side of the image or the right-half side of the image. I would like to show an arrow (left and right) when the user is mouseover the image and depending on the location I will show the right or the left arrow. I just need to know how to achieve the detection of the mousemove over the image. Thanks!
Use event onmouseenter and onmouseleave in img tag or div tag (you can divide two areas left-right in slideshow)
For example:
<img onmouseenter="showArrow(position)" onmouseleave="hideArrow(position)" src="">
onmouseenter when the mouse pointer onto an image
onmouseleave when the mouse pointer out of an image
var imageElement = document.querySelector('.imageElement');
var arrowsElemennt = document.querySelector('.arrowsElement');
var setStatusForArrows = function(status){return function(){arrowsElement.style.display = status}};
imageElement.addEventListener('mouseover',setStatusForArrows('block'));
imageElement.addEventListener('mouseout', setStatusForArrows('none'));
This is some code that is able to detect the relative cursor position over an image. You could repurpose this to show/hide your arrow icons based on its return value (instead of the console.log).
Added mouseout listener for auto-hiding arrows.
const img = document.getElementById('imageTest');
const [imgRects] = img.getClientRects();
// let showLeftArrow = false;
// let showRightArrow = false;
img.addEventListener('mouseover', evt => {
const distanceLeft = Math.abs(evt.clientX - imgRects.left);
const distanceRight = Math.abs(evt.clientX - imgRects.right);
if (distanceLeft < distanceRight) {
// showLeftArrow = true;
// showRightArrow = false;
console.log('left');
} else {
// showLeftArrow = false;
// showRightArrow = true;
console.log('right');
}
});
/*
img.addEventListener('mouseout', () => {
showLeftArrow = false;
showRightArrow = false;
})
*/
<img id="imageTest" src="https://vuejs.org/images/logo.png" style="height:30px;width:30px" />

How to detect mouse x/y in keypress/keydown

I want to change my cursor image to an animated gif when user press on key.
I tried to change the css "cursor" property but it doesn't move...
So I want to make a div with background image and place it in my cursor X/Y position.
What I tried to do so far is:
var xPlace;
var yPlace;
$(document).mousemove(function(eventParent) {
xPlace = eventParent.pageX;
yPlace = eventParent.pageY;
});
$(document).keydown(function(event) {
if (event.keyCode == 109) {
$("body").addClass("accessibility_cursordetect");
var cursorDetect = '<div class="accessibility_cursordetect_img"></div>';
$(cursorDetect).appendTo("body");
$(".accessibility_cursordetect_img").css({
"top": yPlace,
"right": xPlace
});
}
});
The problem is - in my keydown function -xPlace&yPlace return "undefined"
How can I detect the x/y position of my cursor when the user press on a specific key ("m" for example = keyCode = 109)?
Thank you.
You should be able to use the "cursor" property in the following manner to change the cursor image (using your profile photo in this example) on click of the button considering you already have the jQuery to add the body class:
.accessibility_cursordetect{
cursor: url(https://www.gravatar.com/avatar/9b2dfec811b4643164cba1fd1f244404?s=32&d=identicon&r=PG), auto;
}

Show / hide elements on mouse move

I'm building a site where I want the certain sections to be hidden until the mouse is moved. They then remain visible whilst the mouse is moving, however, if it remains still for a couple of seconds they hide again.
I'm using jQuery on the site, in my ready state I have:
var hide = setTimeout(function() {
hideNav();
}, 2000);
$('body').mousemove(function() {
clearTimeout(hide);
var hide = setTimeout(function() {
hideNav();
}, 2000);
showNav();
});
And the functions that show/hide content
function hideNav() {
$('#primary').fadeOut(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeOut(1000);
}
}
function showNav() {
$('#primary').fadeIn(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeIn(1000);
}
}
This sort of works, except the timeout for hiding the elements ends up fighting with the function to show it when the mouse moves resulting in a lot of flickering.
EDIT: The mouse movement needs to be for anywhere on the page, not just when hovering over the element that is to be shown/hidden.
Any help would be appreciated.
Thanks
Try using $.stop http://api.jquery.com/stop/
If its in the 1 second of fading out when you move your mouse, it should stop the animation of fading out and fade back in.
function hideNav() {
$('#primary').stop().fadeOut(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeOut(1000);
}
}
function showNav() {
$('#primary').stop().fadeIn(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeIn(1000);
}
}
Also, I would remove var from the var hide = ... in your mousemove function. If hide is a global variable, just reuse it inside mousemove (doesn't need to be redeclared).

Lasso tool in javascript

Hay, I'm writing a simple web based image maker, and would like to know if anyone has any idea's how to implement a lasso tool. I'd like to be able to save all the points so that I can easily send them to a database and retrieve them at a later date.
As a basic plug-in, this would probably look something like this:
$.fn.extend({
lasso: function () {
return this
.mousedown(function (e) {
// left mouse down switches on "capturing mode"
if (e.which === 1 && !$(this).is(".lassoRunning")) {
$(this).addClass("lassoRunning");
$(this).data("lassoPoints", []);
}
})
.mouseup(function (e) {
// left mouse up ends "capturing mode" + triggers "Done" event
if (e.which === 1 && $(this).is(".lassoRunning")) {
$(this).removeClass("lassoRunning");
$(this).trigger("lassoDone", [$(this).data("lassoPoints")]);
}
})
.mousemove(function (e) {
// mouse move captures co-ordinates + triggers "Point" event
if ($(this).hasClass(".lassoRunning")) {
var point = [e.offsetX, e.offsetY];
$(this).data("lassoPoints").push(point);
$(this).trigger("lassoPoint", [point]);
}
});
}
});
later, apply lasso() to any element and handle the events accordingly:
$("#myImg")
.lasso()
.on("lassoDone", function(e, lassoPoints) {
// do something with lassoPoints
})
.bind("lassoPoint", function(e, lassoPoint) {
// do something with lassoPoint
});
lassoPoint will be an array of X,Y co-ordinates. lassoPoints will be an array of lassoPoint.
You should probably include an extra check for a "lasso enabled" flag of some sort into the mousedown handler, so that you can switch it on or off independently.
Heres a plugin that seems to do just that
http://odyniec.net/projects/imgareaselect/examples.html
I haven't used it.
I've never made one, but if you're looking to make your own, id imagine they work like
onmousedown record initial mouse coords(this is the coords of the corner of lasso box)
onmousemove subtract new coords from initial coords to get width and height of div being used for the visual lasso box.
onmouseup, stop listening to mousemove, do something with coords and dimension of any lasso box existing

Categories

Resources