0

I'm creating a rolodex type animation and I'm using timers to set a class for 3d animation and setting the z-index dynamically as well in order for the elements to overlay and underlay each other when needed. Every second I'm expecting the bottom span (divs.children[1]) to have the class and style attributes set, and then halfway between that second, I expect the bottom to remove the attributes and the top half (divs.children[0]) to begin it's animation.

When I use the code below, every call to hideTop(), showTop(), and showBottom() work as expected, but whenever hideBottom() is called, neither the style or class attributes are being removed. I've also tried using setAttribute("style", ""), but to no avail. I was using setInterval(function() { ... }, 1000) before which produced the same behavior as well.

Codepen as well.

    var i = 0;
    var x = 100;
    var firstRun = true;

    var digit = document.getElementById("digit");
    var divs = digit.getElementsByTagName("div");

    divs[0].children[0].setAttribute("style", "-webkit-transform: rotateX(0deg);");

    (function scrollRolodex() {
        function showTop(i, x) {
            divs[i].children[0].setAttribute("style", "z-index: " + ((i * x) + 10));
            divs[i].children[0].setAttribute("class", "flip-top");
        }

        function hideTop(i) {
            divs[i].children[0].removeAttribute("style");
            divs[i].children[0].removeAttribute("class");
        }

        function showBottom(i, x) {
            divs[i].children[1].setAttribute("style", "z-index: " + ((i * x) + 5));
            divs[i].children[1].setAttribute("class", "flip-bottom");       
        }

        function hideBottom(i) {
            divs[i].children[1].removeAttribute("style");
            divs[i].children[1].removeAttribute("class");
        }

        if (i < divs.length) { 
            if (i == 0 && !firstRun) {
                hideTop(divs.length - 1);
            } else if (i > 0) {
                hideTop(i - 1); 
            }

            showBottom(i, x);

            window.setTimeout(function() {
                hideBottom(i);
                if (i != (divs.length - 1)) {
                    showTop(i, x);
                } else {
                    showTop(divs.length - 1, x);
                }
            }, 500);

            if (i == divs.length - 1) {
                i = 0;
                x = 100;
                firstRun = false;
            } else {
                i++;
                x++;
            }
        }
        setTimeout(scrollRolodex, 1000);
    }());

Thanks!

EnergyMud
  • 31
  • 6

1 Answers1

0

You shouldn't use addAttribute/removeAttribute to add/remove classes/styles. (HTML attributes determine the current state of your HTML, but the authoritative information about current DOM state is in DOM node properties. See this question.) Instead, if you don't want to use any utility library like jQuery, use HTMLElement.style property to set inline styles and Element.classList API to add/remove classes.

Edit: At second glance, I see one additional bug in your code. You're scheduling part of your operations to occur 0.5 seconds later with the original variable values, but then you change the values. What you need to do in that case is pass the required values to setTimeout as additional parameters.

Here's your codepen, updated with my suggestions. It's still not working properly, but the part you were asking about seems to be fixed. Here's another codepen where I modified the code to be more transparent, but it's not working either and I don't have time to debug it.

Community
  • 1
  • 1
hon2a
  • 7,006
  • 5
  • 41
  • 55
  • It looks like the class `flip-bottom` still isn't being removed, although the style is being cleared now. You'll notice because the class is not being removed, the bottom half just constantly flips up and down, and without a `z-index` set the upper most span will be displayed on top. – EnergyMud Dec 05 '14 at 10:39
  • The class is getting removed all right, just insert `console.log(divs[i].children[1].classList.contains('flip-bottom'));` after the removal. There must be another problem with your algorithm. – hon2a Dec 05 '14 at 11:19
  • The Chrome inspector is still showing the `flip-bottom` class on the elements, if it's being removed shouldn't the animation not be applied on the closest element? – EnergyMud Dec 05 '14 at 11:46
  • I've updated my answer. You're expecting the code executed 0.5s later to use original values of `i` and `x`, but it's actually executing with the updated values. – hon2a Dec 05 '14 at 12:12
  • For some reason, it's not applying the z-index style though. Any idea why not? The timing seems spot on now, it just seems like it's having issues applying the properties. – EnergyMud Dec 05 '14 at 12:34
  • Because I messed up style assignment (I don't usually use native API). When assigning styles, assign the value to the particular property (`element.style.zIndex = 123`), string assignment to `.style` doesn't work. – hon2a Dec 05 '14 at 13:17