how to start transition with onclick on div? - javascript

I am developing a widget, for this i am using addClass and removeClass method of jquery but some how it is not working please help me with this.
Here is the code:
$('#test').click(function() {
$(this).addClass('second');
console.log("hello");
}, function() {
$(this).removeClass('second');
});
#test {
transition: all 0.5s ease;
}
.first {
width: 150px;
height: 30px;
position: fixed;
bottom: 0px;
right: 25px;
}
#prop {
width: 150px;
height: 30px;
position: fixed;
bottom: 0px;
right: 25px;
background-color: #abc322;
color: white;
text-align: center;
}
.second {
width: 150px;
height: 300px;
position: fixed;
bottom: 0px;
right: 25px;
box-shadow: 3px 4px 40px grey;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<div id="test" class="first">
<div id="prop">
freight Calculator
</div>
<p>
welcome to freight calculator
</p>
</div>
when i click on the div it should change its class and start transition but it is not working. please identify the mistake that i have done.
Thank you for your time.

jQuery .click() takes one function as event listener. You can use .toggleClass() instead.
$('#prop').click(function(e) {
e.preventDefault();
$('#test').toggleClass('second');
});
#test {
transition : all 0.5s ease;
}
.first {
width: 150px;
height: 30px;
position: fixed;
bottom: 0px;
right: 25px;
}
#prop {
cursor: pointer;
width: 150px;
height: 30px;
position: fixed;
bottom: 0px;
right: 25px;
background-color: #abc322;
color: white;
text-align: center;
}
.second {
width: 150px;
height: 300px;
position: fixed;
bottom: 0px;
right: 25px;
box-shadow: 3px 4px 40px grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="test" class="first">
<div id="prop">
freight Calculator
</div>
<p>
welcome to freight calculator
</p>
</div>

The click method only takes one callback function: the one that should fire on click. You provided two callbacks (one that adds the class and one that removes it). jQuery doesn't know what to do with that, it assumes the first callback is an eventData object and takes the second function as the action to perform on click. This means that on click, all it does is remove the class.
Refer to https://api.jquery.com/click/ to read more about how to use the click() method.
If you provide only one callback it works fine: https://jsfiddle.net/uqmupq3h/

The .click() method only takes one callback function so you should use .toggleClass() instead of .addClass() and .removeClass().
$('#test').click(function(){
$(this).toggleClass('second');
})
https://jsfiddle.net/knj0ec6n/

Related

Unwanted HTML element flickering

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.

Show overlay fullscreen div then hide it by clicking on it

I'm new to the html/css/jquery languages, so please pardon me if my question seems too obvious.
My aim is to make a fullscreen overlay div appear when clicking on a div (this step actually worked with the toggle function) and then make this same div disappear by just clicking on it.
I've browsed many related topics but I can't seem to find a way to resolve my issue. How can I make the full screen div disappear by clicking anywhere on it (clicking back on the first div is not an option since it's intentionally hidden)?
Here's my code so far:
JavaScript (jQuery):
$(function() {
$("#bandeau").click(function() {
$("#full_screen").toggle();
});
});
HTML:
<div id="bandeau">content</div>
<div id="full_screen">
<div class="info_visible" id="about">content</div>
</div>
CSS:
#bandeau {
background-color: black;
overflow: hidden;
cursor: crosshair;
width: 100%;
height: 57px;
z-index: 1000;
position: fixed;
}
#full_screen {
background-color: black;
overflow: hidden;
cursor: crosshair;
width: 100%;
height: 100%;
z-index: 1000;
position: fixed;
display: none;
margin: 0px;
padding: 0px;
}
.info_visible {
width: 100%;
height: auto;
color: white;
padding-top: 10px;
padding-bottom: 20px;
padding-left: 30px;
position: fixed;
}
Pure CSS solution with undercover checkbox:
html {
width: 100%;
height: 100%;
background: lavender;
text-align: center;
font-family: arial, sans-serif;
}
input {
display: none;
}
#target {
display: none;
}
#click:checked ~ label > #target {
position: fixed;
top: 0;
left: 0;
display: inline-block;
height: 100%;
width: 100%;
background: url('http://i.imgur.com/bv80Nb7.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
.item {
position: fixed;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
left: 0;
right: 0;
margin: auto;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
}
#warning {
position: fixed;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
left: 0;
right: 0;
margin: auto;
}
<input type="checkbox" id="click" name="click" value="click" />
<label for="click">
<p class="item"><b>CLICK HERE</b></p>
<div id=target><h1 id=warning>FULLSCREEN CONTENT</h1></div>
</label>
This will toggle full screen on or off
https://jsfiddle.net/42atLz1g/1/
$("#bandeau, #full_screen").click(function(){
$("#full_screen").toggle();
});
Below is a simple and easy way to do it with one command and full explination. Enjoy and welcome to website development!
Note: scroll to end of answer to see a short list of helpful links
// this is simply jQuery shorthand for document.ready = function ...
$(function(){
// this is how to dynamically assign events
// why is this important? let's say, in the future,
// you decide to add elements after the page is loaded,
// this allows the NEW elements to still use the same events you've assigned
$(document)
// .on and .off are as simple as they appear,
// on adds an event to a group of elements and off removes
// as you'll notice, I assign just one method to both elements
// the reason is this move is extremely simple
// all you need is to have one element hide or show, based on
// clicking one of the divs
.on('click', '#bandeau, #full_screen', function(e) {
// .toggle accepts a booleen argument
// if true = show, if false = hide
// thus i simply test the id name within the parameter!
$('#full_screen').toggle(this.id == 'bandeau');
})
});
#bandeau{
background-color: black;
color: green;
overflow: hidden;
cursor: crosshair;
width:100%;
height: 57px;
z-index: 1000;
position: fixed;
}
#full_screen {
background-color: black;
overflow: hidden;
cursor: crosshair;
width: 100%;
height: 100%;
z-index: 1000;
position: fixed;
display: none;
margin: 0px;
padding: 0px;
}
.info_visible {
width:100%;
height: auto;
color:white;
padding-top: 10px;
padding-bottom: 20px;
padding-left: 30px;
position: fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="bandeau">content</div>
<div id="full_screen">
<div class="info_visible" id="about">tnetnoc</div>
</div>
See more about jQuery Dynamic Events here (.on) && here (.off)
More you should read about dynamic entry
.toggle()
Try to replace your jQuery code with this
$(function(){
$("#bandeau").click(function(){
$("#full_screen").show();
});
$("#full_screen").click(function(){
$(this).hide();
});
});

On display of hidden element it shows on wrong place because of scroll, only in chrome

I don't realy know how to explain this thing in short sentence.
I don't know if it is bug or not..
In parent div with fixed height and overflow-y scroll, I have multiple children elements, which has jquery function click, what displays hidden element in these divs. When I scroll down to last div, after click, hidden element displays in wrong place.
I tried to search for this problem, cause it should be pretty common. But nothing came up.s
It's realy hard to explain with words. Just look at this jquery example with mozilla and after that with chrome.
https://jsfiddle.net/zvwcdzjz/2/#
P.S. I need my original example work and look exactly the same on chrome and mozilla, cause right now on mozilla everything looks exactly as i want it to be, but it bugs on chrome.
It can be solved with jQuery too, makes no difference for me.
HTML:
<div id="el">
<div class="content">
<div class="block">
<div class="blocktoopen"></div>
<div class="button">click to open</div>
</div>
<div class="block">
<div class="blocktoopen"></div>
<div class="button">click to open</div>
</div>
<div class="block">
<div class="blocktoopen"></div>
<div class="button">click to open</div>
</div>
</div>
</div>
CSS:
#el {
width: 300px;
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
#el .content {
width: 300px;
height: auto;
}
.block {
width: 300px;
height: 200px;
margin-top: 10px;
background-color: rgba(0,0,0,0.2);
}
.button {
background-color: blue;
color: #fff;
cursor: pointer;
text-align: center;
margin-top: 90px;
float: left;
}
.blocktoopen {
width: 50px;
height: 50px;
position: absolute;
margin-left: 300px;
background-color: red;
display: none;
}
JS:
$(function(){
$(".button").click(function(){
$(this).parent(".block").children(".blocktoopen").show();
});
$("#el").scroll(function(){
$(".blocktoopen").hide(); });
});
The set height of #el was causing the red box to appear in the incorrect location. I have removed this. See the example below:
Change:
#el {
width: 300px;
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
To:
#el {
width: 300px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
And then you're good to go.
To make your life simpler make the parent .bloc relative so the blocktoopen will be computed relatively. Will help with the responsiveness.
.block {
width: 300px;
height: 200px;
margin-top: 10px;
background-color: rgba(0,0,0,0.2);
position: relative;
}
.blocktoopen {
width: 50px;
height: 50px;
position: absolute;
top: 50%;
bottom: 50%;
background-color: red;
display: none;
right: 0;
}
I can't post comment so here is another try with jsfiddle. I am not sure if you have horizontal scroll as well. remove margin-right from .blocktoopen and add right:0; Also wrap all your internal content inside a div and set the width to maybe 225px
#el {
width: 300px;
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
#el .content {
width: 300px;
height: auto;
}
.block {
width: 300px;
height: 200px;
margin-top: 10px;
background-color: rgba(0,0,0,0.2);
position: relative;
}
.button {
background-color: blue;
color: #fff;
cursor: pointer;
text-align: center;
margin-top: 90px;
float: left;
}
.blocktoopen {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
display: none;
top: 50%;
bottom: 50%;
right: 0;
}
.internal{
width: 225px;
}
Have you tried to click on 2 buttons without scrolling? Try it. Looks like you were using visibility: hidden; and not display: none;. Maybe trying to set the position: relative; ...
Just seen the jquery script. Show() and hide() appears to work as visibility css property.
If u look with Chrome DevTools the jsFiddle example you will see that you can't see the red boxes but they are still there.

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>

