Force Chrome cursor update when mouse-idling vanilla javascript - javascript

I have a similar issue as related in this link :
https://code.google.com/p/chromium/issues/detail?id=26723
When new div appears and when mouse does not move, cursor is not updated in Chrome 40.
The Chrome issue list some workarounds, but I don't get them to work with my code.
There are also some stackoverflow question listing this issue but they don't fix this particular case with vanilla javascript.
HTML :
<div id ="d">
Hello
</div>
CSS :
div#d {
width: 100px;
height: 100px;
background-color: red;
}
div.curs {
cursor: pointer;
height: 80px;
background-color: grey;
}
JS :
setTimeout(function(){
var div = document.getElementById('d');
div.innerHTML = div.innerHTML + '<div class="curs">World</div>';
}, 5000);
What is the easiest vanilla javascript workaround for this particular case?
Fiddle : http://jsfiddle.net/2zh90st6/

On Google Chrome v42, you can schedule a cursor update by changing the cursor style of the element currently under the cursor, or any of this element's ancestors. Note that the cursor style has to change after the new element has been added to the DOM.
var container, overlay;
container = document.getElementById('container');
setTimeout(function() {
overlay = document.createElement('div');
overlay.id = 'overlay';
container.appendChild(overlay);
// Change container cursor from 'auto' to 'default',
// to schedule cursor update while hovering overlay
container.style.cursor = 'default';
}, 5000);
#container {
position: relative;
padding: 10px;
cursor: auto;
background: #7FDBFF;
color: #001F3F;
width: 100px;
height: 100px;
}
#overlay {
cursor: pointer;
width: 100px;
height: 100px;
background: #001F3F;
color: #7FDBFF;
position: absolute;
top: 10px;
left: 10px;
}
<div id="container">
Hover me and wait for a dark overlay.
</div>
The chromium issue you linked to, Issue 26723: Mouse cursor doesn't change when mouse-idling, seems quite active at the moment, so hopefully this kind of workaround won't be required for long.

Hmm this is interesting. Either way, triggering a change in the body's cursor, seems to do the trick in Chrome v42:
setTimeout(function(){
var div = document.getElementById('d');
div.innerHTML = div.innerHTML + '<div class="curs">World</div>';
document.body.style.cursor = 'default';
}, 5000);

Related

Popup text box starts glitching when i hover over it with hover color changing effect

I have a simple Page with 3 Div elements, and I want when you hover over them for a box with specific text to show up.
First issue is, when it starts to change color the box dissapears and shows again.
Second issue is, when you have multiple divs, it works for only the first one.
var trigger = document.getElementById("trigger");
var popup = document.getElementById("popup");
var text = document.getElementById("popup-text");
text.innerHTML = "This is the pop-up text.";
trigger.addEventListener("mouseover", function () {
popup.style.display = "block";
popup.style.left = event.clientX + "px";
popup.style.top = event.clientY + "px";
});
trigger.addEventListener("mouseout", function () {
popup.style.display = "none";
});
#popup {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
color: black;
border: 1px solid black;
padding: 20px;
width: 200px;
}
#trigger {
height: 100px;
width: 100px;
background-color: blue;
}
#trigger:hover {
background-color: green;
transition: 0.6s;
}
<div id="trigger"></div>
<div id="trigger" style="background-color: aqua;"></div>
<div id="trigger" style="background-color: brown;"></div>
<div id="popup"><p id="popup-text"></p></div>
From what I can see is that you are generating a blue box in your css,
#trigger {
height: 100px;
width: 100px;
background-color: blue;
}
and you are applying the popup text to only occur on the blue box.
To get the popup to apply to both aqua and brown boxes, end your "trigger" div after the "popup" div.
I'm not sure what you wanted to be blue though>
You are going to come across more issues due to naming conventions with multiple divs with the same IDs (those should be unique to individual divs, class names can be used multiple times), but this answer is to only solve your popup issue.
I suggest looking a little more into trying to accomplish this with CSS only, and then moving onto how to do it with JS.
Good luck!

