0

I am trying to implement a lift in JavaScript. Just in its simplest form. There are several levels and a lift. When the user clicks on some level the lift goes right there. If the user clicks several levels while the lift is still going to its first destination the lift must remember the position of levels and stop at each of them by order. So finally I wrote something that looks like working code. But I think the logic is wrong, cause the lift sometimes interrupt its current action and goes to the final pointed destination. Here is the code

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Lift</title>
    <style>
        * {
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
        }

        .building {
            width: 400px;
            height: 600px;
            border: 1px solid #CCC;
            margin: auto auto;
        }

        .floors {
            width: 70%;
            height: 600px;
            border: 1px solid #AAA;
            float: left;
        }

            .floors .level {
                width: 100%;
                height: 100px;
                border-bottom: 1px solid #AAA;
                position: relative;
            }

        .lift-shaft {
            width: 30%;
            height: 600px;
            border: 1px solid #AAA;
            float: right;
            position: relative;
        }

        .lift {
            width: 100%;
            height: 100px;
            border: 1px solid blue;
            position: absolute;
            top: 0;
            left: 0;
            -webkit-transition: all 1s ease-in-out;
            -moz-transition: all 1s ease-in-out;
            -o-transition: all 1s ease-in-out;
            transition: all 1s ease-in-out;
        }
    </style>
</head>
<body>
    <div class="building">
        <div class="floors">
            <div class="level"></div>
            <div class="level"></div>
            <div class="level"></div>
            <div class="level"></div>
            <div class="level"></div>
            <div class="level"></div>
        </div>
        <div class="lift-shaft">
            <div class="lift"></div>
        </div>
    </div>

    <script>

        (function () {

            var levels = document.getElementsByClassName('level'),
                theLift = document.querySelector('.lift'),
                position = {},
                animationInProgress = false;

            Array.prototype.forEach.call(levels, function (elem) {
                elem.addEventListener('click', function (e) {
                    position.top = e.target.getBoundingClientRect().top - 10;
                    animateLift(position.top);
                }, false);
            });

            function animateLift(top) {
                if (animationInProgress) {
                    theLift.addEventListener('webkitTransitionEnd', function (e) {                      
                        e.target.style.top = top + 'px';
                        animationInProgress = false;                    
                    }, true);
                }
                else {
                    theLift.style.top = top + 'px';
                    animationInProgress = true;
                    theLift.addEventListener('webkitTransitionEnd', function (e) {                      
                        e.target.style.top = top + 'px';
                        animationInProgress = false;                    
                    }, true);                   
                }
            }

        })();

    </script>

</body>
</html>
3
  • Is this a homework assignment? Commented Jun 1, 2013 at 18:44
  • No. I am not a student. Commented Jun 1, 2013 at 18:45
  • 1
    You've already answered your question in the title: you need a queue (in JS, a simple array). Currently, your script has only one position object which it writes to. Commented Jun 1, 2013 at 20:14

1 Answer 1

2

You only need to assign once the animation ended event.
Handle a !queue! to store the level choices, and have :
1) a click either to launch the anim or pile up the move
2) the end of an animation triggers the next move taken from the queue.

You have to take care also of not requesting twice the same position since this will stop the animations. I did this by storing the last requested position, and ignoring clicks that request the same target position.

something like this is working quite good :

    (function () {

        var levels = document.getElementsByClassName('level'),
            theLift = document.querySelector('.lift'),
            position = {},
            targetPosition = -1,
            animationInProgress = false;

        var StackOfRequestedLevels=[];

       theLift.addEventListener('webkitTransitionEnd', function (e) {                      
              if (StackOfRequestedLevels.length) 
                  theLift.style.top = StackOfRequestedLevels.shift()  + 'px';
           else
               animationInProgress = false;
                }, true);

        Array.prototype.forEach.call(levels, function (elem) {
       elem.addEventListener('click', function (e) {
              position.top = e.target.getBoundingClientRect().top;
              if ( position.top === targetPosition ) return;
              targetPosition = position.top;
              if (!animationInProgress)   
                    theLift.style.top = position.top + 'px';
              else {
                    StackOfRequestedLevels.push (position.top);
                   }
                animationInProgress=true;
            }, false);

        });

    })();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.