Javascript - How to set the property working? - javascript

here is my code which is not working
function gauche() {
var voiture = document.getElementsByClassName("voiture")[0];
var position = window.getComputedStyle(voiture).left;
alert(position);
position = parseInt(position, 10) - 30 + "px";
alert(position);
}
I want to move "voiture" position 30px to the left. So I want to subtract 30 from the position.
This alert well 30px, then this alert well 0px (because 30 - 30 = 0)
But unfortunately, it doesn't update on my page. My "voiture" div is always with 30 px and not width 0px. Thanks

Use voiture.offsetLeft; instead of window.getComputedStyle(voiture).left; so you don't have to parse it.
The HTMLElement.offsetLeft read-only method returns the number of
pixels that the upper left corner of the current element is offset to
the left within the HTMLElement.offsetParent node.
and to set the position simply: voiture.style.left = voiture.offsetLeft - 30 + 'px';
offsetLeft doc
element.style.left doc

You need to use DOM element's style property:
voiture.style.left = parseInt(position, 10) - 30 + "px";
Also, there's a very very wrong assumption in your code: you think that setting current left value to a local variable bounds its value to the element, while this won't happen. Whenever you want to change a DOM element (and this applies to any of its properties), you need to set its properties again instead of assuming that changing a local variable will change the element.

Related

Can any explain why this jQuery.offset() shifts each time its used?

Can anyone explain to me what is happening here?
I am trying to use jQuery to center wizard elements on a page. The first time showCentered() is called on an element, it is correctly centered on the page and all looks good. The second time however the element is shifted way off to the side (and not exactly double the previous values either).
SO the first time it's called it works fine. The second (and third, .. etc) times it gets shifted farther and farther off the page.
Example Code:
function showCentered(selector){
d = $(selector);
h = d.outerHeight();
w = d.outerWidth();
hMax = $(window).height();
wMax = $(window).width();
_top = (hMax / 2) - (h / 2);
_left = (wMax / 2) - (w / 2);
if (_left < 0) _left = 0;
if (_top < 0) _top = 0;
d.offset({
top: _top,
left: _left
});
d.show();
}
//1st time, OK
$('.demo').hide();
showCentered('.demo');
//2nd time, NOT OK
$('.demo').hide();
showCentered('.demo');
Here is a working demo of the above: Codepen.io
When running the above function for the .demo element I get the following values for h, w, hMax, wMax, _top, _left, and then offset().top, offset().left. Notice how the offset values changes the second time around.
Also of note is that this will affect any element that uses offset after the first time around.
Can anyone explain why offset is shifting after each use?
You cannot reliably get the dimensions of a hidden element.
See jQuery outerHeight for hidden element
jQuery attempts to compensate, but you can sometimes still end up with incorrect values. See jQuery: height()/width() and "display:none"
EDIT: Actually the real problem is $.offset() cannot be used to correctly set the position of a hidden element. It attempts to do calculations based on the current location of the element in relation to its offset parent and these calculations are just wrong if the element is hidden. Just move d.show(); to just before you set the offset fixes the problem.

Why does Firefox return NaN from this parseInt of a CSS padding value?

