Issue with jQuery's slideDown() - javascript

Check this code: http://jsfiddle.net/ZXN4S/1/
HTML:
<div class="input">
<input type="text" size="50" id="test_input">
<input type="submit" value="send" id="test_submit">
</div>
<ul>
<li class="clear">
<div class="comment">
<div class="image">
<img src="http://www.chooseby.info/materiale/Alcantara-Black_granito_nero_naturale_lucido_3754.jpg">
</div>
<div class="info">
<div class="name">Name</div>
<div class="text">text</div>
<div class="timestamp">timestamp</div>
</div>
</div>
</li>
</ul>
jQuery:
$(document).ready(function() {
$("#test_submit").click(function() {
$.post('/echo/json/', function(data) {
last = $("ul li:first-child");
new_line = last.clone();
new_line.hide();
last.before(new_line);
new_line.slideDown('slow');
});
return false;
});
});
If you try to insert some text in the input field and click on the submit you can see the issue I'm talking about. When it slides down the height of slide is wrong and the effect is ugly. But if you remove the div info it works well. How can I fix?

Setting:
ul li .info {
float: left;
}
did it for me (tested in chrome)

This trick seems to solve the issue:
ul li .info {
float: right;
width: 485px; // fixed width to the div
}

The problem is simply the layout model. You can add overflow:hidden to give layout to an element in most browsers:
ul li .info {
overflow: hidden;
}
Will also solve it. You could fix your width optionally as well, but it's not required.
Bonus pedantic help that you didn't actually ask for:
You're using "return false" to prevent the default event. There's a function for that, which is more efficient in terms of how events bubble. Simply pass the event into the function (you can use any name you want, but I call it "event" for clarity) and then call preventDefault() on it:
$("#test_submit").click(function(event) {
event.preventDefault()
// ... the rest of your code ... //
});

After playing in JS Fiddle, this seems to have done the trick:
In your CSS, ul li .info { }
Add: height: 50px;

Related

Using addEventListener

I'm trying to toggle a second element by clicking on the first, and not having the second as interactive but it's not working. What am I doing wrong? The element.timage should change itself and the element . rimage when selected, but only the element.timage should be clickable.
function myFunction(x) {
if (x.target.matches('.timage'))
this.classList.toggle('change');
}
document.querySelector('.container4').addEventListener('click', myFunction);
.container4 {
cursor: pointer;
display: inline- block;
}
.timage {
position: relative;
left: 50px;
}
.change .timage {
left: 200px;
}
.rimage {
position: relative;
left: 200px;
}
.change .rimage {
position: relative;
left 500px;
}
<a id="mobile-nav" href="#">
<div class="container4" onclick="myFunction
(this,event)">
<div class="container4">
<div class="timage"><img class="size-medium wp-
image-13846" src="http://4309.co.uk/wp-
content/uploads/2020/05/
IMG_20200509_104613-
288x300.jpg" alt="" width="70" height="300" />.
</div>
<div class="rimage">
<img class="size-medium wp-
image-13669" src="http://4309.co.uk/
wp-content/uploads
/2020/05/IMG_20200508_1
30758-287x300.jpg" alt="" width="90" height="300" />.
</div>
</div>
</a>
You're probably clicking the img, not the div that the image is in, so event.target is the img.
To find the nearest ancestor (starting with the current element) that matches a selector, use closest.
You're also using myFunction both in onclick="myFunction(this,event)" and in an addEventListener call. Those will provide different arguments to the function. Remove the onclick and just use addEventListener.
Here's the updated function:
function myFunction(x) {
const timage = x.target.closest(".timage");
if (timage && this.contains(timage)) {
this.classList.toggle('change');
}
}
The reason for the contains is just completeness and in many cases you can leave it off: It's to defend against closest having gone past the container element and found the match in the container's ancestors. That won't happen with your layout because timage is only used with the container, but for more general situations, I include that check. For instance:
<div class="x">
<div id="container">
<div class="x">xxx</div>
<div class="y">yyy</div>
</div>
</div>
There, if I have click hooked on #container and the user clicks yyy and I'm doing const x = event.target.closest(".x"), I'll get the .x that's the parent of the container. So this.contains(x) weeds those out.

