Drazen
Drazen

Reputation: 2826

Backbone.js progress bar while fetching collection

i'd like to show a progress bar while i update the app with fresh content. I guess the best thing to do would be to do it while calling .fetch on a collection.

The content i fetch is primarily images (video poster etc) but i only get the link, not a base64 string or something big. What i would like to do is overlay the screen with a progress bar while fetching the image links, render the view so all images are ready and then the overlay should go away and show the app with the fresh content already loaded.

Now i have no idea how i could build a progress bar for this since i am not really getting images directly but only the link and then rendering the view.

Upvotes: 7

Views: 9103

Answers (6)

Harish.bazee
Harish.bazee

Reputation: 668

Overwrite backbone sync method, instead of writing every place add it to sync method. It will work for new pages without writing any new code.

Upvotes: 0

Brian Lewis
Brian Lewis

Reputation: 5729

Try this:

var SomeView = Backbone.View.extend({
    loadStuff: function(){
        var self = this;
        someModel.fetch({
            xhr: function() {
                var xhr = $.ajaxSettings.xhr();
                xhr.onprogress = self.handleProgress;
                return xhr;
            }
        });
    },
    handleProgress: function(evt){
        var percentComplete = 0;
        if (evt.lengthComputable) {  
            percentComplete = evt.loaded / evt.total;
        }
        //console.log(Math.round(percentComplete * 100)+"%");
    }
});

Upvotes: 14

JayC
JayC

Reputation: 7141

Here's some steps that might work out.

  1. when the fetch starts (maybe using ajaxStart or whatever), bring up your pop-over.
  2. when the fetch finishes, identify or create the image urls from the JSON and use one of the several image preloaders out there that have a callback whenever all the images are loaded. If you want to make that yourself, I'd say this would be the psuedocode for that:
    1. Push all your images to an array imagesurls. (this will be an array of strings).
    2. Capture the array length into a variable imagesleft.
    3. Create a function var imageOnLoad = function () {...} capturing that variable which
      1. decrements imagesleft by 1
      2. Does whatever it needs to to update the popover
      3. if imagesleft reaches 0, invoke the code/method to cause the popover to eventually go away
    4. For each of the strings imagesurls[i] in the imagesurls array
      1. create a new Image object. var img = new Image();
      2. img.onload = imageOnLoad;
      3. img.src = imagesurls[i];

Of course I'm ignoring error situations (Images have an onerror property you could assign similarly and the original ajax could fail). but I think the gist of a solution is there. The only thing I'm wondering about is whether or not you actually need to keep a reference to each of the images objects as they're being created. It might be a good idea, at least until you are done with the whole image set. Otherwise, I'd have to worry about garbage collection somehow interfering in some implementation... but then maybe I'm just being paranoid.

Upvotes: 1

abraham
abraham

Reputation: 47833

Before you fetch the collection put up the progress bar. When the collection is done and you are rendering the images to the DOM add listeners to the image load events. When all the images have successfully loaded remove the progress bar.

You will want to make sure you are also listening for load failures incase an image doesn't load since the progress bar would never get removed in that case.

Upvotes: 1

ryanmarc
ryanmarc

Reputation: 1680

You could use jQuery ajaxStart and ajaxStop to show the progress on start and hide it on end. Doing it this way, however, will show your indicator any time and ajax request is made on your page.

A route you could take if you want to limit it to just that particular fetch would be to override the sync method in that collection or model and wrap the default sync with some code that shows and hides the progress bar.

Upvotes: 3

tkone
tkone

Reputation: 22728

When you call fetch put up your loading bar.

Then pass a function as options.success to the fetch method (docs) that takes it the screen.

Or, when you render your objects to the screen you can pull it down then.

We use this for one of our views and just pull it off using the options.success method

Upvotes: 0

Related Questions