7

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.

Drazen
  • 2,776
  • 1
  • 25
  • 39

6 Answers6

14

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)+"%");
    }
});
Brian Lewis
  • 5,739
  • 1
  • 21
  • 28
  • I may have misread what you were trying to load. This would allow you to monitor the progress of a model or collection fetch. – Brian Lewis May 09 '12 at 04:32
  • I need to do similar thing for progress bar but should support IE8 and IE9. But "onprogress" event is not supported in IE9 and below. Is there any other alternative? – Coding man Jul 17 '15 at 07:38
  • how to get lengthComputable to equal true? – zeros-and-ones Aug 06 '16 at 19:45
  • @zeros-and-ones Check out this question: http://stackoverflow.com/questions/11127654/why-is-progressevent-lengthcomputable-false – Brian Lewis Aug 08 '16 at 02:55
3

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.

ryanmarc
  • 1,670
  • 1
  • 10
  • 9
1

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.

Community
  • 1
  • 1
abraham
  • 46,583
  • 10
  • 100
  • 152
1

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.

JayC
  • 7,053
  • 2
  • 25
  • 41
0

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.

Harish.bazee
  • 638
  • 6
  • 8
0

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

tkone
  • 22,092
  • 5
  • 54
  • 78
  • Wouldn't that be a 'fake' preloader? I mean .fetch is only getting some strings from the server, which is pretty fast so the overlay would just flash in and out. I need the preloaded to go away when the content of the fetch (images) are loaded and in the DOM. – Drazen Mar 21 '12 at 15:02
  • Then do the same thing, only don't put a loading screen up, but pass a function as `options.success` that removes the preloaded content. – tkone Mar 21 '12 at 15:12
  • I am not sure what you mean. I need the preloader to go away after all images are loaded and the DOM is ready. Sorry if i miss something but i don't understand how "don't put a loading screen up" would help me :) – Drazen Mar 21 '12 at 18:38
  • i thought you said you didn't want a loading screen, but wanted to dump the content. regardless, the concept still holds the same: throw up a loading screen. then rather than pulling down the loading screen from `option.success` pull it down from whatever adds the images to the DOM. I mean, what are the strings you're pulling from the server? The image urls? If so, then you're generating the image tags and adding them to the dom programatically, right? – tkone Mar 21 '12 at 19:00
  • Yeah i am pulling a JSON output with all images as backbone models with image url's and i have a Template (Eco Template Engine) where i have my markup for the image view template. Then i just render the view with that template – Drazen Mar 21 '12 at 19:33
  • So pull down the loading screen after you've rendered the view with that template in the same function that renders the template. – tkone Mar 21 '12 at 19:50