In an application I'm working on, we have a fixed height modal with form content. The modal content is usually longer than the modal, so the user will have to scroll down inside the modal container to view and fill in the entire form.
Each form <input> also has a small tooltip that appears below the <input> when it is in focus. To ensure this tooltip is visible for users if they're tabbing through the form or click on a form field close to the bottom of the current scroll position in the modal, I've written some JavaScript/jQuery to scroll the content automatically if the tooltip would be hidden by the bottom of the modal.
This is my code:
// The amount of padding an element should always have to the bottom
var padding = 50;
// Add focus event to the form elements
$(".modal-content input, .modal-content textarea").focus(function(){
// Get element bottom position relative to modal bottom
var elementBottom = $(this).offset().top + $(this).height();
var modalPadding = parseInt($('.modal-content').css('padding'), 10);
var modalBottom = $('.modal-content').offset().top + $('.modal-content').height() + modalPadding;
var distanceFromBottom = modalBottom - elementBottom;
// Get current scroll location
var modalScroll = $('.modal-content').scrollTop();
// Scroll the modal if the element's tooltip would appear outside visible area
if (distanceFromBottom < padding){
var amountToScroll = padding + modalScroll + -distanceFromBottom;
$('.modal-content').animate({ scrollTop: amountToScroll },250);
}
});
Don't worry if things seem a bit confusing out of context; the problem here is on line 8, where I use parseInt to get an integer of the content area's padding value for use in the calculation on how much to scroll the content.
.modal-content has a padding value of 15px. As you would expect, parseInt returns 15 which I can then add to the other values in my modalBottom variable. This works perfectly in Chrome, Safari and Internet Explorer 8.
However, in Firefox, this parseInt always returns NaN (Not-a-Number) for some reason. If I replace modalPadding in the modalBottom variable with 15, like in the following code, it also works in Firefox:
var modalBottom = $('.modal-content').offset().top + $('.modal-content').height() + 15;
Obviously, the only reason for using the modalPadding variable is so that we won't have to update the JS code if we change the padding of the modal content, which is unlikely. Still, it annoys me to hell that Firefox returns a NaN no matter how I try to parse the padding value into an integer.
First I thought it had to do with the radix value of parseInt (which should be 10 for base 10) but as you can see I have it right there and it still doesn't work.
I've also tried using parseFloat and removing "px" from the value with .replace('px','') before attempting to make the value an integer with parseInt, neither of which returned anything but NaN in Firefox.
I'm running Firefox 27.0.1. Can anyone please explain to me why Firefox won't parse my padding?
Documentation says:
Shorthand CSS properties (e.g. margin, background, border) are not supported. For example, if you want to retrieve the rendered margin, use: $(elem).css('marginTop') and $(elem).css('marginRight'), and so on.
Therefore you will need to specify paddingLeft or paddingTop... etc
As can see in this live example, $.css doesn't return anything in Firefox.
If your padding is going to be 15px for all directions (left, right, top and bottom) then just get one:
var modalPadding = parseInt($('.modal-content').css('paddingLeft'), 10);
Firefox can be picky with this. Padding could refer to padding left, padding right etc. If you know that all paddings are the same, try this:
Replace
var modalPadding = parseInt($('.modal-content').css('padding'), 10);
With
var modalPadding = parseInt($('.modal-content').css('padding-left'), 10);
Check out this JSFiddle.

issue with $(document).scrollLeft() as a variable

I'm trying to use the left variable to replace '1493' in this code. It works fine when it's a number but when I changed it over to use 'left' the if statement stops working.
$(document).scroll(function () {
var width = $(document).width();
var left = $(document).scrollLeft();
var postCount = $(".post").length;
var columnLength = ( width - ((postCount*743) - 1493)) - (width-(postCount*743));
if(left >= columnLength) {
$(".num").text(left);
}
});
Does anyone have any ideas where I'm going wrong with this? Any pointers would be great.
You may need to force it to be an integer:
var left = parseInt($(document).scrollLeft());
Lets take a look at the math you have really quick.
var columnLength = ( width - ((postCount*743) - 1493)) - (width-(postCount*743));
You are basically cancelling out width, and (postCount*743). It leaves you with --1493 which is positive 1493. The following would have the same effect:
var columnLength = 1493;
So, the reason the if statement fires when you put in the static value 1493, is because columnLength ALWAYS equals 1493 which, of course satisfies this condition:
if (1493 >= columnLength)
You could as easily write:
if (1493 >= 1493)
That said, it should still, theoretically fire when left becomes greater than or equal to 1493. But left is the current horizontal scroll position in pixels. It would be a HUGELY wide page to hit a scroll position of 1493.
Edit: Here's a fiddle to give an idea of how fast the scroll position increases: http://jsfiddle.net/vdQ7B/16/
EDIT 2:
Here is an update in response to your comment.
As I understand it, you were trying to get a horizontal scrollbar that would, essentially, scroll forever.
Please see the following fiddle for a demo: http://jsfiddle.net/vdQ7B/40/
The code is below:
$(document).scroll(function () {
var width = $(document).width();
var left = $(document).scrollLeft();
var viewportwidth = window.innerWidth;
// If our scrollbar gets to the end,
// add 50 more pixels. This could be set
// to anything.
if((left + viewportwidth) === width) {
$("body").css("width", width + 50);
}
});
Per the comments in the code, we simply increase the width of the body if we determine we've reached the end. scrollLeft() will only tell us the number of pixels that are currently not visible to the left of the viewable area. So, we need to know how much viewable area we have, and how much is hidden to the left to know if we've scrolled all the way to the end.
If you have a scroll bar on an inner element, like a div, you'd need to update with width of the div, not the body.
Note: You may also need to use $(window) instead of $(document) to get scrollLeft() to work across all browsers.
Note: See here about using "innerWidth". There are some compatibility issues, and you may need to expand it a bit to handle other cases (IE6).

