rivets-error-binder.js 3.27 KB
define(function(require) {
    'use strict';
    var module = require('module');
    var rivets = require('rivets');
    var $ = require('jquery');

    var rivetsBinderCall = function(binding, binderName, methodName, args) {
        var binder = rivets.binders[binderName];
        binder[methodName].apply(binding, args);
    };

    var render = function(el, cmd, errorList) {
        var viewClassPath = module.config().viewClassPath;
        if (viewClassPath) {
            var $el = $(el);
            var view = $el.data('error-view');
            if (view === undefined && cmd === 'bind') {
                $el.data('error-view', null);
                require([viewClassPath], function(ViewClass) {
                    $el.data('error-view', new ViewClass({el: el}));
                });
                return;
            }
            if (view) {
                view.errorCallback(cmd, errorList);
            }
            return;
        }
        var renderImpl = module.config().render;
        if (renderImpl) {
            return renderImpl.apply(this, arguments);
        }
    };

    rivets.binders['error-*'] = {
        bind: function(el) {
            var observer = this.observer;
            var keyPath = observer.key.path;
            var holder = this.validationHolder = {
                //marker: el.parentNode.insertBefore(document.createComment(" rivets: " + this.type + " "), el),
                observer: observer,
                seen: {},
                focus: function() {
                    render(el, 'focus', false);
                },
                blur: function() {
                    holder.seen[keyPath] = true;
                    render(el, 'blur', false);
                    if (observer.target) {
                        observer.target.validate();
                    }
                },
                validated: function(isValid, model, errors) {
                    var errorList = errors[keyPath];
                    if (errorList && holder.seen[keyPath]) {
                        render(el, 'validated', errorList);
                    } else {
                        render(el, 'validated', false);
                    }
                }
            };
            $(el).on('focus.rivets-error-binder', holder.focus).on('blur.rivets-error-binder', holder.blur);
            rivetsBinderCall(this, this.args[0], 'bind', arguments);
            render(el, 'bind');
        },
        unbind: function(el) {
            var holder = this.validationHolder;
            render(el, 'unbind');
            $(this.validationHolder.marker).after(el).remove();
            $(el).off('.rivets-error-binder');
            if (holder.observer.target) {
                holder.observer.target.off('validated', holder.validated);
            }
            delete this.validationHolder;
            rivetsBinderCall(this, this.args[0], 'unbind', arguments);
        },
        routine: function() {
            var holder = this.validationHolder;
            if (this.observer.target) {
                this.observer.target.off('validated', holder.validated);
            }
            if (this.observer.target) {
                this.observer.target.on('validated', holder.validated);
            }
            rivetsBinderCall(this, this.args[0], 'routine', arguments);
        }
    };
});