Using outerHeight(); to measure the same class name, but with different heights - javascript

The distance of the animation depends on the item0 height. However, when I use a secondary class to change the height of the div, the jQuery does not takes the new height into practice.
Is it possible to factor in the new height, given by the new class name?
http://jsfiddle.net/tmyie/28N7M/1/
jQuery:
var height = $('.item0').outerHeight();
$('p').click(function(){
$('.item0').animate({top:height}, 300);
});
HTML:
<p>click here</p>
<div class="item0"></div>
<div class="item0"></div>
<div class="item0"></div>
<div class="item0 half"></div>
CSS
.item0 {
background-color: red;
height: 50px;
width: 25px;
float: left;
margin-left: 5px;
position: relative;
}
.half {
height: 10px;
background-color: blue;
}

$('p').click(function(){
var $this;
$('.item0').each(function() {
$this = $(this);
$this.animate({
top: $this.outerHeight()
}, 300);
});
});
DEMO

You are first calculating the height, and then defining the click event handler. Obviously you've only calculated the height once and you should recalculate it again. Also you need to calculate it for every item.
Simply calculate the height on click:
$('p').click(function () {
$('.item0').each(function() {
var height = $(this).outerHeight();
$(this).animate({top:height}, 300);
});
});

Related

Always scroll the div container to the bottom when creating child divs

first these are my references
jQuery Scroll to bottom of page/iframe
jQuery Scroll To bottom of the page
I create some divs and put them into a div container. I want the container always scrolling down to the newest div at the bottom.
$(document).ready(function() {
var container = $("#container");
var i = 0;
$("#btn").click(function() {
i++;
var div = $("<div></div>");
div.addClass("d");
div.html("Container " + i);
container.append(div);
container.scrollTop(container.height());
});
});
body {
background: white;
}
#container {
height: 160px;
width: 120px;
overflow-y: scroll;
background: gray;
}
.d {
height: 30px;
margin-bottom: 10px;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">-- Add --</button>
<div id="container">
</div>
As you can see, this works fine untill I create more than 8 divs. Then the logic will break and the container does not scroll anymore.
The container should scroll to the current div with the number i (the current index)
Simply because the height is always fixed, instead consider scrolling with the height of all the child elements including their top/bottom margin. In other words, the height of the container if there is no fixed height specified.
To be more precise you only need to scroll with the height of all the child element minus the fixed height of the container which is the overflowing part. That's why your code work partially because until 8 elements you have an overflow lower than the fixed height of the container ( 8 * 40 = 320 => 320 - 160(fixed height) = 160(overflow) )
$(document).ready(function() {
var container = $("#container");
var i = 0;
$("#btn").click(function() {
i++;
var div = $("<div></div>");
div.addClass("d");
div.html("Container " + i);
container.append(div);
container.scrollTop(container.find('.d').length *
($('.d').height() + 10) -
container.height());
});
});
body {
background: white;
}
#container {
height: 160px;
width: 120px;
overflow-y: scroll;
background: gray;
}
.d {
height: 30px;
margin-bottom: 10px;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">-- Add --</button>
<div id="container">
</div>

javascript: change CSS position by relative amount

Basically what I'm trying to do is every time the JavaScript is executed (by click), the CSS left value for my <div> descreases by 20%. So, for example, left starts at 40%. The first time you click it should become 20%, and then 0%, and then -20%, and so on. I've updated my code below:
FilmstripLeft = parseInt(document.defaultView.getComputedStyle(ul).left, 10) / 4;
ul.style.left = (FilmstripLeft - 20) + "%";
ul is a <div> I get using document.getElementById(). This code works now, but I'm unsure about the divided by 4 at the end of the first line. I tested than that line was returning a value of 160 before I added the / 4 at the end, even though the starting value is 40%. I'm not sure if this is because it's returning the value in pixels instead of percent, in which case dividing by 4 would only work if left is at 160px?
"left" value for my div descreases by 20%
No. According to your explanation, you want to decrease it by 20 percentage points, not by 20%.
getComputedStyle(ul).left
Be aware percentages are relative units. When computed, they are transformed to an absolute length.
You can only access the raw percentage as an inline style
var target = document.getElementById("target");
document.querySelector('input').addEventListener('click', function() {
target.style.left = parseFloat(target.style.left) - 20 + '%';
});
#target {
position: relative;
width: 30px;
height: 30px;
background: blue;
}
<div id="target" style="left: 80%"></div>
<input type="button" value="Click" />
But you don't need the raw percentage in order to subtract 20 percentage points. You can use calc:
var target = document.getElementById("target");
document.querySelector('input').addEventListener('click', function() {
var current = getComputedStyle(target).left;
target.style.left = 'calc(' + current + ' - 20%)';
});
#target {
position: relative;
left: 80%;
width: 30px;
height: 30px;
background: blue;
}
<div id="target"></div>
<input type="button" value="Click" />
getComputedStyle() won't work well for your purposes because it, by definition, returns the computed value of the style in terms of pixels, not the relative percentage of the original value. In order to calculate what "20%" is using computed styles, you will have to do it manually by finding the parent element's width and then taking 20% of that:
function onClick(){
var myElement = document.getElementById("inner");
var leftValue = parseFloat(window.getComputedStyle(myElement).left);
var parentElement = myElement.parentElement;
var parentWidth = parseFloat(window.getComputedStyle(parentElement).width);
var twentyPercent = parentWidth * 0.20;
var newLeftValue = (leftValue - twentyPercent) + "px";
myElement.style.left = newLeftValue;
updateStatus();
}
function updateStatus(){
document.getElementById("status").innerHTML = window.getComputedStyle(document.getElementById("inner")).left;
}
updateStatus();
document.getElementById("btn").addEventListener("click", onClick);
#outer {
width: 400px;
height: 20px;
background: #888;
}
#inner {
width: 20px;
height: 20px;
position: relative;
left: 80%;
background: red;
}
<div id="outer">
<div id="inner"></div>
</div>
<button id="btn">click me</button>
<div id="status"></div>
The downside of this method is that it fixes left as a pixel value instead of a true percentage of the parent, so if the window/parent width changes, the left value won't match properly.
It's easier if the left value is an inline HTML style instead of a CSS style because you can get it directly with element.style, which reads the inline HTML style value. Then you can assign a new left value as a true percentage that will update if the window/parent width changes.
function onClick(){
var myElement = document.getElementById("inner");
// Note how #inner's left value is now inline instead of CSS
var leftValue = parseFloat(myElement.style.left);
var newLeftValue = (leftValue - 20) + "%";
myElement.style.left = newLeftValue;
updateStatus();
}
function updateStatus(){
document.getElementById("status").innerHTML = document.getElementById("inner").style.left;
}
updateStatus();
document.getElementById("btn").addEventListener("click", onClick);
#outer {
width: 400px;
height: 20px;
background: #888;
}
#inner {
width: 20px;
height: 20px;
position: relative;
background: red;
}
<div id="outer">
<div id="inner" style="left: 80%"></div>
</div>
<button id="btn">click me</button>
<div id="status"></div>
So, if possible, put your styles inline instead of into CSS because they're easier to access. Technically it is possible to access CSS stylesheet rules using JavaScript but it is very convoluted and I don't recommend it if you're new to web development.

