Move an <img> when button pressed - javascript

Here is my code that I am currently using for the function, I have made imgs move in the past using key codes but what I used a function to move it for me, the code looks like it should work there is probably just a silly error:
<!DOCTYPE html>
<html>
<head>
<title>Return To Alnerwick</title>
<style>
body
{
background-image: url("https://s-media-cache-ak0.pinimg.com/736x/e8/d6/fc/e8d6fc15671a05eeaf592f85c6dbb2db.jpg");
background-size: 1500px 1000px;
background-repeat: no-repeat;
}
img
{
position:absolute;
TOP:650px;
LEFT:750px;
width:100px;
height:100px
}
</style>
<script>
function move() {
var element = document.getElementById("char");
element.style.left = parseInt(element.style.left) - 90 + 'px';
}
</script>
</head>
<body>
<img id="char"src="/New Piskel (5).gif">
<button onclick="move();">move</button>
</body>
</html>

It's because you are using a stylesheet. When using a stylesheet, you have get the computed styles:
function move() {
var element = document.getElementById("char");
var style = window.getComputedStyle(element);
console.log("Current value: " + style.left);
element.style.left = (parseInt(style.left) - 90) + 'px';
}
See a working fiddle: https://jsfiddle.net/vgb7tc03/1/
Also getComputedStyle reference: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

In your move function, you are referencing element.style.left. This is the element's inline style property. That inline style property is not defined in your markup at all.
You are defining the LEFT property in your css (not inline). What you will need to do is either reference the LEFT css property from your function, or set the left property inline in your element instead of in CSS.

Your problem is that element.style.left won't return its position. There are a couple of solutions:
1) You know that your image is already 750px from the left so you can just go
var img_left=750;
at the beginning of your script tag and then go
img_left=img_left-90;
element.style.left = img_left + "px";
in your function.
2) if you want to get the position of the element, you would go
element.getBoundingClientRect().left;
instead of element.style.left so the whole line would be
element.style.left=(element.getBoundingClientRect().left-90)+"px";

Related

How to increment progressively the margin left using DOM

I have an image of a black cat
I want to progressively increase its width and also make the image moving from left to right increasing its own left margin.
I can't understand why the width is increased and the margin-left shows NaN value.
Down here the Html :-
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cat Walk</title>
</head>
<body>
<img id="cat-gif" style="position:absolute;" src="http://www.anniemation.com/clip_art/images/cat-walk.gif">
<script src="main.js"></script>
</body>
Down here the function to make move the cat:-
var catWalk = function() {
var cat = document.getElementById("cat-gif");
cat.setAttribute('width', cat.width+10); //THIS WORKS
cat.setAttribute('marginLeft', cat.marginLeft+10); //THIS DOES NOT WORK!
}
//Call to the function
window.setInterval(catWalk, 500);
try using the following:
cat.style.marginLeft = (parseInt((cat.style.marginLeft) || parseInt(window.getComputedStyle(cat).marginLeft))) + 10 + 'px';
instead of cat.setAttribute('marginLeft', cat.marginLeft+10); there is no attribute marginLeft by default on your Element. So you gotta go by getting the computed styles and add it to your style attribute then you can access it.
Margin left is not a attribute hence it does not work in your case.
its a style property hence you need to do it differently
replace
cat.setAttribute('marginLeft', cat.marginLeft+10);
with
var p = cat.style.marginLeft; // return value in px; i.e 50px
p = p.substr(0,p.length-2); // remove px ie : 50px becomes 50
cat.style.marginLeft = (+p)+ 10 +'px' // convert p to number and add 10

Insert inline element and animate shift to left

