Load bar with pure Javascript

Asked

Viewed 715 times

3

Sometimes I see loading bars with percentage on sites that I believe overwrite the default behavior of the page when loading (white screen until the content is ready). There are some jQuery plugins that do this, but I want to understand exactly how this process works with pure JS.

I take care of what to find out the loading percentage on a page?

  • in this case, the request to the server is a data download? or some intensive routine?

  • http://github.hubspot.com/pace/docs/welcome/ If you access this page, you will see that the jQuery plugin somehow detects the page load progress and represents it graphically. That’s what I want to know How it works....

  • 3

    it is possible to do with XMLHttpRequest.addEventListener("progress", function, false), but the page needs to expose your work in Header through the property Content-Length.

  • Interesting what you said @Tobymosque. I’ll read more about it...

1 answer

2

Using the Pace.js plugin as the basis (https://github.com/HubSpot/pace), it uses several methods to detect page load percentage:

    • Ajax requests:
        - The plugin checks the requests by calculating the percentage of each one depending on its type:
          If the request is an Xmlhttprequest it uses the "Progress" event, which returns an object with the file size being downloaded and when it has been completed, if Content-Length is available in the Response request header. In addition to also checking the events "load", "abort", "timeout" and "error" to determine whether the request has ended.
  • request.addEventListener('progress', function(evt) {
          //Verifica se Content-Length foi declarado no Header de resposta
          if (evt.lengthComputable) {
            //Calcula a porcentagem de acordo com o quanto já foi baixado.
            return _this.progress = 100 * evt.loaded / evt.total;
          } else {
            //Se não há Content-Length retorna uma porcentagem sintética.
            return _this.progress = _this.progress + (100 - _this.progress) / 2;
          }
        }, false);
    

      If the request type is a Websocket it checks the "error" and "open" events to determine if the request has ended.

    SocketRequestTracker = (function() {
      function SocketRequestTracker(request) {
        var event, _j, _len1, _ref2,
          _this = this;
        this.progress = 0;
        _ref2 = ['error', 'open'];
        //Registra listener aos eventos acima para determinar quando conexão estiver estabelecida, ou não.
        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
          event = _ref2[_j];
          request.addEventListener(event, function() {
            return _this.progress = 100;
          }, false);
        }
      }
    
      return SocketRequestTracker;
    })();
    

    • HTML document:
        - The plugin uses the Document.readystate to determine the state the document is in ("loading", "Interactive", "complete") and assigns a percentage to each.
  • DocumentMonitor = (function() {
      //Determina porcentagens para cada estado de document.readyState.
      DocumentMonitor.prototype.states = {
        loading: 0,
        interactive: 50,
        complete: 100
      };
    
      function DocumentMonitor() {
        var _onreadystatechange, _ref2,
          _this = this;
        //Verifica document.readystate e atribui valor ao estado atual da página
        this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100;
        _onreadystatechange = document.onreadystatechange;
        //Nas mudanças de estado atualiza o valor da porcentagem
        document.onreadystatechange = function() {
          if (_this.states[document.readyState] != null) {
            _this.progress = _this.states[document.readyState];
          }
          return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
        };
      }
    
      return DocumentMonitor;
    })();
    

    • Lag in the Loop of Events:
        - The plugin checks by lag in the event loop whether there is javascript code running and calculates a lag percentage.
  • EventLagMonitor = (function() {
      function EventLagMonitor() {
        var avg, interval, last, points, samples,
          _this = this;
        this.progress = 0;
        avg = 0;
        samples = [];
        points = 0;
        last = now();
        //Utiliza um timer para calcular o Lag no loop de eventos do javascript
        interval = setInterval(function() {
          var diff;
          //Calcula a diferença entre o tempo de execução determinado para o Timer (50ms) e o tempo real de execução
          diff = now() - last - 50;
          last = now();
          samples.push(diff);
          if (samples.length > options.eventLag.sampleCount) {
            samples.shift();
          }
          //Calcula a amplitude media a partir dos Lag's salvos
          avg = avgAmplitude(samples);
          //Verifica se a amplitude dos Lag's está acima do limite na execução do javascript
          if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) {
            _this.progress = 100;
            return clearInterval(interval);
          } else {
            //Se estiver, calcula a porcentagem a partir dessa amplitude.
            return _this.progress = 100 * (3 / (avg + 3));
          }
        }, 50);
      }
    
      return EventLagMonitor;
    })();
    

    • HTML elements (optional):
        - The plugin checks the existence of certain predetermined elements using the Document.querySelector.
  • //De acordo com a documentação - Define as classes/id's a serem verificados pelo pace.js
    paceOptions = {
     elements: {
      selectors: ['.timeline,.timeline-error', '.user-profile,.profile-error']
     }
    }
    


    //Para verificar a existência dos elementos no documento
    ElementTracker = (function() {
      function ElementTracker(selector) {
        this.selector = selector;
        this.progress = 0;
        this.check();
      }
    
      ElementTracker.prototype.check = function() {
        var _this = this;
        if (document.querySelector(this.selector)) {
          return this.done();
        } else {
          return setTimeout((function() {
            return _this.check();
          }), options.elements.checkInterval);
        }
      };
    
      ElementTracker.prototype.done = function() {
        return this.progress = 100;
      };
    
      return ElementTracker;
    })();
    

    Browser other questions tagged

    You are not signed in. Login or sign up in order to post.