How to move an image/div from right to left continuously?

What I'd like to do is animate a small image as well as a div (or an image within a div) from the right to the left of the screen, repeating once the image/div leaves the screen.
I found an example online that moves an image/div from left to right, but not all the way to the other side of the screen, and I am struggling to make it from right to left.
Here's what I have been doing
function moveTruck() {
$("#ImageToMove").animate({
"margin-right": "5000px"
}, 3000, function () { $("#ImageToMove").css("margin-right", "10000"); moveTruck(); });
}
moveTruck();
Playing with the margin-right values. My CSS class is:
.HomeImageAnimate{
position:absolute;
margin-top:80px;
right:1000px;
}
Try setting , animating left property using values of window.innerWidth , container element width
(function fx(el) {
$(el).css("left", window.innerWidth)
.animate({
left: "-" + (window.innerWidth - $(el).width() * 2)
}, 3000, "linear", function() {
fx(this)
})
}($("div")))
body {
overflow: hidden;
}
div {
width: 50px;
height: 50px;
position: absolute;
}
img {
background: gold;
width: 50px;
height: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div>
<img />
</div>
Try this out, this truck div repeatedly goes from right to left.
HTML:
<div class="truck"></div>
CSS:
body{
background: green;
overflow: hidden;
}
.truck {
margin-top:20px;
width: 272px;
height: 174px;
cursor:pointer;
position: absolute;
margin-right: -150px;
z-index: 3;
background: red;
border-radius:4px;
width:200px;
height:50px;
}
JS:
$(function() {
var moveTruck = function(){
$(".truck").delay(2000).animate( {'right': '120%' }, 5000,'linear',function(){
$(this).css({'right': '-50px'});
moveTruck();
});
}
moveTruck();
})
CODEPEN DEMO
function move(){
width = $(window).width();
objectWidth = $('#demo').width();
margin = width + objectWidth + 'px';
restart = -100 - objectWidth + 'px';
$('#demo').animate({
'margin-left': margin
}, 3000, function(){
$('#demo').css('margin-left', restart);
move();
});
}
move();
Try this out, it calculates the exact width of object and window - should always work no matter the screen size. You were trying to use an absolute pixel value, won't always work.
https://jsfiddle.net/w9pgmm9d/3/

How to trigger the layout to change?

I've a sticked element which gets the top-alignment from current scroll-offset. Problem is, that the layout is not "retriggerd" if the space from it is free. So there stays a ghost-gap where the sticked element was...
http://fiddle.jshell.net/pPc4V/
The markup is pretty simple:
...
as well as the js:
var $win = $(this);
var sticked = document.querySelector('a.sticked');
$win.on('scroll', function () {
var scrollTop = $win.scrollTop();
sticked.style.top = scrollTop + 'px';
// $win.resize();
});
...and the css looks good so far:
a {
display: inline-block;
width: 90px;
height: 90px;
background: deepskyblue;
}
.sticked {
position: relative;
top: 0;
left: 0;
background: tomato;
}
I tried to trigger the resize-event on scroll (as you see above uncommented), but no success! Any ideas, how to retrigger the layout so that the free-gap is filled with the next floated element?
Update
To clarify what I mean I made a simple image-timelime:
Step 1
Step 2
Step 3
The issue is that you are setting position fixed on an element which is displayed inline. That will cause that space to occur. I have redid your jsFiddle with proper alignment.
To fix it, I added the class "stuck" only when the document's scrollTop position is greater than the scrollTop position of your target element.
jsFiddle: http://fiddle.jshell.net/pPc4V/44/
HMTL:
<div id="grid">
etc...
</div>
CSS:
#grid {
height:1000px;
overflow:hidden;
float:left
}
#grid > a {
display: inline-block;
width: 90px;
height: 90px;
background: deepskyblue;
}
.stuck {
position: fixed;
background: navy !important;
}
JS:
$(window).on('scroll', function () {
var $doc = $(document),
parentElement = $('#grid'),
childToGetStuck = parentElement.find('a:nth-child(5)');
if ($doc.scrollTop() > childToGetStuck.scrollTop()) {
childToGetStuck.addClass('stuck');
//console.log($('.stuck').scrollTop())
} else {
childToGetStuck.removeClass('stuck');
}
});