I've been trying to solve this problem for a week now and it seems basic, so maybe I'm missing something.
I want to have a div centered on the screen (or its container), and then insert a second div to the right of it, so that afterwards the two of them are centered (space on each side is equal).
Inserting the second div is not a problem, but I need the first block to slide over to where its going to be after the new block is inserted.
http://jsfiddle.net/rdbLbnw1/
.container {
width:100%;
text-align:center;
}
.inside {
border:solid 1px black;
width:100px;
height:100px;
display:inline-block;
}
$(document).ready(function() {
$("#add").click(function() {
$(".container").append("<div class='inside'></div>");
});
});
<div class="container">
<div class="inside"></div>
</div>
<input id="add" type="button" value="add"/>
Do I need to explicitly calculate where the original box is going to end up and then animate that, or is there a better way to do it?
I like your question so decide to write this:
$(document).ready(function() {
var isInAction = false;
var intNumOfBoxes = 1;
var intMargin = 10;
$containerWidth = $(".container").width();
$insideWidth = $(".inside").width();
$(".inside").css('margin-left',($containerWidth - $insideWidth - intMargin)/2 + 'px');
$("#add").click(function() {
if (!isInAction){
isInAction = true;
intNumOfBoxes +=1;
$(".current").removeClass("current");
$(".container").append("<div class='inside current'></div>");
$('.inside').animate({
'margin-left': '-=' + ($insideWidth + intMargin)/2 + 'px'
}, 300, function () {
$(".current").css('margin-left',($containerWidth + ((intNumOfBoxes - 2) * ($insideWidth + intMargin)))/2 + 'px');
$(".current").fadeIn(500,function(){
isInAction = false;
});
});
}
});
});
Also add this class in CSS:
.current {
display:none;
}
You don't need to change variables in JS code except intMargin. you can change this var to set margin between boxes.
Note: This code works fine on older browsers too and not need to support CSS3 features like transition.
Update: Some bugs like repeated clicks fixed.
Check JSFiddle Demo
First, we can animate only things that have explicit numerical values such as width, left or margin. We can't animate things like alignment (which actually use the same margin property but implicitly, never mind). So if we know width of inserted div let's just add it to our container.
1) Let's centre container itself and add transition to it
.container {
width: 102px; /* set explicit width; 102 - because of borders */
margin: auto; /* set margin to 'auto' - that will centre the div */
transition: width 0.5s;
}
2) Then increase the width when add div
$(".container").width($(".container").width() + 102);
3) But wait! If we add div to too narrow container it will be added to bottom not to right. So we need another container set to appropriate width before.
See final example on JSFiddle.
BTW, remove all line breaks and tabs from your code when you use inline-block, because it will cause spaces between your blocks.

JavaScript: Get window width minus scrollbar width