Insert HTML or append Child onClick, and remove from previous clicked element

I have a set of div elements inside a container, .div-to-hide is displayed by default whilst .div-to-show is hidden.
When I click in .set, .div-to-hide should hide and .div-to-show should be visible. Next click should return the previous clicked element to its default state.
I need to display to buttons on click inside on .div-to-show.
<div class="container">
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
</div>
So far I have this:
let lastClicked;
$('.container').on('click', function(e) {
if (this == lastClicked) {
lastClicked = '';
$('.div-to-hide').show();
$(this).children('.div-to-hide').hide();
} else {
lastClicked = this;
$('.div-to-hide').hide();
$(this).children('.div-to-hide').show();
$(this).children('.div-to-show').hide();
}
});
Can't get it to work properly tho.. I don't know what I am missing...
Any help is deeply appreciated!
UPDATE: got it working! Thanks everyone!
First, you are not using delegation (second parameter on the $.on() function) to define the .set element as your this inside the function.
If I understood correctly, you want to show the elements on the last one clicked and hide the rest. You don't really need to know which one you last clicked to do that
$('.container').on('click', '.set', function (e) {
// Now "this" is the clicked .set element
var $this = $(this);
// We'll get the children of .set we want to manipulate
var $div_to_hide = $this.find(".div-to-hide");
var $div_to_show = $this.find(".div-to-show");
// If it's already visible, there's no need to do anything
if ($div_to_show.is(":visible")) {
$div_to_hide.show();
$div_to_show.hide();
}
// Now we get the other .sets
var $other_sets = $this.siblings(".set");
// This second way works for more complex hierarchies. Uncomment if you need it
// var $other_sets = $this.closest(".container").find(".set").not(this);
// We reset ALL af them
$other_sets.find(".div-to-show").hide();
$other_sets.find(".div-to-hide").show();
});
Consider using class toggling instead.
$('.set').on('click', function(e) {
$('.set').removeClass('hidden-child');
$(this).addClass('hidden-child');
});
css:
.hidden-child .div-to-hide, .div-to-show {
display: none;
}
.hidden-child .div-to-show, .div-to-hide {
display: block;
}
This will make your code easier to reason about, and lets css control the display (style) rules.
Edit: changed class name for clarity; expanded explanation; corrected answer to conform to question
Try to make use of siblings() jQuery to hide and show other divs and toggle() jQuery to show and hide itself and also you will need to set click() event on .set, not in .container
$(document).on('click', '.set', function(e) {
$(this).find('.hide').toggle();
$(this).find('.show').toggle();
$(this).siblings('.set').find('.hide').show();
$(this).siblings('.set').find('.show').hide();
});
.show {
display: none;
}
.set div {
padding: 10px;
font: 13px Verdana;
font-weight: bold;
background: red;
color: #ffffff;
margin-bottom: 10px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="set">
<div class="hide">1 Hide</div>
<div class="show">1 Show</div>
</div>
<div class="set">
<div class="hide">2 Hide</div>
<div class="show">2 Show</div>
</div>
<div class="set">
<div class="hide">3 Hide</div>
<div class="show">3 Show</div>
</div>
</div>

Menu drawer toggle (slide up/down)

I have a simple menu and from it, i am using jQuery to toggle visibility of few DIV's.
Code is pretty straightforward, like bellow, and if i am not asking too much, i could use some help with additional functionalities.
<div id="one" class="navLinks"> content 1 </div>
<div id="two" class="navLinks"> content 2 </div>
<div id="three" class="navLinks"> content 3 </div>
<div class="nav">
<nav>
1
2
3
Normal Link
</nav>
</div>
$('nav a').click(function() {
$('.navLinks').hide();
$(this.getAttribute('href')).slideToggle('slow')
});
So, currently, if the user click on the link, a div will slide from the top, but except that, i would need 2 more things.
If user opens, lets say link no.2, and after that, he wants to close it by clicking on the same link, div should slide up (instead of down like it currently does).
Similiar to this, if the user opens link no2, and after that wants to open link no1, after the click, that div would need to slide up and be shown.
I know i am asking too much, but any help would be greately appreciated.
FIDDLE http://jsfiddle.net/4rfYB/38/
I suggest using jQuery's not() to exclude the requested element from those being hidden.
That way, you can hide all content areas that are not the requested one.
I've also used slideUp('slow') instead of hide(), purely for stylistic reasons.
$('nav a').click(function() {
var $requested = $(this.getAttribute('href'));
$('.navLinks').not($requested).slideUp('slow');
$requested.slideToggle('slow')
});
.navLinks {
display: none;
color: white;
}
div#one {
background: red;
height: 100px;
}
div#two {
background: blue;
height: 80px;
}
div#three {
background: black;
height: 60px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav">
<nav>
1
2
3
</nav>
</div>
<div id="one" class="navLinks">content 1</div>
<div id="two" class="navLinks">content 2</div>
<div id="three" class="navLinks">content 3</div>
You can do something like this:
$('nav a').click(function() {
$(this.getAttribute('href')).toggleClass('open').slideToggle('slow',function() {
$(this).siblings('.open').slideToggle('slow').toggleClass('open');
});
});
http://jsfiddle.net/4rfYB/39/

