Phed
Phed

Reputation: 43

"Math.abs(parseInt($(this).css('left')" returning a different value than expected

Example: jsfiddle

<style>
#slider-outer {
width: 400px;
overflow: hidden;
}

#slider-inner {
width: 1200px;
overflow: visible;
height: 200px;
position: relative;
}

#slider-inner div {
background: ;
width: 200px;
height: 200px;
float: left;
}

.a{background: red;}
.b{background: green;}
.c{background: blue;}
.d{background: yellow;}
.e{background: grey;}
.f{background: coral;}
.g{background: olive;}
</style>

<div id="slider-outer">
    <div id="slider-inner">
        <div class="a"></div>
        <div class="b"></div>
        <div class="c"></div>
        <div class="e"></div>
        <div class="f"></div>
        <div class="g"></div>
    </div>
</div>
$(document).ready(function(){

$('#slider-inner').click(function(){

var scrollAmount = $(this).width() - $(this).parent().width();
var currentPos = Math.abs(parseInt($(this).css('left')));
var remainingScroll = scrollAmount - currentPos;
var nextScroll = Math.floor($(this).parent().width() / 2);

if (remainingScroll < nextScroll) {
  nextScroll = remainingScroll;
}

if (currentPos < scrollAmount) {
  $(this).animate({'left':'-=' + nextScroll}, 'slow');

   console.log(currentPos)
} 

else {
  $(this).animate({'left':'0'}, 'fast');
}
});
});

I am going through the process of learning jQuery and some javascript and I came across this example of a simple slider and was going through the lines of code and understand how it all works. I understood everything except for the value that thevar = currentPos returns to the console.

The value returns 0 on the first click, this confuses me as I think it should be -200px because the slider-inner is moving -200px to the left?

Could someone please explain why the variable is returning the value it is to the console?

Thanks

Upvotes: 0

Views: 543

Answers (2)

Useless Code
Useless Code

Reputation: 12402

If you look at the CSS rule for #slider-inner, you'll see that it does not have an explicit left set.

#slider-inner {
width: 1200px;
overflow: visible;
height: 200px;
position: relative;
}

Because there is no explicit left value, it defaults to auto. Since #slider-inner is relatively positioned and it also has no right property specified, it receives no offset.

This means left is effectively 0px (which is exactly what you get when you when $(this).css('left') runs on the first click). var currentPos = Math.abs(parseInt($(this).css('left'))); parses that value into an absolute integer, 0, and stores it in the variable currentPos. If you look at all the code that comes after that:

    var remainingScroll = scrollAmount - currentPos;
    var nextScroll = Math.floor($(this).parent().width() / 2);

    if (remainingScroll < nextScroll) {
      nextScroll = remainingScroll;
    }

    if (currentPos < scrollAmount) {
      $(this).animate({'left':'-=' + nextScroll}, 'slow');
       console.log(currentPos)
    } 

    else {
      $(this).animate({'left':'0'}, 'fast');
    }
  });
});

Nothing in there assigns a new value to currentPos, so the value remains 0. The zero you get from parsing the string into an integer is a literal, not a reference to the current value of .left. Even if it were a live reference to the .left property of the DOM element, it would not be -200, the .animate method runs asynchronously, console.log is called immediately after it, it might have moved a few pixles to the left in the time between calling .animate and the console output, but certainly not the full 200 pixels.

Upvotes: 0

James Hibbard
James Hibbard

Reputation: 17735

The console.log statement is not waiting for the animation to complete and even if it did, currentPos will remain at 0, as the animation doesn't alter the value of the variable.

A better way to understand the difference is so:

if (currentPos < scrollAmount) {
  $(this).animate({'left':'-=' + nextScroll}, 'slow', function(){
    console.log("After the animation has completed: " + $(this).css('left'));
  });
  console.log("Before the animation has completed: " + $(this).css('left'))
} 

The third argument to .animate() is an anonymous function that will be executed when the animation is finished.

This will output:

Before the animation has completed: 0px 
After the animation has completed: -200px

Which is hopefully more in line with what you expect.

Upvotes: 4

Related Questions