jQuery += a variable help

So I have
VARIABLE = Math.floor(5*Math.random());
Then
.animate({left: '+=VARIABLE'}
but it doesn't work.
In my css my div already has a left attribute. If I do left: newx + 'px' it sends it to the random number I generated, meaning it jumps to the top of the page.
Variables are not interpolated in strings. Try this:
.animate({left: '+='+VARIABLE}
What do you mean by += a variable? You want to increase the current value of the left position? If so you can also fetch the raw number with the .offset() method, increase it, and use it as the new position.

Convert absolute position to relative

Is it possible to change DIV position from absolute to relative (and from relative to absolute)?
DIV should remain on same place.
Because formatting in comments is not work I will publish solution here
$(object).css({position: 'absolute',top: dy, left:dx});
// dy, dx - some coordinates
$(object).css({position: 'relative'});
Does not work: element position after changing to relative is different.
But when I stored offset and set it again after changing to relative, position is the same:
$(object).css({position: 'absolute',top: dy, left:dx});
var x = $(object).offset().left;
var y = $(object).offset().top;
$(object).css({position: 'relative'});
$(object).offset({ top: y, left: x });
you can change that attribute with
$(object).css({position: 'absolute'});
For instance:
You could use jQuery's methods .position() or .offset() to set "top" and "left"
css attribute aswell, that way your object should stay at it's position changing
from relative -> absolute.
I don't think that works vice versa.
demo code: http://jsbin.com/uvoka
If you really want to get the total top offset of an element that is a child of elements with absolute and relative positions you could use this function
function calcTotalOffsetTop(elm)
{
var totalOffsetTop = 0,
curr = elm;
while( curr.parent().is(':not(body)') )
{
curr = curr.parent();
totalOffsetTop += curr[0].offsetTop;
}
return totalOffsetTop;
}
this is the basically the code for the solution given by plodder above.
You can quite easily change it from relative to absolute by using it's offsetLeft and offsetTop values as left and top styles.
The other way around is harder. You would basically have to change it to relative and see where it ended up, then calculate new offset values from the current offset and the desired location.
Note that when the positioning is relative, the element is part of the page flow and may affect other elements. When the position is absolute, the element is outside the page flow and doesn't affect other elements. So, if you change between absolute and relative positioning, you may need to do changes to other elements also if you don't want them to move.
prototype.js has element.absolutize() and element.relativize which work very well.
The problem with going from relative to absolute is that
element.offsetTop and offsetLeft
only give the offset of your element to its parent.
You need to measure the cumualtive offset (i.e.
the offset of your element to its parent +
the offset of the parent to its parent +
the offset of its parent to its parent +
etc.)

Categories

Resources