rivets-error-binder.js
4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
define(function(require) {
'use strict';
var module = require('module');
var rivets = require('rivets');
var _ = require('underscore');
var Backbone = require('backbone');
var $ = require('jquery');
var rivetsBinderCall = function(binding, binderName, methodName, args) {
var binder = rivets.binders[binderName];
var method = binder[methodName];
if (_.isFunction(binder)) {
if (methodName === 'routine') {
binder.apply(binding, args);
}
} else {
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);
}
};
function createTriggerProxy(obj, eventName) {
return function() {
obj.trigger.apply(obj, [eventName].concat(_.toArray(arguments)));
};
}
function ErrorHandler(binding, el) {
var seen = {};
var observer = binding.observer;
var oldParent;
var parentObserver;
var keyPath = observer.key.path;
var parentPath = _.collect(observer.tokens, function(token) {
return token.i + token.path;
}).join('');
this.on('bind', function() {
render(el, 'bind');
parentObserver = binding.observe(binding.view.models, parentPath, createTriggerProxy(this, 'parent-change'));
}, this);
this.on('focus', function() {
render(el, 'focus', false);
});
this.on('blur', function() {
seen[keyPath] = true;
render(el, 'blur', false);
if (observer.target) {
observer.target.validate();
}
});
this.on('validated', function(isValid, model, errors) {
var errorList = errors[keyPath];
if (errorList && seen[keyPath]) {
render(el, 'validated', errorList);
} else {
render(el, 'validated', false);
}
});
this.on('unbind', function() {
render(el, 'unbind');
this.trigger('stop-monitoring-parent');
parentObserver.unobserve();
parentObserver = null;
$(el).off('.rivets-error-binder');
});
this.on('unbind parent-change', function() {
if (oldParent) {
this.stopListening(oldParent);
}
oldParent = null;
}, this);
this.on('bind parent-change', function() {
var newParent = parentObserver.value();
if (newParent) {
seen = {};
render(el, 'validated', false);
this.listenTo(newParent, 'validated', createTriggerProxy(this, 'validated'));
}
oldParent = newParent;
}, this);
var $el = $(el);
$el.on('focus.rivets-error-binder', createTriggerProxy(this, 'focus'));
$el.on('blur.rivets-error-binder', createTriggerProxy(this, 'blur'));
}
_.extend(ErrorHandler.prototype, Backbone.Events);
rivets.binders['error-*'] = {
bind: function(el) {
this.errorHandler = new ErrorHandler(this, el);
this.errorHandler.trigger('bind');
rivetsBinderCall(this, this.args[0], 'bind', arguments);
},
unbind: function(el) {
this.errorHandler.trigger('unbind');
delete this.errorHandler;
rivetsBinderCall(this, this.args[0], 'unbind', arguments);
},
routine: function() {
rivetsBinderCall(this, this.args[0], 'routine', arguments);
}
};
});