Animation for the automatic height change when content is resized with javascript

I want to control the automatic height change of the container when I add something that changes the lenght of the content. Right now, if I apply a innerHTML change on the content, the height is changed accordingly. I want to apply a transition to that height change. How can I do that? ( I can also use jQuery )
Record the height before changing the content, change the content, record the height after, set the height to the former height, and animate to the latter height. When the animation has completed, set the height to be automatic again. You can do this using height and animate.
Try it on JSFiddle.
var texts = [
"This is just some sample text that's being used to demonstrate animating the height when content changes.",
"Shorter."
];
var div = $('div').click(changeContent);
function changeContent() {
var oldHeight = div.height();
texts.push(div.text());
div.text(texts.shift());
var newHeight = div.height();
div.height(oldHeight);
div.animate({height: newHeight}, 'fast', function() {
div.height('auto');
});
}
div {
width: 150px;
background: lightgray;
overflow-y: hidden;
}
<div>This is some example content.</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="containter" style="overflow:hidden">
<div>
Content.....
</div>
</div>
//add something...
$('#container').animate({height:$('#container').content().outerHeight()});
or:
$('#container').animate({height:$('#container').children().first().outerHeight()});
and when adding append to the div inside the containter:
$('#container').children().first().append(somethingNew);
Based on icktoofay's answer.
I make the button disabled while changing the height and add a fading effect. This solution is useful for updating of the products filter and so on.
Also I check the box-sizing property. If it's box-sizing then I get newHeight by .outerHeigth() instead of .height() to prevent the height fluctuation when new content has the same height. You can check this situation, for example by setting the random variable to value 5. The reason is that
.height() will always return the content height, regardless of the value of the CSS box-sizing property.
CodePen
$('#button').click(function() {
var $button = $(this),
buttonOriginalText = $button.html();
$button.prop('disabled', true).html('Updating...');
$('#content').animate({
opacity: 0
}, 'fast', function() {
var newHeight,
$content = $(this),
oldHeight = $content.height();
$content.html(getRandomContent());
newHeight = ('border-box' === $content.css('box-sizing') ? $content.outerHeight() : $content.height());
$content.height(oldHeight).animate({
height: newHeight,
opacity: 1
}, 'slow', function() {
$content.height('auto');
$button.prop('disabled', false).html(buttonOriginalText);
});
});
});
function getRandomContent() {
var random = 1 + Math.round(Math.random() * 11), // 1..12
paragraph = '<p>Paragraph</p>';
return paragraph.repeat(random);
}
* {
box-sizing: border-box; /* comment out to test "content-box" */
font: 16px Helvetica, 'sans-serif';
}
.content {
counter-reset: content;
padding: 6px 18px;
}
.content p {
counter-increment: content;
}
.content p:after {
content: ' ' counter(content) '.';
}
.content-box {
border: 2px solid red;
margin-top: 24px;
max-width: 220px;
}
<button id="button" class="button">Update the content</button>
<div class="content-box">
<div id="content" class="content">Animatie the automatic height when content is resized.</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

Categories