forked from share/sharedb-string-binding
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
109 lines (93 loc) · 2.81 KB
/
index.js
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
var TextDiffBinding = require('text-diff-binding');
module.exports = StringBinding;
function StringBinding(element, doc, path) {
TextDiffBinding.call(this, element);
this.doc = doc;
this.path = path || [];
this._opListener = null;
this._inputListener = null;
}
StringBinding.prototype = Object.create(TextDiffBinding.prototype);
StringBinding.prototype.constructor = StringBinding;
StringBinding.prototype.setup = function() {
this.update();
this.attachDoc();
this.attachElement();
};
StringBinding.prototype.destroy = function() {
this.detachElement();
this.detachDoc();
};
StringBinding.prototype.attachElement = function() {
var binding = this;
this._inputListener = function() {
binding.onInput();
};
this.element.addEventListener('input', this._inputListener, false);
};
StringBinding.prototype.detachElement = function() {
this.element.removeEventListener('input', this._inputListener, false);
};
StringBinding.prototype.attachDoc = function() {
var binding = this;
this._opListener = function(op, source) {
binding._onOp(op, source);
};
this.doc.on('op', this._opListener);
};
StringBinding.prototype.detachDoc = function() {
this.doc.removeListener('op', this._opListener);
};
StringBinding.prototype._onOp = function(op, source) {
if (source === this) return;
if (op.length === 0) return;
if (op.length > 1) {
throw new Error('Op with multiple components emitted');
}
var component = op[0];
if (isSubpath(this.path, component.p)) {
this._parseInsertOp(component);
this._parseRemoveOp(component);
} else if (isSubpath(component.p, this.path)) {
this._parseParentOp();
}
};
StringBinding.prototype._parseInsertOp = function(component) {
if (!component.si) return;
var index = component.p[component.p.length - 1];
var length = component.si.length;
this.onInsert(index, length);
};
StringBinding.prototype._parseRemoveOp = function(component) {
if (!component.sd) return;
var index = component.p[component.p.length - 1];
var length = component.sd.length;
this.onRemove(index, length);
};
StringBinding.prototype._parseParentOp = function() {
this.update();
};
StringBinding.prototype._get = function() {
var value = this.doc.data;
for (var i = 0; i < this.path.length; i++) {
var segment = this.path[i];
value = value[segment];
}
return value;
};
StringBinding.prototype._insert = function(index, text) {
var path = this.path.concat(index);
var op = {p: path, si: text};
this.doc.submitOp(op, {source: this});
};
StringBinding.prototype._remove = function(index, text) {
var path = this.path.concat(index);
var op = {p: path, sd: text};
this.doc.submitOp(op, {source: this});
};
function isSubpath(path, testPath) {
for (var i = 0; i < path.length; i++) {
if (testPath[i] !== path[i]) return false;
}
return true;
}