Child element is causing issues with parent onmousemove event listener

I have created a very simple example of my problem.
Fiddle Link
In the fiddle, I have created a div named parent containing 2 imgs (i take divs in the example for simplicity but in my project, these are images) and a controller div. I place the images on the top of each other by positioning 2nd image as absolute.
I want to clip the 2nd image using clip-path property whenever, I click and then drag the controller" over the parent div.
But the controller div is causing issue with parent mousemove event whenever cursor goes on controller div, mouseout event is fired on parent div causing glitch in animation.
Adding pointer-events: none property to controller div fix the glitch but it also takes away every kind of mouse interaction from the element and I want click and drag effect.
I want to create similar effect used in this website.
The problem seems to be that the positioning of the controller sometimes (not always) 'interferes' with the reading of offsetX on the parent. And the offset goes down (to 0 or up to about 10 in the given fiddle). Hence you get the flickering as the controller moves back and then up along again.
I cannot at the moment totally explain this, particularly since the controller is an absolutely positioned element.
However, one solution is to move the controller out of the parent.
UPDATE It is though possible to leave the controller in the parent if one ignores any mousemove within the controller (so we don't get readings of 0 to 10 for the offset when the mousemove is within the controller - ignore them and we'll get the event bubbling through to the parent and can then take a reading of offset).
_
<head>
<style>
* {
margin: 0;
padding: 0;
}
#parent {
width: 100%;
position: relative;
}
#img1, #img2 {
display: block;
width: 100%;
height: 200px;
pointer-events: none;
}
#img1 {
background: red;
}
#img2 {
background: green;
position: absolute;
top: 0;
left: 0;
}
#controller {
position: absolute;
top: 0;
left: 10px;
width: 10px;
height: 100%;
height: 200px;
background: black;
z-index: 1;
cursor: ew-resize;
/* pointer-events: none; */
}
</style>
</head>
<body>
<div id="parent">
<div id="img1"></div>
<div id="img2"></div>
<div id="controller"></div>
</div>
<h4>
Click and Drag the controller to clip the front image
</h4>
<!-- img1, img2 are images in my case so i named them as imgs -->
<script>
const parent = document.getElementById('parent'),
img2 = document.getElementById('img2'),
controller = document.getElementById('controller');
let pressed = false;
console.log(pressed)
parent.addEventListener('mousemove', (e) => {
if(!pressed) return;
if (e.target != parent) return;
img2.style.clipPath = `inset(0px 0px 0px ${e.offsetX}px)`;
controller.style.left = `${e.offsetX}px`;
});
// for testing purpose
/* parent.addEventListener('mouseout', (e) => {
console.log('mouse out is called');
}); */
controller.addEventListener('mousedown', (e) => {
pressed = true;
});
controller.addEventListener('mouseup', (e) => {
pressed = false;
});
</script>
</body>
const parent = document.getElementById('parent'),
img2 = document.getElementById('img2'),
controller = document.getElementById('controller');
let pressed = false;
parent.addEventListener('mousemove', (e) => {
if (pressed) {
img2.style.clipPath = `inset(0px 0px 0px ${e.clientX - parent.offsetLeft}px)`;
controller.style.left = `${e.clientX - parent.offsetLeft}px`;
}
});
controller.addEventListener('mousedown', (e) => {
pressed = true;
});
controller.addEventListener('mouseup', (e) => {
pressed = false;
});
#parent {
width: 100%;
position: relative;
}
#img1,
#img2 {
display: block;
width: 100%;
height: 200px;
pointer-events: none;
}
#img1 {
background: red;
}
#img2 {
background: green;
position: absolute;
top: 0;
left: 0;
}
#controller {
position: absolute;
top: 0;
left: 10px;
width: 10px;
height: 100%;
background: black;
z-index: 1;
cursor: ew-resize;
/* pointer-events: none; */
}
<div id="parent">
<div id="img1"></div>
<div id="img2"></div>
<div id="controller"></div>
</div>
<h4>
Click and Drag the controller to clip the front image
</h4>
The problem is, you used offsetX which defines the distance between the top left edge of your controller element. This means the distance is about 5px, your controller jumps to 5px from left, the distance is bigger now, the controller jumps back and so on.
The offsetX read-only property of the MouseEvent interface provides
the offset in the X coordinate of the mouse pointer between that event
and the padding edge of the target node.
So therefore you can use the difference between the mouse x-position and the x-position of parent for positioning your controller:
Instead use clientX which gets the mouse position relative to the window.
img2.style.clipPath = `inset(0px 0px 0px ${e.clientX - parent.offsetLeft}px)`;
controller.style.left = `${e.clientX - parent.offsetLeft}px`;
Top expression has following meaning:
<mouse x-position> - <distance between left screen edge and parent>