how to toggle visibility of div on mouseover of another a tag

I will try to be as simple as possible, i am trying to achieve a simple visibility toggle on a div when someone mouseover an a tag, kind of like this the four buttons on this link:
http://www.bt.com/help/home/
now the problem is i want it to appear or want it to be visible on mouseover of a tag, but when once i hide the div it never comes back, i have tried multiple things, some are
$("#function").on("mouseover",this, function () {
$(this).addClass("show");
})
$("#function").on("mouseout",this, function () {
$(this).removeClass("show");
$(this).addClass("hide");
})
Another is:
$("#function").hover(
function () {
$(this).addClass("hide");
},
function () {
$(this).removeClass("hide");
}
);
and also
$("#butt").on("mouseover", this, function(){
$(this).find("div#function").show();
//$("#function").toggleClass("visible");
});
$("#butt").on("mouseout", this, function(){
$(this).find("div#function").hide();
//$("#function").toggleClass("visible");
});
You should use mouseenter instead of mouseover. It is because mouseover event will be triggered when you move within the element. Go here and scroll to the bottom to check the different between mouseover and mouseenter. http://api.jquery.com/mouseenter mouseenter event will be fired only when you entering the element but not move within element.
This is the solution you want. It is almost similar to the site you provided.
JavaScript
<script>
$(document).ready(function()
{
$("#function").mouseenter(function(event)
{
event.stopPropagation()
$(this).addClass("show");
}).mouseleave(function(event)
{
event.stopPropagation()
$(this).removeClass("show");
})
});
</script>
Style
<style>
.functionBlock { width:200px; height:200px; border:1px solid #CCC; padding:15px;}
.functionBlock ul { visibility: hidden}
.functionBlock.show ul { visibility: visible;}
</style>
HTML
<div id="function" class="functionBlock">
<h5>Demo </h5>
<ul>
<li>APPLE</li>
<li>SAMSUNG</li>
</ul>
</div>
Example on jsFiddle http://jsfiddle.net/TAZmt/1/
I got it, slight changes in selectors
$("#butt")
.mouseover(function () {
$("#function").show();
})
.mouseout(function () {
$("#function").hide();
});
$("#link").hover(function(){
$("#DIV").slideToggle();
});
and the html is
LINK
<div id="DIV" style="display:none">Your content in it</div>
This should do it. Check the jsfiddle. The basic idea here is to add a class (.shown) to your root-div on the mouseenter event, this class then makes the hidden <ul> in the div show up due to.
.shown ul{
display: block !important;
}
http://jsfiddle.net/28bb8/2/
EDIT:
Made some minor css changes, to better reflect the behaviour you're looking for, but you have to change the css to accommodate your own code basically. I hope this helps.
$("document").ready(function(){
$(".wrap").hover(
function () {
$(this).addClass("shown");
},
function () {
$(this).removeClass("shown");
}
);
});
You don't need Javascript here. This is possible with CSS alone
HTML:
<div class="panel">
<div class="teaser"><img src="http://lorempixel.com/300/400"/></div>
<div class="info">
<ul>
<li>Go here ...</li>
<li>Or there ...</li>
</ul>
</div>
</div>
CSS:
.panel {
width: 300px;
height: 400px;
}
.info {
display: none;
}
.panel:hover .teaser {
display: none;
}
.panel:hover .info {
display: block;
}
And JSFiddle for playing.
i hope this is the solution you're seaching for.
Just place the following code below your <body> tag:
<script type="text/javascript">
function toggle(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
</script>
And here is a link and the div which is toggled:
<a href="javascript: return false();" onmouseover="toggle('toggleme');">
Mouseover this link to toggle the visibility of #toggleme
</a>
<div id="toggleme">This div is "toggled"</div>

Best practice for a button with image and text in mobile website

Refer to the screenshot below, I have created a div to wrap another two div of image and text, then I use CSS position: absolute to make these div merge together.
However, I found that the button is not sensitive while testing on mobile devices, sometime I need to touch the button few time to take effect.
So, is there something wrong for my code and what is the best practice to create a button with image and text?
Thanks
<div class="r">
<div class="a">
<div class="i"><img src="store_btn_on.png" /></div>
<div class="t">Shatin</div>
</div>
<div class="b">
<div class="i"><img src="store_btn_off.png" /></div>
<div class="t">Causeway Bay</div>
</div>
<div class="c">
<div class="i"><img src="store_btn_off.png" /></div>
<div class="t">Kowloon Bay</div>
</div>
</div>
Update for the part of javascript
addButtonListener($("#store > .r > .a"), function(event, target){
$("#some_content").css("display", "none");
$("#other_content").css("display", "block");
$(".r > .b > .a > img").attr("src" , "store_btn_on.png");
$(".r > .b > .b > img, .r > .b > .c > img").attr("src" , "store_btn_off.png");
});
function addButtonListener(targets, job){
if ("ontouchstart" in document.documentElement){
targets.each(function(){
$(this)[0].addEventListener('touchstart', function(event){
event.preventDefault();
$(this).attr({ "x": event.targetTouches[0].clientX, "diffX": 0, "y": event.targetTouches[0].clientY, "diffY": 0 });
$(this).addClass("on");
}, false);
$(this)[0].addEventListener('touchmove', function(event){
$(this).attr({
"diffX": Math.abs(event.targetTouches[0].clientX - $(this).attr("x")),
"diffY": Math.abs(event.targetTouches[0].clientY - $(this).attr("y"))
});
}, false);
$(this)[0].addEventListener("touchend", function(event){
$(this).removeClass("on");
if ($(this).attr("diffX") < 5 && $(this).attr("diffY") < 5){ $(job(event, $(this))); }
}, false);
});
}
else {
targets.each(function(){
$(this).mousedown(function(event){ event.preventDefault(); $(this).addClass("on"); });
$(this).mouseup(function(event){ event.preventDefault(); if ($(this).hasClass("on")){ $(job(event, $(this))); } $(this).removeClass("on"); });
$(this).hover(function(event){ $(this).removeClass("on"); });
});
}
}
I am not sure about the sensitivity of your button on mobile devices (you haven't shown any of your code for handling click events), but I think it is better to write your HTML like this:
<div class="r">
<div class="button on">
<span>Shatin</span>
</div>
<div class="button">
<span>Bay</span>
</div>
<div class="button">
<span>Bay</span>
</div>
</div>
Then use CSS in your stylesheet:
.button {
background: url(http://domain.com/images/store_btn_off.png) no-repeat 0 0;
/* Additional button styles */
}
.button.on {
background: url(http://domain.com/images/store_btn_on.png) no-repeat 0 0;
}
.button span {
color: #FFF;
margin: auto;
}
This makes it easy to dynamically turn a button on or off just by adding or removing the on class.
Although not necessary, you may also be interested in looking at CSS3 gradients to create simple gradient background images like that, and then degrade nicely to an image in browsers without any gradient support.
The class names "r" and "b" are not very descriptive. Unless some HTML/CSS minifier put those there and you have proper names in your development code, I would consider giving your classes more descriptive names as well.

Categories

Resources