Unwanted HTML element flickering - javascript

I was working on a quick pen for a project when I ran into flickering issues when dragging an element across an image I'm using. Not really sure whats going on here, the problem doesn't seem to occur when you initially load the pen and pan over it the first time, but after that it starts bugging out.
Link to Pen.
Snippet Demo:
$(document).bind('mousemove', function(e){
$('.tagger').css({
left: e.pageX - 55,
top: e.pageY - 55
});
});
$('#crowd').hover(function(){
$('.tagger').show();
});
$('#crowd').mouseleave(function(){
$('.tagging').attr('class', 'tagger');
$('.tagger').hide();
});
$('#crowd').click(function(){
$('.tagging').attr('class', 'tagger');
});
$('.tagger').click(function(){
$('.tagger').attr('class', 'tagging');
});
$(document).on('click', '.tagging li', function(){
alert($(event.target).text());
});
.tagger {
top: 0px;
left: 0px;
position: absolute;
z-index: 3;
}
.tagger .frame {
position: relative;
height: 100px;
width: 100px;
padding: 0px;
border: 5px;
border-style: solid;
border-color: red;
}
.tagger .name {
display: none;
position: relative;
top: -5px;
height: 90px;
width: 90px;
padding: 5px;
border: 5px;
border-style: solid;
border-color: red;
background-color: white;
}
.tagger .name ul {
list-style: none;
padding: 0px;
margin: 0px;
display: inline-block;
}
.tagging {
position: absolute;
z-index: 3;
}
.tagging .frame {
position: relative;
height: 100px;
width: 100px;
padding: 0px;
border: 5px;
border-style: solid;
border-color: red;
}
.tagging .name {
position: relative;
top: -5px;
height: 90px;
width: 90px;
padding: 5px;
border: 5px;
border-style: solid;
border-color: red;
background-color: white;
}
.tagging .name ul {
list-style: none;
padding: 0px;
margin: 0px;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<img id="crowd" src="https://s3.amazonaws.com/viking_education/web_development/web_app_eng/photo_tagging_small.png" height="600">
</div>
<div class="tagger">
<div class="frame"></div>
<div class="name">
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Fork</li>
<li>Fyve</li>
</ul>
</div>
</div>
$(document).bind('mousemove', function(e){
$('.tagger').css({
left: e.pageX - 55,
top: e.pageY - 55
});
});
$('#crowd').hover(function(){
$('.tagger').show();
});
$('#crowd').mouseleave(function(){
$('.tagging').attr('class', 'tagger');
$('.tagger').hide();
});
$('#crowd').click(function(){
$('.tagging').attr('class', 'tagger');
});
$('.tagger').click(function(){
$('.tagger').attr('class', 'tagging');
});
$(document).on('click', '.tagging li', function(){
alert($(event.target).text());
});

The hover effect consider the cursor and actually your are moving an element with the cursor so what's happening is this:
You start inside the .tagger element and everything is ok as the cursor is on the .tagger element. No event on the #crowd as the cursor never touched/hovered the #crowd until now.
Once you click or you do something that bring the cursor on #crowd you trigger the hover effect which mean that if you leave you will trigger the mouseleave!
So you hover again on the element .tagger and you trigger the mouseleave as expected.
The element disappear (because of what written in the handler of mouseleave) and the cursor is now on #crowd and you trigger again the hover!
The element .tagger appear again, the cursor is on it and you trigger the mouseleave of #croud and so on ...
The flicker is the infinite sequence (4) (5) (4) (5) (4) ...
To fix this you may change the logic as follow. No need to apply the hide/show function, you can simply wrap the image and .tagger element inside the same wrapper and apply overflow:hidden then keep only the click events.
Here is the full code (I made the image smaller so we can see it in the reduced snippet)
$(document).bind('mousemove', function(e){
$('.tagger').css({
left: e.pageX - 55,
top: e.pageY - 55
});
});
$('#crowd').hover(function(){
$('.tagging').attr('class', 'tagger');
});
$('.tagger').click(function(){
$('.tagger').attr('class', 'tagging');
});
$(document).on('click', '.tagging li', function(){
alert($(event.target).text());
});
.tagger {
top: 0px;
left: 0px;
position: absolute;
z-index: 3;
}
.tagger .frame {
position: relative;
height: 100px;
width: 100px;
padding: 0px;
border: 5px;
border-style: solid;
border-color: red;
}
.tagger .name {
display: none;
position: relative;
top: -5px;
height: 90px;
width: 90px;
padding: 5px;
border: 5px;
border-style: solid;
border-color: red;
background-color: white;
}
.tagger .name ul {
list-style: none;
padding: 0px;
margin: 0px;
display: inline-block;
}
.tagging {
position: absolute;
z-index: 3;
}
.tagging .frame {
position: relative;
height: 100px;
width: 100px;
padding: 0px;
border: 5px;
border-style: solid;
border-color: red;
}
.tagging .name {
position: relative;
top: -5px;
height: 90px;
width: 90px;
padding: 5px;
border: 5px;
border-style: solid;
border-color: red;
background-color: white;
}
.tagging .name ul {
list-style: none;
padding: 0px;
margin: 0px;
display: inline-block;
}
.container {
overflow:hidden;
position:relative;
display:inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<img id="crowd" src="https://s3.amazonaws.com/viking_education/web_development/web_app_eng/photo_tagging_small.png" width='400' height="300">
<div class="tagger">
<div class="frame"></div>
<div class="name">
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Fork</li>
<li>Fyve</li>
</ul>
</div>
</div>
</div>

You are assuming .tagger is JUST the border you've drawn. In actuality, there is an invisible box there. The invisible box is on top of #crowd. When .tagger loads, you are no longer hovering over #crowd, you are hovering over .tagger, which is hovering over #crowd.
To fix it, you may change .tagger from one large box around the mouse, to 4 skinny boxes, so that there is nothing directly below the mouse.

You continuously hide() and show() .tagger repeatedly. mouseleave hides and :hover shows.
there are two ways to fix this:
move the mouseover effect inside the #crowd .hover()
this makes the movement a bit shuddery
see this Pen enter link description here
delete the .delete() call within the .mouseleave handler
Also, a note: The jQuery .hover() method takes two callbacks:
1. for the mouseenter
2. for the mouseleave
So the code could be changed a bit in that regard too.

Related

I want to display div below cursor

I want to display div "box" below the cursor, what i have done is making div come on cursor i want to display it below the cursor
$(document).bind('mousemove', function(e) {
$('.box').css({
top: e.clientY - $(".box").height() / 2,
});
});
.box {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 10px;
background: yellow;
border-style: solid;
border-color: black;
border-width: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box"></div>
this prints the div just below cursor, I want it to appear below cursor.
One option is to add a margin to the top of your box.
Example
margin-top: 30px;
With your code
$(document).bind('mousemove', function(e) {
$('.box').css({
top: e.clientY - $(".box").height() / 2,
});
});
.box {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 10px;
background: yellow;
border-style: solid;
border-color: black;
border-width: 5px;
margin-top: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box"></div>

Change colour only during mouse click event

I have a CSS shape that acts as a stop button for some audio:
.double-border {
background-color: #f1f1f1;
border: 2px solid black;
width: 2em;
height: 2em;
position: relative;
margin: 0 auto;
}
.double-border:before {
background: black;
content: "";
display: block;
position: absolute;
top: 7px;
left: 7px;
right: 7px;
bottom: 7px;
pointer-events: none;
}
When the button is clicked it changes colour during the click, and returns to the original colour when the click is released.
I've achieved this by creating two functions to chnage the colour:
function toggleStop(param) {
param.setAttribute("style", "background-color: #C8C8C8;");
}
function toggleStart(param) {
param.setAttribute("style", "background-color: #f1f1f1;");
}
One function is for an onmousedown event and one for an onmouseup event.
<div class="double-border" onclick="stop();" onmousedown="toggleStop(this);" onmouseup="toggleStart(this);">
This kind of works, except if the user hold down the click and simultaneously moves the mouse pointer off the button. In this scenario the button remains the onmousedown colour which I don't want.
Is there a better way of achieving this without too much additional code?
have you tried this with pure css?
.double-border:active,.double-border:focus {
background-color: #f1f1f1;
}
.double-border {
background-color: #f1f1f1;
border: 2px solid black;
width: 2em;
height: 2em;
position: relative;
margin: 0 auto;
}
.double-border:before {
background: black;
content: "";
display: block;
position: absolute;
top: 7px;
left: 7px;
right: 7px;
bottom: 7px;
pointer-events: none;
}
.double-border:active,.double-border:focus {
background-color: #888;
}
<div class="double-border" onclick="stop();"></div>

Mouseover Mouseout with overlapping content

When I mouseover the div with class=background (the little green square in the demo) I fade in the div with class=hover (displaying the grey and blue divs in the demo).
The grey partially overlaps the .background and I can move the mouse around inside it without triggering the mouseout on .background.
But..
If I move the mouse outside the grey div (to hover over the blue for example) then the mouseout on .background gets triggered.
How can I prevent this from happening so that as long as I am hovering over the newly displayed .hover div the mouseout on '.background' will not be triggered?
$('.AddDiv').on('click', function() {
var html = '<div class="container"><div class="background"></div><div class="hover"></div></div>';
$('.Wrap').prepend(html);
});
$(".Wrap").on("mouseover", ".background", function() {
$(this).next(".hover").fadeIn(500);
});
$(".Wrap").on("mouseout", ".hover", function() {
$(this).fadeOut(200);
});
.Wrap {
width: 650px;
height: 800px;
}
.container {
position: relative;
top: 5px;
left: 5px;
width: 200px;
height: 200px;
background-color: red;
float: left;
margin-left: 5px;
margin-top: 5px;
}
.AddDiv {
position: absolute;
top: 0px;
}
.background {
width: 20px;
height: 20px;
background-color: green;
position: absolute;
left: 170px;
top: 10px;
}
.content {
width: 170px;
height: 120px;
background-color: grey;
position: relative;
left: 15px;
top: 15px;
}
.navigation {
width: 190px;
height: 40px;
background-color: blue;
position: relative;
top: 30px;
left: 5px;
}
.hover {
width: 200px;
height: 200px;
background-color: rgba(255, 255, 255, 0.8);
position: absolute;
z-index: 1001;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Wrap">
<div class="container">
<div class="background"></div>
<div class="hover">
<div class="content"></div>
<div class="navigation"></div>
</div>
</div>
</div>
<button class=AddDiv>AddDiv</button>
Use mouseleave instead of mouseout:
$('.AddDiv').on('click', function() {
$('.Wrap').prepend($('<div class="container"><div class="background"></div><div class="hover"></div></div>'));
});
$(".Wrap").on("mouseover", ".background", function () {
$(this).next(".hover").fadeIn(500);
});
$(".Wrap").on("mouseleave", ".hover", function () {
$(this).fadeOut(200);
});

Force CSS transition to update multiple times in JavaScript function

I know how to get CSS transitions to work, but in this case I want to know why getComputedStyle() won't update the right class. Here's a reference to use the getComputedStyle() method to force style recalculation: jQuery addClass method chaining to perform CSS transitions
An example of it working:
http://jsfiddle.net/j8x0dzbz/8/
Now here's my fiddle of it not working:
http://jsfiddle.net/me8ukkLe/12/
And here's my code:
$('button').click(function() {
$('div div').eq(0).addClass('right');
window.getComputedStyle(document.getElementById('blue')).left; // FORCE "right" CLASS
$('div div').eq(0).addClass('left_zero');
});
#container {
border: 1px solid purple;
position: absolute;
height: 12px;
width: 12px;
}
#blue {
background-color: blue;
}
button {
margin-top: 30px;
}
div div {
position: absolute;
width: 10px;
height: 10px;
left: -10px;
transition: left 1000ms;
}
.right {
left: 10px;
}
.left_zero {
left: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div id="blue"></div>
</div>
<button>go</button>
Since the transition property is on the $('div div') object, it is performing the transition, but the left_zero class is added so quickly that the element never gets a chance to transition to the right class coordinates. For this example the best thing to do is put the transition property on the left_zero class.
$('button').click(function() {
$('div div').eq(0).addClass('right');
window.getComputedStyle(document.getElementById('blue')).left; // FORCE "right" CLASS
console.log(window.getComputedStyle(document.getElementById('blue')).left);
$('div div').eq(0).addClass('left_zero');
});
#container {
border: 1px solid purple;
position: absolute;
height: 12px;
width: 12px;
}
#blue {
background-color: blue;
}
button {
margin-top: 30px;
}
div div {
position: absolute;
width: 10px;
height: 10px;
left: -10px;
}
.right {
left: 10px;
}
.left_zero {
left: 0px;
transition: left 1000ms;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div id="blue"></div>
</div>
<button>go</button>

List item click to make div appear in wrong position

So I am having trouble getting a div to position absolute over another div using javascript. The main picture is a background image. I want to click on a list item to bring a div over that image using javascript.
$(document).ready(function() {
//Carpet
$('#gray').click(function(event) {
$('.carpetArea img').remove();
$('.carpetArea').html('<img style="opacity:0; margin-top:-20px;" src="http://192.185.2.154/~sogo/tempsourceoneevents.com/wp-content/uploads/2014/10/lightgray.png"/>');
$('.carpetArea img').animate({opacity: '1', marginTop : '0px' }, 500);
});
});
The css for the carpet image
.carpetArea img {
position:absolute;
zoom:1;
}
The problem is that the image when clicked goes below the main image. It is supposed to animate a little from the top of the page a little downwards to line up over the carpet thats on the background image.
Full Code
$(document).ready(function () {
//Carpet
$('#gray').click(function (event) {
$('.carpetArea img').remove();
$('.carpetArea').html('<img style="opacity:0; margin-top:-20px;" src="http://192.185.2.154/~sogo/tempsourceoneevents.com/wp-content/uploads/2014/10/lightgray.png"/>');
$('.carpetArea img').animate({
opacity: '1',
marginTop: '0px'
}, 500);
});
});
.babBGD {
background: url("http://192.185.2.154/~sogo/tempsourceoneevents.com/wp-content/uploads/2014/10/booth.jpg") repeat scroll 0 0 transparent;
height: 612px;
margin: 0 auto;
position: relative;
width: 1112px;
}
.carpet {
height: 118px;
left: 35px;
position: absolute;
top: 132px;
width: 185px;
z-index: 1;
}
.carpet ul {
list-style: none outside none;
margin: 0;
padding: 0;
}
.carpet ul li {
cursor: pointer;
display: block;
float: left;
height: 34px;
margin-bottom: 7px;
margin-right: 2px;
text-indent: -5000px;
width: 34px;
}
.table {
height: 116px;
position: absolute;
right: 28px;
top: 134px;
width: 185px;
z-index: 1000;
}
.table ul {
list-style: none outside none;
margin: 0;
padding: 0;
}
.table ul li {
cursor: pointer;
display: block;
float: left;
height: 34px;
margin-bottom: 7px;
margin-right: 2px;
text-indent: -5000px;
width: 35px;
}
.carpet-color {
position:absolute;
zoom:1;
z-index: 100;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="babBGD">
<div class="carpet">
<ul>
<li id="gray">Gray</li>
</ul>
</div>
</div>
<div class="carpetArea carpet-color"></div>
Looks like the only thing you need to do is to move .carpetArea into .babBGD container to make carpet position relatively to it:
<div class="babBGD">
<div class="carpet">
<ul>
<li id="gray">Gray</li>
</ul>
</div>
<div class="carpetArea carpet-color"></div>
</div>
Demo: http://jsfiddle.net/w0x0vz56/6/

Categories