Div flickers on hover

I have read a lot of the questions on here but can't find one that fixes this. I have programmed a div to follow my cursor. I only want it to appear when the cursor is over #backgroundiv. I have got it working but it sometimes randomly flickers on chrome and disappears entirely on firefox. Even more randomly is it sometimes appears to work and then starts flickering. I have tried a variety of things from hover to mouseenter/mouseover but nothing seems to work.
What I want is for #newdot to appear when the cursor is over #backgroundiv and then follow the cursor around the div. Any help would be much appreciated.
//hide dot when leaves the page
$(document).ready(function() {
$("#backgroundiv").hover(function() {
$("#newdot").removeClass("hide");
}, function() {
$("#newdot").addClass("hide");
});
});
//div follows the cursor
$("#backgroundiv").on('mousemove', function(e) {
//below centres the div
var newdotwidth = $("#newdot").width() / 2;
$('#newdot').css({
left: e.pageX - newdotwidth,
top: e.pageY - newdotwidth
});
});
//tried below too but it doesn't work
/*$(document).ready(function(){
$("#backgroundiv").mouseenter(function(){
$("#newdot").removeClass("hide");
});
$("#backgroundiv").mouseout(function(){
$("#newdot").addClass("hide");
});
}); */
#backgroundiv {
width: 400px;
height: 400px;
background-color: blue;
z-index: 1;
}
#newdot {
width: 40px;
height: 40px;
background-color: red;
position: absolute;
z-index: 2;
}
.hide {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="newdot"></div>
<div id="backgroundiv"></div>
There is not issue but a logical behavior, when you hover on the blue div you trigger mouseenter so you remove the class and you see the red one BUT when you hover the red one you trigger mouseleave from the blue div thus you add the class and you hide the red one. Now the red is hidden you trigger again the mouseenter on the blue div and you remove the class again and the red div is shown, and so on ... this is the flicker.
To avoid this you can consider the hover on the red box to make the red box appear on its hover when you lose the hover from the blue one.
$(document).ready(function() {
$("#backgroundiv").hover(function() {
$("#newdot").removeClass("hide");
}, function() {
$("#newdot").addClass("hide");
});
});
//div follows the cursor
$("#backgroundiv").on('mousemove', function(e) {
//below centres the div
var newdotwidth = $("#newdot").width() / 2;
$('#newdot').css({
left: e.pageX - newdotwidth,
top: e.pageY - newdotwidth
});
});
#backgroundiv {
width: 400px;
height: 400px;
background-color: blue;
z-index: 1;
}
#newdot {
width: 40px;
height: 40px;
background-color: red;
position: absolute;
z-index: 2;
}
.hide {
display: none;
}
/* Added this code */
#newdot:hover {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="newdot">
</div>
<div id="backgroundiv">
</div>

Show overlay on image on mobile devices using pure JavaScript