JQuery drop functionality not working as expected?

I've been trying to implement drag and drop functionality using JQuery. I've got 3 'draggable' divs and 3 'droppable' divs. Div with id 'draggable1' should be accepted by div with id 'droppable1' and so on. However, it only works for one pair of the divs(draggable1 and droppable1). It doesn't work for the other two.
I think it's somehow related to the css positioning. When I don't set the margin properties for the individual divs, it works. However, if I want to position the divs elsewhere, the functionality doesn't work anymore.
Here's a jsfiddle I've created: https://jsfiddle.net/3ews8j8x/
HTML
<center><h3>Drag and Drop</h3></center>
<div class="wrap">
<div class="draggables" id="draggable1"></div><br>
<div class="draggables" id="draggable2"></div><br>
<div class="draggables" id="draggable3"></div><br>
</div>
<div id="droppable1"></div>
<div id="droppable2"></div>
<div id="droppable3"></div>
CSS
body{
margin: 0;
}
.wrap{
width: 400px;
height: 300px;
background: #e3e3e3;
position: relative;
margin-top: 80px;
}
.draggables{
width: 20px;
height: 20px;
margin: auto;
position: absolute;
margin-left: 30px;
}
#draggable1{
background: #003366;
position: relative;
}
#draggable2{
background: #ffff00;
position: relative;
margin-top: 90px;
}
#draggable3{
background: #ff0000;
margin-top: -150px;
margin-left: 220px;
}
#droppable1{
width: 50px;
height: 50px;
background: #0000FF;
margin-left: 600px;
margin-top: -200px;
}
#droppable2{
width: 50px;
height: 50px;
background: #008080;
margin-left: 700px;
margin-top: -50px;
}
#droppable3{
width: 50px;
height: 50px;
background: #00cc00;
margin-left: 800px;
margin-top: -50px;
}
Javascript code is provided in the link.
I want to know why it doesn't work when I try to change the positioning of the divs. Can it not be done or am I doing something wrong? I've been stuck with this problem for over 3 days now. Any help would be appreciated.
Thank you in advance.
So there were a few fundamental errors. Firstly the .draggables are set to position:relative; These need to be absolute. You were positioning these .draggables with margins, you should be positioning them with top & left:
JSFiddle
.draggables{
width: 20px;
height: 20px;
position: absolute;
}
#draggable1{
background: #003366;
}
#draggable2{
background: #ffff00;
top: 90px;
}
#draggable3{
background: #ff0000;
top: 150px;
left: 220px;
}

Categories