rivets-switch-binder.js 4.17 KB
define(function(require, exports, module) {
    'use strict';
    var $ = require('jquery');
    var rivets = require('rivets');

    function rivetsBinderCall(binding, binderName, methodName, args) {
        var binder = rivets.binders[binderName];
        if (binder instanceof Function) {
            if (methodName === 'routine') {
                binder.apply(binding, args);
            }
        } else if (binder) {
            if (binder[methodName]) {
                binder[methodName].apply(binding, args);
            }
        }
    }
    function SwitchObject(name) {
        var cases = {};
        var defaultCase = null;
        var lastCase = null;
        var switchValue;
        function updateCase(foundCase, value) {
            rivetsBinderCall(foundCase, 'show', 'routine', [foundCase.el, value]);
        }
        this.addCase = function(binding) {
            /* global console:false */
            var value = binding.value !== undefined ? binding.value : binding.observer.value();
            console.log('SWITCH[' + name + '].addCase(' + value + ')');
            updateCase(cases[value] = binding, false);
            applyValue();
        };
        this.removeCase = function(binding) {
            var value = binding.value !== undefined ? binding.value : binding.observer.value();
            delete cases[value];
            updateCase(binding, true);
            applyValue();
        };
        this.setDefault = function(binding) {
            updateCase(defaultCase = binding, false);
            applyValue();
        };
        this.removeDefault = function(binding) {
            defaultCase = null;
            updateCase(binding, true);
            applyValue();
        };
        this.setValue = function(value) {
            /* global console:false */
            console.log('SWITCH[' + name + '].setValue(' + value + ')');
            switchValue = value;
            applyValue();
        };
        function applyValue() {
            var foundCase;
            if (switchValue === undefined || switchValue === null || !(foundCase = cases[switchValue]) || foundCase !== lastCase) {
                if (lastCase) {
                    updateCase(lastCase, false);
                    lastCase = null;
                }
                if (!foundCase) {
                    foundCase = defaultCase;
                }
                if (foundCase) {
                    updateCase(lastCase = foundCase, true);
                }
            }
        }
        this.name = name;
    }

    function findSwitchObject(el, switchName, doCreate) {
        var ptr = el, switchObject;
        while (ptr) {
            var $ptr = $(ptr);
            if ($ptr.attr('rv-switch-' + switchName)) {
                switchObject = $ptr.data('rivets-switchObject-' + switchName);
                if (!switchObject) {
                    switchObject = new SwitchObject(switchName);
                    if (doCreate) {
                        $ptr.data('rivets-switchObject-' + switchName, switchObject);
                    }
                }
                return switchObject;
            }
            ptr = ptr.parentNode;
        }
    }

    rivets.binders['switch-*'] = {
        bind: function(el) {
            $(el).data('rivets-switchObject-' + this.args[0], findSwitchObject(el, this.args[0], true));
        },
        unbind: function(el) {
            $(el).data('rivets-switchObject-' + this.args[0], null);
        },
        routine: function(el, value) {
            findSwitchObject(el, this.args[0], true).setValue(value);
        }
    };
    rivets.binders['switch-*-case'] = {
        bind: function(el) {
            findSwitchObject(el, this.args[0], true).addCase(this);
        },
        unbind: function(el) {
            findSwitchObject(el, this.args[0], false).removeCase(this);
        },
        routine: function(el, value) {
        }
    };
    rivets.binders['switch-*-default'] = {
        bind: function(el) {
            findSwitchObject(el, this.args[0], true).setDefault(this);
        },
        unbind: function(el) {
            findSwitchObject(el, this.args[0], false).removeDefault(this);
        },
        routine: function(el, value) {
        }
    };
    return {};
});