Question

I have been searching Google to get some ideas and I found some code but it's incomplete and hard to understand. I want to use knockout to bind a list of images.

What's the best way to set up a spinner background while the images are loading. I have a spinner class I can set and unset to the background image.

Here is the code but it's not clear

 ko.bindingHandlers.Loading = {
        update: function (element, valueAccessor, allBindingsAccessor) {
            var value = valueAccessor(), allBindings = allBindingsAccessor();
            var valueUnwrapped = ko.utils.unwrapObservable(value);

            if (valueUnwrapped == true)
                $(element).showLoading(); // Make the element visible
            else
                $(element).hideLoading();   // Make the element invisible
        }
    };

and then use it like

<div data-bind="Loading: isLoading" >

update

    <img src="http://www.aero-sa.com/images/ajax-loader.gif" data-bind="visible:loading" />
var model = function() {
    var self = this;
    this.loading =  ko.observable(true);
    setTimeout(function() {
        self.loading(false);
    }, 4000);
}
ko.applyBindings(new model());

i have few question on the above code. what is this here? this point to what? when i write the code like then image is not getting hide....why this is not working.

var model = function() {
        //var self = this;
        this.loading =  ko.observable(true);
        setTimeout(function() {
            this.loading(false);
        }, 4000);
    }
    ko.applyBindings(new model());

please explain if possible.

Was it helpful?

Solution

I had a similar problem. In my case, I needed to hide a whole block of HTML if an image inside the block could not be loaded. I ended up using the imagesLoaded library (https://github.com/desandro/imagesloaded), which I wrapped in a knockout custom binding :

function tryRegisterEvent(imgLoad, event, handler) {
    if (handler === undefined) return;

    imgLoad.on(event, handler);
}

function tryRegisterEvents(imgLoad, events, bindings) {
    for (var i = 0; i < events.length; ++i) {
        var event = events[i];
        tryRegisterEvent(imgLoad, event, bindings[event]);
    }
}

ko.bindingHandlers['imagesLoaded'] = {
    'init': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        if (imagesLoaded === undefined) {
            throw new Error('imagesLoaded is not defined');
        }

        var bindings = ko.utils.unwrapObservable(valueAccessor());

        var imgLoad = imagesLoaded(element);

        tryRegisterEvents(imgLoad, ['always', 'done', 'fail', 'progress'], bindings);
    },
    'update': function () {}
};

Then I could use this binding in my HTML, as follow:

<div data-bind="visible: isLoading() || isLoaded()">
    Some more HTML and text...
    <img src="..." data-bind="imagesLoaded: { done: function () { isLoaded(true); }, always: function () { isLoading(false); } }" />
</div>

I initially set isLoading to true and isLoaded to false, and the event handlers would then change my view model's state accordingly, based on the image load status.

Note that since the imagesLoaded library can work with container instead of single images (and monitor all images inside the container), you can use this custom binding on a parent element containing all your image gallery, then display your spinner and hide it when the always event is triggered.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top