I have a requirement where I need to show overlay on image on mobile devices whenever user touches the image. I am doing it with the code shown below:
document.getElementsByTagName('img')[0].addEventListener('touchstart', function(event){
let elementExists = document.getElementById('wrapper');
let Center = document.createElement('div');
if (!elementExists) {
let Wrapper = document.createElement('div');
let parentElement = event.currentTarget.parentElement;
Wrapper.classList.add('Wrapper');
Wrapper.id = 'wrapper';
Center.classList.add('Center');
parentElement.appendChild(Wrapper);
Wrapper.appendChild(Center);
Wrapper.addEventListener('touchend', function(event){
if (document.getElementById('wrapper')) {
document.getElementById('wrapper').remove();
}
});
}
});
.col-md-6 {
width: 375px;
height: 211px;
margin: 20px;
position: relative;
}
.Wrapper {
display: table;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
height: 100% !important;
width: 100%;
text-align: center;
z-index: 1000;
font-family: arial;
color: #fff;
top: 0;
}
.Center {
display: table-cell;
vertical-align: middle;
}
<div class="col-md-6">
<a href="https://google.com">
<img src="https://www.blog.google/static/blog/images/google-200x200.7714256da16f.png" />
</a>
</div>
The above code works fine, but I have image wrapped in a tag so by default it showing me screen when user touches an image as shown below:
And because of it overlay is not displaying on mobile screen. I would require help how can I fix it.
EDIT:
I am thinking of adding touch swipe event using plain JavaScript but I am not able to do it exactly.
Please let me know if I can get any help!
Why not just leave out the link and just add the event listener directly to the image?
Native behaviour for links on mobile devices works as you explained. It will trigger menu when holding. If you don't need link just remove it like Bojan said.

Javascript, HTML5 (canvas) progressbar with update

I'm looking for the best way to do a progress bar (in my case it's a life bar for a game) in an html5 canvas.
I don't know if it's better to use javascript and dom element, or draw this bar directly in the canvas.
I need an update function, for example myBar.updateValue(40), and I need to show the new bar without refresh all the page or all the canvas, of course.
Do you know something like that? An existing script? Thanks!
It’s very easy in HTML/CSS:
<style>
#progress-holder{width:400px;height:20px;background:grey}
#progress{width:0;height:100%;background:black}
</style>
<div id="progress-holder">
<div id="progress"></div>
</div>
<script>
var progress = document.getElementById('progress');
function updateValue(perc) {
progress.style.width = perc+'%';
}
updateValue(40);
</script>
DEMO: http://jsbin.com/EGAzAZEK/1/edit
And animating with CSS: http://jsbin.com/EGAzAZEK/3/edit
HTML:
<div class='progress'>
<div class='progress-bar' data-width='//Enter a percent value here'>
<div class='progress-bar-text'>
Progress: <span class='data-percent'>//This is auto-generated by the script</span>
</div>
</div>
</div>
CSS:
html, body {
margin: 0;
padding: 15px;
width: 100%;
height: 100%;
position: relative;
color: #fff;
}
.progress {
position: relative;
width: 100%;
height: 30px;
}
.progress-bar {
margin-bottom: 5px;
width: 0%;
height: 30px;
position: relative;
background-color: rgb(66, 139, 202);
}
.progress-bar-text {
position: absolute;
top: 0px;
width: 100%;
text-align: center;
/*
Do not change the values below,
unless you want your text to display away from the bar itself. */
line-height: 30px;
vertical-align: middle;
}
jQuery:
$('.progress-bar').each(function (){
var datawidth = $(this).attr('data-width');
$(this).find("span.data-percent").html(datawidth + "%");
$(this).animate({
width: datawidth + "%"
}, 800);
});
Link to JSFiddle
The HTML data-width attribute is used to track the percent the bar should be set to. Change it to your liking.
The jQuery script works with ALL progress bars on your page (See the JSFiddle, so you don't have to copy and paste the same jQuery for every new progress bar.
(Just be sure to keep the structure of the HTML, or change it to your liking).
The div "progress" is just an expander, it can be named whatever your want - without you having to change the jQuery.
EDIT:
If you can use Javascript & HTML, don't use a canvas. Canvas (imho) are good for only 1 thing: Seat bookings for concerts, theaters and alike.

Categories

Resources