Knockout image transition

by sh54

HTML

<div data-bind="transitionImage: img" style="width: 300px; height: 300px"></div>

CSS

div.transition {
    -webkit-transition: opacity 0.5s linear;
    -moz-transition: opacity 0.5s linear;
    -o-transition: opacity 0.5s linear;
    transition: opacity 0.5s linear;
}

JavaScript

var vm = {
    img: ko.observable("http://media.npr.org/assets/img/2012/01/04/ap99121501386_custom-feedbb6efa738efee47e7828e805758dc427fa60-s6-c30.jpg")
}

ko.bindingHandlers.transitionImage = {
    init: function (element, valueAccessor) {
        // create a holder for the images
        var holder = document.createElement('div');
        holder.style['position'] = 'relative';
        holder.style['height'] = '100%';
        holder.style['width'] = '100%';
        element.appendChild(holder);

        // create initial image
        var url = ko.utils.unwrapObservable(valueAccessor());
        var fore = document.createElement('div');
        fore.style['background-image'] = 'url(' + url + ')';
        fore.style['position'] = 'absolute';
        fore.style['height'] = '100%';
        fore.style['width'] = '100%';
        fore.style['background-size'] = '100% 100%'
        holder.appendChild(fore);
    },
    update: function (element, valueAccessor) {
        var url = ko.utils.unwrapObservable(valueAccessor());

        // retrieve the holder element
        var holder = element.childNodes[0];

        // create new image to transition to
        var fore = document.createElement('div');
        fore.className = 'transition';
        fore.style['background-image'] = 'url(' + url + ')';
        fore.style['position'] = 'absolute';
        fore.style['height'] = '100%';
        fore.style['width'] = '100%';
        fore.style['background-size'] = '100% 100%'
        fore.style['opacity'] = '0'; // ensure it is hidden
        holder.appendChild(fore);

        // CSS3 animate opacity
        setTimeout(function () {
            fore.style['opacity'] = '1';
        }, 0);

        // dispose of unnecessary hidden images eventually
        setTimeout(function () {
            var toRemove = holder.childNodes[0];
            var removed = holder.removeChild(toRemove);
            delete removed;
        }, 10000);
    }
};

ko.applyBindings(vm)

// change image...