Ok, I thought this would be really simple, but it's turning out not to be. I think I'm just messing something up in my HTML/CSS, but here goes.
I have a basic page like so:
HTML
<!DOCTYPE html>
<html>
<head>
<link href='test2.css' rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="test2.js"></script>
</head>
<body>
<div id="scroll"></div>
</body>
</html>
test2.css
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
width: 100%;
}
#scroll {
height: 100%;
width: 100%;
overflow: scroll;
background-color: black;
}
test2.js
$(document).ready(function() {
// my resolution is 1440x900
alert('innerwidth should be 1425');
// all of these return 1440
alert('body innerwidth: ' + $('body').innerWidth());
alert('document width: ' + $(document).width());
alert('window width: ' + $(window).width());
alert('scroll div innerwidth: ' + $('#scroll').innerWidth());
alert('document.documentElement.clientWidth: ' + document.documentElement.clientWidth);
alert('document.documentElement.scrollWidth: ' + document.documentElement.scrollWidth);
});
So I've got one element on the page... a div that takes up the entire screen, or rather it should be taking up the entire screen minus the scrollbars. Now, I've been doing some snooping on how to grab the width and height of a page without the scrollbars, but unfortunately, none of them return the proper value... which makes me believe I'm missing the boat in my HTML or CSS.
I looked at the following:
jquery - how to get screen width without scrollbar?
how to get the browser window size without the scroll bars
So what I need is for a method to return the value of my viewable screen minus the respective scrollbar value... so for my width, my value should be 1425 because the scrollbar is 15 pixels wide. I thought that's what innerWidth's job was, but apparently I'm wrong?
Can anyone provide any insight? (I'm running Firefox 24.)
EDIT
To add some background, I've got a blank page. I will be adding elements one by one to this page, and I need to use the width of the page when calculating the sizes for these elements. Eventually, this page will grow and grow until the scrollbar appears, which is why I'm trying to force the scrollbar there from the start, but apparently, that still doesn't do anything.
EDIT2
Here's something even more interesting... if I do document.getElementById('scroll').clientWidth, I get the proper innerWidth, but if I do $('#scroll').width() or $('#scroll').innerWidth(), they both return the max resolution... sounds like a jQuery bug.
I got this somewhere and would give credit if I knew where, but this has been succesfull for me. I added the result as padding when setting the html overflow to hidden.
Problem is that the scrollbar is a feature of the browser and not the web page self. Measurement should be done dynamically. A measurement with a scrollbar and a measurement without a scrollbar will resolve into calculating the difference in width.
Found the source: http://www.fleegix.org/articles/2006/05/30/getting-the-scrollbar-width-in-pixels
scrollCompensate = function () {
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild(inner);
document.body.appendChild(outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;
document.body.removeChild(outer);
return (w1 - w2);
}
var htmlpadding = scrollCompensate();
The correct answer is in this post marked as accepted:
CSS media queries and JavaScript window width do not match
This is the correct code:
function viewport() {
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
Discovered a very hacky solution... by adding this before my alerts in test2.js, I get the proper width:
var p = $('body').append('<p style="height: 100%; width: 100%;"></p>');
alert(p.width());
$('body').remove('p');
And consequently, all of the alerts now have the proper width. I also don't even need overflow-y in the CSS if I do it this way. Curious why this solves it...
The real answer should be keeping the HTML and CSS as is, then using document.getElementById('scroll').clientWidth. Using clientWidth gets the viewable area minus the scrollbar width.
The correct width of the page is given by $(document).width().
Your problem is that you're using a scroll within the div (overflow: scroll).
Using $(document).width() the returned value is already discounting the visible width of the scroll, but how do you put a scroll within the div value returned is no longer the same.
As the width of the scroll is not standard and varies from system to system and browser to browser, it is difficult to solve.
I suggest you remove the scroll of the div and let the browser manage this by default in the body, then yes you have the correct width.

Can't get left position with global stylesheet in JavaScript

I need to get the upper left position of an image in JavaScript. I define the location of an image in a global style sheet:
<style type="text/css">
img.movable { position:relative; top:0px; left:375px; }
</style>
When I define the image using the global style
<img id="image11" class="movable" src="testimage.jpg" onclick="jump()" />
The style.left attribute is empty:
<script type="text/javascript">
function jump() {
xpos = document.getElementById("image11").style.left;
alert( "style.left="+xpos );
xpos = document.getElementById("image11").offsetLeft;
alert( "offsetLeft="+xpos );
}
</script>
But when I define the image using an inline style:
<img id="image11" style="position:relative; top:0px; left:375px;" src="logo.jpg" onclick="jump()" />
style.left contains a value.
This behaviour is the same for IE8 and Firefox. Any ideas why that is?
Cheers,
Martin.
el.style is actually a map of all the css properties applied using the style attribute. To get styles defined in stylesheets or default browser styles, you need to use computed style. Quirksmode, as usual, is a first stop.
The DOM element that represents the IMG tag you specified has its own style property, and its values will override any given by globals. Unfortunately in this case, the property of the element you specified will indeed be empty, as the values do not cascade down to the JavaScript object level.
You will need to get the position from either the offsetLeft property or the CSS rule itself.
.style properties only relate to inline css. Styles specified in a stylesheet will thus not be present in the .style list. If you want to get the position of an element on the page (as opposed to viewport) something like this should work:
function getNodePosition(node) {
var top = left = 0;
while (node) {
if (node.tagName) {
top = top + node.offsetTop;
left = left + node.offsetLeft;
node = node.offsetParent;
} else {
node = node.parentNode;
}
}
return [top, left];
}
Adapted from Quirksmode. OffsetTop and OffsetLeft are wrt to the parent, so this iterates up the tree to get the total offsets, and hence page position. If you want to know the position wrt the viewport, you can adjust the values returned here by the scroll distance.
Get Left Element of a given HTMLElement
function getHTMLElementLeft(HTMLElement, left)
{
if (left == undefined)
{
var left = 0;
}
if (HTMLElement.nodeType == 1)
{
left += HTMLElement.offsetLeft;
if (HTMLElement.offsetParent)
{
left = getHTMLElementLeft(HTMLElement.offsetParent, left);
}
}
return left;
}

How can I Animate an Element to its natural height using jQuery [duplicate]

This question already has answers here:
Animate element to auto height with jQuery
(21 answers)
Closed 7 years ago.
I'm trying to get an element to animate to its "natural" height - i.e. the height it would be if it had height: auto;.
I've come up with this:
var currentHeight = $this.height();
$this.css('height', 'auto');
var height = $this.height();
$this.css('height', currentHeight + 'px');
$this.animate({'height': height});
Is there a better way to do this? It feels like a bit of a hack.
Edit:
Here's a complete script to play with for anyone that wants to test.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>jQuery</title>
<style type="text/css">
p { overflow: hidden; background-color: red; border: 1px solid black; }
.closed { height: 1px; }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript">
$().ready(function()
{
$('div').click(function()
{
$('p').each(function()
{
var $this = $(this);
if ($this.hasClass('closed'))
{
var currentHeight = $this.height();
$this.css('height', 'auto');
var height = $this.height();
$this.css('height', currentHeight + 'px');
$this.animate({'height': height});
}
else
{
$this.animate({'height': 1});
}
$this.toggleClass('closed');
});
});
});
</script>
</head>
<body>
<div>Click Me</div>
<p>Hello - I started open</p>
<p class="closed">Hello - I started closed</p>
</body>
</html>
I permit myself to answer this thread, even if it's been answered a long time ago, cuz it just helped me.
In fact, i don't understand the first answer : why opening a half-closed element to get its height, and then closing it again ?
At the beginning, you hide the element so that just a part of it appears, right ? The best way (i believe) to do this is onready, with javascript. So, when you hide the element onready, just save the orig height in a var, so you don't have to hide(onready)-show-save height-hide to be able to toggle the elements visibility.
Look at what i did, it works perfectly :
$(document).ready(function(){
var origHeight = $("#foo").css('height');
$("#foo").css({"height" : "80px"});
$("#foo .toggle").bind("click", function(event){ toggleFoo(event, lastSearchesMidHeight); });
});
Here, when you call your toggle function, you know what is your original element height without wanking around.
I wrote it fast, hoping it could help someone in the future.
the easiest solution I found was to simply wrap the content element with a div that is limited in height and set to overflow:hidden. This truncates the inner content element to the height of the wrapping div. when the user clicks, hovers, etc. to show the full height of the content element - simply animate the wrapping div to the height of the inner content div.
I could suggest an equally-hackish solution...Clone the element, position it out of view, and get its height...then delete it and animate your original.
That aside, you could also use $.slideUp() and $.slideDown():
$this.hasClass('closed') ? $(this).slideDown() : $(this).slideUp() ;
If you need to keep a 1px line, you can apply that with a parent element:
<div style='border-top:1px solid #333333'>
<div class='toggleMe'>Hello World</div>
</div>
And apply the slidingUp/Down on the .toggleMe div.
I'd also like to chime in on this old thread, if I may, in case my solution helps anyone. My specific situation is this: I have some div's that are set with a max-height value that limits them to three lines tall, and when the user mouseovers them I want them to expand to their natural height; and when the mouse cursor leaves the div, I want them to shrink back down to the clipped, max-three-lines-tall height. I need to use the CSS max-height property, rather than height, because I have some div's that contain only one or two lines of text and I don't want them unnecessarily tall.
I tried many of the solutions in this thread, and the one that worked for me was the 'hackish suggestion' involving cloned elements suggested by Jonathan Sampson. I translated his idea into the following code. Please feel free to suggest improvements.
The functions are delegated to a parent element to handle div's created via an Ajax call. The div.overflow_expandable class has the following declaration: { max-height: 5em; overflow: hidden; }
$('#results').delegate('div.overflow_expandable', 'mouseenter', function() {
var $this = $(this);
// Close any other open divs
$('#results div.overflow_expandable').not($(this)).trigger('mouseleave');
// We need to convert the div's current natural height (which is less than
// or equal to its CSS max-height) to be a defined CSS 'height' property,
// which can then animate; and we unset max-height so that it doesn't
// prevent the div from growing taller.
if (!$this.data('originalHeight')) {
$this.data('originalHeight', $this.height());
$this.data('originalMaxHeight', parseInt($this.css('max-height')));
$this.css({ 'max-height':'none',
height: $this.data('originalHeight') });
}
// Now slide out if the div is at its original height
// (i.e. in 'closed' state) and if its original height was equal to
// its original 'max-height' (so when closed, it had overflow clipped)
if ($this.height() == $this.data('originalHeight') &&
$this.data('originalMaxHeight') == $this.data('originalHeight')) {
// To figure out the new height, clone the original element and set
// its height to auto, then measure the cloned element's new height;
// then animate our div to that height
var $clone = $this.clone().css({ height: 'auto', position: 'absolute',
zIndex: '-9999', left: '-9999px', width: $this.width() })
.appendTo($this);
$this.animate({ height: $clone.height() }, 'slow');
$clone.detach();
}
}).delegate('div.overflow_expandable', 'mouseleave', function() {
var $this = $(this);
// If the div has 'originalHeight' defined (it's been opened before) and
// if it's current height is greater than 'originalHeight' (it's open
// now), slide it back to its original height
if ($this.data('originalHeight') &&
$this.height() > $this.data('originalHeight'))
$this.animate({ height: $this.data('originalHeight') }, 'slow');
});
Found this post and end up using Greg's original 1px suggestion - works great!
Just added a callback to the animate function, to set the height of the element to 'auto' when the animation ends (in my case, the content of that specific element could change and be bigger).
$('div').click(function() {
if($('p').is(':hidden')) {
$('p').slideUp();
} else {
$('p').slideDown(function() { $('p').css('height','1px'); });
}
}
That should set the height of the p tags to be 1px once they've finished sliding.
This worked for me.
<div class="product-category">
<div class="category-name">
Cars
</div>
<div class="category-products" style="display: none; overflow: hidden;">
<div class="product">Red Car</div>
<div class="product">Green Car</div>
<div class="product">Yellow Car</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('.product-category .category-name').click(function() {
if ($(this).parent().hasClass('active')) {
$(this).parent().removeClass('active');
var height = $(this).parent().find('.category-products').height();
$(this).parent().find('.category-products').animate({ height : '0px' }, 600, function() {
$(this).parent().find('.category-products').height(height).hide();
});
} else {
$(this).parent().addClass('active');
var height = $(this).parent().find('.category-products').height();
$(this).parent().find('.category-products').height(0).show().animate({ height : height + 'px' }, 600);
}
});
});
</script>
My solution is to store in the data attribute of the close button the original size of container (could have been stored also in the container itself, if you don't use the same button to also show again the container):
$(document).ready(function(){
$('.infoBox .closeBtn').toggle(hideBox, showBox);
});
function hideBox()
{
var parent = $(this).parent();
$(this).text('Show').data('originalHeight', parent.css('height'));
parent.animate({'height': 20});
return false;
}
function showBox()
{
var parent = $(this).parent();
$(this).text('Hide');
parent.animate({
'height': $(this).data('originalHeight')
});
return false;
}
I wanted to point to this answer, which suggest setting the height to "show" with the animate() function. I had to edit my "slideUp" style animate to use height:"hide" to work with it.

Categories

Resources