Search code examples
javascriptjqueryanimationknockout.jssammy.js

Animating knockout template views


Is there a way to have transitional animations between "page" changes while using knockout for changing templates? I'm looking for something similar to Knockback-Navigators. I cant figure out a way to do this? Is there a package I can use to make this easier? Here is a JSFiddle with the same type of binding my project uses. And a sample of my javascript here:

var View = function (title, templateName, data) {
var self = this;
this.title = title;
this.templateName = templateName;
this.data = data;
this.url = ko.observable('#' + templateName);
};
var test1View = {
    test: ko.observable("TEST1")
};
var test2View = {
    test: ko.observable("TEST2")
};

var viewModel = {
views: ko.observableArray([
    new View("Test 1", "test1", test1View),
    new View("Test 2", "test2", test2View)]),
    selectedView: ko.observable(),
}
//Apply knockout bindings
ko.applyBindings(viewModel);

//Set up sammy url routes
Sammy(function () {
    //Handles only groups basically
    this.get('#:view', function () {
        var viewName = this.params.view;
        var tempViewObj = ko.utils.arrayFirst(viewModel.views(), function (item) {
            return item.templateName === viewName;

        });
        //set selectedView
        viewModel.selectedView(tempViewObj);
    });
}).run('#test1');

Solution

  • There are plenty of ways of doing this, here is one

    ko.bindingHandlers.withFade = {    
        init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            var $element = $(element);
            var observable = valueAccessor();
            var wrapper = ko.observable(observable());
    
            observable.subscribe(function(value) {
                var current = wrapper();
                fadeIn = function() {
                    wrapper(value);
                    $element.fadeIn();
                };
    
                if(current) {
                    $element.fadeOut(fadeIn);
                } else {
                    $element.hide();
                    fadeIn();
                }
            });
    
            ko.applyBindingsToNode(element, { with: wrapper }, bindingContext);
    
            return { controlsDescendantBindings: true };
        }
    };
    

    http://jsfiddle.net/7E84t/19/

    You can abstract the effect like this

    ko.transitions = {
        fade: {
            out: function(element, callback) {
                element.fadeOut(callback);
            },
            in: function(element) {
                element.fadeIn();
            }
        },
        slide: {
            out: function(element, callback) {
                element.slideUp(callback);
            },
            in: function(element) {
                element.slideDown();
            }
        }
    };
    

    html

    <div data-bind="withFade: { data: selectedView, transition: ko.transitions.slide }">
    

    http://jsfiddle.net/7E84t/23/