Search code examples
javascripthtmlcallbackprototypesynchronous

How to run the Callback function inside of the prototype in JavaScript?


According to this question and mdn.doc articles, I'm giving a Callback function inside of aprototype for managing the next code line after it's done.

But even if I create the Callback, the browser keeps ignoring it and running the next code line no matter the Callback is completed or not.

This is the code:

'use strict';
(function() {

  function Box($el, $frame) {
    // Reassign the Values
    this.$el = $el;
    this.$frame = $frame;

    // Event Register Zone
    this.$el.addEventListener('touchstart', (e) => this.start(e));
    this.$el.addEventListener('touchmove', (e) => this.move(e));
    this.$el.addEventListener('touchend', (e) => this.end(e));
  }

  Box.prototype = {
    start: function(e) {
      console.log('touchstart has been detected');
    },
    move: function(e) {
      console.log('touchmove has been detected');
    },
    end: function(e) {
      console.log('touchend has been detected');
      this.getanAction(this.moveTop);
    },
    getanAction: function(callback) {
      let bound = callback.bind(this);
      bound();
      this.$frame[1].classList.add('leftMover');
      // Expectation: move the purple box first, and move the orange box next
    },
    moveTop: function() {
      this.$frame[0].classList.add('topMover');
    }
  }

  /***************************************************************/
  // Declare & Assign the Original Values

  let _elem = document.getElementById('box');
  let _frame = _elem.querySelectorAll('.contents');

  const proBox = new Box(_elem, _frame);

}());
      * {
        margin: 0;
        padding: 0;
      }
      #box {
        width: auto;
        height: 800px;
        border: 4px dotted black;
      }
      .contents {
        position: absolute;
        width: 200px;
        height: 200px;
        float: left;
        top: 0;
        left: 0;
        transition: 800ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
      }
      .purple { background-color: purple; }
      .orange { background-color: orange; }

      .topMover { top: 600px; }
      .leftMover { left: 600px; }
    <div id="box">
      <div class="contents purple">

      </div>
      <div class="contents orange">

      </div>
    </div>

My expectation is the .orange box moves after the .purple box moves done.

Did I miss or do something wrong from the code?


Solution

  • The problem is they are being called one after the other with no delay as JavaScript won't wait for the CSS transition to finish before moving to the next line.

    I've fixed waiting for the first transition has finished before calling the bound callback. This way the purple box will move, wait for the transition to finish, then the orange box will move.

    'use strict';
        (function() {
    
          function Box($el, $frame) {
            // Reassign the Values
            this.$el = $el;
            this.$frame = $frame;
    
            // Event Register Zone
            this.$el.addEventListener('touchstart', (e) => this.start(e));
            this.$el.addEventListener('touchmove', (e) => this.move(e));
            // Added mouse up so it works on desktop
            this.$el.addEventListener('mouseup', (e) => this.end(e));
            this.$el.addEventListener('touchend', (e) => this.end(e));
          }
    
          Box.prototype = {
            start: function(e) {
              console.log('touchstart has been detected');
            },
            move: function(e) {
              console.log('touchmove has been detected');
            },
            end: function(e) {
              console.log('touchend has been detected');
              this.getanAction(this.moveTop);
            },
            getanAction: function(callback) {
              let bound = callback.bind(this);
              // Listen for css transition end
              this.$frame[0].addEventListener('transitionend', function() {
             // Call callback to move orange box
                bound()
              });
              
              // Move the purple box now
              this.$frame[0].classList.add('topMover1')
            },
            moveTop: function() {
              this.$frame[1].classList.add('topMover2');
            }
          }
    
          /***************************************************************/
          // Declare & Assign the Original Values
    
          let _elem = document.getElementById('box');
          let _frame = _elem.querySelectorAll('.contents');
    
          const proBox = new Box(_elem, _frame);
    
        }());
    * {
                margin: 0;
                padding: 0;
              }
              #box {
                width: auto;
                height: 800px;
                border: 4px dotted black;
              }
              .contents {
                position: absolute;
                width: 200px;
                height: 200px;
                float: left;
                top: 0;
                left: 0;
                transition: 800ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
              }
              .purple { background-color: purple; }
              .orange { background-color: orange; }
    
              .topMover1 { top: 600px; }
              .topMover2 { left: 600px; }
    <div id="box">
              <div class="contents purple">
    
              </div>
              <div class="contents orange">
    
              </div>
            </div>