0

In html I have a button which when clicked animates the document's scrollTop to a certain position.

The issue I'm facing is that I have to make this support down to ie9.

So, I have the following function which returns the correct scrollTopPosition depending on what the browser can support. This is working correctly:

function posTop(){
    return typeof window.pageYOffset != 'undefined' ?
        window.pageYOffset : document.documentElement.scrollTop ?
            document.documentElement.scrollTop : document.body.scrollTop ?
                document.body.scrollTop : 0;
}

I am using the greensock library to manage the animation, and it is implemented like this:

TweenLite.to(document.body, 1, { scrollTop: targetPos });

The issue is that even though posTop() returns the correct value, I have to manually ensure with an if statement that I can indeed use document.body.scrollTop in the animation call... For example...

if (document.documentElement.scrollTop) { // for ie11 and below
    var tween = TweenLite.to(document.documentElement, 1, { scrollTop: targetPos });
}
else { 
    var tween = TweenLite.to(document.body, 1, { scrollTop: targetPos });
}


Is there a way that I can modify posTop() so that it returns a reference to the element property rather than its value? Or a better way to implement this without the need for the if statement everytime I want to animate scrollTop?

Clarification:

I would like to change the if statement block to something like:

var correctScrollTopProperty = pointer to document.body // psuedo
var correctPropertyToBeAnimated = pointer to document.body.scrollTop // pseudo
TweenLite.to(correctScrollTopProperty , 1, { correctPropertyToBeAnimated : targetPos });
Community
  • 1
  • 1
Zze
  • 18,229
  • 13
  • 85
  • 118
  • Multi-multi-ternary is killing my eyes :( :D – Matthew Herbst Mar 27 '17 at 03:58
  • 1
    @MatthewHerbst Yeah, I was going to change it from the original SO answer, but haven't gotten around to it yet.... as it currently works and I'm just trying to get it implemented before tidying that bad boy up – Zze Mar 27 '17 at 04:00
  • Rather than changing your function's signature which seems pretty solid, I would say just run the if-statement logic once at the start of execution and save the output. Then you can just do `if (hasScrollTop)` which should be extremely performant. Or is the issue that you don't like how it looks rather than it being a performance issue? – Matthew Herbst Mar 27 '17 at 04:01
  • pageYOffset cannot be "undefined". – Bekim Bacaj Mar 27 '17 at 04:03
  • @BekimBacaj Notice the `typeof` call that comes before `window.pageYOffset` – gyre Mar 27 '17 at 04:04
  • @MatthewHerbst That is an interesting suggestion.. I am basically trying to just reduce line count and remove the if statement... Something like: `TweenLite.to(correctScrollTop, 1, { propertyToBeAnimated: targetPos });` where `var correctScrollTop, propertyToBeAnimated` would be set somewhere?? I'll add this to the question for clarity. – Zze Mar 27 '17 at 04:05
  • Well, you need the `if` statement _somewhere_, so just up to you where to put it, but there's certainly no reason to do the evaluation every time – Matthew Herbst Mar 27 '17 at 04:09
  • @MatthewHerbst Quite probably you are correct and if that is the case, then so be it... but you never know until you ask and there are much more savvy javascript folk on here than I. Thanks for the feedback! – Zze Mar 27 '17 at 04:12
  • @gyre furthermore IE supports pageYOffset, down to version 9 anyway. – Bekim Bacaj Mar 27 '17 at 04:17

3 Answers3

0

I believe this should solve your issue: instead of just returning the correct "scrollTop" return an array with two values: the correct "scrollTop" and a reference to the correct element:

function posTop(){
return typeof window.pageYOffset != 'undefined' ?
    window.pageYOffset : document.documentElement.scrollTop ?
        [document.documentElement.scrollTop, document.documentElement] : document.body.scrollTop ?
            [document.body.scrollTop, document.body] : 0;
}

And then you can use the function like this:

var tween = TweenLite.to(posTop()[1], 1, { scrollTop: targetPos });

of course i do not mean really use it like that - wherever in your code you do use the function - store the second value from the array that is being returned. and there you have the reference you wanted :)

Ariel Ferdman
  • 124
  • 3
  • 11
  • Thanks for your answer, unfortunately that array would yield the values of the properties whereas I am looking for references/pointers to those properties. – Zze Mar 27 '17 at 04:50
  • why do you need the refference? if you have the value you can use the correct value inside "TweenLite.to" without needing the "if" - am i missing something? – Ariel Ferdman Mar 27 '17 at 05:03
  • The first parameter is a DOM element, the third parameter is an object containing a list of properties on that element and what that property will lerp to over x time. – Zze Mar 27 '17 at 05:21
0

In case I undestand your problem (and the request) correctly, u need to make use of your function result somewhere.

function posTop(){
    return typeof window.pageYOffset != 'undefined' ?
        window.pageYOffset : document.documentElement.scrollTop ?
            document.documentElement.scrollTop : document.body.scrollTop ?
                document.body.scrollTop : 0;
}

I'm not seeing the posTop() being used anywhere in your code. So quoting your question request "Is there a way that I can modify posTop() so that it returns a reference to the element property rather than its value?" Is unnecessary...

Just feed the posTop() as a value.

Bekim Bacaj
  • 5,707
  • 2
  • 24
  • 26
  • Sorry, but I think you missunderstood my question. I am looking for references/pointers to the property. I actually left out the code where I use `posTop()` to calculate `targetPos ` as I didn't think it was relevant. – Zze Mar 27 '17 at 04:52
0

I think you can use this

instead of returning the property, return an Object.

function posTop(){
    return { // return an object
       scrollItem : typeof window.pageYOffset != 'undefined' ?
        window.pageYOffset : document.documentElement.scrollTop ?
            document.documentElement.scrollTop : document.body.scrollTop ?
                document.body.scrollTop : 0,
        body : document.body
    }
}

console.log(posTop().scrollItem);
console.log(posTop().body);

Then you can use this

var correctScrollTopProperty = posTop().scrollItem;
var correctPropertyToBeAnimated = posTop().body;
TweenLite.to(correctScrollTopProperty , 1, { correctPropertyToBeAnimated : targetPos });
Sagar V
  • 12,158
  • 7
  • 41
  • 68
  • Now this looks incredibly promising - thank you, I will implement this tomorrow at work and get back to you. – Zze Mar 27 '17 at 05:39
  • you can check the console and see the implementation after running the snippet. If any problem, mention my name here – Sagar V Mar 27 '17 at 05:40