-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.js
180 lines (162 loc) · 4.93 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
var Range = require('quilljs/lib/lib/range');
var LINE_FORMATS = {
'align': true
};
var BINARY_FORMATS = {
'bold': true
, 'italic': true
, 'strike': true
, 'underline': true
};
var MIXED_FORMAT_VALUE = '*';
module.exports = DerbyQuill;
function DerbyQuill() {}
DerbyQuill.prototype.view = __dirname;
DerbyQuill.prototype.init = function() {
this.quill = null;
this.activeFormats = this.model.at('activeFormats');
this.value = this.model.at('value');
};
DerbyQuill.prototype.create = function() {
var Quill = require('quilljs');
var quill = this.quill = new Quill(this.editor);
var self = this;
quill.on('text-change', function() {
self.value.set(quill.editor.innerHTML);
var range = quill.getSelection();
self.updateActiveFormats(range);
});
quill.on('selection-change', function(range) {
self.updateActiveFormats(range);
});
// HACK: Quill should provide an event here, but we wrap the method to
// get a hook into what's going on instead
var prepareFormat = quill.prepareFormat;
quill.prepareFormat = function(name, value) {
prepareFormat.call(quill, name, value);
self.activeFormats.set(name, value);
};
// Iframes will stop bubbling at their window, so re-dispatch all clicks
// that bubble to the top of the iframe document on the containing element.
// This is helpful for popups to figure out when they should close
this.dom.on('click', quill.root.ownerDocument, function(e) {
var event = new MouseEvent(e.type, e);
self.editor.dispatchEvent(event);
});
};
DerbyQuill.prototype.clearFormatting = function() {
this.quill.focus();
var range = this.quill.getSelection();
var formats = this.getContainedFormats(range);
for (type in formats) {
this.setFormat(type, false);
}
};
DerbyQuill.prototype.toggleFormat = function(type) {
var value = !this.activeFormats.get(type);
this.setFormat(type, value);
};
DerbyQuill.prototype.setFormat = function(type, value) {
this.quill.focus();
var range = this.quill.getSelection();
if (range.isCollapsed()) {
this.quill.prepareFormat(type, value);
} else if (LINE_FORMATS[type]) {
this.quill.formatLine(range, type, value, 'user');
} else {
this.quill.formatText(range, type, value, 'user');
}
};
DerbyQuill.prototype.updateActiveFormats = function(range) {
if (!range) return;
var activeFormats = this.getActiveFormats(range);
this.activeFormats.set(activeFormats);
};
// Formats that are contained within part of the range
DerbyQuill.prototype.getContainedFormats = function(range) {
return this._getFormats(range, addContainedFormats);
};
// Formats that span the entire range
DerbyQuill.prototype.getActiveFormats = function(range) {
return this._getFormats(range, addActiveFormats);
};
DerbyQuill.prototype._getFormats = function(range, addFn) {
var formats = {};
var ops = this.getRangeContents(range).ops;
var lines = this.getRangeLines(range);
addFn(formats, ops, 'attributes');
addFn(formats, lines, 'formats');
return formats;
};
function addContainedFormats(formats, items, key) {
for (var i = 0; i < items.length; i++) {
var itemFormats = items[i][key];
for (var type in itemFormats) {
formats[type] = true;
}
}
}
function addActiveFormats(formats, items, key) {
var counts = {};
for (var i = 0; i < items.length; i++) {
var itemFormats = items[i][key];
for (var type in itemFormats) {
if (counts[type]) {
counts[type]++;
if (formats[type] !== itemFormats[type]) {
formats[type] = MIXED_FORMAT_VALUE;
}
} else {
counts[type] = 1;
formats[type] = itemFormats[type];
}
}
}
for (var type in counts) {
if (counts[type] !== items.length) {
if (BINARY_FORMATS[type]) {
delete formats[type];
} else {
formats[type] = MIXED_FORMAT_VALUE;
}
}
}
}
DerbyQuill.prototype.getRangeContents = function(range) {
if (range.isCollapsed()) {
var start = Math.max(0, range.start - 1);
return this.quill.getContents(start, range.end);
}
return this.quill.getContents(range);
};
DerbyQuill.prototype.getRangeLines = function(range) {
var line = this.quill.editor.doc.findLineAt(range.start)[0];
var lastLine = this.quill.editor.doc.findLineAt(range.end)[0];
var lines = [];
while (line) {
lines.push(line);
if (line === lastLine) break;
line = line.next;
}
return lines;
};
DerbyQuill.prototype.setRangeContents = function(range, value, attributes) {
var startLength = this.quill.getLength();
this.quill.setContents({
startLength: startLength
, ops: [
{start: 0, end: range.start}
, {value: value, attributes: attributes}
, {start: range.end, end: startLength}
]
});
var end = range.start + value.length;
if (range.isCollapsed()) {
this.quill.setSelection(end, end);
} else {
this.quill.setSelection(range.start, end);
}
};
DerbyQuill.prototype.createRange = function(start, end) {
return new Range(start, end);
};