1 |
efrain |
1 |
/**
|
|
|
2 |
* TinyMCE version 6.8.3 (2024-02-08)
|
|
|
3 |
*/
|
|
|
4 |
|
|
|
5 |
(function () {
|
|
|
6 |
'use strict';
|
|
|
7 |
|
|
|
8 |
var global$1 = tinymce.util.Tools.resolve('tinymce.ModelManager');
|
|
|
9 |
|
|
|
10 |
const hasProto = (v, constructor, predicate) => {
|
|
|
11 |
var _a;
|
|
|
12 |
if (predicate(v, constructor.prototype)) {
|
|
|
13 |
return true;
|
|
|
14 |
} else {
|
|
|
15 |
return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
|
|
|
16 |
}
|
|
|
17 |
};
|
|
|
18 |
const typeOf = x => {
|
|
|
19 |
const t = typeof x;
|
|
|
20 |
if (x === null) {
|
|
|
21 |
return 'null';
|
|
|
22 |
} else if (t === 'object' && Array.isArray(x)) {
|
|
|
23 |
return 'array';
|
|
|
24 |
} else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
|
|
|
25 |
return 'string';
|
|
|
26 |
} else {
|
|
|
27 |
return t;
|
|
|
28 |
}
|
|
|
29 |
};
|
|
|
30 |
const isType$1 = type => value => typeOf(value) === type;
|
|
|
31 |
const isSimpleType = type => value => typeof value === type;
|
|
|
32 |
const eq$2 = t => a => t === a;
|
|
|
33 |
const isString = isType$1('string');
|
|
|
34 |
const isObject = isType$1('object');
|
|
|
35 |
const isArray = isType$1('array');
|
|
|
36 |
const isNull = eq$2(null);
|
|
|
37 |
const isBoolean = isSimpleType('boolean');
|
|
|
38 |
const isUndefined = eq$2(undefined);
|
|
|
39 |
const isNullable = a => a === null || a === undefined;
|
|
|
40 |
const isNonNullable = a => !isNullable(a);
|
|
|
41 |
const isFunction = isSimpleType('function');
|
|
|
42 |
const isNumber = isSimpleType('number');
|
|
|
43 |
|
|
|
44 |
const noop = () => {
|
|
|
45 |
};
|
|
|
46 |
const compose = (fa, fb) => {
|
|
|
47 |
return (...args) => {
|
|
|
48 |
return fa(fb.apply(null, args));
|
|
|
49 |
};
|
|
|
50 |
};
|
|
|
51 |
const compose1 = (fbc, fab) => a => fbc(fab(a));
|
|
|
52 |
const constant = value => {
|
|
|
53 |
return () => {
|
|
|
54 |
return value;
|
|
|
55 |
};
|
|
|
56 |
};
|
|
|
57 |
const identity = x => {
|
|
|
58 |
return x;
|
|
|
59 |
};
|
|
|
60 |
const tripleEquals = (a, b) => {
|
|
|
61 |
return a === b;
|
|
|
62 |
};
|
|
|
63 |
function curry(fn, ...initialArgs) {
|
|
|
64 |
return (...restArgs) => {
|
|
|
65 |
const all = initialArgs.concat(restArgs);
|
|
|
66 |
return fn.apply(null, all);
|
|
|
67 |
};
|
|
|
68 |
}
|
|
|
69 |
const not = f => t => !f(t);
|
|
|
70 |
const die = msg => {
|
|
|
71 |
return () => {
|
|
|
72 |
throw new Error(msg);
|
|
|
73 |
};
|
|
|
74 |
};
|
|
|
75 |
const apply = f => {
|
|
|
76 |
return f();
|
|
|
77 |
};
|
|
|
78 |
const never = constant(false);
|
|
|
79 |
const always = constant(true);
|
|
|
80 |
|
|
|
81 |
class Optional {
|
|
|
82 |
constructor(tag, value) {
|
|
|
83 |
this.tag = tag;
|
|
|
84 |
this.value = value;
|
|
|
85 |
}
|
|
|
86 |
static some(value) {
|
|
|
87 |
return new Optional(true, value);
|
|
|
88 |
}
|
|
|
89 |
static none() {
|
|
|
90 |
return Optional.singletonNone;
|
|
|
91 |
}
|
|
|
92 |
fold(onNone, onSome) {
|
|
|
93 |
if (this.tag) {
|
|
|
94 |
return onSome(this.value);
|
|
|
95 |
} else {
|
|
|
96 |
return onNone();
|
|
|
97 |
}
|
|
|
98 |
}
|
|
|
99 |
isSome() {
|
|
|
100 |
return this.tag;
|
|
|
101 |
}
|
|
|
102 |
isNone() {
|
|
|
103 |
return !this.tag;
|
|
|
104 |
}
|
|
|
105 |
map(mapper) {
|
|
|
106 |
if (this.tag) {
|
|
|
107 |
return Optional.some(mapper(this.value));
|
|
|
108 |
} else {
|
|
|
109 |
return Optional.none();
|
|
|
110 |
}
|
|
|
111 |
}
|
|
|
112 |
bind(binder) {
|
|
|
113 |
if (this.tag) {
|
|
|
114 |
return binder(this.value);
|
|
|
115 |
} else {
|
|
|
116 |
return Optional.none();
|
|
|
117 |
}
|
|
|
118 |
}
|
|
|
119 |
exists(predicate) {
|
|
|
120 |
return this.tag && predicate(this.value);
|
|
|
121 |
}
|
|
|
122 |
forall(predicate) {
|
|
|
123 |
return !this.tag || predicate(this.value);
|
|
|
124 |
}
|
|
|
125 |
filter(predicate) {
|
|
|
126 |
if (!this.tag || predicate(this.value)) {
|
|
|
127 |
return this;
|
|
|
128 |
} else {
|
|
|
129 |
return Optional.none();
|
|
|
130 |
}
|
|
|
131 |
}
|
|
|
132 |
getOr(replacement) {
|
|
|
133 |
return this.tag ? this.value : replacement;
|
|
|
134 |
}
|
|
|
135 |
or(replacement) {
|
|
|
136 |
return this.tag ? this : replacement;
|
|
|
137 |
}
|
|
|
138 |
getOrThunk(thunk) {
|
|
|
139 |
return this.tag ? this.value : thunk();
|
|
|
140 |
}
|
|
|
141 |
orThunk(thunk) {
|
|
|
142 |
return this.tag ? this : thunk();
|
|
|
143 |
}
|
|
|
144 |
getOrDie(message) {
|
|
|
145 |
if (!this.tag) {
|
|
|
146 |
throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
|
|
|
147 |
} else {
|
|
|
148 |
return this.value;
|
|
|
149 |
}
|
|
|
150 |
}
|
|
|
151 |
static from(value) {
|
|
|
152 |
return isNonNullable(value) ? Optional.some(value) : Optional.none();
|
|
|
153 |
}
|
|
|
154 |
getOrNull() {
|
|
|
155 |
return this.tag ? this.value : null;
|
|
|
156 |
}
|
|
|
157 |
getOrUndefined() {
|
|
|
158 |
return this.value;
|
|
|
159 |
}
|
|
|
160 |
each(worker) {
|
|
|
161 |
if (this.tag) {
|
|
|
162 |
worker(this.value);
|
|
|
163 |
}
|
|
|
164 |
}
|
|
|
165 |
toArray() {
|
|
|
166 |
return this.tag ? [this.value] : [];
|
|
|
167 |
}
|
|
|
168 |
toString() {
|
|
|
169 |
return this.tag ? `some(${ this.value })` : 'none()';
|
|
|
170 |
}
|
|
|
171 |
}
|
|
|
172 |
Optional.singletonNone = new Optional(false);
|
|
|
173 |
|
|
|
174 |
const nativeSlice = Array.prototype.slice;
|
|
|
175 |
const nativeIndexOf = Array.prototype.indexOf;
|
|
|
176 |
const nativePush = Array.prototype.push;
|
|
|
177 |
const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
|
|
|
178 |
const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
|
|
|
179 |
const exists = (xs, pred) => {
|
|
|
180 |
for (let i = 0, len = xs.length; i < len; i++) {
|
|
|
181 |
const x = xs[i];
|
|
|
182 |
if (pred(x, i)) {
|
|
|
183 |
return true;
|
|
|
184 |
}
|
|
|
185 |
}
|
|
|
186 |
return false;
|
|
|
187 |
};
|
|
|
188 |
const range$1 = (num, f) => {
|
|
|
189 |
const r = [];
|
|
|
190 |
for (let i = 0; i < num; i++) {
|
|
|
191 |
r.push(f(i));
|
|
|
192 |
}
|
|
|
193 |
return r;
|
|
|
194 |
};
|
|
|
195 |
const map$1 = (xs, f) => {
|
|
|
196 |
const len = xs.length;
|
|
|
197 |
const r = new Array(len);
|
|
|
198 |
for (let i = 0; i < len; i++) {
|
|
|
199 |
const x = xs[i];
|
|
|
200 |
r[i] = f(x, i);
|
|
|
201 |
}
|
|
|
202 |
return r;
|
|
|
203 |
};
|
|
|
204 |
const each$2 = (xs, f) => {
|
|
|
205 |
for (let i = 0, len = xs.length; i < len; i++) {
|
|
|
206 |
const x = xs[i];
|
|
|
207 |
f(x, i);
|
|
|
208 |
}
|
|
|
209 |
};
|
|
|
210 |
const eachr = (xs, f) => {
|
|
|
211 |
for (let i = xs.length - 1; i >= 0; i--) {
|
|
|
212 |
const x = xs[i];
|
|
|
213 |
f(x, i);
|
|
|
214 |
}
|
|
|
215 |
};
|
|
|
216 |
const partition = (xs, pred) => {
|
|
|
217 |
const pass = [];
|
|
|
218 |
const fail = [];
|
|
|
219 |
for (let i = 0, len = xs.length; i < len; i++) {
|
|
|
220 |
const x = xs[i];
|
|
|
221 |
const arr = pred(x, i) ? pass : fail;
|
|
|
222 |
arr.push(x);
|
|
|
223 |
}
|
|
|
224 |
return {
|
|
|
225 |
pass,
|
|
|
226 |
fail
|
|
|
227 |
};
|
|
|
228 |
};
|
|
|
229 |
const filter$2 = (xs, pred) => {
|
|
|
230 |
const r = [];
|
|
|
231 |
for (let i = 0, len = xs.length; i < len; i++) {
|
|
|
232 |
const x = xs[i];
|
|
|
233 |
if (pred(x, i)) {
|
|
|
234 |
r.push(x);
|
|
|
235 |
}
|
|
|
236 |
}
|
|
|
237 |
return r;
|
|
|
238 |
};
|
|
|
239 |
const foldr = (xs, f, acc) => {
|
|
|
240 |
eachr(xs, (x, i) => {
|
|
|
241 |
acc = f(acc, x, i);
|
|
|
242 |
});
|
|
|
243 |
return acc;
|
|
|
244 |
};
|
|
|
245 |
const foldl = (xs, f, acc) => {
|
|
|
246 |
each$2(xs, (x, i) => {
|
|
|
247 |
acc = f(acc, x, i);
|
|
|
248 |
});
|
|
|
249 |
return acc;
|
|
|
250 |
};
|
|
|
251 |
const findUntil = (xs, pred, until) => {
|
|
|
252 |
for (let i = 0, len = xs.length; i < len; i++) {
|
|
|
253 |
const x = xs[i];
|
|
|
254 |
if (pred(x, i)) {
|
|
|
255 |
return Optional.some(x);
|
|
|
256 |
} else if (until(x, i)) {
|
|
|
257 |
break;
|
|
|
258 |
}
|
|
|
259 |
}
|
|
|
260 |
return Optional.none();
|
|
|
261 |
};
|
|
|
262 |
const find$1 = (xs, pred) => {
|
|
|
263 |
return findUntil(xs, pred, never);
|
|
|
264 |
};
|
|
|
265 |
const findIndex = (xs, pred) => {
|
|
|
266 |
for (let i = 0, len = xs.length; i < len; i++) {
|
|
|
267 |
const x = xs[i];
|
|
|
268 |
if (pred(x, i)) {
|
|
|
269 |
return Optional.some(i);
|
|
|
270 |
}
|
|
|
271 |
}
|
|
|
272 |
return Optional.none();
|
|
|
273 |
};
|
|
|
274 |
const flatten = xs => {
|
|
|
275 |
const r = [];
|
|
|
276 |
for (let i = 0, len = xs.length; i < len; ++i) {
|
|
|
277 |
if (!isArray(xs[i])) {
|
|
|
278 |
throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
|
|
|
279 |
}
|
|
|
280 |
nativePush.apply(r, xs[i]);
|
|
|
281 |
}
|
|
|
282 |
return r;
|
|
|
283 |
};
|
|
|
284 |
const bind$2 = (xs, f) => flatten(map$1(xs, f));
|
|
|
285 |
const forall = (xs, pred) => {
|
|
|
286 |
for (let i = 0, len = xs.length; i < len; ++i) {
|
|
|
287 |
const x = xs[i];
|
|
|
288 |
if (pred(x, i) !== true) {
|
|
|
289 |
return false;
|
|
|
290 |
}
|
|
|
291 |
}
|
|
|
292 |
return true;
|
|
|
293 |
};
|
|
|
294 |
const reverse = xs => {
|
|
|
295 |
const r = nativeSlice.call(xs, 0);
|
|
|
296 |
r.reverse();
|
|
|
297 |
return r;
|
|
|
298 |
};
|
|
|
299 |
const mapToObject = (xs, f) => {
|
|
|
300 |
const r = {};
|
|
|
301 |
for (let i = 0, len = xs.length; i < len; i++) {
|
|
|
302 |
const x = xs[i];
|
|
|
303 |
r[String(x)] = f(x, i);
|
|
|
304 |
}
|
|
|
305 |
return r;
|
|
|
306 |
};
|
|
|
307 |
const sort$1 = (xs, comparator) => {
|
|
|
308 |
const copy = nativeSlice.call(xs, 0);
|
|
|
309 |
copy.sort(comparator);
|
|
|
310 |
return copy;
|
|
|
311 |
};
|
|
|
312 |
const get$d = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
|
|
|
313 |
const head = xs => get$d(xs, 0);
|
|
|
314 |
const last$2 = xs => get$d(xs, xs.length - 1);
|
|
|
315 |
const findMap = (arr, f) => {
|
|
|
316 |
for (let i = 0; i < arr.length; i++) {
|
|
|
317 |
const r = f(arr[i], i);
|
|
|
318 |
if (r.isSome()) {
|
|
|
319 |
return r;
|
|
|
320 |
}
|
|
|
321 |
}
|
|
|
322 |
return Optional.none();
|
|
|
323 |
};
|
|
|
324 |
|
|
|
325 |
const keys = Object.keys;
|
|
|
326 |
const hasOwnProperty = Object.hasOwnProperty;
|
|
|
327 |
const each$1 = (obj, f) => {
|
|
|
328 |
const props = keys(obj);
|
|
|
329 |
for (let k = 0, len = props.length; k < len; k++) {
|
|
|
330 |
const i = props[k];
|
|
|
331 |
const x = obj[i];
|
|
|
332 |
f(x, i);
|
|
|
333 |
}
|
|
|
334 |
};
|
|
|
335 |
const map = (obj, f) => {
|
|
|
336 |
return tupleMap(obj, (x, i) => ({
|
|
|
337 |
k: i,
|
|
|
338 |
v: f(x, i)
|
|
|
339 |
}));
|
|
|
340 |
};
|
|
|
341 |
const tupleMap = (obj, f) => {
|
|
|
342 |
const r = {};
|
|
|
343 |
each$1(obj, (x, i) => {
|
|
|
344 |
const tuple = f(x, i);
|
|
|
345 |
r[tuple.k] = tuple.v;
|
|
|
346 |
});
|
|
|
347 |
return r;
|
|
|
348 |
};
|
|
|
349 |
const objAcc = r => (x, i) => {
|
|
|
350 |
r[i] = x;
|
|
|
351 |
};
|
|
|
352 |
const internalFilter = (obj, pred, onTrue, onFalse) => {
|
|
|
353 |
each$1(obj, (x, i) => {
|
|
|
354 |
(pred(x, i) ? onTrue : onFalse)(x, i);
|
|
|
355 |
});
|
|
|
356 |
};
|
|
|
357 |
const filter$1 = (obj, pred) => {
|
|
|
358 |
const t = {};
|
|
|
359 |
internalFilter(obj, pred, objAcc(t), noop);
|
|
|
360 |
return t;
|
|
|
361 |
};
|
|
|
362 |
const mapToArray = (obj, f) => {
|
|
|
363 |
const r = [];
|
|
|
364 |
each$1(obj, (value, name) => {
|
|
|
365 |
r.push(f(value, name));
|
|
|
366 |
});
|
|
|
367 |
return r;
|
|
|
368 |
};
|
|
|
369 |
const values = obj => {
|
|
|
370 |
return mapToArray(obj, identity);
|
|
|
371 |
};
|
|
|
372 |
const get$c = (obj, key) => {
|
|
|
373 |
return has$1(obj, key) ? Optional.from(obj[key]) : Optional.none();
|
|
|
374 |
};
|
|
|
375 |
const has$1 = (obj, key) => hasOwnProperty.call(obj, key);
|
|
|
376 |
const hasNonNullableKey = (obj, key) => has$1(obj, key) && obj[key] !== undefined && obj[key] !== null;
|
|
|
377 |
const isEmpty = r => {
|
|
|
378 |
for (const x in r) {
|
|
|
379 |
if (hasOwnProperty.call(r, x)) {
|
|
|
380 |
return false;
|
|
|
381 |
}
|
|
|
382 |
}
|
|
|
383 |
return true;
|
|
|
384 |
};
|
|
|
385 |
|
|
|
386 |
const Global = typeof window !== 'undefined' ? window : Function('return this;')();
|
|
|
387 |
|
|
|
388 |
const path = (parts, scope) => {
|
|
|
389 |
let o = scope !== undefined && scope !== null ? scope : Global;
|
|
|
390 |
for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
|
|
|
391 |
o = o[parts[i]];
|
|
|
392 |
}
|
|
|
393 |
return o;
|
|
|
394 |
};
|
|
|
395 |
const resolve$2 = (p, scope) => {
|
|
|
396 |
const parts = p.split('.');
|
|
|
397 |
return path(parts, scope);
|
|
|
398 |
};
|
|
|
399 |
|
|
|
400 |
const unsafe = (name, scope) => {
|
|
|
401 |
return resolve$2(name, scope);
|
|
|
402 |
};
|
|
|
403 |
const getOrDie = (name, scope) => {
|
|
|
404 |
const actual = unsafe(name, scope);
|
|
|
405 |
if (actual === undefined || actual === null) {
|
|
|
406 |
throw new Error(name + ' not available on this browser');
|
|
|
407 |
}
|
|
|
408 |
return actual;
|
|
|
409 |
};
|
|
|
410 |
|
|
|
411 |
const getPrototypeOf = Object.getPrototypeOf;
|
|
|
412 |
const sandHTMLElement = scope => {
|
|
|
413 |
return getOrDie('HTMLElement', scope);
|
|
|
414 |
};
|
|
|
415 |
const isPrototypeOf = x => {
|
|
|
416 |
const scope = resolve$2('ownerDocument.defaultView', x);
|
|
|
417 |
return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf(x).constructor.name));
|
|
|
418 |
};
|
|
|
419 |
|
|
|
420 |
const COMMENT = 8;
|
|
|
421 |
const DOCUMENT = 9;
|
|
|
422 |
const DOCUMENT_FRAGMENT = 11;
|
|
|
423 |
const ELEMENT = 1;
|
|
|
424 |
const TEXT = 3;
|
|
|
425 |
|
|
|
426 |
const name = element => {
|
|
|
427 |
const r = element.dom.nodeName;
|
|
|
428 |
return r.toLowerCase();
|
|
|
429 |
};
|
|
|
430 |
const type = element => element.dom.nodeType;
|
|
|
431 |
const isType = t => element => type(element) === t;
|
|
|
432 |
const isComment = element => type(element) === COMMENT || name(element) === '#comment';
|
|
|
433 |
const isHTMLElement = element => isElement(element) && isPrototypeOf(element.dom);
|
|
|
434 |
const isElement = isType(ELEMENT);
|
|
|
435 |
const isText = isType(TEXT);
|
|
|
436 |
const isDocument = isType(DOCUMENT);
|
|
|
437 |
const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
|
|
|
438 |
const isTag = tag => e => isElement(e) && name(e) === tag;
|
|
|
439 |
|
|
|
440 |
const rawSet = (dom, key, value) => {
|
|
|
441 |
if (isString(value) || isBoolean(value) || isNumber(value)) {
|
|
|
442 |
dom.setAttribute(key, value + '');
|
|
|
443 |
} else {
|
|
|
444 |
console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
|
|
|
445 |
throw new Error('Attribute value was not simple');
|
|
|
446 |
}
|
|
|
447 |
};
|
|
|
448 |
const set$2 = (element, key, value) => {
|
|
|
449 |
rawSet(element.dom, key, value);
|
|
|
450 |
};
|
|
|
451 |
const setAll$1 = (element, attrs) => {
|
|
|
452 |
const dom = element.dom;
|
|
|
453 |
each$1(attrs, (v, k) => {
|
|
|
454 |
rawSet(dom, k, v);
|
|
|
455 |
});
|
|
|
456 |
};
|
|
|
457 |
const setOptions = (element, attrs) => {
|
|
|
458 |
each$1(attrs, (v, k) => {
|
|
|
459 |
v.fold(() => {
|
|
|
460 |
remove$7(element, k);
|
|
|
461 |
}, value => {
|
|
|
462 |
rawSet(element.dom, k, value);
|
|
|
463 |
});
|
|
|
464 |
});
|
|
|
465 |
};
|
|
|
466 |
const get$b = (element, key) => {
|
|
|
467 |
const v = element.dom.getAttribute(key);
|
|
|
468 |
return v === null ? undefined : v;
|
|
|
469 |
};
|
|
|
470 |
const getOpt = (element, key) => Optional.from(get$b(element, key));
|
|
|
471 |
const remove$7 = (element, key) => {
|
|
|
472 |
element.dom.removeAttribute(key);
|
|
|
473 |
};
|
|
|
474 |
const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
|
|
|
475 |
acc[attr.name] = attr.value;
|
|
|
476 |
return acc;
|
|
|
477 |
}, {});
|
|
|
478 |
|
|
|
479 |
const fromHtml$1 = (html, scope) => {
|
|
|
480 |
const doc = scope || document;
|
|
|
481 |
const div = doc.createElement('div');
|
|
|
482 |
div.innerHTML = html;
|
|
|
483 |
if (!div.hasChildNodes() || div.childNodes.length > 1) {
|
|
|
484 |
const message = 'HTML does not have a single root node';
|
|
|
485 |
console.error(message, html);
|
|
|
486 |
throw new Error(message);
|
|
|
487 |
}
|
|
|
488 |
return fromDom$1(div.childNodes[0]);
|
|
|
489 |
};
|
|
|
490 |
const fromTag = (tag, scope) => {
|
|
|
491 |
const doc = scope || document;
|
|
|
492 |
const node = doc.createElement(tag);
|
|
|
493 |
return fromDom$1(node);
|
|
|
494 |
};
|
|
|
495 |
const fromText = (text, scope) => {
|
|
|
496 |
const doc = scope || document;
|
|
|
497 |
const node = doc.createTextNode(text);
|
|
|
498 |
return fromDom$1(node);
|
|
|
499 |
};
|
|
|
500 |
const fromDom$1 = node => {
|
|
|
501 |
if (node === null || node === undefined) {
|
|
|
502 |
throw new Error('Node cannot be null or undefined');
|
|
|
503 |
}
|
|
|
504 |
return { dom: node };
|
|
|
505 |
};
|
|
|
506 |
const fromPoint$1 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$1);
|
|
|
507 |
const SugarElement = {
|
|
|
508 |
fromHtml: fromHtml$1,
|
|
|
509 |
fromTag,
|
|
|
510 |
fromText,
|
|
|
511 |
fromDom: fromDom$1,
|
|
|
512 |
fromPoint: fromPoint$1
|
|
|
513 |
};
|
|
|
514 |
|
|
|
515 |
const is$2 = (element, selector) => {
|
|
|
516 |
const dom = element.dom;
|
|
|
517 |
if (dom.nodeType !== ELEMENT) {
|
|
|
518 |
return false;
|
|
|
519 |
} else {
|
|
|
520 |
const elem = dom;
|
|
|
521 |
if (elem.matches !== undefined) {
|
|
|
522 |
return elem.matches(selector);
|
|
|
523 |
} else if (elem.msMatchesSelector !== undefined) {
|
|
|
524 |
return elem.msMatchesSelector(selector);
|
|
|
525 |
} else if (elem.webkitMatchesSelector !== undefined) {
|
|
|
526 |
return elem.webkitMatchesSelector(selector);
|
|
|
527 |
} else if (elem.mozMatchesSelector !== undefined) {
|
|
|
528 |
return elem.mozMatchesSelector(selector);
|
|
|
529 |
} else {
|
|
|
530 |
throw new Error('Browser lacks native selectors');
|
|
|
531 |
}
|
|
|
532 |
}
|
|
|
533 |
};
|
|
|
534 |
const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
|
|
|
535 |
const all$1 = (selector, scope) => {
|
|
|
536 |
const base = scope === undefined ? document : scope.dom;
|
|
|
537 |
return bypassSelector(base) ? [] : map$1(base.querySelectorAll(selector), SugarElement.fromDom);
|
|
|
538 |
};
|
|
|
539 |
const one = (selector, scope) => {
|
|
|
540 |
const base = scope === undefined ? document : scope.dom;
|
|
|
541 |
return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
|
|
|
542 |
};
|
|
|
543 |
|
|
|
544 |
const eq$1 = (e1, e2) => e1.dom === e2.dom;
|
|
|
545 |
const contains$1 = (e1, e2) => {
|
|
|
546 |
const d1 = e1.dom;
|
|
|
547 |
const d2 = e2.dom;
|
|
|
548 |
return d1 === d2 ? false : d1.contains(d2);
|
|
|
549 |
};
|
|
|
550 |
const is$1 = is$2;
|
|
|
551 |
|
|
|
552 |
const owner = element => SugarElement.fromDom(element.dom.ownerDocument);
|
|
|
553 |
const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos);
|
|
|
554 |
const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
|
|
|
555 |
const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
|
|
|
556 |
const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
|
|
|
557 |
const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
|
|
|
558 |
const parents = (element, isRoot) => {
|
|
|
559 |
const stop = isFunction(isRoot) ? isRoot : never;
|
|
|
560 |
let dom = element.dom;
|
|
|
561 |
const ret = [];
|
|
|
562 |
while (dom.parentNode !== null && dom.parentNode !== undefined) {
|
|
|
563 |
const rawParent = dom.parentNode;
|
|
|
564 |
const p = SugarElement.fromDom(rawParent);
|
|
|
565 |
ret.push(p);
|
|
|
566 |
if (stop(p) === true) {
|
|
|
567 |
break;
|
|
|
568 |
} else {
|
|
|
569 |
dom = rawParent;
|
|
|
570 |
}
|
|
|
571 |
}
|
|
|
572 |
return ret;
|
|
|
573 |
};
|
|
|
574 |
const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
|
|
|
575 |
const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
|
|
|
576 |
const children$2 = element => map$1(element.dom.childNodes, SugarElement.fromDom);
|
|
|
577 |
const child$2 = (element, index) => {
|
|
|
578 |
const cs = element.dom.childNodes;
|
|
|
579 |
return Optional.from(cs[index]).map(SugarElement.fromDom);
|
|
|
580 |
};
|
|
|
581 |
const firstChild = element => child$2(element, 0);
|
|
|
582 |
|
|
|
583 |
const before$3 = (marker, element) => {
|
|
|
584 |
const parent$1 = parent(marker);
|
|
|
585 |
parent$1.each(v => {
|
|
|
586 |
v.dom.insertBefore(element.dom, marker.dom);
|
|
|
587 |
});
|
|
|
588 |
};
|
|
|
589 |
const after$5 = (marker, element) => {
|
|
|
590 |
const sibling = nextSibling(marker);
|
|
|
591 |
sibling.fold(() => {
|
|
|
592 |
const parent$1 = parent(marker);
|
|
|
593 |
parent$1.each(v => {
|
|
|
594 |
append$1(v, element);
|
|
|
595 |
});
|
|
|
596 |
}, v => {
|
|
|
597 |
before$3(v, element);
|
|
|
598 |
});
|
|
|
599 |
};
|
|
|
600 |
const prepend = (parent, element) => {
|
|
|
601 |
const firstChild$1 = firstChild(parent);
|
|
|
602 |
firstChild$1.fold(() => {
|
|
|
603 |
append$1(parent, element);
|
|
|
604 |
}, v => {
|
|
|
605 |
parent.dom.insertBefore(element.dom, v.dom);
|
|
|
606 |
});
|
|
|
607 |
};
|
|
|
608 |
const append$1 = (parent, element) => {
|
|
|
609 |
parent.dom.appendChild(element.dom);
|
|
|
610 |
};
|
|
|
611 |
const appendAt = (parent, element, index) => {
|
|
|
612 |
child$2(parent, index).fold(() => {
|
|
|
613 |
append$1(parent, element);
|
|
|
614 |
}, v => {
|
|
|
615 |
before$3(v, element);
|
|
|
616 |
});
|
|
|
617 |
};
|
|
|
618 |
const wrap = (element, wrapper) => {
|
|
|
619 |
before$3(element, wrapper);
|
|
|
620 |
append$1(wrapper, element);
|
|
|
621 |
};
|
|
|
622 |
|
|
|
623 |
const after$4 = (marker, elements) => {
|
|
|
624 |
each$2(elements, (x, i) => {
|
|
|
625 |
const e = i === 0 ? marker : elements[i - 1];
|
|
|
626 |
after$5(e, x);
|
|
|
627 |
});
|
|
|
628 |
};
|
|
|
629 |
const append = (parent, elements) => {
|
|
|
630 |
each$2(elements, x => {
|
|
|
631 |
append$1(parent, x);
|
|
|
632 |
});
|
|
|
633 |
};
|
|
|
634 |
|
|
|
635 |
const empty = element => {
|
|
|
636 |
element.dom.textContent = '';
|
|
|
637 |
each$2(children$2(element), rogue => {
|
|
|
638 |
remove$6(rogue);
|
|
|
639 |
});
|
|
|
640 |
};
|
|
|
641 |
const remove$6 = element => {
|
|
|
642 |
const dom = element.dom;
|
|
|
643 |
if (dom.parentNode !== null) {
|
|
|
644 |
dom.parentNode.removeChild(dom);
|
|
|
645 |
}
|
|
|
646 |
};
|
|
|
647 |
const unwrap = wrapper => {
|
|
|
648 |
const children = children$2(wrapper);
|
|
|
649 |
if (children.length > 0) {
|
|
|
650 |
after$4(wrapper, children);
|
|
|
651 |
}
|
|
|
652 |
remove$6(wrapper);
|
|
|
653 |
};
|
|
|
654 |
|
|
|
655 |
const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
|
|
|
656 |
const shallow = original => clone$1(original, false);
|
|
|
657 |
const deep = original => clone$1(original, true);
|
|
|
658 |
const shallowAs = (original, tag) => {
|
|
|
659 |
const nu = SugarElement.fromTag(tag);
|
|
|
660 |
const attributes = clone$2(original);
|
|
|
661 |
setAll$1(nu, attributes);
|
|
|
662 |
return nu;
|
|
|
663 |
};
|
|
|
664 |
const copy$2 = (original, tag) => {
|
|
|
665 |
const nu = shallowAs(original, tag);
|
|
|
666 |
const cloneChildren = children$2(deep(original));
|
|
|
667 |
append(nu, cloneChildren);
|
|
|
668 |
return nu;
|
|
|
669 |
};
|
|
|
670 |
const mutate$1 = (original, tag) => {
|
|
|
671 |
const nu = shallowAs(original, tag);
|
|
|
672 |
after$5(original, nu);
|
|
|
673 |
const children = children$2(original);
|
|
|
674 |
append(nu, children);
|
|
|
675 |
remove$6(original);
|
|
|
676 |
return nu;
|
|
|
677 |
};
|
|
|
678 |
|
|
|
679 |
const validSectionList = [
|
|
|
680 |
'tfoot',
|
|
|
681 |
'thead',
|
|
|
682 |
'tbody',
|
|
|
683 |
'colgroup'
|
|
|
684 |
];
|
|
|
685 |
const isValidSection = parentName => contains$2(validSectionList, parentName);
|
|
|
686 |
const grid = (rows, columns) => ({
|
|
|
687 |
rows,
|
|
|
688 |
columns
|
|
|
689 |
});
|
|
|
690 |
const address = (row, column) => ({
|
|
|
691 |
row,
|
|
|
692 |
column
|
|
|
693 |
});
|
|
|
694 |
const detail = (element, rowspan, colspan) => ({
|
|
|
695 |
element,
|
|
|
696 |
rowspan,
|
|
|
697 |
colspan
|
|
|
698 |
});
|
|
|
699 |
const detailnew = (element, rowspan, colspan, isNew) => ({
|
|
|
700 |
element,
|
|
|
701 |
rowspan,
|
|
|
702 |
colspan,
|
|
|
703 |
isNew
|
|
|
704 |
});
|
|
|
705 |
const extended = (element, rowspan, colspan, row, column, isLocked) => ({
|
|
|
706 |
element,
|
|
|
707 |
rowspan,
|
|
|
708 |
colspan,
|
|
|
709 |
row,
|
|
|
710 |
column,
|
|
|
711 |
isLocked
|
|
|
712 |
});
|
|
|
713 |
const rowdetail = (element, cells, section) => ({
|
|
|
714 |
element,
|
|
|
715 |
cells,
|
|
|
716 |
section
|
|
|
717 |
});
|
|
|
718 |
const rowdetailnew = (element, cells, section, isNew) => ({
|
|
|
719 |
element,
|
|
|
720 |
cells,
|
|
|
721 |
section,
|
|
|
722 |
isNew
|
|
|
723 |
});
|
|
|
724 |
const elementnew = (element, isNew, isLocked) => ({
|
|
|
725 |
element,
|
|
|
726 |
isNew,
|
|
|
727 |
isLocked
|
|
|
728 |
});
|
|
|
729 |
const rowcells = (element, cells, section, isNew) => ({
|
|
|
730 |
element,
|
|
|
731 |
cells,
|
|
|
732 |
section,
|
|
|
733 |
isNew
|
|
|
734 |
});
|
|
|
735 |
const bounds = (startRow, startCol, finishRow, finishCol) => ({
|
|
|
736 |
startRow,
|
|
|
737 |
startCol,
|
|
|
738 |
finishRow,
|
|
|
739 |
finishCol
|
|
|
740 |
});
|
|
|
741 |
const columnext = (element, colspan, column) => ({
|
|
|
742 |
element,
|
|
|
743 |
colspan,
|
|
|
744 |
column
|
|
|
745 |
});
|
|
|
746 |
const colgroup = (element, columns) => ({
|
|
|
747 |
element,
|
|
|
748 |
columns
|
|
|
749 |
});
|
|
|
750 |
|
|
|
751 |
const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
|
|
|
752 |
const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
|
|
|
753 |
const isSupported$1 = constant(supported);
|
|
|
754 |
const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
|
|
|
755 |
const getShadowRoot = e => {
|
|
|
756 |
const r = getRootNode(e);
|
|
|
757 |
return isShadowRoot(r) ? Optional.some(r) : Optional.none();
|
|
|
758 |
};
|
|
|
759 |
const getShadowHost = e => SugarElement.fromDom(e.dom.host);
|
|
|
760 |
const getOriginalEventTarget = event => {
|
|
|
761 |
if (isSupported$1() && isNonNullable(event.target)) {
|
|
|
762 |
const el = SugarElement.fromDom(event.target);
|
|
|
763 |
if (isElement(el) && isOpenShadowHost(el)) {
|
|
|
764 |
if (event.composed && event.composedPath) {
|
|
|
765 |
const composedPath = event.composedPath();
|
|
|
766 |
if (composedPath) {
|
|
|
767 |
return head(composedPath);
|
|
|
768 |
}
|
|
|
769 |
}
|
|
|
770 |
}
|
|
|
771 |
}
|
|
|
772 |
return Optional.from(event.target);
|
|
|
773 |
};
|
|
|
774 |
const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
|
|
|
775 |
|
|
|
776 |
const inBody = element => {
|
|
|
777 |
const dom = isText(element) ? element.dom.parentNode : element.dom;
|
|
|
778 |
if (dom === undefined || dom === null || dom.ownerDocument === null) {
|
|
|
779 |
return false;
|
|
|
780 |
}
|
|
|
781 |
const doc = dom.ownerDocument;
|
|
|
782 |
return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
|
|
|
783 |
};
|
|
|
784 |
const body$1 = () => getBody$1(SugarElement.fromDom(document));
|
|
|
785 |
const getBody$1 = doc => {
|
|
|
786 |
const b = doc.dom.body;
|
|
|
787 |
if (b === null || b === undefined) {
|
|
|
788 |
throw new Error('Body is not available yet');
|
|
|
789 |
}
|
|
|
790 |
return SugarElement.fromDom(b);
|
|
|
791 |
};
|
|
|
792 |
|
|
|
793 |
const ancestors$4 = (scope, predicate, isRoot) => filter$2(parents(scope, isRoot), predicate);
|
|
|
794 |
const children$1 = (scope, predicate) => filter$2(children$2(scope), predicate);
|
|
|
795 |
const descendants$1 = (scope, predicate) => {
|
|
|
796 |
let result = [];
|
|
|
797 |
each$2(children$2(scope), x => {
|
|
|
798 |
if (predicate(x)) {
|
|
|
799 |
result = result.concat([x]);
|
|
|
800 |
}
|
|
|
801 |
result = result.concat(descendants$1(x, predicate));
|
|
|
802 |
});
|
|
|
803 |
return result;
|
|
|
804 |
};
|
|
|
805 |
|
|
|
806 |
const ancestors$3 = (scope, selector, isRoot) => ancestors$4(scope, e => is$2(e, selector), isRoot);
|
|
|
807 |
const children = (scope, selector) => children$1(scope, e => is$2(e, selector));
|
|
|
808 |
const descendants = (scope, selector) => all$1(selector, scope);
|
|
|
809 |
|
|
|
810 |
var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
|
|
|
811 |
if (is(scope, a)) {
|
|
|
812 |
return Optional.some(scope);
|
|
|
813 |
} else if (isFunction(isRoot) && isRoot(scope)) {
|
|
|
814 |
return Optional.none();
|
|
|
815 |
} else {
|
|
|
816 |
return ancestor(scope, a, isRoot);
|
|
|
817 |
}
|
|
|
818 |
};
|
|
|
819 |
|
|
|
820 |
const ancestor$2 = (scope, predicate, isRoot) => {
|
|
|
821 |
let element = scope.dom;
|
|
|
822 |
const stop = isFunction(isRoot) ? isRoot : never;
|
|
|
823 |
while (element.parentNode) {
|
|
|
824 |
element = element.parentNode;
|
|
|
825 |
const el = SugarElement.fromDom(element);
|
|
|
826 |
if (predicate(el)) {
|
|
|
827 |
return Optional.some(el);
|
|
|
828 |
} else if (stop(el)) {
|
|
|
829 |
break;
|
|
|
830 |
}
|
|
|
831 |
}
|
|
|
832 |
return Optional.none();
|
|
|
833 |
};
|
|
|
834 |
const closest$2 = (scope, predicate, isRoot) => {
|
|
|
835 |
const is = (s, test) => test(s);
|
|
|
836 |
return ClosestOrAncestor(is, ancestor$2, scope, predicate, isRoot);
|
|
|
837 |
};
|
|
|
838 |
const child$1 = (scope, predicate) => {
|
|
|
839 |
const pred = node => predicate(SugarElement.fromDom(node));
|
|
|
840 |
const result = find$1(scope.dom.childNodes, pred);
|
|
|
841 |
return result.map(SugarElement.fromDom);
|
|
|
842 |
};
|
|
|
843 |
const descendant$1 = (scope, predicate) => {
|
|
|
844 |
const descend = node => {
|
|
|
845 |
for (let i = 0; i < node.childNodes.length; i++) {
|
|
|
846 |
const child = SugarElement.fromDom(node.childNodes[i]);
|
|
|
847 |
if (predicate(child)) {
|
|
|
848 |
return Optional.some(child);
|
|
|
849 |
}
|
|
|
850 |
const res = descend(node.childNodes[i]);
|
|
|
851 |
if (res.isSome()) {
|
|
|
852 |
return res;
|
|
|
853 |
}
|
|
|
854 |
}
|
|
|
855 |
return Optional.none();
|
|
|
856 |
};
|
|
|
857 |
return descend(scope.dom);
|
|
|
858 |
};
|
|
|
859 |
|
|
|
860 |
const ancestor$1 = (scope, selector, isRoot) => ancestor$2(scope, e => is$2(e, selector), isRoot);
|
|
|
861 |
const child = (scope, selector) => child$1(scope, e => is$2(e, selector));
|
|
|
862 |
const descendant = (scope, selector) => one(selector, scope);
|
|
|
863 |
const closest$1 = (scope, selector, isRoot) => {
|
|
|
864 |
const is = (element, selector) => is$2(element, selector);
|
|
|
865 |
return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot);
|
|
|
866 |
};
|
|
|
867 |
|
|
|
868 |
const is = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
|
|
|
869 |
const cat = arr => {
|
|
|
870 |
const r = [];
|
|
|
871 |
const push = x => {
|
|
|
872 |
r.push(x);
|
|
|
873 |
};
|
|
|
874 |
for (let i = 0; i < arr.length; i++) {
|
|
|
875 |
arr[i].each(push);
|
|
|
876 |
}
|
|
|
877 |
return r;
|
|
|
878 |
};
|
|
|
879 |
const bindFrom = (a, f) => a !== undefined && a !== null ? f(a) : Optional.none();
|
|
|
880 |
const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
|
|
|
881 |
|
|
|
882 |
const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
|
|
|
883 |
const contains = (str, substr, start = 0, end) => {
|
|
|
884 |
const idx = str.indexOf(substr, start);
|
|
|
885 |
if (idx !== -1) {
|
|
|
886 |
return isUndefined(end) ? true : idx + substr.length <= end;
|
|
|
887 |
} else {
|
|
|
888 |
return false;
|
|
|
889 |
}
|
|
|
890 |
};
|
|
|
891 |
const startsWith = (str, prefix) => {
|
|
|
892 |
return checkRange(str, prefix, 0);
|
|
|
893 |
};
|
|
|
894 |
const endsWith = (str, suffix) => {
|
|
|
895 |
return checkRange(str, suffix, str.length - suffix.length);
|
|
|
896 |
};
|
|
|
897 |
const blank = r => s => s.replace(r, '');
|
|
|
898 |
const trim = blank(/^\s+|\s+$/g);
|
|
|
899 |
const isNotEmpty = s => s.length > 0;
|
|
|
900 |
const toFloat = value => {
|
|
|
901 |
const num = parseFloat(value);
|
|
|
902 |
return isNaN(num) ? Optional.none() : Optional.some(num);
|
|
|
903 |
};
|
|
|
904 |
|
|
|
905 |
const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
|
|
|
906 |
|
|
|
907 |
const internalSet = (dom, property, value) => {
|
|
|
908 |
if (!isString(value)) {
|
|
|
909 |
console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
|
|
|
910 |
throw new Error('CSS value must be a string: ' + value);
|
|
|
911 |
}
|
|
|
912 |
if (isSupported(dom)) {
|
|
|
913 |
dom.style.setProperty(property, value);
|
|
|
914 |
}
|
|
|
915 |
};
|
|
|
916 |
const internalRemove = (dom, property) => {
|
|
|
917 |
if (isSupported(dom)) {
|
|
|
918 |
dom.style.removeProperty(property);
|
|
|
919 |
}
|
|
|
920 |
};
|
|
|
921 |
const set$1 = (element, property, value) => {
|
|
|
922 |
const dom = element.dom;
|
|
|
923 |
internalSet(dom, property, value);
|
|
|
924 |
};
|
|
|
925 |
const setAll = (element, css) => {
|
|
|
926 |
const dom = element.dom;
|
|
|
927 |
each$1(css, (v, k) => {
|
|
|
928 |
internalSet(dom, k, v);
|
|
|
929 |
});
|
|
|
930 |
};
|
|
|
931 |
const get$a = (element, property) => {
|
|
|
932 |
const dom = element.dom;
|
|
|
933 |
const styles = window.getComputedStyle(dom);
|
|
|
934 |
const r = styles.getPropertyValue(property);
|
|
|
935 |
return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
|
|
|
936 |
};
|
|
|
937 |
const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
|
|
|
938 |
const getRaw$2 = (element, property) => {
|
|
|
939 |
const dom = element.dom;
|
|
|
940 |
const raw = getUnsafeProperty(dom, property);
|
|
|
941 |
return Optional.from(raw).filter(r => r.length > 0);
|
|
|
942 |
};
|
|
|
943 |
const remove$5 = (element, property) => {
|
|
|
944 |
const dom = element.dom;
|
|
|
945 |
internalRemove(dom, property);
|
|
|
946 |
if (is(getOpt(element, 'style').map(trim), '')) {
|
|
|
947 |
remove$7(element, 'style');
|
|
|
948 |
}
|
|
|
949 |
};
|
|
|
950 |
const copy$1 = (source, target) => {
|
|
|
951 |
const sourceDom = source.dom;
|
|
|
952 |
const targetDom = target.dom;
|
|
|
953 |
if (isSupported(sourceDom) && isSupported(targetDom)) {
|
|
|
954 |
targetDom.style.cssText = sourceDom.style.cssText;
|
|
|
955 |
}
|
|
|
956 |
};
|
|
|
957 |
|
|
|
958 |
const getAttrValue = (cell, name, fallback = 0) => getOpt(cell, name).map(value => parseInt(value, 10)).getOr(fallback);
|
|
|
959 |
const getSpan = (cell, type) => getAttrValue(cell, type, 1);
|
|
|
960 |
const hasColspan = cellOrCol => {
|
|
|
961 |
if (isTag('col')(cellOrCol)) {
|
|
|
962 |
return getAttrValue(cellOrCol, 'span', 1) > 1;
|
|
|
963 |
} else {
|
|
|
964 |
return getSpan(cellOrCol, 'colspan') > 1;
|
|
|
965 |
}
|
|
|
966 |
};
|
|
|
967 |
const hasRowspan = cell => getSpan(cell, 'rowspan') > 1;
|
|
|
968 |
const getCssValue = (element, property) => parseInt(get$a(element, property), 10);
|
|
|
969 |
const minWidth = constant(10);
|
|
|
970 |
const minHeight = constant(10);
|
|
|
971 |
|
|
|
972 |
const firstLayer = (scope, selector) => {
|
|
|
973 |
return filterFirstLayer(scope, selector, always);
|
|
|
974 |
};
|
|
|
975 |
const filterFirstLayer = (scope, selector, predicate) => {
|
|
|
976 |
return bind$2(children$2(scope), x => {
|
|
|
977 |
if (is$2(x, selector)) {
|
|
|
978 |
return predicate(x) ? [x] : [];
|
|
|
979 |
} else {
|
|
|
980 |
return filterFirstLayer(x, selector, predicate);
|
|
|
981 |
}
|
|
|
982 |
});
|
|
|
983 |
};
|
|
|
984 |
|
|
|
985 |
const lookup = (tags, element, isRoot = never) => {
|
|
|
986 |
if (isRoot(element)) {
|
|
|
987 |
return Optional.none();
|
|
|
988 |
}
|
|
|
989 |
if (contains$2(tags, name(element))) {
|
|
|
990 |
return Optional.some(element);
|
|
|
991 |
}
|
|
|
992 |
const isRootOrUpperTable = elm => is$2(elm, 'table') || isRoot(elm);
|
|
|
993 |
return ancestor$1(element, tags.join(','), isRootOrUpperTable);
|
|
|
994 |
};
|
|
|
995 |
const cell = (element, isRoot) => lookup([
|
|
|
996 |
'td',
|
|
|
997 |
'th'
|
|
|
998 |
], element, isRoot);
|
|
|
999 |
const cells$1 = ancestor => firstLayer(ancestor, 'th,td');
|
|
|
1000 |
const columns$1 = ancestor => {
|
|
|
1001 |
if (is$2(ancestor, 'colgroup')) {
|
|
|
1002 |
return children(ancestor, 'col');
|
|
|
1003 |
} else {
|
|
|
1004 |
return bind$2(columnGroups(ancestor), columnGroup => children(columnGroup, 'col'));
|
|
|
1005 |
}
|
|
|
1006 |
};
|
|
|
1007 |
const table = (element, isRoot) => closest$1(element, 'table', isRoot);
|
|
|
1008 |
const rows$1 = ancestor => firstLayer(ancestor, 'tr');
|
|
|
1009 |
const columnGroups = ancestor => table(ancestor).fold(constant([]), table => children(table, 'colgroup'));
|
|
|
1010 |
|
|
|
1011 |
const fromRowsOrColGroups = (elems, getSection) => map$1(elems, row => {
|
|
|
1012 |
if (name(row) === 'colgroup') {
|
|
|
1013 |
const cells = map$1(columns$1(row), column => {
|
|
|
1014 |
const colspan = getAttrValue(column, 'span', 1);
|
|
|
1015 |
return detail(column, 1, colspan);
|
|
|
1016 |
});
|
|
|
1017 |
return rowdetail(row, cells, 'colgroup');
|
|
|
1018 |
} else {
|
|
|
1019 |
const cells = map$1(cells$1(row), cell => {
|
|
|
1020 |
const rowspan = getAttrValue(cell, 'rowspan', 1);
|
|
|
1021 |
const colspan = getAttrValue(cell, 'colspan', 1);
|
|
|
1022 |
return detail(cell, rowspan, colspan);
|
|
|
1023 |
});
|
|
|
1024 |
return rowdetail(row, cells, getSection(row));
|
|
|
1025 |
}
|
|
|
1026 |
});
|
|
|
1027 |
const getParentSection = group => parent(group).map(parent => {
|
|
|
1028 |
const parentName = name(parent);
|
|
|
1029 |
return isValidSection(parentName) ? parentName : 'tbody';
|
|
|
1030 |
}).getOr('tbody');
|
|
|
1031 |
const fromTable$1 = table => {
|
|
|
1032 |
const rows = rows$1(table);
|
|
|
1033 |
const columnGroups$1 = columnGroups(table);
|
|
|
1034 |
const elems = [
|
|
|
1035 |
...columnGroups$1,
|
|
|
1036 |
...rows
|
|
|
1037 |
];
|
|
|
1038 |
return fromRowsOrColGroups(elems, getParentSection);
|
|
|
1039 |
};
|
|
|
1040 |
const fromPastedRows = (elems, section) => fromRowsOrColGroups(elems, () => section);
|
|
|
1041 |
|
|
|
1042 |
const cached = f => {
|
|
|
1043 |
let called = false;
|
|
|
1044 |
let r;
|
|
|
1045 |
return (...args) => {
|
|
|
1046 |
if (!called) {
|
|
|
1047 |
called = true;
|
|
|
1048 |
r = f.apply(null, args);
|
|
|
1049 |
}
|
|
|
1050 |
return r;
|
|
|
1051 |
};
|
|
|
1052 |
};
|
|
|
1053 |
|
|
|
1054 |
const DeviceType = (os, browser, userAgent, mediaMatch) => {
|
|
|
1055 |
const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
|
|
|
1056 |
const isiPhone = os.isiOS() && !isiPad;
|
|
|
1057 |
const isMobile = os.isiOS() || os.isAndroid();
|
|
|
1058 |
const isTouch = isMobile || mediaMatch('(pointer:coarse)');
|
|
|
1059 |
const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
|
|
|
1060 |
const isPhone = isiPhone || isMobile && !isTablet;
|
|
|
1061 |
const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
|
|
|
1062 |
const isDesktop = !isPhone && !isTablet && !iOSwebview;
|
|
|
1063 |
return {
|
|
|
1064 |
isiPad: constant(isiPad),
|
|
|
1065 |
isiPhone: constant(isiPhone),
|
|
|
1066 |
isTablet: constant(isTablet),
|
|
|
1067 |
isPhone: constant(isPhone),
|
|
|
1068 |
isTouch: constant(isTouch),
|
|
|
1069 |
isAndroid: os.isAndroid,
|
|
|
1070 |
isiOS: os.isiOS,
|
|
|
1071 |
isWebView: constant(iOSwebview),
|
|
|
1072 |
isDesktop: constant(isDesktop)
|
|
|
1073 |
};
|
|
|
1074 |
};
|
|
|
1075 |
|
|
|
1076 |
const firstMatch = (regexes, s) => {
|
|
|
1077 |
for (let i = 0; i < regexes.length; i++) {
|
|
|
1078 |
const x = regexes[i];
|
|
|
1079 |
if (x.test(s)) {
|
|
|
1080 |
return x;
|
|
|
1081 |
}
|
|
|
1082 |
}
|
|
|
1083 |
return undefined;
|
|
|
1084 |
};
|
|
|
1085 |
const find = (regexes, agent) => {
|
|
|
1086 |
const r = firstMatch(regexes, agent);
|
|
|
1087 |
if (!r) {
|
|
|
1088 |
return {
|
|
|
1089 |
major: 0,
|
|
|
1090 |
minor: 0
|
|
|
1091 |
};
|
|
|
1092 |
}
|
|
|
1093 |
const group = i => {
|
|
|
1094 |
return Number(agent.replace(r, '$' + i));
|
|
|
1095 |
};
|
|
|
1096 |
return nu$2(group(1), group(2));
|
|
|
1097 |
};
|
|
|
1098 |
const detect$5 = (versionRegexes, agent) => {
|
|
|
1099 |
const cleanedAgent = String(agent).toLowerCase();
|
|
|
1100 |
if (versionRegexes.length === 0) {
|
|
|
1101 |
return unknown$2();
|
|
|
1102 |
}
|
|
|
1103 |
return find(versionRegexes, cleanedAgent);
|
|
|
1104 |
};
|
|
|
1105 |
const unknown$2 = () => {
|
|
|
1106 |
return nu$2(0, 0);
|
|
|
1107 |
};
|
|
|
1108 |
const nu$2 = (major, minor) => {
|
|
|
1109 |
return {
|
|
|
1110 |
major,
|
|
|
1111 |
minor
|
|
|
1112 |
};
|
|
|
1113 |
};
|
|
|
1114 |
const Version = {
|
|
|
1115 |
nu: nu$2,
|
|
|
1116 |
detect: detect$5,
|
|
|
1117 |
unknown: unknown$2
|
|
|
1118 |
};
|
|
|
1119 |
|
|
|
1120 |
const detectBrowser$1 = (browsers, userAgentData) => {
|
|
|
1121 |
return findMap(userAgentData.brands, uaBrand => {
|
|
|
1122 |
const lcBrand = uaBrand.brand.toLowerCase();
|
|
|
1123 |
return find$1(browsers, browser => {
|
|
|
1124 |
var _a;
|
|
|
1125 |
return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
|
|
|
1126 |
}).map(info => ({
|
|
|
1127 |
current: info.name,
|
|
|
1128 |
version: Version.nu(parseInt(uaBrand.version, 10), 0)
|
|
|
1129 |
}));
|
|
|
1130 |
});
|
|
|
1131 |
};
|
|
|
1132 |
|
|
|
1133 |
const detect$4 = (candidates, userAgent) => {
|
|
|
1134 |
const agent = String(userAgent).toLowerCase();
|
|
|
1135 |
return find$1(candidates, candidate => {
|
|
|
1136 |
return candidate.search(agent);
|
|
|
1137 |
});
|
|
|
1138 |
};
|
|
|
1139 |
const detectBrowser = (browsers, userAgent) => {
|
|
|
1140 |
return detect$4(browsers, userAgent).map(browser => {
|
|
|
1141 |
const version = Version.detect(browser.versionRegexes, userAgent);
|
|
|
1142 |
return {
|
|
|
1143 |
current: browser.name,
|
|
|
1144 |
version
|
|
|
1145 |
};
|
|
|
1146 |
});
|
|
|
1147 |
};
|
|
|
1148 |
const detectOs = (oses, userAgent) => {
|
|
|
1149 |
return detect$4(oses, userAgent).map(os => {
|
|
|
1150 |
const version = Version.detect(os.versionRegexes, userAgent);
|
|
|
1151 |
return {
|
|
|
1152 |
current: os.name,
|
|
|
1153 |
version
|
|
|
1154 |
};
|
|
|
1155 |
});
|
|
|
1156 |
};
|
|
|
1157 |
|
|
|
1158 |
const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
|
|
|
1159 |
const checkContains = target => {
|
|
|
1160 |
return uastring => {
|
|
|
1161 |
return contains(uastring, target);
|
|
|
1162 |
};
|
|
|
1163 |
};
|
|
|
1164 |
const browsers = [
|
|
|
1165 |
{
|
|
|
1166 |
name: 'Edge',
|
|
|
1167 |
versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
|
|
|
1168 |
search: uastring => {
|
|
|
1169 |
return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
|
|
|
1170 |
}
|
|
|
1171 |
},
|
|
|
1172 |
{
|
|
|
1173 |
name: 'Chromium',
|
|
|
1174 |
brand: 'Chromium',
|
|
|
1175 |
versionRegexes: [
|
|
|
1176 |
/.*?chrome\/([0-9]+)\.([0-9]+).*/,
|
|
|
1177 |
normalVersionRegex
|
|
|
1178 |
],
|
|
|
1179 |
search: uastring => {
|
|
|
1180 |
return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
|
|
|
1181 |
}
|
|
|
1182 |
},
|
|
|
1183 |
{
|
|
|
1184 |
name: 'IE',
|
|
|
1185 |
versionRegexes: [
|
|
|
1186 |
/.*?msie\ ?([0-9]+)\.([0-9]+).*/,
|
|
|
1187 |
/.*?rv:([0-9]+)\.([0-9]+).*/
|
|
|
1188 |
],
|
|
|
1189 |
search: uastring => {
|
|
|
1190 |
return contains(uastring, 'msie') || contains(uastring, 'trident');
|
|
|
1191 |
}
|
|
|
1192 |
},
|
|
|
1193 |
{
|
|
|
1194 |
name: 'Opera',
|
|
|
1195 |
versionRegexes: [
|
|
|
1196 |
normalVersionRegex,
|
|
|
1197 |
/.*?opera\/([0-9]+)\.([0-9]+).*/
|
|
|
1198 |
],
|
|
|
1199 |
search: checkContains('opera')
|
|
|
1200 |
},
|
|
|
1201 |
{
|
|
|
1202 |
name: 'Firefox',
|
|
|
1203 |
versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
|
|
|
1204 |
search: checkContains('firefox')
|
|
|
1205 |
},
|
|
|
1206 |
{
|
|
|
1207 |
name: 'Safari',
|
|
|
1208 |
versionRegexes: [
|
|
|
1209 |
normalVersionRegex,
|
|
|
1210 |
/.*?cpu os ([0-9]+)_([0-9]+).*/
|
|
|
1211 |
],
|
|
|
1212 |
search: uastring => {
|
|
|
1213 |
return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
|
|
|
1214 |
}
|
|
|
1215 |
}
|
|
|
1216 |
];
|
|
|
1217 |
const oses = [
|
|
|
1218 |
{
|
|
|
1219 |
name: 'Windows',
|
|
|
1220 |
search: checkContains('win'),
|
|
|
1221 |
versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
|
|
|
1222 |
},
|
|
|
1223 |
{
|
|
|
1224 |
name: 'iOS',
|
|
|
1225 |
search: uastring => {
|
|
|
1226 |
return contains(uastring, 'iphone') || contains(uastring, 'ipad');
|
|
|
1227 |
},
|
|
|
1228 |
versionRegexes: [
|
|
|
1229 |
/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
|
|
|
1230 |
/.*cpu os ([0-9]+)_([0-9]+).*/,
|
|
|
1231 |
/.*cpu iphone os ([0-9]+)_([0-9]+).*/
|
|
|
1232 |
]
|
|
|
1233 |
},
|
|
|
1234 |
{
|
|
|
1235 |
name: 'Android',
|
|
|
1236 |
search: checkContains('android'),
|
|
|
1237 |
versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
|
|
|
1238 |
},
|
|
|
1239 |
{
|
|
|
1240 |
name: 'macOS',
|
|
|
1241 |
search: checkContains('mac os x'),
|
|
|
1242 |
versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
|
|
|
1243 |
},
|
|
|
1244 |
{
|
|
|
1245 |
name: 'Linux',
|
|
|
1246 |
search: checkContains('linux'),
|
|
|
1247 |
versionRegexes: []
|
|
|
1248 |
},
|
|
|
1249 |
{
|
|
|
1250 |
name: 'Solaris',
|
|
|
1251 |
search: checkContains('sunos'),
|
|
|
1252 |
versionRegexes: []
|
|
|
1253 |
},
|
|
|
1254 |
{
|
|
|
1255 |
name: 'FreeBSD',
|
|
|
1256 |
search: checkContains('freebsd'),
|
|
|
1257 |
versionRegexes: []
|
|
|
1258 |
},
|
|
|
1259 |
{
|
|
|
1260 |
name: 'ChromeOS',
|
|
|
1261 |
search: checkContains('cros'),
|
|
|
1262 |
versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
|
|
|
1263 |
}
|
|
|
1264 |
];
|
|
|
1265 |
const PlatformInfo = {
|
|
|
1266 |
browsers: constant(browsers),
|
|
|
1267 |
oses: constant(oses)
|
|
|
1268 |
};
|
|
|
1269 |
|
|
|
1270 |
const edge = 'Edge';
|
|
|
1271 |
const chromium = 'Chromium';
|
|
|
1272 |
const ie = 'IE';
|
|
|
1273 |
const opera = 'Opera';
|
|
|
1274 |
const firefox = 'Firefox';
|
|
|
1275 |
const safari = 'Safari';
|
|
|
1276 |
const unknown$1 = () => {
|
|
|
1277 |
return nu$1({
|
|
|
1278 |
current: undefined,
|
|
|
1279 |
version: Version.unknown()
|
|
|
1280 |
});
|
|
|
1281 |
};
|
|
|
1282 |
const nu$1 = info => {
|
|
|
1283 |
const current = info.current;
|
|
|
1284 |
const version = info.version;
|
|
|
1285 |
const isBrowser = name => () => current === name;
|
|
|
1286 |
return {
|
|
|
1287 |
current,
|
|
|
1288 |
version,
|
|
|
1289 |
isEdge: isBrowser(edge),
|
|
|
1290 |
isChromium: isBrowser(chromium),
|
|
|
1291 |
isIE: isBrowser(ie),
|
|
|
1292 |
isOpera: isBrowser(opera),
|
|
|
1293 |
isFirefox: isBrowser(firefox),
|
|
|
1294 |
isSafari: isBrowser(safari)
|
|
|
1295 |
};
|
|
|
1296 |
};
|
|
|
1297 |
const Browser = {
|
|
|
1298 |
unknown: unknown$1,
|
|
|
1299 |
nu: nu$1,
|
|
|
1300 |
edge: constant(edge),
|
|
|
1301 |
chromium: constant(chromium),
|
|
|
1302 |
ie: constant(ie),
|
|
|
1303 |
opera: constant(opera),
|
|
|
1304 |
firefox: constant(firefox),
|
|
|
1305 |
safari: constant(safari)
|
|
|
1306 |
};
|
|
|
1307 |
|
|
|
1308 |
const windows = 'Windows';
|
|
|
1309 |
const ios = 'iOS';
|
|
|
1310 |
const android = 'Android';
|
|
|
1311 |
const linux = 'Linux';
|
|
|
1312 |
const macos = 'macOS';
|
|
|
1313 |
const solaris = 'Solaris';
|
|
|
1314 |
const freebsd = 'FreeBSD';
|
|
|
1315 |
const chromeos = 'ChromeOS';
|
|
|
1316 |
const unknown = () => {
|
|
|
1317 |
return nu({
|
|
|
1318 |
current: undefined,
|
|
|
1319 |
version: Version.unknown()
|
|
|
1320 |
});
|
|
|
1321 |
};
|
|
|
1322 |
const nu = info => {
|
|
|
1323 |
const current = info.current;
|
|
|
1324 |
const version = info.version;
|
|
|
1325 |
const isOS = name => () => current === name;
|
|
|
1326 |
return {
|
|
|
1327 |
current,
|
|
|
1328 |
version,
|
|
|
1329 |
isWindows: isOS(windows),
|
|
|
1330 |
isiOS: isOS(ios),
|
|
|
1331 |
isAndroid: isOS(android),
|
|
|
1332 |
isMacOS: isOS(macos),
|
|
|
1333 |
isLinux: isOS(linux),
|
|
|
1334 |
isSolaris: isOS(solaris),
|
|
|
1335 |
isFreeBSD: isOS(freebsd),
|
|
|
1336 |
isChromeOS: isOS(chromeos)
|
|
|
1337 |
};
|
|
|
1338 |
};
|
|
|
1339 |
const OperatingSystem = {
|
|
|
1340 |
unknown,
|
|
|
1341 |
nu,
|
|
|
1342 |
windows: constant(windows),
|
|
|
1343 |
ios: constant(ios),
|
|
|
1344 |
android: constant(android),
|
|
|
1345 |
linux: constant(linux),
|
|
|
1346 |
macos: constant(macos),
|
|
|
1347 |
solaris: constant(solaris),
|
|
|
1348 |
freebsd: constant(freebsd),
|
|
|
1349 |
chromeos: constant(chromeos)
|
|
|
1350 |
};
|
|
|
1351 |
|
|
|
1352 |
const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
|
|
|
1353 |
const browsers = PlatformInfo.browsers();
|
|
|
1354 |
const oses = PlatformInfo.oses();
|
|
|
1355 |
const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
|
|
|
1356 |
const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
|
|
|
1357 |
const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
|
|
|
1358 |
return {
|
|
|
1359 |
browser,
|
|
|
1360 |
os,
|
|
|
1361 |
deviceType
|
|
|
1362 |
};
|
|
|
1363 |
};
|
|
|
1364 |
const PlatformDetection = { detect: detect$3 };
|
|
|
1365 |
|
|
|
1366 |
const mediaMatch = query => window.matchMedia(query).matches;
|
|
|
1367 |
let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
|
|
|
1368 |
const detect$2 = () => platform();
|
|
|
1369 |
|
|
|
1370 |
const Dimension = (name, getOffset) => {
|
|
|
1371 |
const set = (element, h) => {
|
|
|
1372 |
if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
|
|
|
1373 |
throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
|
|
|
1374 |
}
|
|
|
1375 |
const dom = element.dom;
|
|
|
1376 |
if (isSupported(dom)) {
|
|
|
1377 |
dom.style[name] = h + 'px';
|
|
|
1378 |
}
|
|
|
1379 |
};
|
|
|
1380 |
const get = element => {
|
|
|
1381 |
const r = getOffset(element);
|
|
|
1382 |
if (r <= 0 || r === null) {
|
|
|
1383 |
const css = get$a(element, name);
|
|
|
1384 |
return parseFloat(css) || 0;
|
|
|
1385 |
}
|
|
|
1386 |
return r;
|
|
|
1387 |
};
|
|
|
1388 |
const getOuter = get;
|
|
|
1389 |
const aggregate = (element, properties) => foldl(properties, (acc, property) => {
|
|
|
1390 |
const val = get$a(element, property);
|
|
|
1391 |
const value = val === undefined ? 0 : parseInt(val, 10);
|
|
|
1392 |
return isNaN(value) ? acc : acc + value;
|
|
|
1393 |
}, 0);
|
|
|
1394 |
const max = (element, value, properties) => {
|
|
|
1395 |
const cumulativeInclusions = aggregate(element, properties);
|
|
|
1396 |
const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
|
|
|
1397 |
return absoluteMax;
|
|
|
1398 |
};
|
|
|
1399 |
return {
|
|
|
1400 |
set,
|
|
|
1401 |
get,
|
|
|
1402 |
getOuter,
|
|
|
1403 |
aggregate,
|
|
|
1404 |
max
|
|
|
1405 |
};
|
|
|
1406 |
};
|
|
|
1407 |
|
|
|
1408 |
const toNumber = (px, fallback) => toFloat(px).getOr(fallback);
|
|
|
1409 |
const getProp = (element, name, fallback) => toNumber(get$a(element, name), fallback);
|
|
|
1410 |
const calcContentBoxSize = (element, size, upper, lower) => {
|
|
|
1411 |
const paddingUpper = getProp(element, `padding-${ upper }`, 0);
|
|
|
1412 |
const paddingLower = getProp(element, `padding-${ lower }`, 0);
|
|
|
1413 |
const borderUpper = getProp(element, `border-${ upper }-width`, 0);
|
|
|
1414 |
const borderLower = getProp(element, `border-${ lower }-width`, 0);
|
|
|
1415 |
return size - paddingUpper - paddingLower - borderUpper - borderLower;
|
|
|
1416 |
};
|
|
|
1417 |
const getCalculatedWidth = (element, boxSizing) => {
|
|
|
1418 |
const dom = element.dom;
|
|
|
1419 |
const width = dom.getBoundingClientRect().width || dom.offsetWidth;
|
|
|
1420 |
return boxSizing === 'border-box' ? width : calcContentBoxSize(element, width, 'left', 'right');
|
|
|
1421 |
};
|
|
|
1422 |
const getHeight$1 = element => getProp(element, 'height', element.dom.offsetHeight);
|
|
|
1423 |
const getWidth = element => getProp(element, 'width', element.dom.offsetWidth);
|
|
|
1424 |
const getInnerWidth = element => getCalculatedWidth(element, 'content-box');
|
|
|
1425 |
|
|
|
1426 |
const api$2 = Dimension('width', element => element.dom.offsetWidth);
|
|
|
1427 |
const get$9 = element => api$2.get(element);
|
|
|
1428 |
const getOuter$2 = element => api$2.getOuter(element);
|
|
|
1429 |
const getInner = getInnerWidth;
|
|
|
1430 |
const getRuntime$1 = getWidth;
|
|
|
1431 |
|
|
|
1432 |
const addCells = (gridRow, index, cells) => {
|
|
|
1433 |
const existingCells = gridRow.cells;
|
|
|
1434 |
const before = existingCells.slice(0, index);
|
|
|
1435 |
const after = existingCells.slice(index);
|
|
|
1436 |
const newCells = before.concat(cells).concat(after);
|
|
|
1437 |
return setCells(gridRow, newCells);
|
|
|
1438 |
};
|
|
|
1439 |
const addCell = (gridRow, index, cell) => addCells(gridRow, index, [cell]);
|
|
|
1440 |
const mutateCell = (gridRow, index, cell) => {
|
|
|
1441 |
const cells = gridRow.cells;
|
|
|
1442 |
cells[index] = cell;
|
|
|
1443 |
};
|
|
|
1444 |
const setCells = (gridRow, cells) => rowcells(gridRow.element, cells, gridRow.section, gridRow.isNew);
|
|
|
1445 |
const mapCells = (gridRow, f) => {
|
|
|
1446 |
const cells = gridRow.cells;
|
|
|
1447 |
const r = map$1(cells, f);
|
|
|
1448 |
return rowcells(gridRow.element, r, gridRow.section, gridRow.isNew);
|
|
|
1449 |
};
|
|
|
1450 |
const getCell = (gridRow, index) => gridRow.cells[index];
|
|
|
1451 |
const getCellElement = (gridRow, index) => getCell(gridRow, index).element;
|
|
|
1452 |
const cellLength = gridRow => gridRow.cells.length;
|
|
|
1453 |
const extractGridDetails = grid => {
|
|
|
1454 |
const result = partition(grid, row => row.section === 'colgroup');
|
|
|
1455 |
return {
|
|
|
1456 |
rows: result.fail,
|
|
|
1457 |
cols: result.pass
|
|
|
1458 |
};
|
|
|
1459 |
};
|
|
|
1460 |
const clone = (gridRow, cloneRow, cloneCell) => {
|
|
|
1461 |
const newCells = map$1(gridRow.cells, cloneCell);
|
|
|
1462 |
return rowcells(cloneRow(gridRow.element), newCells, gridRow.section, true);
|
|
|
1463 |
};
|
|
|
1464 |
|
|
|
1465 |
const LOCKED_COL_ATTR = 'data-snooker-locked-cols';
|
|
|
1466 |
const getLockedColumnsFromTable = table => getOpt(table, LOCKED_COL_ATTR).bind(lockedColStr => Optional.from(lockedColStr.match(/\d+/g))).map(lockedCols => mapToObject(lockedCols, always));
|
|
|
1467 |
const getLockedColumnsFromGrid = grid => {
|
|
|
1468 |
const locked = foldl(extractGridDetails(grid).rows, (acc, row) => {
|
|
|
1469 |
each$2(row.cells, (cell, idx) => {
|
|
|
1470 |
if (cell.isLocked) {
|
|
|
1471 |
acc[idx] = true;
|
|
|
1472 |
}
|
|
|
1473 |
});
|
|
|
1474 |
return acc;
|
|
|
1475 |
}, {});
|
|
|
1476 |
const lockedArr = mapToArray(locked, (_val, key) => parseInt(key, 10));
|
|
|
1477 |
return sort$1(lockedArr);
|
|
|
1478 |
};
|
|
|
1479 |
|
|
|
1480 |
const key = (row, column) => {
|
|
|
1481 |
return row + ',' + column;
|
|
|
1482 |
};
|
|
|
1483 |
const getAt = (warehouse, row, column) => Optional.from(warehouse.access[key(row, column)]);
|
|
|
1484 |
const findItem = (warehouse, item, comparator) => {
|
|
|
1485 |
const filtered = filterItems(warehouse, detail => {
|
|
|
1486 |
return comparator(item, detail.element);
|
|
|
1487 |
});
|
|
|
1488 |
return filtered.length > 0 ? Optional.some(filtered[0]) : Optional.none();
|
|
|
1489 |
};
|
|
|
1490 |
const filterItems = (warehouse, predicate) => {
|
|
|
1491 |
const all = bind$2(warehouse.all, r => {
|
|
|
1492 |
return r.cells;
|
|
|
1493 |
});
|
|
|
1494 |
return filter$2(all, predicate);
|
|
|
1495 |
};
|
|
|
1496 |
const generateColumns = rowData => {
|
|
|
1497 |
const columnsGroup = {};
|
|
|
1498 |
let index = 0;
|
|
|
1499 |
each$2(rowData.cells, column => {
|
|
|
1500 |
const colspan = column.colspan;
|
|
|
1501 |
range$1(colspan, columnIndex => {
|
|
|
1502 |
const colIndex = index + columnIndex;
|
|
|
1503 |
columnsGroup[colIndex] = columnext(column.element, colspan, colIndex);
|
|
|
1504 |
});
|
|
|
1505 |
index += colspan;
|
|
|
1506 |
});
|
|
|
1507 |
return columnsGroup;
|
|
|
1508 |
};
|
|
|
1509 |
const generate$1 = list => {
|
|
|
1510 |
const access = {};
|
|
|
1511 |
const cells = [];
|
|
|
1512 |
const tableOpt = head(list).map(rowData => rowData.element).bind(table);
|
|
|
1513 |
const lockedColumns = tableOpt.bind(getLockedColumnsFromTable).getOr({});
|
|
|
1514 |
let maxRows = 0;
|
|
|
1515 |
let maxColumns = 0;
|
|
|
1516 |
let rowCount = 0;
|
|
|
1517 |
const {
|
|
|
1518 |
pass: colgroupRows,
|
|
|
1519 |
fail: rows
|
|
|
1520 |
} = partition(list, rowData => rowData.section === 'colgroup');
|
|
|
1521 |
each$2(rows, rowData => {
|
|
|
1522 |
const currentRow = [];
|
|
|
1523 |
each$2(rowData.cells, rowCell => {
|
|
|
1524 |
let start = 0;
|
|
|
1525 |
while (access[key(rowCount, start)] !== undefined) {
|
|
|
1526 |
start++;
|
|
|
1527 |
}
|
|
|
1528 |
const isLocked = hasNonNullableKey(lockedColumns, start.toString());
|
|
|
1529 |
const current = extended(rowCell.element, rowCell.rowspan, rowCell.colspan, rowCount, start, isLocked);
|
|
|
1530 |
for (let occupiedColumnPosition = 0; occupiedColumnPosition < rowCell.colspan; occupiedColumnPosition++) {
|
|
|
1531 |
for (let occupiedRowPosition = 0; occupiedRowPosition < rowCell.rowspan; occupiedRowPosition++) {
|
|
|
1532 |
const rowPosition = rowCount + occupiedRowPosition;
|
|
|
1533 |
const columnPosition = start + occupiedColumnPosition;
|
|
|
1534 |
const newpos = key(rowPosition, columnPosition);
|
|
|
1535 |
access[newpos] = current;
|
|
|
1536 |
maxColumns = Math.max(maxColumns, columnPosition + 1);
|
|
|
1537 |
}
|
|
|
1538 |
}
|
|
|
1539 |
currentRow.push(current);
|
|
|
1540 |
});
|
|
|
1541 |
maxRows++;
|
|
|
1542 |
cells.push(rowdetail(rowData.element, currentRow, rowData.section));
|
|
|
1543 |
rowCount++;
|
|
|
1544 |
});
|
|
|
1545 |
const {columns, colgroups} = last$2(colgroupRows).map(rowData => {
|
|
|
1546 |
const columns = generateColumns(rowData);
|
|
|
1547 |
const colgroup$1 = colgroup(rowData.element, values(columns));
|
|
|
1548 |
return {
|
|
|
1549 |
colgroups: [colgroup$1],
|
|
|
1550 |
columns
|
|
|
1551 |
};
|
|
|
1552 |
}).getOrThunk(() => ({
|
|
|
1553 |
colgroups: [],
|
|
|
1554 |
columns: {}
|
|
|
1555 |
}));
|
|
|
1556 |
const grid$1 = grid(maxRows, maxColumns);
|
|
|
1557 |
return {
|
|
|
1558 |
grid: grid$1,
|
|
|
1559 |
access,
|
|
|
1560 |
all: cells,
|
|
|
1561 |
columns,
|
|
|
1562 |
colgroups
|
|
|
1563 |
};
|
|
|
1564 |
};
|
|
|
1565 |
const fromTable = table => {
|
|
|
1566 |
const list = fromTable$1(table);
|
|
|
1567 |
return generate$1(list);
|
|
|
1568 |
};
|
|
|
1569 |
const justCells = warehouse => bind$2(warehouse.all, w => w.cells);
|
|
|
1570 |
const justColumns = warehouse => values(warehouse.columns);
|
|
|
1571 |
const hasColumns = warehouse => keys(warehouse.columns).length > 0;
|
|
|
1572 |
const getColumnAt = (warehouse, columnIndex) => Optional.from(warehouse.columns[columnIndex]);
|
|
|
1573 |
const Warehouse = {
|
|
|
1574 |
fromTable,
|
|
|
1575 |
generate: generate$1,
|
|
|
1576 |
getAt,
|
|
|
1577 |
findItem,
|
|
|
1578 |
filterItems,
|
|
|
1579 |
justCells,
|
|
|
1580 |
justColumns,
|
|
|
1581 |
hasColumns,
|
|
|
1582 |
getColumnAt
|
|
|
1583 |
};
|
|
|
1584 |
|
|
|
1585 |
const columns = (warehouse, isValidCell = always) => {
|
|
|
1586 |
const grid = warehouse.grid;
|
|
|
1587 |
const cols = range$1(grid.columns, identity);
|
|
|
1588 |
const rowsArr = range$1(grid.rows, identity);
|
|
|
1589 |
return map$1(cols, col => {
|
|
|
1590 |
const getBlock = () => bind$2(rowsArr, r => Warehouse.getAt(warehouse, r, col).filter(detail => detail.column === col).toArray());
|
|
|
1591 |
const isValid = detail => detail.colspan === 1 && isValidCell(detail.element);
|
|
|
1592 |
const getFallback = () => Warehouse.getAt(warehouse, 0, col);
|
|
|
1593 |
return decide(getBlock, isValid, getFallback);
|
|
|
1594 |
});
|
|
|
1595 |
};
|
|
|
1596 |
const decide = (getBlock, isValid, getFallback) => {
|
|
|
1597 |
const inBlock = getBlock();
|
|
|
1598 |
const validInBlock = find$1(inBlock, isValid);
|
|
|
1599 |
const detailOption = validInBlock.orThunk(() => Optional.from(inBlock[0]).orThunk(getFallback));
|
|
|
1600 |
return detailOption.map(detail => detail.element);
|
|
|
1601 |
};
|
|
|
1602 |
const rows = warehouse => {
|
|
|
1603 |
const grid = warehouse.grid;
|
|
|
1604 |
const rowsArr = range$1(grid.rows, identity);
|
|
|
1605 |
const cols = range$1(grid.columns, identity);
|
|
|
1606 |
return map$1(rowsArr, row => {
|
|
|
1607 |
const getBlock = () => bind$2(cols, c => Warehouse.getAt(warehouse, row, c).filter(detail => detail.row === row).fold(constant([]), detail => [detail]));
|
|
|
1608 |
const isSingle = detail => detail.rowspan === 1;
|
|
|
1609 |
const getFallback = () => Warehouse.getAt(warehouse, row, 0);
|
|
|
1610 |
return decide(getBlock, isSingle, getFallback);
|
|
|
1611 |
});
|
|
|
1612 |
};
|
|
|
1613 |
|
|
|
1614 |
const deduce = (xs, index) => {
|
|
|
1615 |
if (index < 0 || index >= xs.length - 1) {
|
|
|
1616 |
return Optional.none();
|
|
|
1617 |
}
|
|
|
1618 |
const current = xs[index].fold(() => {
|
|
|
1619 |
const rest = reverse(xs.slice(0, index));
|
|
|
1620 |
return findMap(rest, (a, i) => a.map(aa => ({
|
|
|
1621 |
value: aa,
|
|
|
1622 |
delta: i + 1
|
|
|
1623 |
})));
|
|
|
1624 |
}, c => Optional.some({
|
|
|
1625 |
value: c,
|
|
|
1626 |
delta: 0
|
|
|
1627 |
}));
|
|
|
1628 |
const next = xs[index + 1].fold(() => {
|
|
|
1629 |
const rest = xs.slice(index + 1);
|
|
|
1630 |
return findMap(rest, (a, i) => a.map(aa => ({
|
|
|
1631 |
value: aa,
|
|
|
1632 |
delta: i + 1
|
|
|
1633 |
})));
|
|
|
1634 |
}, n => Optional.some({
|
|
|
1635 |
value: n,
|
|
|
1636 |
delta: 1
|
|
|
1637 |
}));
|
|
|
1638 |
return current.bind(c => next.map(n => {
|
|
|
1639 |
const extras = n.delta + c.delta;
|
|
|
1640 |
return Math.abs(n.value - c.value) / extras;
|
|
|
1641 |
}));
|
|
|
1642 |
};
|
|
|
1643 |
|
|
|
1644 |
const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
|
|
|
1645 |
const getDirection = element => get$a(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
|
|
|
1646 |
|
|
|
1647 |
const api$1 = Dimension('height', element => {
|
|
|
1648 |
const dom = element.dom;
|
|
|
1649 |
return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
|
|
|
1650 |
});
|
|
|
1651 |
const get$8 = element => api$1.get(element);
|
|
|
1652 |
const getOuter$1 = element => api$1.getOuter(element);
|
|
|
1653 |
const getRuntime = getHeight$1;
|
|
|
1654 |
|
|
|
1655 |
const r = (left, top) => {
|
|
|
1656 |
const translate = (x, y) => r(left + x, top + y);
|
|
|
1657 |
return {
|
|
|
1658 |
left,
|
|
|
1659 |
top,
|
|
|
1660 |
translate
|
|
|
1661 |
};
|
|
|
1662 |
};
|
|
|
1663 |
const SugarPosition = r;
|
|
|
1664 |
|
|
|
1665 |
const boxPosition = dom => {
|
|
|
1666 |
const box = dom.getBoundingClientRect();
|
|
|
1667 |
return SugarPosition(box.left, box.top);
|
|
|
1668 |
};
|
|
|
1669 |
const firstDefinedOrZero = (a, b) => {
|
|
|
1670 |
if (a !== undefined) {
|
|
|
1671 |
return a;
|
|
|
1672 |
} else {
|
|
|
1673 |
return b !== undefined ? b : 0;
|
|
|
1674 |
}
|
|
|
1675 |
};
|
|
|
1676 |
const absolute = element => {
|
|
|
1677 |
const doc = element.dom.ownerDocument;
|
|
|
1678 |
const body = doc.body;
|
|
|
1679 |
const win = doc.defaultView;
|
|
|
1680 |
const html = doc.documentElement;
|
|
|
1681 |
if (body === element.dom) {
|
|
|
1682 |
return SugarPosition(body.offsetLeft, body.offsetTop);
|
|
|
1683 |
}
|
|
|
1684 |
const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
|
|
|
1685 |
const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
|
|
|
1686 |
const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
|
|
|
1687 |
const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
|
|
|
1688 |
return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
|
|
|
1689 |
};
|
|
|
1690 |
const viewport = element => {
|
|
|
1691 |
const dom = element.dom;
|
|
|
1692 |
const doc = dom.ownerDocument;
|
|
|
1693 |
const body = doc.body;
|
|
|
1694 |
if (body === dom) {
|
|
|
1695 |
return SugarPosition(body.offsetLeft, body.offsetTop);
|
|
|
1696 |
}
|
|
|
1697 |
if (!inBody(element)) {
|
|
|
1698 |
return SugarPosition(0, 0);
|
|
|
1699 |
}
|
|
|
1700 |
return boxPosition(dom);
|
|
|
1701 |
};
|
|
|
1702 |
|
|
|
1703 |
const rowInfo = (row, y) => ({
|
|
|
1704 |
row,
|
|
|
1705 |
y
|
|
|
1706 |
});
|
|
|
1707 |
const colInfo = (col, x) => ({
|
|
|
1708 |
col,
|
|
|
1709 |
x
|
|
|
1710 |
});
|
|
|
1711 |
const rtlEdge = cell => {
|
|
|
1712 |
const pos = absolute(cell);
|
|
|
1713 |
return pos.left + getOuter$2(cell);
|
|
|
1714 |
};
|
|
|
1715 |
const ltrEdge = cell => {
|
|
|
1716 |
return absolute(cell).left;
|
|
|
1717 |
};
|
|
|
1718 |
const getLeftEdge = (index, cell) => {
|
|
|
1719 |
return colInfo(index, ltrEdge(cell));
|
|
|
1720 |
};
|
|
|
1721 |
const getRightEdge = (index, cell) => {
|
|
|
1722 |
return colInfo(index, rtlEdge(cell));
|
|
|
1723 |
};
|
|
|
1724 |
const getTop$1 = cell => {
|
|
|
1725 |
return absolute(cell).top;
|
|
|
1726 |
};
|
|
|
1727 |
const getTopEdge = (index, cell) => {
|
|
|
1728 |
return rowInfo(index, getTop$1(cell));
|
|
|
1729 |
};
|
|
|
1730 |
const getBottomEdge = (index, cell) => {
|
|
|
1731 |
return rowInfo(index, getTop$1(cell) + getOuter$1(cell));
|
|
|
1732 |
};
|
|
|
1733 |
const findPositions = (getInnerEdge, getOuterEdge, array) => {
|
|
|
1734 |
if (array.length === 0) {
|
|
|
1735 |
return [];
|
|
|
1736 |
}
|
|
|
1737 |
const lines = map$1(array.slice(1), (cellOption, index) => {
|
|
|
1738 |
return cellOption.map(cell => {
|
|
|
1739 |
return getInnerEdge(index, cell);
|
|
|
1740 |
});
|
|
|
1741 |
});
|
|
|
1742 |
const lastLine = array[array.length - 1].map(cell => {
|
|
|
1743 |
return getOuterEdge(array.length - 1, cell);
|
|
|
1744 |
});
|
|
|
1745 |
return lines.concat([lastLine]);
|
|
|
1746 |
};
|
|
|
1747 |
const negate = step => {
|
|
|
1748 |
return -step;
|
|
|
1749 |
};
|
|
|
1750 |
const height = {
|
|
|
1751 |
delta: identity,
|
|
|
1752 |
positions: optElements => findPositions(getTopEdge, getBottomEdge, optElements),
|
|
|
1753 |
edge: getTop$1
|
|
|
1754 |
};
|
|
|
1755 |
const ltr$1 = {
|
|
|
1756 |
delta: identity,
|
|
|
1757 |
edge: ltrEdge,
|
|
|
1758 |
positions: optElements => findPositions(getLeftEdge, getRightEdge, optElements)
|
|
|
1759 |
};
|
|
|
1760 |
const rtl$1 = {
|
|
|
1761 |
delta: negate,
|
|
|
1762 |
edge: rtlEdge,
|
|
|
1763 |
positions: optElements => findPositions(getRightEdge, getLeftEdge, optElements)
|
|
|
1764 |
};
|
|
|
1765 |
const detect$1 = onDirection(ltr$1, rtl$1);
|
|
|
1766 |
const width = {
|
|
|
1767 |
delta: (amount, table) => detect$1(table).delta(amount, table),
|
|
|
1768 |
positions: (cols, table) => detect$1(table).positions(cols, table),
|
|
|
1769 |
edge: cell => detect$1(cell).edge(cell)
|
|
|
1770 |
};
|
|
|
1771 |
|
|
|
1772 |
const units = {
|
|
|
1773 |
unsupportedLength: [
|
|
|
1774 |
'em',
|
|
|
1775 |
'ex',
|
|
|
1776 |
'cap',
|
|
|
1777 |
'ch',
|
|
|
1778 |
'ic',
|
|
|
1779 |
'rem',
|
|
|
1780 |
'lh',
|
|
|
1781 |
'rlh',
|
|
|
1782 |
'vw',
|
|
|
1783 |
'vh',
|
|
|
1784 |
'vi',
|
|
|
1785 |
'vb',
|
|
|
1786 |
'vmin',
|
|
|
1787 |
'vmax',
|
|
|
1788 |
'cm',
|
|
|
1789 |
'mm',
|
|
|
1790 |
'Q',
|
|
|
1791 |
'in',
|
|
|
1792 |
'pc',
|
|
|
1793 |
'pt',
|
|
|
1794 |
'px'
|
|
|
1795 |
],
|
|
|
1796 |
fixed: [
|
|
|
1797 |
'px',
|
|
|
1798 |
'pt'
|
|
|
1799 |
],
|
|
|
1800 |
relative: ['%'],
|
|
|
1801 |
empty: ['']
|
|
|
1802 |
};
|
|
|
1803 |
const pattern = (() => {
|
|
|
1804 |
const decimalDigits = '[0-9]+';
|
|
|
1805 |
const signedInteger = '[+-]?' + decimalDigits;
|
|
|
1806 |
const exponentPart = '[eE]' + signedInteger;
|
|
|
1807 |
const dot = '\\.';
|
|
|
1808 |
const opt = input => `(?:${ input })?`;
|
|
|
1809 |
const unsignedDecimalLiteral = [
|
|
|
1810 |
'Infinity',
|
|
|
1811 |
decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
|
|
|
1812 |
dot + decimalDigits + opt(exponentPart),
|
|
|
1813 |
decimalDigits + opt(exponentPart)
|
|
|
1814 |
].join('|');
|
|
|
1815 |
const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
|
|
|
1816 |
return new RegExp(`^(${ float })(.*)$`);
|
|
|
1817 |
})();
|
|
|
1818 |
const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
|
|
|
1819 |
const parse = (input, accepted) => {
|
|
|
1820 |
const match = Optional.from(pattern.exec(input));
|
|
|
1821 |
return match.bind(array => {
|
|
|
1822 |
const value = Number(array[1]);
|
|
|
1823 |
const unitRaw = array[2];
|
|
|
1824 |
if (isUnit(unitRaw, accepted)) {
|
|
|
1825 |
return Optional.some({
|
|
|
1826 |
value,
|
|
|
1827 |
unit: unitRaw
|
|
|
1828 |
});
|
|
|
1829 |
} else {
|
|
|
1830 |
return Optional.none();
|
|
|
1831 |
}
|
|
|
1832 |
});
|
|
|
1833 |
};
|
|
|
1834 |
|
|
|
1835 |
const rPercentageBasedSizeRegex = /(\d+(\.\d+)?)%/;
|
|
|
1836 |
const rPixelBasedSizeRegex = /(\d+(\.\d+)?)px|em/;
|
|
|
1837 |
const isCol$2 = isTag('col');
|
|
|
1838 |
const getPercentSize = (elm, outerGetter, innerGetter) => {
|
|
|
1839 |
const relativeParent = parentElement(elm).getOrThunk(() => getBody$1(owner(elm)));
|
|
|
1840 |
return outerGetter(elm) / innerGetter(relativeParent) * 100;
|
|
|
1841 |
};
|
|
|
1842 |
const setPixelWidth = (cell, amount) => {
|
|
|
1843 |
set$1(cell, 'width', amount + 'px');
|
|
|
1844 |
};
|
|
|
1845 |
const setPercentageWidth = (cell, amount) => {
|
|
|
1846 |
set$1(cell, 'width', amount + '%');
|
|
|
1847 |
};
|
|
|
1848 |
const setHeight = (cell, amount) => {
|
|
|
1849 |
set$1(cell, 'height', amount + 'px');
|
|
|
1850 |
};
|
|
|
1851 |
const getHeightValue = cell => getRuntime(cell) + 'px';
|
|
|
1852 |
const convert = (cell, number, getter, setter) => {
|
|
|
1853 |
const newSize = table(cell).map(table => {
|
|
|
1854 |
const total = getter(table);
|
|
|
1855 |
return Math.floor(number / 100 * total);
|
|
|
1856 |
}).getOr(number);
|
|
|
1857 |
setter(cell, newSize);
|
|
|
1858 |
return newSize;
|
|
|
1859 |
};
|
|
|
1860 |
const normalizePixelSize = (value, cell, getter, setter) => {
|
|
|
1861 |
const number = parseFloat(value);
|
|
|
1862 |
return endsWith(value, '%') && name(cell) !== 'table' ? convert(cell, number, getter, setter) : number;
|
|
|
1863 |
};
|
|
|
1864 |
const getTotalHeight = cell => {
|
|
|
1865 |
const value = getHeightValue(cell);
|
|
|
1866 |
if (!value) {
|
|
|
1867 |
return get$8(cell);
|
|
|
1868 |
}
|
|
|
1869 |
return normalizePixelSize(value, cell, get$8, setHeight);
|
|
|
1870 |
};
|
|
|
1871 |
const get$7 = (cell, type, f) => {
|
|
|
1872 |
const v = f(cell);
|
|
|
1873 |
const span = getSpan(cell, type);
|
|
|
1874 |
return v / span;
|
|
|
1875 |
};
|
|
|
1876 |
const getRaw$1 = (element, prop) => {
|
|
|
1877 |
return getRaw$2(element, prop).orThunk(() => {
|
|
|
1878 |
return getOpt(element, prop).map(val => val + 'px');
|
|
|
1879 |
});
|
|
|
1880 |
};
|
|
|
1881 |
const getRawWidth$1 = element => getRaw$1(element, 'width');
|
|
|
1882 |
const getRawHeight = element => getRaw$1(element, 'height');
|
|
|
1883 |
const getPercentageWidth = cell => getPercentSize(cell, get$9, getInner);
|
|
|
1884 |
const getPixelWidth$1 = cell => isCol$2(cell) ? get$9(cell) : getRuntime$1(cell);
|
|
|
1885 |
const getHeight = cell => {
|
|
|
1886 |
return get$7(cell, 'rowspan', getTotalHeight);
|
|
|
1887 |
};
|
|
|
1888 |
const getGenericWidth = cell => {
|
|
|
1889 |
const width = getRawWidth$1(cell);
|
|
|
1890 |
return width.bind(w => parse(w, [
|
|
|
1891 |
'fixed',
|
|
|
1892 |
'relative',
|
|
|
1893 |
'empty'
|
|
|
1894 |
]));
|
|
|
1895 |
};
|
|
|
1896 |
const setGenericWidth = (cell, amount, unit) => {
|
|
|
1897 |
set$1(cell, 'width', amount + unit);
|
|
|
1898 |
};
|
|
|
1899 |
const getPixelTableWidth = table => get$9(table) + 'px';
|
|
|
1900 |
const getPercentTableWidth = table => getPercentSize(table, get$9, getInner) + '%';
|
|
|
1901 |
const isPercentSizing$1 = table => getRawWidth$1(table).exists(size => rPercentageBasedSizeRegex.test(size));
|
|
|
1902 |
const isPixelSizing$1 = table => getRawWidth$1(table).exists(size => rPixelBasedSizeRegex.test(size));
|
|
|
1903 |
const isNoneSizing$1 = table => getRawWidth$1(table).isNone();
|
|
|
1904 |
const percentageBasedSizeRegex = constant(rPercentageBasedSizeRegex);
|
|
|
1905 |
|
|
|
1906 |
const isCol$1 = isTag('col');
|
|
|
1907 |
const getRawW = cell => {
|
|
|
1908 |
return getRawWidth$1(cell).getOrThunk(() => getPixelWidth$1(cell) + 'px');
|
|
|
1909 |
};
|
|
|
1910 |
const getRawH = cell => {
|
|
|
1911 |
return getRawHeight(cell).getOrThunk(() => getHeight(cell) + 'px');
|
|
|
1912 |
};
|
|
|
1913 |
const justCols = warehouse => map$1(Warehouse.justColumns(warehouse), column => Optional.from(column.element));
|
|
|
1914 |
const isValidColumn = cell => {
|
|
|
1915 |
const browser = detect$2().browser;
|
|
|
1916 |
const supportsColWidths = browser.isChromium() || browser.isFirefox();
|
|
|
1917 |
return isCol$1(cell) ? supportsColWidths : true;
|
|
|
1918 |
};
|
|
|
1919 |
const getDimension = (cellOpt, index, backups, filter, getter, fallback) => cellOpt.filter(filter).fold(() => fallback(deduce(backups, index)), cell => getter(cell));
|
|
|
1920 |
const getWidthFrom = (warehouse, table, getWidth, fallback) => {
|
|
|
1921 |
const columnCells = columns(warehouse);
|
|
|
1922 |
const columns$1 = Warehouse.hasColumns(warehouse) ? justCols(warehouse) : columnCells;
|
|
|
1923 |
const backups = [Optional.some(width.edge(table))].concat(map$1(width.positions(columnCells, table), pos => pos.map(p => p.x)));
|
|
|
1924 |
const colFilter = not(hasColspan);
|
|
|
1925 |
return map$1(columns$1, (cellOption, c) => {
|
|
|
1926 |
return getDimension(cellOption, c, backups, colFilter, column => {
|
|
|
1927 |
if (isValidColumn(column)) {
|
|
|
1928 |
return getWidth(column);
|
|
|
1929 |
} else {
|
|
|
1930 |
const cell = bindFrom(columnCells[c], identity);
|
|
|
1931 |
return getDimension(cell, c, backups, colFilter, cell => fallback(Optional.some(get$9(cell))), fallback);
|
|
|
1932 |
}
|
|
|
1933 |
}, fallback);
|
|
|
1934 |
});
|
|
|
1935 |
};
|
|
|
1936 |
const getDeduced = deduced => {
|
|
|
1937 |
return deduced.map(d => {
|
|
|
1938 |
return d + 'px';
|
|
|
1939 |
}).getOr('');
|
|
|
1940 |
};
|
|
|
1941 |
const getRawWidths = (warehouse, table) => {
|
|
|
1942 |
return getWidthFrom(warehouse, table, getRawW, getDeduced);
|
|
|
1943 |
};
|
|
|
1944 |
const getPercentageWidths = (warehouse, table, tableSize) => {
|
|
|
1945 |
return getWidthFrom(warehouse, table, getPercentageWidth, deduced => {
|
|
|
1946 |
return deduced.fold(() => {
|
|
|
1947 |
return tableSize.minCellWidth();
|
|
|
1948 |
}, cellWidth => {
|
|
|
1949 |
return cellWidth / tableSize.pixelWidth() * 100;
|
|
|
1950 |
});
|
|
|
1951 |
});
|
|
|
1952 |
};
|
|
|
1953 |
const getPixelWidths = (warehouse, table, tableSize) => {
|
|
|
1954 |
return getWidthFrom(warehouse, table, getPixelWidth$1, deduced => {
|
|
|
1955 |
return deduced.getOrThunk(tableSize.minCellWidth);
|
|
|
1956 |
});
|
|
|
1957 |
};
|
|
|
1958 |
const getHeightFrom = (warehouse, table, direction, getHeight, fallback) => {
|
|
|
1959 |
const rows$1 = rows(warehouse);
|
|
|
1960 |
const backups = [Optional.some(direction.edge(table))].concat(map$1(direction.positions(rows$1, table), pos => pos.map(p => p.y)));
|
|
|
1961 |
return map$1(rows$1, (cellOption, c) => {
|
|
|
1962 |
return getDimension(cellOption, c, backups, not(hasRowspan), getHeight, fallback);
|
|
|
1963 |
});
|
|
|
1964 |
};
|
|
|
1965 |
const getPixelHeights = (warehouse, table, direction) => {
|
|
|
1966 |
return getHeightFrom(warehouse, table, direction, getHeight, deduced => {
|
|
|
1967 |
return deduced.getOrThunk(minHeight);
|
|
|
1968 |
});
|
|
|
1969 |
};
|
|
|
1970 |
const getRawHeights = (warehouse, table, direction) => {
|
|
|
1971 |
return getHeightFrom(warehouse, table, direction, getRawH, getDeduced);
|
|
|
1972 |
};
|
|
|
1973 |
|
|
|
1974 |
const widthLookup = (table, getter) => () => {
|
|
|
1975 |
if (inBody(table)) {
|
|
|
1976 |
return getter(table);
|
|
|
1977 |
} else {
|
|
|
1978 |
return parseFloat(getRaw$2(table, 'width').getOr('0'));
|
|
|
1979 |
}
|
|
|
1980 |
};
|
|
|
1981 |
const noneSize = table => {
|
|
|
1982 |
const getWidth = widthLookup(table, get$9);
|
|
|
1983 |
const zero = constant(0);
|
|
|
1984 |
const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
|
|
|
1985 |
return {
|
|
|
1986 |
width: getWidth,
|
|
|
1987 |
pixelWidth: getWidth,
|
|
|
1988 |
getWidths,
|
|
|
1989 |
getCellDelta: zero,
|
|
|
1990 |
singleColumnWidth: constant([0]),
|
|
|
1991 |
minCellWidth: zero,
|
|
|
1992 |
setElementWidth: noop,
|
|
|
1993 |
adjustTableWidth: noop,
|
|
|
1994 |
isRelative: true,
|
|
|
1995 |
label: 'none'
|
|
|
1996 |
};
|
|
|
1997 |
};
|
|
|
1998 |
const percentageSize = table => {
|
|
|
1999 |
const getFloatWidth = widthLookup(table, elem => parseFloat(getPercentTableWidth(elem)));
|
|
|
2000 |
const getWidth = widthLookup(table, get$9);
|
|
|
2001 |
const getCellDelta = delta => delta / getWidth() * 100;
|
|
|
2002 |
const singleColumnWidth = (w, _delta) => [100 - w];
|
|
|
2003 |
const minCellWidth = () => minWidth() / getWidth() * 100;
|
|
|
2004 |
const adjustTableWidth = delta => {
|
|
|
2005 |
const currentWidth = getFloatWidth();
|
|
|
2006 |
const change = delta / 100 * currentWidth;
|
|
|
2007 |
const newWidth = currentWidth + change;
|
|
|
2008 |
setPercentageWidth(table, newWidth);
|
|
|
2009 |
};
|
|
|
2010 |
const getWidths = (warehouse, tableSize) => getPercentageWidths(warehouse, table, tableSize);
|
|
|
2011 |
return {
|
|
|
2012 |
width: getFloatWidth,
|
|
|
2013 |
pixelWidth: getWidth,
|
|
|
2014 |
getWidths,
|
|
|
2015 |
getCellDelta,
|
|
|
2016 |
singleColumnWidth,
|
|
|
2017 |
minCellWidth,
|
|
|
2018 |
setElementWidth: setPercentageWidth,
|
|
|
2019 |
adjustTableWidth,
|
|
|
2020 |
isRelative: true,
|
|
|
2021 |
label: 'percent'
|
|
|
2022 |
};
|
|
|
2023 |
};
|
|
|
2024 |
const pixelSize = table => {
|
|
|
2025 |
const getWidth = widthLookup(table, get$9);
|
|
|
2026 |
const getCellDelta = identity;
|
|
|
2027 |
const singleColumnWidth = (w, delta) => {
|
|
|
2028 |
const newNext = Math.max(minWidth(), w + delta);
|
|
|
2029 |
return [newNext - w];
|
|
|
2030 |
};
|
|
|
2031 |
const adjustTableWidth = delta => {
|
|
|
2032 |
const newWidth = getWidth() + delta;
|
|
|
2033 |
setPixelWidth(table, newWidth);
|
|
|
2034 |
};
|
|
|
2035 |
const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
|
|
|
2036 |
return {
|
|
|
2037 |
width: getWidth,
|
|
|
2038 |
pixelWidth: getWidth,
|
|
|
2039 |
getWidths,
|
|
|
2040 |
getCellDelta,
|
|
|
2041 |
singleColumnWidth,
|
|
|
2042 |
minCellWidth: minWidth,
|
|
|
2043 |
setElementWidth: setPixelWidth,
|
|
|
2044 |
adjustTableWidth,
|
|
|
2045 |
isRelative: false,
|
|
|
2046 |
label: 'pixel'
|
|
|
2047 |
};
|
|
|
2048 |
};
|
|
|
2049 |
const chooseSize = (element, width) => {
|
|
|
2050 |
const percentMatch = percentageBasedSizeRegex().exec(width);
|
|
|
2051 |
if (percentMatch !== null) {
|
|
|
2052 |
return percentageSize(element);
|
|
|
2053 |
} else {
|
|
|
2054 |
return pixelSize(element);
|
|
|
2055 |
}
|
|
|
2056 |
};
|
|
|
2057 |
const getTableSize = table => {
|
|
|
2058 |
const width = getRawWidth$1(table);
|
|
|
2059 |
return width.fold(() => noneSize(table), w => chooseSize(table, w));
|
|
|
2060 |
};
|
|
|
2061 |
const TableSize = {
|
|
|
2062 |
getTableSize,
|
|
|
2063 |
pixelSize,
|
|
|
2064 |
percentageSize,
|
|
|
2065 |
noneSize
|
|
|
2066 |
};
|
|
|
2067 |
|
|
|
2068 |
const statsStruct = (minRow, minCol, maxRow, maxCol, allCells, selectedCells) => ({
|
|
|
2069 |
minRow,
|
|
|
2070 |
minCol,
|
|
|
2071 |
maxRow,
|
|
|
2072 |
maxCol,
|
|
|
2073 |
allCells,
|
|
|
2074 |
selectedCells
|
|
|
2075 |
});
|
|
|
2076 |
const findSelectedStats = (house, isSelected) => {
|
|
|
2077 |
const totalColumns = house.grid.columns;
|
|
|
2078 |
const totalRows = house.grid.rows;
|
|
|
2079 |
let minRow = totalRows;
|
|
|
2080 |
let minCol = totalColumns;
|
|
|
2081 |
let maxRow = 0;
|
|
|
2082 |
let maxCol = 0;
|
|
|
2083 |
const allCells = [];
|
|
|
2084 |
const selectedCells = [];
|
|
|
2085 |
each$1(house.access, detail => {
|
|
|
2086 |
allCells.push(detail);
|
|
|
2087 |
if (isSelected(detail)) {
|
|
|
2088 |
selectedCells.push(detail);
|
|
|
2089 |
const startRow = detail.row;
|
|
|
2090 |
const endRow = startRow + detail.rowspan - 1;
|
|
|
2091 |
const startCol = detail.column;
|
|
|
2092 |
const endCol = startCol + detail.colspan - 1;
|
|
|
2093 |
if (startRow < minRow) {
|
|
|
2094 |
minRow = startRow;
|
|
|
2095 |
} else if (endRow > maxRow) {
|
|
|
2096 |
maxRow = endRow;
|
|
|
2097 |
}
|
|
|
2098 |
if (startCol < minCol) {
|
|
|
2099 |
minCol = startCol;
|
|
|
2100 |
} else if (endCol > maxCol) {
|
|
|
2101 |
maxCol = endCol;
|
|
|
2102 |
}
|
|
|
2103 |
}
|
|
|
2104 |
});
|
|
|
2105 |
return statsStruct(minRow, minCol, maxRow, maxCol, allCells, selectedCells);
|
|
|
2106 |
};
|
|
|
2107 |
const makeCell = (list, seenSelected, rowIndex) => {
|
|
|
2108 |
const row = list[rowIndex].element;
|
|
|
2109 |
const td = SugarElement.fromTag('td');
|
|
|
2110 |
append$1(td, SugarElement.fromTag('br'));
|
|
|
2111 |
const f = seenSelected ? append$1 : prepend;
|
|
|
2112 |
f(row, td);
|
|
|
2113 |
};
|
|
|
2114 |
const fillInGaps = (list, house, stats, isSelected) => {
|
|
|
2115 |
const rows = filter$2(list, row => row.section !== 'colgroup');
|
|
|
2116 |
const totalColumns = house.grid.columns;
|
|
|
2117 |
const totalRows = house.grid.rows;
|
|
|
2118 |
for (let i = 0; i < totalRows; i++) {
|
|
|
2119 |
let seenSelected = false;
|
|
|
2120 |
for (let j = 0; j < totalColumns; j++) {
|
|
|
2121 |
if (!(i < stats.minRow || i > stats.maxRow || j < stats.minCol || j > stats.maxCol)) {
|
|
|
2122 |
const needCell = Warehouse.getAt(house, i, j).filter(isSelected).isNone();
|
|
|
2123 |
if (needCell) {
|
|
|
2124 |
makeCell(rows, seenSelected, i);
|
|
|
2125 |
} else {
|
|
|
2126 |
seenSelected = true;
|
|
|
2127 |
}
|
|
|
2128 |
}
|
|
|
2129 |
}
|
|
|
2130 |
}
|
|
|
2131 |
};
|
|
|
2132 |
const clean = (replica, stats, house, widthDelta) => {
|
|
|
2133 |
each$1(house.columns, col => {
|
|
|
2134 |
if (col.column < stats.minCol || col.column > stats.maxCol) {
|
|
|
2135 |
remove$6(col.element);
|
|
|
2136 |
}
|
|
|
2137 |
});
|
|
|
2138 |
const emptyRows = filter$2(firstLayer(replica, 'tr'), row => row.dom.childElementCount === 0);
|
|
|
2139 |
each$2(emptyRows, remove$6);
|
|
|
2140 |
if (stats.minCol === stats.maxCol || stats.minRow === stats.maxRow) {
|
|
|
2141 |
each$2(firstLayer(replica, 'th,td'), cell => {
|
|
|
2142 |
remove$7(cell, 'rowspan');
|
|
|
2143 |
remove$7(cell, 'colspan');
|
|
|
2144 |
});
|
|
|
2145 |
}
|
|
|
2146 |
remove$7(replica, LOCKED_COL_ATTR);
|
|
|
2147 |
remove$7(replica, 'data-snooker-col-series');
|
|
|
2148 |
const tableSize = TableSize.getTableSize(replica);
|
|
|
2149 |
tableSize.adjustTableWidth(widthDelta);
|
|
|
2150 |
};
|
|
|
2151 |
const getTableWidthDelta = (table, warehouse, tableSize, stats) => {
|
|
|
2152 |
if (stats.minCol === 0 && warehouse.grid.columns === stats.maxCol + 1) {
|
|
|
2153 |
return 0;
|
|
|
2154 |
}
|
|
|
2155 |
const colWidths = getPixelWidths(warehouse, table, tableSize);
|
|
|
2156 |
const allColsWidth = foldl(colWidths, (acc, width) => acc + width, 0);
|
|
|
2157 |
const selectedColsWidth = foldl(colWidths.slice(stats.minCol, stats.maxCol + 1), (acc, width) => acc + width, 0);
|
|
|
2158 |
const newWidth = selectedColsWidth / allColsWidth * tableSize.pixelWidth();
|
|
|
2159 |
const delta = newWidth - tableSize.pixelWidth();
|
|
|
2160 |
return tableSize.getCellDelta(delta);
|
|
|
2161 |
};
|
|
|
2162 |
const extract$1 = (table, selectedSelector) => {
|
|
|
2163 |
const isSelected = detail => is$2(detail.element, selectedSelector);
|
|
|
2164 |
const replica = deep(table);
|
|
|
2165 |
const list = fromTable$1(replica);
|
|
|
2166 |
const tableSize = TableSize.getTableSize(table);
|
|
|
2167 |
const replicaHouse = Warehouse.generate(list);
|
|
|
2168 |
const replicaStats = findSelectedStats(replicaHouse, isSelected);
|
|
|
2169 |
const selector = 'th:not(' + selectedSelector + ')' + ',td:not(' + selectedSelector + ')';
|
|
|
2170 |
const unselectedCells = filterFirstLayer(replica, 'th,td', cell => is$2(cell, selector));
|
|
|
2171 |
each$2(unselectedCells, remove$6);
|
|
|
2172 |
fillInGaps(list, replicaHouse, replicaStats, isSelected);
|
|
|
2173 |
const house = Warehouse.fromTable(table);
|
|
|
2174 |
const widthDelta = getTableWidthDelta(table, house, tableSize, replicaStats);
|
|
|
2175 |
clean(replica, replicaStats, replicaHouse, widthDelta);
|
|
|
2176 |
return replica;
|
|
|
2177 |
};
|
|
|
2178 |
|
|
|
2179 |
const nbsp = '\xA0';
|
|
|
2180 |
|
|
|
2181 |
const NodeValue = (is, name) => {
|
|
|
2182 |
const get = element => {
|
|
|
2183 |
if (!is(element)) {
|
|
|
2184 |
throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
|
|
|
2185 |
}
|
|
|
2186 |
return getOption(element).getOr('');
|
|
|
2187 |
};
|
|
|
2188 |
const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
|
|
|
2189 |
const set = (element, value) => {
|
|
|
2190 |
if (!is(element)) {
|
|
|
2191 |
throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
|
|
|
2192 |
}
|
|
|
2193 |
element.dom.nodeValue = value;
|
|
|
2194 |
};
|
|
|
2195 |
return {
|
|
|
2196 |
get,
|
|
|
2197 |
getOption,
|
|
|
2198 |
set
|
|
|
2199 |
};
|
|
|
2200 |
};
|
|
|
2201 |
|
|
|
2202 |
const api = NodeValue(isText, 'text');
|
|
|
2203 |
const get$6 = element => api.get(element);
|
|
|
2204 |
const getOption = element => api.getOption(element);
|
|
|
2205 |
const set = (element, value) => api.set(element, value);
|
|
|
2206 |
|
|
|
2207 |
const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$2(element).length, v => v.length);
|
|
|
2208 |
const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
|
|
|
2209 |
const isContentEditableFalse = elem => isHTMLElement(elem) && get$b(elem, 'contenteditable') === 'false';
|
|
|
2210 |
const elementsWithCursorPosition = [
|
|
|
2211 |
'img',
|
|
|
2212 |
'br'
|
|
|
2213 |
];
|
|
|
2214 |
const isCursorPosition = elem => {
|
|
|
2215 |
const hasCursorPosition = isTextNodeWithCursorPosition(elem);
|
|
|
2216 |
return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse(elem);
|
|
|
2217 |
};
|
|
|
2218 |
|
|
|
2219 |
const first = element => descendant$1(element, isCursorPosition);
|
|
|
2220 |
const last$1 = element => descendantRtl(element, isCursorPosition);
|
|
|
2221 |
const descendantRtl = (scope, predicate) => {
|
|
|
2222 |
const descend = element => {
|
|
|
2223 |
const children = children$2(element);
|
|
|
2224 |
for (let i = children.length - 1; i >= 0; i--) {
|
|
|
2225 |
const child = children[i];
|
|
|
2226 |
if (predicate(child)) {
|
|
|
2227 |
return Optional.some(child);
|
|
|
2228 |
}
|
|
|
2229 |
const res = descend(child);
|
|
|
2230 |
if (res.isSome()) {
|
|
|
2231 |
return res;
|
|
|
2232 |
}
|
|
|
2233 |
}
|
|
|
2234 |
return Optional.none();
|
|
|
2235 |
};
|
|
|
2236 |
return descend(scope);
|
|
|
2237 |
};
|
|
|
2238 |
|
|
|
2239 |
const transferableAttributes = {
|
|
|
2240 |
scope: [
|
|
|
2241 |
'row',
|
|
|
2242 |
'col'
|
|
|
2243 |
]
|
|
|
2244 |
};
|
|
|
2245 |
const createCell = doc => () => {
|
|
|
2246 |
const td = SugarElement.fromTag('td', doc.dom);
|
|
|
2247 |
append$1(td, SugarElement.fromTag('br', doc.dom));
|
|
|
2248 |
return td;
|
|
|
2249 |
};
|
|
|
2250 |
const createCol = doc => () => {
|
|
|
2251 |
return SugarElement.fromTag('col', doc.dom);
|
|
|
2252 |
};
|
|
|
2253 |
const createColgroup = doc => () => {
|
|
|
2254 |
return SugarElement.fromTag('colgroup', doc.dom);
|
|
|
2255 |
};
|
|
|
2256 |
const createRow$1 = doc => () => {
|
|
|
2257 |
return SugarElement.fromTag('tr', doc.dom);
|
|
|
2258 |
};
|
|
|
2259 |
const replace$1 = (cell, tag, attrs) => {
|
|
|
2260 |
const replica = copy$2(cell, tag);
|
|
|
2261 |
each$1(attrs, (v, k) => {
|
|
|
2262 |
if (v === null) {
|
|
|
2263 |
remove$7(replica, k);
|
|
|
2264 |
} else {
|
|
|
2265 |
set$2(replica, k, v);
|
|
|
2266 |
}
|
|
|
2267 |
});
|
|
|
2268 |
return replica;
|
|
|
2269 |
};
|
|
|
2270 |
const pasteReplace = cell => {
|
|
|
2271 |
return cell;
|
|
|
2272 |
};
|
|
|
2273 |
const cloneFormats = (oldCell, newCell, formats) => {
|
|
|
2274 |
const first$1 = first(oldCell);
|
|
|
2275 |
return first$1.map(firstText => {
|
|
|
2276 |
const formatSelector = formats.join(',');
|
|
|
2277 |
const parents = ancestors$3(firstText, formatSelector, element => {
|
|
|
2278 |
return eq$1(element, oldCell);
|
|
|
2279 |
});
|
|
|
2280 |
return foldr(parents, (last, parent) => {
|
|
|
2281 |
const clonedFormat = shallow(parent);
|
|
|
2282 |
append$1(last, clonedFormat);
|
|
|
2283 |
return clonedFormat;
|
|
|
2284 |
}, newCell);
|
|
|
2285 |
}).getOr(newCell);
|
|
|
2286 |
};
|
|
|
2287 |
const cloneAppropriateAttributes = (original, clone) => {
|
|
|
2288 |
each$1(transferableAttributes, (validAttributes, attributeName) => getOpt(original, attributeName).filter(attribute => contains$2(validAttributes, attribute)).each(attribute => set$2(clone, attributeName, attribute)));
|
|
|
2289 |
};
|
|
|
2290 |
const cellOperations = (mutate, doc, formatsToClone) => {
|
|
|
2291 |
const cloneCss = (prev, clone) => {
|
|
|
2292 |
copy$1(prev.element, clone);
|
|
|
2293 |
remove$5(clone, 'height');
|
|
|
2294 |
if (prev.colspan !== 1) {
|
|
|
2295 |
remove$5(clone, 'width');
|
|
|
2296 |
}
|
|
|
2297 |
};
|
|
|
2298 |
const newCell = prev => {
|
|
|
2299 |
const td = SugarElement.fromTag(name(prev.element), doc.dom);
|
|
|
2300 |
const formats = formatsToClone.getOr([
|
|
|
2301 |
'strong',
|
|
|
2302 |
'em',
|
|
|
2303 |
'b',
|
|
|
2304 |
'i',
|
|
|
2305 |
'span',
|
|
|
2306 |
'font',
|
|
|
2307 |
'h1',
|
|
|
2308 |
'h2',
|
|
|
2309 |
'h3',
|
|
|
2310 |
'h4',
|
|
|
2311 |
'h5',
|
|
|
2312 |
'h6',
|
|
|
2313 |
'p',
|
|
|
2314 |
'div'
|
|
|
2315 |
]);
|
|
|
2316 |
const lastNode = formats.length > 0 ? cloneFormats(prev.element, td, formats) : td;
|
|
|
2317 |
append$1(lastNode, SugarElement.fromTag('br'));
|
|
|
2318 |
cloneCss(prev, td);
|
|
|
2319 |
cloneAppropriateAttributes(prev.element, td);
|
|
|
2320 |
mutate(prev.element, td);
|
|
|
2321 |
return td;
|
|
|
2322 |
};
|
|
|
2323 |
const newCol = prev => {
|
|
|
2324 |
const col = SugarElement.fromTag(name(prev.element), doc.dom);
|
|
|
2325 |
cloneCss(prev, col);
|
|
|
2326 |
mutate(prev.element, col);
|
|
|
2327 |
return col;
|
|
|
2328 |
};
|
|
|
2329 |
return {
|
|
|
2330 |
col: newCol,
|
|
|
2331 |
colgroup: createColgroup(doc),
|
|
|
2332 |
row: createRow$1(doc),
|
|
|
2333 |
cell: newCell,
|
|
|
2334 |
replace: replace$1,
|
|
|
2335 |
colGap: createCol(doc),
|
|
|
2336 |
gap: createCell(doc)
|
|
|
2337 |
};
|
|
|
2338 |
};
|
|
|
2339 |
const paste$1 = doc => {
|
|
|
2340 |
return {
|
|
|
2341 |
col: createCol(doc),
|
|
|
2342 |
colgroup: createColgroup(doc),
|
|
|
2343 |
row: createRow$1(doc),
|
|
|
2344 |
cell: createCell(doc),
|
|
|
2345 |
replace: pasteReplace,
|
|
|
2346 |
colGap: createCol(doc),
|
|
|
2347 |
gap: createCell(doc)
|
|
|
2348 |
};
|
|
|
2349 |
};
|
|
|
2350 |
|
|
|
2351 |
const fromHtml = (html, scope) => {
|
|
|
2352 |
const doc = scope || document;
|
|
|
2353 |
const div = doc.createElement('div');
|
|
|
2354 |
div.innerHTML = html;
|
|
|
2355 |
return children$2(SugarElement.fromDom(div));
|
|
|
2356 |
};
|
|
|
2357 |
const fromDom = nodes => map$1(nodes, SugarElement.fromDom);
|
|
|
2358 |
|
|
|
2359 |
const option = name => editor => editor.options.get(name);
|
|
|
2360 |
const defaultWidth = '100%';
|
|
|
2361 |
const getPixelForcedWidth = editor => {
|
|
|
2362 |
var _a;
|
|
|
2363 |
const dom = editor.dom;
|
|
|
2364 |
const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
|
|
|
2365 |
return getInner(SugarElement.fromDom(parentBlock)) + 'px';
|
|
|
2366 |
};
|
|
|
2367 |
const determineDefaultTableStyles = (editor, defaultStyles) => {
|
|
|
2368 |
if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
|
|
|
2369 |
return defaultStyles;
|
|
|
2370 |
} else if (isTablePixelsForced(editor)) {
|
|
|
2371 |
return {
|
|
|
2372 |
...defaultStyles,
|
|
|
2373 |
width: getPixelForcedWidth(editor)
|
|
|
2374 |
};
|
|
|
2375 |
} else {
|
|
|
2376 |
return {
|
|
|
2377 |
...defaultStyles,
|
|
|
2378 |
width: defaultWidth
|
|
|
2379 |
};
|
|
|
2380 |
}
|
|
|
2381 |
};
|
|
|
2382 |
const determineDefaultTableAttributes = (editor, defaultAttributes) => {
|
|
|
2383 |
if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) {
|
|
|
2384 |
return defaultAttributes;
|
|
|
2385 |
} else if (isTablePixelsForced(editor)) {
|
|
|
2386 |
return {
|
|
|
2387 |
...defaultAttributes,
|
|
|
2388 |
width: getPixelForcedWidth(editor)
|
|
|
2389 |
};
|
|
|
2390 |
} else {
|
|
|
2391 |
return {
|
|
|
2392 |
...defaultAttributes,
|
|
|
2393 |
width: defaultWidth
|
|
|
2394 |
};
|
|
|
2395 |
}
|
|
|
2396 |
};
|
|
|
2397 |
const register = editor => {
|
|
|
2398 |
const registerOption = editor.options.register;
|
|
|
2399 |
registerOption('table_clone_elements', { processor: 'string[]' });
|
|
|
2400 |
registerOption('table_use_colgroups', {
|
|
|
2401 |
processor: 'boolean',
|
|
|
2402 |
default: true
|
|
|
2403 |
});
|
|
|
2404 |
registerOption('table_header_type', {
|
|
|
2405 |
processor: value => {
|
|
|
2406 |
const valid = contains$2([
|
|
|
2407 |
'section',
|
|
|
2408 |
'cells',
|
|
|
2409 |
'sectionCells',
|
|
|
2410 |
'auto'
|
|
|
2411 |
], value);
|
|
|
2412 |
return valid ? {
|
|
|
2413 |
value,
|
|
|
2414 |
valid
|
|
|
2415 |
} : {
|
|
|
2416 |
valid: false,
|
|
|
2417 |
message: 'Must be one of: section, cells, sectionCells or auto.'
|
|
|
2418 |
};
|
|
|
2419 |
},
|
|
|
2420 |
default: 'section'
|
|
|
2421 |
});
|
|
|
2422 |
registerOption('table_sizing_mode', {
|
|
|
2423 |
processor: 'string',
|
|
|
2424 |
default: 'auto'
|
|
|
2425 |
});
|
|
|
2426 |
registerOption('table_default_attributes', {
|
|
|
2427 |
processor: 'object',
|
|
|
2428 |
default: { border: '1' }
|
|
|
2429 |
});
|
|
|
2430 |
registerOption('table_default_styles', {
|
|
|
2431 |
processor: 'object',
|
|
|
2432 |
default: { 'border-collapse': 'collapse' }
|
|
|
2433 |
});
|
|
|
2434 |
registerOption('table_column_resizing', {
|
|
|
2435 |
processor: value => {
|
|
|
2436 |
const valid = contains$2([
|
|
|
2437 |
'preservetable',
|
|
|
2438 |
'resizetable'
|
|
|
2439 |
], value);
|
|
|
2440 |
return valid ? {
|
|
|
2441 |
value,
|
|
|
2442 |
valid
|
|
|
2443 |
} : {
|
|
|
2444 |
valid: false,
|
|
|
2445 |
message: 'Must be preservetable, or resizetable.'
|
|
|
2446 |
};
|
|
|
2447 |
},
|
|
|
2448 |
default: 'preservetable'
|
|
|
2449 |
});
|
|
|
2450 |
registerOption('table_resize_bars', {
|
|
|
2451 |
processor: 'boolean',
|
|
|
2452 |
default: true
|
|
|
2453 |
});
|
|
|
2454 |
registerOption('table_style_by_css', {
|
|
|
2455 |
processor: 'boolean',
|
|
|
2456 |
default: true
|
|
|
2457 |
});
|
|
|
2458 |
registerOption('table_merge_content_on_paste', {
|
|
|
2459 |
processor: 'boolean',
|
|
|
2460 |
default: true
|
|
|
2461 |
});
|
|
|
2462 |
};
|
|
|
2463 |
const getTableCloneElements = editor => {
|
|
|
2464 |
return Optional.from(editor.options.get('table_clone_elements'));
|
|
|
2465 |
};
|
|
|
2466 |
const hasTableObjectResizing = editor => {
|
|
|
2467 |
const objectResizing = editor.options.get('object_resizing');
|
|
|
2468 |
return contains$2(objectResizing.split(','), 'table');
|
|
|
2469 |
};
|
|
|
2470 |
const getTableHeaderType = option('table_header_type');
|
|
|
2471 |
const getTableColumnResizingBehaviour = option('table_column_resizing');
|
|
|
2472 |
const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable';
|
|
|
2473 |
const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable';
|
|
|
2474 |
const getTableSizingMode = option('table_sizing_mode');
|
|
|
2475 |
const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative';
|
|
|
2476 |
const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed';
|
|
|
2477 |
const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
|
|
|
2478 |
const hasTableResizeBars = option('table_resize_bars');
|
|
|
2479 |
const shouldStyleWithCss = option('table_style_by_css');
|
|
|
2480 |
const shouldMergeContentOnPaste = option('table_merge_content_on_paste');
|
|
|
2481 |
const getTableDefaultAttributes = editor => {
|
|
|
2482 |
const options = editor.options;
|
|
|
2483 |
const defaultAttributes = options.get('table_default_attributes');
|
|
|
2484 |
return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes);
|
|
|
2485 |
};
|
|
|
2486 |
const getTableDefaultStyles = editor => {
|
|
|
2487 |
const options = editor.options;
|
|
|
2488 |
const defaultStyles = options.get('table_default_styles');
|
|
|
2489 |
return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles);
|
|
|
2490 |
};
|
|
|
2491 |
const tableUseColumnGroup = option('table_use_colgroups');
|
|
|
2492 |
|
|
|
2493 |
const closest = target => closest$1(target, '[contenteditable]');
|
|
|
2494 |
const isEditable$1 = (element, assumeEditable = false) => {
|
|
|
2495 |
if (inBody(element)) {
|
|
|
2496 |
return element.dom.isContentEditable;
|
|
|
2497 |
} else {
|
|
|
2498 |
return closest(element).fold(constant(assumeEditable), editable => getRaw(editable) === 'true');
|
|
|
2499 |
}
|
|
|
2500 |
};
|
|
|
2501 |
const getRaw = element => element.dom.contentEditable;
|
|
|
2502 |
|
|
|
2503 |
const getBody = editor => SugarElement.fromDom(editor.getBody());
|
|
|
2504 |
const getIsRoot = editor => element => eq$1(element, getBody(editor));
|
|
|
2505 |
const removeDataStyle = table => {
|
|
|
2506 |
remove$7(table, 'data-mce-style');
|
|
|
2507 |
const removeStyleAttribute = element => remove$7(element, 'data-mce-style');
|
|
|
2508 |
each$2(cells$1(table), removeStyleAttribute);
|
|
|
2509 |
each$2(columns$1(table), removeStyleAttribute);
|
|
|
2510 |
each$2(rows$1(table), removeStyleAttribute);
|
|
|
2511 |
};
|
|
|
2512 |
const getSelectionStart = editor => SugarElement.fromDom(editor.selection.getStart());
|
|
|
2513 |
const getPixelWidth = elm => elm.getBoundingClientRect().width;
|
|
|
2514 |
const getPixelHeight = elm => elm.getBoundingClientRect().height;
|
|
|
2515 |
const getRawWidth = (editor, elm) => {
|
|
|
2516 |
const raw = editor.dom.getStyle(elm, 'width') || editor.dom.getAttrib(elm, 'width');
|
|
|
2517 |
return Optional.from(raw).filter(isNotEmpty);
|
|
|
2518 |
};
|
|
|
2519 |
const isPercentage$1 = value => /^(\d+(\.\d+)?)%$/.test(value);
|
|
|
2520 |
const isPixel = value => /^(\d+(\.\d+)?)px$/.test(value);
|
|
|
2521 |
const isInEditableContext$1 = cell => closest$2(cell, isTag('table')).exists(isEditable$1);
|
|
|
2522 |
|
|
|
2523 |
const inSelection = (bounds, detail) => {
|
|
|
2524 |
const leftEdge = detail.column;
|
|
|
2525 |
const rightEdge = detail.column + detail.colspan - 1;
|
|
|
2526 |
const topEdge = detail.row;
|
|
|
2527 |
const bottomEdge = detail.row + detail.rowspan - 1;
|
|
|
2528 |
return leftEdge <= bounds.finishCol && rightEdge >= bounds.startCol && (topEdge <= bounds.finishRow && bottomEdge >= bounds.startRow);
|
|
|
2529 |
};
|
|
|
2530 |
const isWithin = (bounds, detail) => {
|
|
|
2531 |
return detail.column >= bounds.startCol && detail.column + detail.colspan - 1 <= bounds.finishCol && detail.row >= bounds.startRow && detail.row + detail.rowspan - 1 <= bounds.finishRow;
|
|
|
2532 |
};
|
|
|
2533 |
const isRectangular = (warehouse, bounds) => {
|
|
|
2534 |
let isRect = true;
|
|
|
2535 |
const detailIsWithin = curry(isWithin, bounds);
|
|
|
2536 |
for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
|
|
|
2537 |
for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
|
|
|
2538 |
isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin);
|
|
|
2539 |
}
|
|
|
2540 |
}
|
|
|
2541 |
return isRect ? Optional.some(bounds) : Optional.none();
|
|
|
2542 |
};
|
|
|
2543 |
|
|
|
2544 |
const getBounds = (detailA, detailB) => {
|
|
|
2545 |
return bounds(Math.min(detailA.row, detailB.row), Math.min(detailA.column, detailB.column), Math.max(detailA.row + detailA.rowspan - 1, detailB.row + detailB.rowspan - 1), Math.max(detailA.column + detailA.colspan - 1, detailB.column + detailB.colspan - 1));
|
|
|
2546 |
};
|
|
|
2547 |
const getAnyBox = (warehouse, startCell, finishCell) => {
|
|
|
2548 |
const startCoords = Warehouse.findItem(warehouse, startCell, eq$1);
|
|
|
2549 |
const finishCoords = Warehouse.findItem(warehouse, finishCell, eq$1);
|
|
|
2550 |
return startCoords.bind(sc => {
|
|
|
2551 |
return finishCoords.map(fc => {
|
|
|
2552 |
return getBounds(sc, fc);
|
|
|
2553 |
});
|
|
|
2554 |
});
|
|
|
2555 |
};
|
|
|
2556 |
const getBox$1 = (warehouse, startCell, finishCell) => {
|
|
|
2557 |
return getAnyBox(warehouse, startCell, finishCell).bind(bounds => {
|
|
|
2558 |
return isRectangular(warehouse, bounds);
|
|
|
2559 |
});
|
|
|
2560 |
};
|
|
|
2561 |
|
|
|
2562 |
const moveBy$1 = (warehouse, cell, row, column) => {
|
|
|
2563 |
return Warehouse.findItem(warehouse, cell, eq$1).bind(detail => {
|
|
|
2564 |
const startRow = row > 0 ? detail.row + detail.rowspan - 1 : detail.row;
|
|
|
2565 |
const startCol = column > 0 ? detail.column + detail.colspan - 1 : detail.column;
|
|
|
2566 |
const dest = Warehouse.getAt(warehouse, startRow + row, startCol + column);
|
|
|
2567 |
return dest.map(d => {
|
|
|
2568 |
return d.element;
|
|
|
2569 |
});
|
|
|
2570 |
});
|
|
|
2571 |
};
|
|
|
2572 |
const intercepts$1 = (warehouse, start, finish) => {
|
|
|
2573 |
return getAnyBox(warehouse, start, finish).map(bounds => {
|
|
|
2574 |
const inside = Warehouse.filterItems(warehouse, curry(inSelection, bounds));
|
|
|
2575 |
return map$1(inside, detail => {
|
|
|
2576 |
return detail.element;
|
|
|
2577 |
});
|
|
|
2578 |
});
|
|
|
2579 |
};
|
|
|
2580 |
const parentCell = (warehouse, innerCell) => {
|
|
|
2581 |
const isContainedBy = (c1, c2) => {
|
|
|
2582 |
return contains$1(c2, c1);
|
|
|
2583 |
};
|
|
|
2584 |
return Warehouse.findItem(warehouse, innerCell, isContainedBy).map(detail => {
|
|
|
2585 |
return detail.element;
|
|
|
2586 |
});
|
|
|
2587 |
};
|
|
|
2588 |
|
|
|
2589 |
const moveBy = (cell, deltaRow, deltaColumn) => {
|
|
|
2590 |
return table(cell).bind(table => {
|
|
|
2591 |
const warehouse = getWarehouse(table);
|
|
|
2592 |
return moveBy$1(warehouse, cell, deltaRow, deltaColumn);
|
|
|
2593 |
});
|
|
|
2594 |
};
|
|
|
2595 |
const intercepts = (table, first, last) => {
|
|
|
2596 |
const warehouse = getWarehouse(table);
|
|
|
2597 |
return intercepts$1(warehouse, first, last);
|
|
|
2598 |
};
|
|
|
2599 |
const nestedIntercepts = (table, first, firstTable, last, lastTable) => {
|
|
|
2600 |
const warehouse = getWarehouse(table);
|
|
|
2601 |
const optStartCell = eq$1(table, firstTable) ? Optional.some(first) : parentCell(warehouse, first);
|
|
|
2602 |
const optLastCell = eq$1(table, lastTable) ? Optional.some(last) : parentCell(warehouse, last);
|
|
|
2603 |
return optStartCell.bind(startCell => optLastCell.bind(lastCell => intercepts$1(warehouse, startCell, lastCell)));
|
|
|
2604 |
};
|
|
|
2605 |
const getBox = (table, first, last) => {
|
|
|
2606 |
const warehouse = getWarehouse(table);
|
|
|
2607 |
return getBox$1(warehouse, first, last);
|
|
|
2608 |
};
|
|
|
2609 |
const getWarehouse = Warehouse.fromTable;
|
|
|
2610 |
|
|
|
2611 |
var TagBoundaries = [
|
|
|
2612 |
'body',
|
|
|
2613 |
'p',
|
|
|
2614 |
'div',
|
|
|
2615 |
'article',
|
|
|
2616 |
'aside',
|
|
|
2617 |
'figcaption',
|
|
|
2618 |
'figure',
|
|
|
2619 |
'footer',
|
|
|
2620 |
'header',
|
|
|
2621 |
'nav',
|
|
|
2622 |
'section',
|
|
|
2623 |
'ol',
|
|
|
2624 |
'ul',
|
|
|
2625 |
'li',
|
|
|
2626 |
'table',
|
|
|
2627 |
'thead',
|
|
|
2628 |
'tbody',
|
|
|
2629 |
'tfoot',
|
|
|
2630 |
'caption',
|
|
|
2631 |
'tr',
|
|
|
2632 |
'td',
|
|
|
2633 |
'th',
|
|
|
2634 |
'h1',
|
|
|
2635 |
'h2',
|
|
|
2636 |
'h3',
|
|
|
2637 |
'h4',
|
|
|
2638 |
'h5',
|
|
|
2639 |
'h6',
|
|
|
2640 |
'blockquote',
|
|
|
2641 |
'pre',
|
|
|
2642 |
'address'
|
|
|
2643 |
];
|
|
|
2644 |
|
|
|
2645 |
var DomUniverse = () => {
|
|
|
2646 |
const clone = element => {
|
|
|
2647 |
return SugarElement.fromDom(element.dom.cloneNode(false));
|
|
|
2648 |
};
|
|
|
2649 |
const document = element => documentOrOwner(element).dom;
|
|
|
2650 |
const isBoundary = element => {
|
|
|
2651 |
if (!isElement(element)) {
|
|
|
2652 |
return false;
|
|
|
2653 |
}
|
|
|
2654 |
if (name(element) === 'body') {
|
|
|
2655 |
return true;
|
|
|
2656 |
}
|
|
|
2657 |
return contains$2(TagBoundaries, name(element));
|
|
|
2658 |
};
|
|
|
2659 |
const isEmptyTag = element => {
|
|
|
2660 |
if (!isElement(element)) {
|
|
|
2661 |
return false;
|
|
|
2662 |
}
|
|
|
2663 |
return contains$2([
|
|
|
2664 |
'br',
|
|
|
2665 |
'img',
|
|
|
2666 |
'hr',
|
|
|
2667 |
'input'
|
|
|
2668 |
], name(element));
|
|
|
2669 |
};
|
|
|
2670 |
const isNonEditable = element => isElement(element) && get$b(element, 'contenteditable') === 'false';
|
|
|
2671 |
const comparePosition = (element, other) => {
|
|
|
2672 |
return element.dom.compareDocumentPosition(other.dom);
|
|
|
2673 |
};
|
|
|
2674 |
const copyAttributesTo = (source, destination) => {
|
|
|
2675 |
const as = clone$2(source);
|
|
|
2676 |
setAll$1(destination, as);
|
|
|
2677 |
};
|
|
|
2678 |
const isSpecial = element => {
|
|
|
2679 |
const tag = name(element);
|
|
|
2680 |
return contains$2([
|
|
|
2681 |
'script',
|
|
|
2682 |
'noscript',
|
|
|
2683 |
'iframe',
|
|
|
2684 |
'noframes',
|
|
|
2685 |
'noembed',
|
|
|
2686 |
'title',
|
|
|
2687 |
'style',
|
|
|
2688 |
'textarea',
|
|
|
2689 |
'xmp'
|
|
|
2690 |
], tag);
|
|
|
2691 |
};
|
|
|
2692 |
const getLanguage = element => isElement(element) ? getOpt(element, 'lang') : Optional.none();
|
|
|
2693 |
return {
|
|
|
2694 |
up: constant({
|
|
|
2695 |
selector: ancestor$1,
|
|
|
2696 |
closest: closest$1,
|
|
|
2697 |
predicate: ancestor$2,
|
|
|
2698 |
all: parents
|
|
|
2699 |
}),
|
|
|
2700 |
down: constant({
|
|
|
2701 |
selector: descendants,
|
|
|
2702 |
predicate: descendants$1
|
|
|
2703 |
}),
|
|
|
2704 |
styles: constant({
|
|
|
2705 |
get: get$a,
|
|
|
2706 |
getRaw: getRaw$2,
|
|
|
2707 |
set: set$1,
|
|
|
2708 |
remove: remove$5
|
|
|
2709 |
}),
|
|
|
2710 |
attrs: constant({
|
|
|
2711 |
get: get$b,
|
|
|
2712 |
set: set$2,
|
|
|
2713 |
remove: remove$7,
|
|
|
2714 |
copyTo: copyAttributesTo
|
|
|
2715 |
}),
|
|
|
2716 |
insert: constant({
|
|
|
2717 |
before: before$3,
|
|
|
2718 |
after: after$5,
|
|
|
2719 |
afterAll: after$4,
|
|
|
2720 |
append: append$1,
|
|
|
2721 |
appendAll: append,
|
|
|
2722 |
prepend: prepend,
|
|
|
2723 |
wrap: wrap
|
|
|
2724 |
}),
|
|
|
2725 |
remove: constant({
|
|
|
2726 |
unwrap: unwrap,
|
|
|
2727 |
remove: remove$6
|
|
|
2728 |
}),
|
|
|
2729 |
create: constant({
|
|
|
2730 |
nu: SugarElement.fromTag,
|
|
|
2731 |
clone,
|
|
|
2732 |
text: SugarElement.fromText
|
|
|
2733 |
}),
|
|
|
2734 |
query: constant({
|
|
|
2735 |
comparePosition,
|
|
|
2736 |
prevSibling: prevSibling,
|
|
|
2737 |
nextSibling: nextSibling
|
|
|
2738 |
}),
|
|
|
2739 |
property: constant({
|
|
|
2740 |
children: children$2,
|
|
|
2741 |
name: name,
|
|
|
2742 |
parent: parent,
|
|
|
2743 |
document,
|
|
|
2744 |
isText: isText,
|
|
|
2745 |
isComment: isComment,
|
|
|
2746 |
isElement: isElement,
|
|
|
2747 |
isSpecial,
|
|
|
2748 |
getLanguage,
|
|
|
2749 |
getText: get$6,
|
|
|
2750 |
setText: set,
|
|
|
2751 |
isBoundary,
|
|
|
2752 |
isEmptyTag,
|
|
|
2753 |
isNonEditable
|
|
|
2754 |
}),
|
|
|
2755 |
eq: eq$1,
|
|
|
2756 |
is: is$1
|
|
|
2757 |
};
|
|
|
2758 |
};
|
|
|
2759 |
|
|
|
2760 |
const all = (universe, look, elements, f) => {
|
|
|
2761 |
const head = elements[0];
|
|
|
2762 |
const tail = elements.slice(1);
|
|
|
2763 |
return f(universe, look, head, tail);
|
|
|
2764 |
};
|
|
|
2765 |
const oneAll = (universe, look, elements) => {
|
|
|
2766 |
return elements.length > 0 ? all(universe, look, elements, unsafeOne) : Optional.none();
|
|
|
2767 |
};
|
|
|
2768 |
const unsafeOne = (universe, look, head, tail) => {
|
|
|
2769 |
const start = look(universe, head);
|
|
|
2770 |
return foldr(tail, (b, a) => {
|
|
|
2771 |
const current = look(universe, a);
|
|
|
2772 |
return commonElement(universe, b, current);
|
|
|
2773 |
}, start);
|
|
|
2774 |
};
|
|
|
2775 |
const commonElement = (universe, start, end) => {
|
|
|
2776 |
return start.bind(s => {
|
|
|
2777 |
return end.filter(curry(universe.eq, s));
|
|
|
2778 |
});
|
|
|
2779 |
};
|
|
|
2780 |
|
|
|
2781 |
const eq = (universe, item) => {
|
|
|
2782 |
return curry(universe.eq, item);
|
|
|
2783 |
};
|
|
|
2784 |
const ancestors$2 = (universe, start, end, isRoot = never) => {
|
|
|
2785 |
const ps1 = [start].concat(universe.up().all(start));
|
|
|
2786 |
const ps2 = [end].concat(universe.up().all(end));
|
|
|
2787 |
const prune = path => {
|
|
|
2788 |
const index = findIndex(path, isRoot);
|
|
|
2789 |
return index.fold(() => {
|
|
|
2790 |
return path;
|
|
|
2791 |
}, ind => {
|
|
|
2792 |
return path.slice(0, ind + 1);
|
|
|
2793 |
});
|
|
|
2794 |
};
|
|
|
2795 |
const pruned1 = prune(ps1);
|
|
|
2796 |
const pruned2 = prune(ps2);
|
|
|
2797 |
const shared = find$1(pruned1, x => {
|
|
|
2798 |
return exists(pruned2, eq(universe, x));
|
|
|
2799 |
});
|
|
|
2800 |
return {
|
|
|
2801 |
firstpath: pruned1,
|
|
|
2802 |
secondpath: pruned2,
|
|
|
2803 |
shared
|
|
|
2804 |
};
|
|
|
2805 |
};
|
|
|
2806 |
|
|
|
2807 |
const sharedOne$1 = oneAll;
|
|
|
2808 |
const ancestors$1 = ancestors$2;
|
|
|
2809 |
|
|
|
2810 |
const universe$3 = DomUniverse();
|
|
|
2811 |
const sharedOne = (look, elements) => {
|
|
|
2812 |
return sharedOne$1(universe$3, (_universe, element) => {
|
|
|
2813 |
return look(element);
|
|
|
2814 |
}, elements);
|
|
|
2815 |
};
|
|
|
2816 |
const ancestors = (start, finish, isRoot) => {
|
|
|
2817 |
return ancestors$1(universe$3, start, finish, isRoot);
|
|
|
2818 |
};
|
|
|
2819 |
|
|
|
2820 |
const lookupTable = container => {
|
|
|
2821 |
return ancestor$1(container, 'table');
|
|
|
2822 |
};
|
|
|
2823 |
const identify = (start, finish, isRoot) => {
|
|
|
2824 |
const getIsRoot = rootTable => {
|
|
|
2825 |
return element => {
|
|
|
2826 |
return isRoot !== undefined && isRoot(element) || eq$1(element, rootTable);
|
|
|
2827 |
};
|
|
|
2828 |
};
|
|
|
2829 |
if (eq$1(start, finish)) {
|
|
|
2830 |
return Optional.some({
|
|
|
2831 |
boxes: Optional.some([start]),
|
|
|
2832 |
start,
|
|
|
2833 |
finish
|
|
|
2834 |
});
|
|
|
2835 |
} else {
|
|
|
2836 |
return lookupTable(start).bind(startTable => {
|
|
|
2837 |
return lookupTable(finish).bind(finishTable => {
|
|
|
2838 |
if (eq$1(startTable, finishTable)) {
|
|
|
2839 |
return Optional.some({
|
|
|
2840 |
boxes: intercepts(startTable, start, finish),
|
|
|
2841 |
start,
|
|
|
2842 |
finish
|
|
|
2843 |
});
|
|
|
2844 |
} else if (contains$1(startTable, finishTable)) {
|
|
|
2845 |
const ancestorCells = ancestors$3(finish, 'td,th', getIsRoot(startTable));
|
|
|
2846 |
const finishCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : finish;
|
|
|
2847 |
return Optional.some({
|
|
|
2848 |
boxes: nestedIntercepts(startTable, start, startTable, finish, finishTable),
|
|
|
2849 |
start,
|
|
|
2850 |
finish: finishCell
|
|
|
2851 |
});
|
|
|
2852 |
} else if (contains$1(finishTable, startTable)) {
|
|
|
2853 |
const ancestorCells = ancestors$3(start, 'td,th', getIsRoot(finishTable));
|
|
|
2854 |
const startCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : start;
|
|
|
2855 |
return Optional.some({
|
|
|
2856 |
boxes: nestedIntercepts(finishTable, start, startTable, finish, finishTable),
|
|
|
2857 |
start,
|
|
|
2858 |
finish: startCell
|
|
|
2859 |
});
|
|
|
2860 |
} else {
|
|
|
2861 |
return ancestors(start, finish).shared.bind(lca => {
|
|
|
2862 |
return closest$1(lca, 'table', isRoot).bind(lcaTable => {
|
|
|
2863 |
const finishAncestorCells = ancestors$3(finish, 'td,th', getIsRoot(lcaTable));
|
|
|
2864 |
const finishCell = finishAncestorCells.length > 0 ? finishAncestorCells[finishAncestorCells.length - 1] : finish;
|
|
|
2865 |
const startAncestorCells = ancestors$3(start, 'td,th', getIsRoot(lcaTable));
|
|
|
2866 |
const startCell = startAncestorCells.length > 0 ? startAncestorCells[startAncestorCells.length - 1] : start;
|
|
|
2867 |
return Optional.some({
|
|
|
2868 |
boxes: nestedIntercepts(lcaTable, start, startTable, finish, finishTable),
|
|
|
2869 |
start: startCell,
|
|
|
2870 |
finish: finishCell
|
|
|
2871 |
});
|
|
|
2872 |
});
|
|
|
2873 |
});
|
|
|
2874 |
}
|
|
|
2875 |
});
|
|
|
2876 |
});
|
|
|
2877 |
}
|
|
|
2878 |
};
|
|
|
2879 |
const retrieve$1 = (container, selector) => {
|
|
|
2880 |
const sels = descendants(container, selector);
|
|
|
2881 |
return sels.length > 0 ? Optional.some(sels) : Optional.none();
|
|
|
2882 |
};
|
|
|
2883 |
const getLast = (boxes, lastSelectedSelector) => {
|
|
|
2884 |
return find$1(boxes, box => {
|
|
|
2885 |
return is$2(box, lastSelectedSelector);
|
|
|
2886 |
});
|
|
|
2887 |
};
|
|
|
2888 |
const getEdges = (container, firstSelectedSelector, lastSelectedSelector) => {
|
|
|
2889 |
return descendant(container, firstSelectedSelector).bind(first => {
|
|
|
2890 |
return descendant(container, lastSelectedSelector).bind(last => {
|
|
|
2891 |
return sharedOne(lookupTable, [
|
|
|
2892 |
first,
|
|
|
2893 |
last
|
|
|
2894 |
]).map(table => {
|
|
|
2895 |
return {
|
|
|
2896 |
first,
|
|
|
2897 |
last,
|
|
|
2898 |
table
|
|
|
2899 |
};
|
|
|
2900 |
});
|
|
|
2901 |
});
|
|
|
2902 |
});
|
|
|
2903 |
};
|
|
|
2904 |
const expandTo = (finish, firstSelectedSelector) => {
|
|
|
2905 |
return ancestor$1(finish, 'table').bind(table => {
|
|
|
2906 |
return descendant(table, firstSelectedSelector).bind(start => {
|
|
|
2907 |
return identify(start, finish).bind(identified => {
|
|
|
2908 |
return identified.boxes.map(boxes => {
|
|
|
2909 |
return {
|
|
|
2910 |
boxes,
|
|
|
2911 |
start: identified.start,
|
|
|
2912 |
finish: identified.finish
|
|
|
2913 |
};
|
|
|
2914 |
});
|
|
|
2915 |
});
|
|
|
2916 |
});
|
|
|
2917 |
});
|
|
|
2918 |
};
|
|
|
2919 |
const shiftSelection = (boxes, deltaRow, deltaColumn, firstSelectedSelector, lastSelectedSelector) => {
|
|
|
2920 |
return getLast(boxes, lastSelectedSelector).bind(last => {
|
|
|
2921 |
return moveBy(last, deltaRow, deltaColumn).bind(finish => {
|
|
|
2922 |
return expandTo(finish, firstSelectedSelector);
|
|
|
2923 |
});
|
|
|
2924 |
});
|
|
|
2925 |
};
|
|
|
2926 |
|
|
|
2927 |
const retrieve = (container, selector) => {
|
|
|
2928 |
return retrieve$1(container, selector);
|
|
|
2929 |
};
|
|
|
2930 |
const retrieveBox = (container, firstSelectedSelector, lastSelectedSelector) => {
|
|
|
2931 |
return getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(edges => {
|
|
|
2932 |
const isRoot = ancestor => {
|
|
|
2933 |
return eq$1(container, ancestor);
|
|
|
2934 |
};
|
|
|
2935 |
const sectionSelector = 'thead,tfoot,tbody,table';
|
|
|
2936 |
const firstAncestor = ancestor$1(edges.first, sectionSelector, isRoot);
|
|
|
2937 |
const lastAncestor = ancestor$1(edges.last, sectionSelector, isRoot);
|
|
|
2938 |
return firstAncestor.bind(fA => {
|
|
|
2939 |
return lastAncestor.bind(lA => {
|
|
|
2940 |
return eq$1(fA, lA) ? getBox(edges.table, edges.first, edges.last) : Optional.none();
|
|
|
2941 |
});
|
|
|
2942 |
});
|
|
|
2943 |
});
|
|
|
2944 |
};
|
|
|
2945 |
|
|
|
2946 |
const selection = identity;
|
|
|
2947 |
const unmergable = selectedCells => {
|
|
|
2948 |
const hasSpan = (elem, type) => getOpt(elem, type).exists(span => parseInt(span, 10) > 1);
|
|
|
2949 |
const hasRowOrColSpan = elem => hasSpan(elem, 'rowspan') || hasSpan(elem, 'colspan');
|
|
|
2950 |
return selectedCells.length > 0 && forall(selectedCells, hasRowOrColSpan) ? Optional.some(selectedCells) : Optional.none();
|
|
|
2951 |
};
|
|
|
2952 |
const mergable = (table, selectedCells, ephemera) => {
|
|
|
2953 |
if (selectedCells.length <= 1) {
|
|
|
2954 |
return Optional.none();
|
|
|
2955 |
} else {
|
|
|
2956 |
return retrieveBox(table, ephemera.firstSelectedSelector, ephemera.lastSelectedSelector).map(bounds => ({
|
|
|
2957 |
bounds,
|
|
|
2958 |
cells: selectedCells
|
|
|
2959 |
}));
|
|
|
2960 |
}
|
|
|
2961 |
};
|
|
|
2962 |
|
|
|
2963 |
const strSelected = 'data-mce-selected';
|
|
|
2964 |
const strSelectedSelector = 'td[' + strSelected + '],th[' + strSelected + ']';
|
|
|
2965 |
const strAttributeSelector = '[' + strSelected + ']';
|
|
|
2966 |
const strFirstSelected = 'data-mce-first-selected';
|
|
|
2967 |
const strFirstSelectedSelector = 'td[' + strFirstSelected + '],th[' + strFirstSelected + ']';
|
|
|
2968 |
const strLastSelected = 'data-mce-last-selected';
|
|
|
2969 |
const strLastSelectedSelector = 'td[' + strLastSelected + '],th[' + strLastSelected + ']';
|
|
|
2970 |
const attributeSelector = strAttributeSelector;
|
|
|
2971 |
const ephemera = {
|
|
|
2972 |
selected: strSelected,
|
|
|
2973 |
selectedSelector: strSelectedSelector,
|
|
|
2974 |
firstSelected: strFirstSelected,
|
|
|
2975 |
firstSelectedSelector: strFirstSelectedSelector,
|
|
|
2976 |
lastSelected: strLastSelected,
|
|
|
2977 |
lastSelectedSelector: strLastSelectedSelector
|
|
|
2978 |
};
|
|
|
2979 |
|
|
|
2980 |
const forMenu = (selectedCells, table, cell) => ({
|
|
|
2981 |
element: cell,
|
|
|
2982 |
mergable: mergable(table, selectedCells, ephemera),
|
|
|
2983 |
unmergable: unmergable(selectedCells),
|
|
|
2984 |
selection: selection(selectedCells)
|
|
|
2985 |
});
|
|
|
2986 |
const paste = (element, clipboard, generators) => ({
|
|
|
2987 |
element,
|
|
|
2988 |
clipboard,
|
|
|
2989 |
generators
|
|
|
2990 |
});
|
|
|
2991 |
const pasteRows = (selectedCells, _cell, clipboard, generators) => ({
|
|
|
2992 |
selection: selection(selectedCells),
|
|
|
2993 |
clipboard,
|
|
|
2994 |
generators
|
|
|
2995 |
});
|
|
|
2996 |
|
|
|
2997 |
const getSelectionCellFallback = element => table(element).bind(table => retrieve(table, ephemera.firstSelectedSelector)).fold(constant(element), cells => cells[0]);
|
|
|
2998 |
const getSelectionFromSelector = selector => (initCell, isRoot) => {
|
|
|
2999 |
const cellName = name(initCell);
|
|
|
3000 |
const cell = cellName === 'col' || cellName === 'colgroup' ? getSelectionCellFallback(initCell) : initCell;
|
|
|
3001 |
return closest$1(cell, selector, isRoot);
|
|
|
3002 |
};
|
|
|
3003 |
const getSelectionCellOrCaption = getSelectionFromSelector('th,td,caption');
|
|
|
3004 |
const getSelectionCell = getSelectionFromSelector('th,td');
|
|
|
3005 |
const getCellsFromSelection = editor => fromDom(editor.model.table.getSelectedCells());
|
|
|
3006 |
const getCellsFromFakeSelection = editor => filter$2(getCellsFromSelection(editor), cell => is$2(cell, ephemera.selectedSelector));
|
|
|
3007 |
|
|
|
3008 |
const extractSelected = cells => {
|
|
|
3009 |
return table(cells[0]).map(table => {
|
|
|
3010 |
const replica = extract$1(table, attributeSelector);
|
|
|
3011 |
removeDataStyle(replica);
|
|
|
3012 |
return [replica];
|
|
|
3013 |
});
|
|
|
3014 |
};
|
|
|
3015 |
const serializeElements = (editor, elements) => map$1(elements, elm => editor.selection.serializer.serialize(elm.dom, {})).join('');
|
|
|
3016 |
const getTextContent = elements => map$1(elements, element => element.dom.innerText).join('');
|
|
|
3017 |
const registerEvents = (editor, actions) => {
|
|
|
3018 |
editor.on('BeforeGetContent', e => {
|
|
|
3019 |
const multiCellContext = cells => {
|
|
|
3020 |
e.preventDefault();
|
|
|
3021 |
extractSelected(cells).each(elements => {
|
|
|
3022 |
e.content = e.format === 'text' ? getTextContent(elements) : serializeElements(editor, elements);
|
|
|
3023 |
});
|
|
|
3024 |
};
|
|
|
3025 |
if (e.selection === true) {
|
|
|
3026 |
const cells = getCellsFromFakeSelection(editor);
|
|
|
3027 |
if (cells.length >= 1) {
|
|
|
3028 |
multiCellContext(cells);
|
|
|
3029 |
}
|
|
|
3030 |
}
|
|
|
3031 |
});
|
|
|
3032 |
editor.on('BeforeSetContent', e => {
|
|
|
3033 |
if (e.selection === true && e.paste === true) {
|
|
|
3034 |
const selectedCells = getCellsFromSelection(editor);
|
|
|
3035 |
head(selectedCells).each(cell => {
|
|
|
3036 |
table(cell).each(table => {
|
|
|
3037 |
const elements = filter$2(fromHtml(e.content), content => {
|
|
|
3038 |
return name(content) !== 'meta';
|
|
|
3039 |
});
|
|
|
3040 |
const isTable = isTag('table');
|
|
|
3041 |
if (shouldMergeContentOnPaste(editor) && elements.length === 1 && isTable(elements[0])) {
|
|
|
3042 |
e.preventDefault();
|
|
|
3043 |
const doc = SugarElement.fromDom(editor.getDoc());
|
|
|
3044 |
const generators = paste$1(doc);
|
|
|
3045 |
const targets = paste(cell, elements[0], generators);
|
|
|
3046 |
actions.pasteCells(table, targets).each(() => {
|
|
|
3047 |
editor.focus();
|
|
|
3048 |
});
|
|
|
3049 |
}
|
|
|
3050 |
});
|
|
|
3051 |
});
|
|
|
3052 |
}
|
|
|
3053 |
});
|
|
|
3054 |
};
|
|
|
3055 |
|
|
|
3056 |
const point = (element, offset) => ({
|
|
|
3057 |
element,
|
|
|
3058 |
offset
|
|
|
3059 |
});
|
|
|
3060 |
|
|
|
3061 |
const scan$1 = (universe, element, direction) => {
|
|
|
3062 |
if (universe.property().isText(element) && universe.property().getText(element).trim().length === 0 || universe.property().isComment(element)) {
|
|
|
3063 |
return direction(element).bind(elem => {
|
|
|
3064 |
return scan$1(universe, elem, direction).orThunk(() => {
|
|
|
3065 |
return Optional.some(elem);
|
|
|
3066 |
});
|
|
|
3067 |
});
|
|
|
3068 |
} else {
|
|
|
3069 |
return Optional.none();
|
|
|
3070 |
}
|
|
|
3071 |
};
|
|
|
3072 |
const toEnd = (universe, element) => {
|
|
|
3073 |
if (universe.property().isText(element)) {
|
|
|
3074 |
return universe.property().getText(element).length;
|
|
|
3075 |
}
|
|
|
3076 |
const children = universe.property().children(element);
|
|
|
3077 |
return children.length;
|
|
|
3078 |
};
|
|
|
3079 |
const freefallRtl$2 = (universe, element) => {
|
|
|
3080 |
const candidate = scan$1(universe, element, universe.query().prevSibling).getOr(element);
|
|
|
3081 |
if (universe.property().isText(candidate)) {
|
|
|
3082 |
return point(candidate, toEnd(universe, candidate));
|
|
|
3083 |
}
|
|
|
3084 |
const children = universe.property().children(candidate);
|
|
|
3085 |
return children.length > 0 ? freefallRtl$2(universe, children[children.length - 1]) : point(candidate, toEnd(universe, candidate));
|
|
|
3086 |
};
|
|
|
3087 |
|
|
|
3088 |
const freefallRtl$1 = freefallRtl$2;
|
|
|
3089 |
|
|
|
3090 |
const universe$2 = DomUniverse();
|
|
|
3091 |
const freefallRtl = element => {
|
|
|
3092 |
return freefallRtl$1(universe$2, element);
|
|
|
3093 |
};
|
|
|
3094 |
|
|
|
3095 |
const halve = (main, other) => {
|
|
|
3096 |
if (!hasColspan(main)) {
|
|
|
3097 |
const width = getGenericWidth(main);
|
|
|
3098 |
width.each(w => {
|
|
|
3099 |
const newWidth = w.value / 2;
|
|
|
3100 |
setGenericWidth(main, newWidth, w.unit);
|
|
|
3101 |
setGenericWidth(other, newWidth, w.unit);
|
|
|
3102 |
});
|
|
|
3103 |
}
|
|
|
3104 |
};
|
|
|
3105 |
|
|
|
3106 |
const zero = array => map$1(array, constant(0));
|
|
|
3107 |
const surround = (sizes, startIndex, endIndex, results, f) => f(sizes.slice(0, startIndex)).concat(results).concat(f(sizes.slice(endIndex)));
|
|
|
3108 |
const clampDeltaHelper = predicate => (sizes, index, delta, minCellSize) => {
|
|
|
3109 |
if (!predicate(delta)) {
|
|
|
3110 |
return delta;
|
|
|
3111 |
} else {
|
|
|
3112 |
const newSize = Math.max(minCellSize, sizes[index] - Math.abs(delta));
|
|
|
3113 |
const diff = Math.abs(newSize - sizes[index]);
|
|
|
3114 |
return delta >= 0 ? diff : -diff;
|
|
|
3115 |
}
|
|
|
3116 |
};
|
|
|
3117 |
const clampNegativeDelta = clampDeltaHelper(delta => delta < 0);
|
|
|
3118 |
const clampDelta = clampDeltaHelper(always);
|
|
|
3119 |
const resizeTable = () => {
|
|
|
3120 |
const calcFixedDeltas = (sizes, index, next, delta, minCellSize) => {
|
|
|
3121 |
const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
|
|
|
3122 |
return surround(sizes, index, next + 1, [
|
|
|
3123 |
clampedDelta,
|
|
|
3124 |
|
|
|
3125 |
], zero);
|
|
|
3126 |
};
|
|
|
3127 |
const calcRelativeDeltas = (sizes, index, delta, minCellSize) => {
|
|
|
3128 |
const ratio = (100 + delta) / 100;
|
|
|
3129 |
const newThis = Math.max(minCellSize, (sizes[index] + delta) / ratio);
|
|
|
3130 |
return map$1(sizes, (size, idx) => {
|
|
|
3131 |
const newSize = idx === index ? newThis : size / ratio;
|
|
|
3132 |
return newSize - size;
|
|
|
3133 |
});
|
|
|
3134 |
};
|
|
|
3135 |
const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize, isRelative) => {
|
|
|
3136 |
if (isRelative) {
|
|
|
3137 |
return calcRelativeDeltas(sizes, index, delta, minCellSize);
|
|
|
3138 |
} else {
|
|
|
3139 |
return calcFixedDeltas(sizes, index, next, delta, minCellSize);
|
|
|
3140 |
}
|
|
|
3141 |
};
|
|
|
3142 |
const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize, isRelative) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize, isRelative);
|
|
|
3143 |
const resizeTable = (resizer, delta) => resizer(delta);
|
|
|
3144 |
const calcRightEdgeDeltas = (sizes, _prev, index, delta, minCellSize, isRelative) => {
|
|
|
3145 |
if (isRelative) {
|
|
|
3146 |
return calcRelativeDeltas(sizes, index, delta, minCellSize);
|
|
|
3147 |
} else {
|
|
|
3148 |
const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
|
|
|
3149 |
return zero(sizes.slice(0, index)).concat([clampedDelta]);
|
|
|
3150 |
}
|
|
|
3151 |
};
|
|
|
3152 |
const calcRedestributedWidths = (sizes, totalWidth, pixelDelta, isRelative) => {
|
|
|
3153 |
if (isRelative) {
|
|
|
3154 |
const tableWidth = totalWidth + pixelDelta;
|
|
|
3155 |
const ratio = tableWidth / totalWidth;
|
|
|
3156 |
const newSizes = map$1(sizes, size => size / ratio);
|
|
|
3157 |
return {
|
|
|
3158 |
delta: ratio * 100 - 100,
|
|
|
3159 |
newSizes
|
|
|
3160 |
};
|
|
|
3161 |
} else {
|
|
|
3162 |
return {
|
|
|
3163 |
delta: pixelDelta,
|
|
|
3164 |
newSizes: sizes
|
|
|
3165 |
};
|
|
|
3166 |
}
|
|
|
3167 |
};
|
|
|
3168 |
return {
|
|
|
3169 |
resizeTable,
|
|
|
3170 |
clampTableDelta: clampNegativeDelta,
|
|
|
3171 |
calcLeftEdgeDeltas,
|
|
|
3172 |
calcMiddleDeltas,
|
|
|
3173 |
calcRightEdgeDeltas,
|
|
|
3174 |
calcRedestributedWidths
|
|
|
3175 |
};
|
|
|
3176 |
};
|
|
|
3177 |
const preserveTable = () => {
|
|
|
3178 |
const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize) => {
|
|
|
3179 |
const idx = delta >= 0 ? next : index;
|
|
|
3180 |
const clampedDelta = clampDelta(sizes, idx, delta, minCellSize);
|
|
|
3181 |
return surround(sizes, index, next + 1, [
|
|
|
3182 |
clampedDelta,
|
|
|
3183 |
-clampedDelta
|
|
|
3184 |
], zero);
|
|
|
3185 |
};
|
|
|
3186 |
const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize);
|
|
|
3187 |
const resizeTable = (resizer, delta, isLastColumn) => {
|
|
|
3188 |
if (isLastColumn) {
|
|
|
3189 |
resizer(delta);
|
|
|
3190 |
}
|
|
|
3191 |
};
|
|
|
3192 |
const calcRightEdgeDeltas = (sizes, _prev, _index, delta, _minCellSize, isRelative) => {
|
|
|
3193 |
if (isRelative) {
|
|
|
3194 |
return zero(sizes);
|
|
|
3195 |
} else {
|
|
|
3196 |
const diff = delta / sizes.length;
|
|
|
3197 |
return map$1(sizes, constant(diff));
|
|
|
3198 |
}
|
|
|
3199 |
};
|
|
|
3200 |
const clampTableDelta = (sizes, index, delta, minCellSize, isLastColumn) => {
|
|
|
3201 |
if (isLastColumn) {
|
|
|
3202 |
if (delta >= 0) {
|
|
|
3203 |
return delta;
|
|
|
3204 |
} else {
|
|
|
3205 |
const maxDelta = foldl(sizes, (a, b) => a + b - minCellSize, 0);
|
|
|
3206 |
return Math.max(-maxDelta, delta);
|
|
|
3207 |
}
|
|
|
3208 |
} else {
|
|
|
3209 |
return clampNegativeDelta(sizes, index, delta, minCellSize);
|
|
|
3210 |
}
|
|
|
3211 |
};
|
|
|
3212 |
const calcRedestributedWidths = (sizes, _totalWidth, _pixelDelta, _isRelative) => ({
|
|
|
3213 |
delta: 0,
|
|
|
3214 |
newSizes: sizes
|
|
|
3215 |
});
|
|
|
3216 |
return {
|
|
|
3217 |
resizeTable,
|
|
|
3218 |
clampTableDelta,
|
|
|
3219 |
calcLeftEdgeDeltas,
|
|
|
3220 |
calcMiddleDeltas,
|
|
|
3221 |
calcRightEdgeDeltas,
|
|
|
3222 |
calcRedestributedWidths
|
|
|
3223 |
};
|
|
|
3224 |
};
|
|
|
3225 |
|
|
|
3226 |
const getGridSize = table => {
|
|
|
3227 |
const warehouse = Warehouse.fromTable(table);
|
|
|
3228 |
return warehouse.grid;
|
|
|
3229 |
};
|
|
|
3230 |
|
|
|
3231 |
const isHeaderCell = isTag('th');
|
|
|
3232 |
const isHeaderCells = cells => forall(cells, cell => isHeaderCell(cell.element));
|
|
|
3233 |
const getRowHeaderType = (isHeaderRow, isHeaderCells) => {
|
|
|
3234 |
if (isHeaderRow && isHeaderCells) {
|
|
|
3235 |
return 'sectionCells';
|
|
|
3236 |
} else if (isHeaderRow) {
|
|
|
3237 |
return 'section';
|
|
|
3238 |
} else {
|
|
|
3239 |
return 'cells';
|
|
|
3240 |
}
|
|
|
3241 |
};
|
|
|
3242 |
const getRowType = row => {
|
|
|
3243 |
const isHeaderRow = row.section === 'thead';
|
|
|
3244 |
const isHeaderCells = is(findCommonCellType(row.cells), 'th');
|
|
|
3245 |
if (row.section === 'tfoot') {
|
|
|
3246 |
return { type: 'footer' };
|
|
|
3247 |
} else if (isHeaderRow || isHeaderCells) {
|
|
|
3248 |
return {
|
|
|
3249 |
type: 'header',
|
|
|
3250 |
subType: getRowHeaderType(isHeaderRow, isHeaderCells)
|
|
|
3251 |
};
|
|
|
3252 |
} else {
|
|
|
3253 |
return { type: 'body' };
|
|
|
3254 |
}
|
|
|
3255 |
};
|
|
|
3256 |
const findCommonCellType = cells => {
|
|
|
3257 |
const headerCells = filter$2(cells, cell => isHeaderCell(cell.element));
|
|
|
3258 |
if (headerCells.length === 0) {
|
|
|
3259 |
return Optional.some('td');
|
|
|
3260 |
} else if (headerCells.length === cells.length) {
|
|
|
3261 |
return Optional.some('th');
|
|
|
3262 |
} else {
|
|
|
3263 |
return Optional.none();
|
|
|
3264 |
}
|
|
|
3265 |
};
|
|
|
3266 |
const findCommonRowType = rows => {
|
|
|
3267 |
const rowTypes = map$1(rows, row => getRowType(row).type);
|
|
|
3268 |
const hasHeader = contains$2(rowTypes, 'header');
|
|
|
3269 |
const hasFooter = contains$2(rowTypes, 'footer');
|
|
|
3270 |
if (!hasHeader && !hasFooter) {
|
|
|
3271 |
return Optional.some('body');
|
|
|
3272 |
} else {
|
|
|
3273 |
const hasBody = contains$2(rowTypes, 'body');
|
|
|
3274 |
if (hasHeader && !hasBody && !hasFooter) {
|
|
|
3275 |
return Optional.some('header');
|
|
|
3276 |
} else if (!hasHeader && !hasBody && hasFooter) {
|
|
|
3277 |
return Optional.some('footer');
|
|
|
3278 |
} else {
|
|
|
3279 |
return Optional.none();
|
|
|
3280 |
}
|
|
|
3281 |
}
|
|
|
3282 |
};
|
|
|
3283 |
const findTableRowHeaderType = warehouse => findMap(warehouse.all, row => {
|
|
|
3284 |
const rowType = getRowType(row);
|
|
|
3285 |
return rowType.type === 'header' ? Optional.from(rowType.subType) : Optional.none();
|
|
|
3286 |
});
|
|
|
3287 |
|
|
|
3288 |
const transformCell = (cell, comparator, substitution) => elementnew(substitution(cell.element, comparator), true, cell.isLocked);
|
|
|
3289 |
const transformRow = (row, section) => row.section !== section ? rowcells(row.element, row.cells, section, row.isNew) : row;
|
|
|
3290 |
const section = () => ({
|
|
|
3291 |
transformRow,
|
|
|
3292 |
transformCell: (cell, comparator, substitution) => {
|
|
|
3293 |
const newCell = substitution(cell.element, comparator);
|
|
|
3294 |
const fixedCell = name(newCell) !== 'td' ? mutate$1(newCell, 'td') : newCell;
|
|
|
3295 |
return elementnew(fixedCell, cell.isNew, cell.isLocked);
|
|
|
3296 |
}
|
|
|
3297 |
});
|
|
|
3298 |
const sectionCells = () => ({
|
|
|
3299 |
transformRow,
|
|
|
3300 |
transformCell
|
|
|
3301 |
});
|
|
|
3302 |
const cells = () => ({
|
|
|
3303 |
transformRow: (row, section) => {
|
|
|
3304 |
const newSection = section === 'thead' ? 'tbody' : section;
|
|
|
3305 |
return transformRow(row, newSection);
|
|
|
3306 |
},
|
|
|
3307 |
transformCell
|
|
|
3308 |
});
|
|
|
3309 |
const fallback = () => ({
|
|
|
3310 |
transformRow: identity,
|
|
|
3311 |
transformCell
|
|
|
3312 |
});
|
|
|
3313 |
const getTableSectionType = (table, fallback) => {
|
|
|
3314 |
const warehouse = Warehouse.fromTable(table);
|
|
|
3315 |
const type = findTableRowHeaderType(warehouse).getOr(fallback);
|
|
|
3316 |
switch (type) {
|
|
|
3317 |
case 'section':
|
|
|
3318 |
return section();
|
|
|
3319 |
case 'sectionCells':
|
|
|
3320 |
return sectionCells();
|
|
|
3321 |
case 'cells':
|
|
|
3322 |
return cells();
|
|
|
3323 |
}
|
|
|
3324 |
};
|
|
|
3325 |
const TableSection = {
|
|
|
3326 |
getTableSectionType,
|
|
|
3327 |
section,
|
|
|
3328 |
sectionCells,
|
|
|
3329 |
cells,
|
|
|
3330 |
fallback
|
|
|
3331 |
};
|
|
|
3332 |
|
|
|
3333 |
const setIfNot = (element, property, value, ignore) => {
|
|
|
3334 |
if (value === ignore) {
|
|
|
3335 |
remove$7(element, property);
|
|
|
3336 |
} else {
|
|
|
3337 |
set$2(element, property, value);
|
|
|
3338 |
}
|
|
|
3339 |
};
|
|
|
3340 |
const insert$1 = (table, selector, element) => {
|
|
|
3341 |
last$2(children(table, selector)).fold(() => prepend(table, element), child => after$5(child, element));
|
|
|
3342 |
};
|
|
|
3343 |
const generateSection = (table, sectionName) => {
|
|
|
3344 |
const section = child(table, sectionName).getOrThunk(() => {
|
|
|
3345 |
const newSection = SugarElement.fromTag(sectionName, owner(table).dom);
|
|
|
3346 |
if (sectionName === 'thead') {
|
|
|
3347 |
insert$1(table, 'caption,colgroup', newSection);
|
|
|
3348 |
} else if (sectionName === 'colgroup') {
|
|
|
3349 |
insert$1(table, 'caption', newSection);
|
|
|
3350 |
} else {
|
|
|
3351 |
append$1(table, newSection);
|
|
|
3352 |
}
|
|
|
3353 |
return newSection;
|
|
|
3354 |
});
|
|
|
3355 |
empty(section);
|
|
|
3356 |
return section;
|
|
|
3357 |
};
|
|
|
3358 |
const render$1 = (table, grid) => {
|
|
|
3359 |
const newRows = [];
|
|
|
3360 |
const newCells = [];
|
|
|
3361 |
const syncRows = gridSection => map$1(gridSection, row => {
|
|
|
3362 |
if (row.isNew) {
|
|
|
3363 |
newRows.push(row.element);
|
|
|
3364 |
}
|
|
|
3365 |
const tr = row.element;
|
|
|
3366 |
empty(tr);
|
|
|
3367 |
each$2(row.cells, cell => {
|
|
|
3368 |
if (cell.isNew) {
|
|
|
3369 |
newCells.push(cell.element);
|
|
|
3370 |
}
|
|
|
3371 |
setIfNot(cell.element, 'colspan', cell.colspan, 1);
|
|
|
3372 |
setIfNot(cell.element, 'rowspan', cell.rowspan, 1);
|
|
|
3373 |
append$1(tr, cell.element);
|
|
|
3374 |
});
|
|
|
3375 |
return tr;
|
|
|
3376 |
});
|
|
|
3377 |
const syncColGroup = gridSection => bind$2(gridSection, colGroup => map$1(colGroup.cells, col => {
|
|
|
3378 |
setIfNot(col.element, 'span', col.colspan, 1);
|
|
|
3379 |
return col.element;
|
|
|
3380 |
}));
|
|
|
3381 |
const renderSection = (gridSection, sectionName) => {
|
|
|
3382 |
const section = generateSection(table, sectionName);
|
|
|
3383 |
const sync = sectionName === 'colgroup' ? syncColGroup : syncRows;
|
|
|
3384 |
const sectionElems = sync(gridSection);
|
|
|
3385 |
append(section, sectionElems);
|
|
|
3386 |
};
|
|
|
3387 |
const removeSection = sectionName => {
|
|
|
3388 |
child(table, sectionName).each(remove$6);
|
|
|
3389 |
};
|
|
|
3390 |
const renderOrRemoveSection = (gridSection, sectionName) => {
|
|
|
3391 |
if (gridSection.length > 0) {
|
|
|
3392 |
renderSection(gridSection, sectionName);
|
|
|
3393 |
} else {
|
|
|
3394 |
removeSection(sectionName);
|
|
|
3395 |
}
|
|
|
3396 |
};
|
|
|
3397 |
const headSection = [];
|
|
|
3398 |
const bodySection = [];
|
|
|
3399 |
const footSection = [];
|
|
|
3400 |
const columnGroupsSection = [];
|
|
|
3401 |
each$2(grid, row => {
|
|
|
3402 |
switch (row.section) {
|
|
|
3403 |
case 'thead':
|
|
|
3404 |
headSection.push(row);
|
|
|
3405 |
break;
|
|
|
3406 |
case 'tbody':
|
|
|
3407 |
bodySection.push(row);
|
|
|
3408 |
break;
|
|
|
3409 |
case 'tfoot':
|
|
|
3410 |
footSection.push(row);
|
|
|
3411 |
break;
|
|
|
3412 |
case 'colgroup':
|
|
|
3413 |
columnGroupsSection.push(row);
|
|
|
3414 |
break;
|
|
|
3415 |
}
|
|
|
3416 |
});
|
|
|
3417 |
renderOrRemoveSection(columnGroupsSection, 'colgroup');
|
|
|
3418 |
renderOrRemoveSection(headSection, 'thead');
|
|
|
3419 |
renderOrRemoveSection(bodySection, 'tbody');
|
|
|
3420 |
renderOrRemoveSection(footSection, 'tfoot');
|
|
|
3421 |
return {
|
|
|
3422 |
newRows,
|
|
|
3423 |
newCells
|
|
|
3424 |
};
|
|
|
3425 |
};
|
|
|
3426 |
const copy = grid => map$1(grid, row => {
|
|
|
3427 |
const tr = shallow(row.element);
|
|
|
3428 |
each$2(row.cells, cell => {
|
|
|
3429 |
const clonedCell = deep(cell.element);
|
|
|
3430 |
setIfNot(clonedCell, 'colspan', cell.colspan, 1);
|
|
|
3431 |
setIfNot(clonedCell, 'rowspan', cell.rowspan, 1);
|
|
|
3432 |
append$1(tr, clonedCell);
|
|
|
3433 |
});
|
|
|
3434 |
return tr;
|
|
|
3435 |
});
|
|
|
3436 |
|
|
|
3437 |
const getColumn = (grid, index) => {
|
|
|
3438 |
return map$1(grid, row => {
|
|
|
3439 |
return getCell(row, index);
|
|
|
3440 |
});
|
|
|
3441 |
};
|
|
|
3442 |
const getRow = (grid, index) => {
|
|
|
3443 |
return grid[index];
|
|
|
3444 |
};
|
|
|
3445 |
const findDiff = (xs, comp) => {
|
|
|
3446 |
if (xs.length === 0) {
|
|
|
3447 |
return 0;
|
|
|
3448 |
}
|
|
|
3449 |
const first = xs[0];
|
|
|
3450 |
const index = findIndex(xs, x => {
|
|
|
3451 |
return !comp(first.element, x.element);
|
|
|
3452 |
});
|
|
|
3453 |
return index.getOr(xs.length);
|
|
|
3454 |
};
|
|
|
3455 |
const subgrid = (grid, row, column, comparator) => {
|
|
|
3456 |
const gridRow = getRow(grid, row);
|
|
|
3457 |
const isColRow = gridRow.section === 'colgroup';
|
|
|
3458 |
const colspan = findDiff(gridRow.cells.slice(column), comparator);
|
|
|
3459 |
const rowspan = isColRow ? 1 : findDiff(getColumn(grid.slice(row), column), comparator);
|
|
|
3460 |
return {
|
|
|
3461 |
colspan,
|
|
|
3462 |
rowspan
|
|
|
3463 |
};
|
|
|
3464 |
};
|
|
|
3465 |
|
|
|
3466 |
const toDetails = (grid, comparator) => {
|
|
|
3467 |
const seen = map$1(grid, row => map$1(row.cells, never));
|
|
|
3468 |
const updateSeen = (rowIndex, columnIndex, rowspan, colspan) => {
|
|
|
3469 |
for (let row = rowIndex; row < rowIndex + rowspan; row++) {
|
|
|
3470 |
for (let column = columnIndex; column < columnIndex + colspan; column++) {
|
|
|
3471 |
seen[row][column] = true;
|
|
|
3472 |
}
|
|
|
3473 |
}
|
|
|
3474 |
};
|
|
|
3475 |
return map$1(grid, (row, rowIndex) => {
|
|
|
3476 |
const details = bind$2(row.cells, (cell, columnIndex) => {
|
|
|
3477 |
if (seen[rowIndex][columnIndex] === false) {
|
|
|
3478 |
const result = subgrid(grid, rowIndex, columnIndex, comparator);
|
|
|
3479 |
updateSeen(rowIndex, columnIndex, result.rowspan, result.colspan);
|
|
|
3480 |
return [detailnew(cell.element, result.rowspan, result.colspan, cell.isNew)];
|
|
|
3481 |
} else {
|
|
|
3482 |
return [];
|
|
|
3483 |
}
|
|
|
3484 |
});
|
|
|
3485 |
return rowdetailnew(row.element, details, row.section, row.isNew);
|
|
|
3486 |
});
|
|
|
3487 |
};
|
|
|
3488 |
const toGrid = (warehouse, generators, isNew) => {
|
|
|
3489 |
const grid = [];
|
|
|
3490 |
each$2(warehouse.colgroups, colgroup => {
|
|
|
3491 |
const colgroupCols = [];
|
|
|
3492 |
for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
|
|
|
3493 |
const element = Warehouse.getColumnAt(warehouse, columnIndex).map(column => elementnew(column.element, isNew, false)).getOrThunk(() => elementnew(generators.colGap(), true, false));
|
|
|
3494 |
colgroupCols.push(element);
|
|
|
3495 |
}
|
|
|
3496 |
grid.push(rowcells(colgroup.element, colgroupCols, 'colgroup', isNew));
|
|
|
3497 |
});
|
|
|
3498 |
for (let rowIndex = 0; rowIndex < warehouse.grid.rows; rowIndex++) {
|
|
|
3499 |
const rowCells = [];
|
|
|
3500 |
for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
|
|
|
3501 |
const element = Warehouse.getAt(warehouse, rowIndex, columnIndex).map(item => elementnew(item.element, isNew, item.isLocked)).getOrThunk(() => elementnew(generators.gap(), true, false));
|
|
|
3502 |
rowCells.push(element);
|
|
|
3503 |
}
|
|
|
3504 |
const rowDetail = warehouse.all[rowIndex];
|
|
|
3505 |
const row = rowcells(rowDetail.element, rowCells, rowDetail.section, isNew);
|
|
|
3506 |
grid.push(row);
|
|
|
3507 |
}
|
|
|
3508 |
return grid;
|
|
|
3509 |
};
|
|
|
3510 |
|
|
|
3511 |
const fromWarehouse = (warehouse, generators) => toGrid(warehouse, generators, false);
|
|
|
3512 |
const toDetailList = grid => toDetails(grid, eq$1);
|
|
|
3513 |
const findInWarehouse = (warehouse, element) => findMap(warehouse.all, r => find$1(r.cells, e => eq$1(element, e.element)));
|
|
|
3514 |
const extractCells = (warehouse, target, predicate) => {
|
|
|
3515 |
const details = map$1(target.selection, cell$1 => {
|
|
|
3516 |
return cell(cell$1).bind(lc => findInWarehouse(warehouse, lc)).filter(predicate);
|
|
|
3517 |
});
|
|
|
3518 |
const cells = cat(details);
|
|
|
3519 |
return someIf(cells.length > 0, cells);
|
|
|
3520 |
};
|
|
|
3521 |
const run = (operation, extract, adjustment, postAction, genWrappers) => (table, target, generators, behaviours) => {
|
|
|
3522 |
const warehouse = Warehouse.fromTable(table);
|
|
|
3523 |
const tableSection = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.section).getOrThunk(TableSection.fallback);
|
|
|
3524 |
const output = extract(warehouse, target).map(info => {
|
|
|
3525 |
const model = fromWarehouse(warehouse, generators);
|
|
|
3526 |
const result = operation(model, info, eq$1, genWrappers(generators), tableSection);
|
|
|
3527 |
const lockedColumns = getLockedColumnsFromGrid(result.grid);
|
|
|
3528 |
const grid = toDetailList(result.grid);
|
|
|
3529 |
return {
|
|
|
3530 |
info,
|
|
|
3531 |
grid,
|
|
|
3532 |
cursor: result.cursor,
|
|
|
3533 |
lockedColumns
|
|
|
3534 |
};
|
|
|
3535 |
});
|
|
|
3536 |
return output.bind(out => {
|
|
|
3537 |
const newElements = render$1(table, out.grid);
|
|
|
3538 |
const tableSizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.sizing).getOrThunk(() => TableSize.getTableSize(table));
|
|
|
3539 |
const resizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.resize).getOrThunk(preserveTable);
|
|
|
3540 |
adjustment(table, out.grid, out.info, {
|
|
|
3541 |
sizing: tableSizing,
|
|
|
3542 |
resize: resizing,
|
|
|
3543 |
section: tableSection
|
|
|
3544 |
});
|
|
|
3545 |
postAction(table);
|
|
|
3546 |
remove$7(table, LOCKED_COL_ATTR);
|
|
|
3547 |
if (out.lockedColumns.length > 0) {
|
|
|
3548 |
set$2(table, LOCKED_COL_ATTR, out.lockedColumns.join(','));
|
|
|
3549 |
}
|
|
|
3550 |
return Optional.some({
|
|
|
3551 |
cursor: out.cursor,
|
|
|
3552 |
newRows: newElements.newRows,
|
|
|
3553 |
newCells: newElements.newCells
|
|
|
3554 |
});
|
|
|
3555 |
});
|
|
|
3556 |
};
|
|
|
3557 |
const onPaste = (warehouse, target) => cell(target.element).bind(cell => findInWarehouse(warehouse, cell).map(details => {
|
|
|
3558 |
const value = {
|
|
|
3559 |
...details,
|
|
|
3560 |
generators: target.generators,
|
|
|
3561 |
clipboard: target.clipboard
|
|
|
3562 |
};
|
|
|
3563 |
return value;
|
|
|
3564 |
}));
|
|
|
3565 |
const onPasteByEditor = (warehouse, target) => extractCells(warehouse, target, always).map(cells => ({
|
|
|
3566 |
cells,
|
|
|
3567 |
generators: target.generators,
|
|
|
3568 |
clipboard: target.clipboard
|
|
|
3569 |
}));
|
|
|
3570 |
const onMergable = (_warehouse, target) => target.mergable;
|
|
|
3571 |
const onUnmergable = (_warehouse, target) => target.unmergable;
|
|
|
3572 |
const onCells = (warehouse, target) => extractCells(warehouse, target, always);
|
|
|
3573 |
const onUnlockedCells = (warehouse, target) => extractCells(warehouse, target, detail => !detail.isLocked);
|
|
|
3574 |
const isUnlockedTableCell = (warehouse, cell) => findInWarehouse(warehouse, cell).exists(detail => !detail.isLocked);
|
|
|
3575 |
const allUnlocked = (warehouse, cells) => forall(cells, cell => isUnlockedTableCell(warehouse, cell));
|
|
|
3576 |
const onUnlockedMergable = (warehouse, target) => onMergable(warehouse, target).filter(mergeable => allUnlocked(warehouse, mergeable.cells));
|
|
|
3577 |
const onUnlockedUnmergable = (warehouse, target) => onUnmergable(warehouse, target).filter(cells => allUnlocked(warehouse, cells));
|
|
|
3578 |
|
|
|
3579 |
const merge$2 = (grid, bounds, comparator, substitution) => {
|
|
|
3580 |
const rows = extractGridDetails(grid).rows;
|
|
|
3581 |
if (rows.length === 0) {
|
|
|
3582 |
return grid;
|
|
|
3583 |
}
|
|
|
3584 |
for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
|
|
|
3585 |
for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
|
|
|
3586 |
const row = rows[i];
|
|
|
3587 |
const isLocked = getCell(row, j).isLocked;
|
|
|
3588 |
mutateCell(row, j, elementnew(substitution(), false, isLocked));
|
|
|
3589 |
}
|
|
|
3590 |
}
|
|
|
3591 |
return grid;
|
|
|
3592 |
};
|
|
|
3593 |
const unmerge = (grid, target, comparator, substitution) => {
|
|
|
3594 |
const rows = extractGridDetails(grid).rows;
|
|
|
3595 |
let first = true;
|
|
|
3596 |
for (let i = 0; i < rows.length; i++) {
|
|
|
3597 |
for (let j = 0; j < cellLength(rows[0]); j++) {
|
|
|
3598 |
const row = rows[i];
|
|
|
3599 |
const currentCell = getCell(row, j);
|
|
|
3600 |
const currentCellElm = currentCell.element;
|
|
|
3601 |
const isToReplace = comparator(currentCellElm, target);
|
|
|
3602 |
if (isToReplace && !first) {
|
|
|
3603 |
mutateCell(row, j, elementnew(substitution(), true, currentCell.isLocked));
|
|
|
3604 |
} else if (isToReplace) {
|
|
|
3605 |
first = false;
|
|
|
3606 |
}
|
|
|
3607 |
}
|
|
|
3608 |
}
|
|
|
3609 |
return grid;
|
|
|
3610 |
};
|
|
|
3611 |
const uniqueCells = (row, comparator) => {
|
|
|
3612 |
return foldl(row, (rest, cell) => {
|
|
|
3613 |
return exists(rest, currentCell => {
|
|
|
3614 |
return comparator(currentCell.element, cell.element);
|
|
|
3615 |
}) ? rest : rest.concat([cell]);
|
|
|
3616 |
}, []);
|
|
|
3617 |
};
|
|
|
3618 |
const splitCols = (grid, index, comparator, substitution) => {
|
|
|
3619 |
if (index > 0 && index < grid[0].cells.length) {
|
|
|
3620 |
each$2(grid, row => {
|
|
|
3621 |
const prevCell = row.cells[index - 1];
|
|
|
3622 |
let offset = 0;
|
|
|
3623 |
const substitute = substitution();
|
|
|
3624 |
while (row.cells.length > index + offset && comparator(prevCell.element, row.cells[index + offset].element)) {
|
|
|
3625 |
mutateCell(row, index + offset, elementnew(substitute, true, row.cells[index + offset].isLocked));
|
|
|
3626 |
offset++;
|
|
|
3627 |
}
|
|
|
3628 |
});
|
|
|
3629 |
}
|
|
|
3630 |
return grid;
|
|
|
3631 |
};
|
|
|
3632 |
const splitRows = (grid, index, comparator, substitution) => {
|
|
|
3633 |
const rows = extractGridDetails(grid).rows;
|
|
|
3634 |
if (index > 0 && index < rows.length) {
|
|
|
3635 |
const rowPrevCells = rows[index - 1].cells;
|
|
|
3636 |
const cells = uniqueCells(rowPrevCells, comparator);
|
|
|
3637 |
each$2(cells, cell => {
|
|
|
3638 |
let replacement = Optional.none();
|
|
|
3639 |
for (let i = index; i < rows.length; i++) {
|
|
|
3640 |
for (let j = 0; j < cellLength(rows[0]); j++) {
|
|
|
3641 |
const row = rows[i];
|
|
|
3642 |
const current = getCell(row, j);
|
|
|
3643 |
const isToReplace = comparator(current.element, cell.element);
|
|
|
3644 |
if (isToReplace) {
|
|
|
3645 |
if (replacement.isNone()) {
|
|
|
3646 |
replacement = Optional.some(substitution());
|
|
|
3647 |
}
|
|
|
3648 |
replacement.each(sub => {
|
|
|
3649 |
mutateCell(row, j, elementnew(sub, true, current.isLocked));
|
|
|
3650 |
});
|
|
|
3651 |
}
|
|
|
3652 |
}
|
|
|
3653 |
}
|
|
|
3654 |
});
|
|
|
3655 |
}
|
|
|
3656 |
return grid;
|
|
|
3657 |
};
|
|
|
3658 |
|
|
|
3659 |
const value$1 = value => {
|
|
|
3660 |
const applyHelper = fn => fn(value);
|
|
|
3661 |
const constHelper = constant(value);
|
|
|
3662 |
const outputHelper = () => output;
|
|
|
3663 |
const output = {
|
|
|
3664 |
tag: true,
|
|
|
3665 |
inner: value,
|
|
|
3666 |
fold: (_onError, onValue) => onValue(value),
|
|
|
3667 |
isValue: always,
|
|
|
3668 |
isError: never,
|
|
|
3669 |
map: mapper => Result.value(mapper(value)),
|
|
|
3670 |
mapError: outputHelper,
|
|
|
3671 |
bind: applyHelper,
|
|
|
3672 |
exists: applyHelper,
|
|
|
3673 |
forall: applyHelper,
|
|
|
3674 |
getOr: constHelper,
|
|
|
3675 |
or: outputHelper,
|
|
|
3676 |
getOrThunk: constHelper,
|
|
|
3677 |
orThunk: outputHelper,
|
|
|
3678 |
getOrDie: constHelper,
|
|
|
3679 |
each: fn => {
|
|
|
3680 |
fn(value);
|
|
|
3681 |
},
|
|
|
3682 |
toOptional: () => Optional.some(value)
|
|
|
3683 |
};
|
|
|
3684 |
return output;
|
|
|
3685 |
};
|
|
|
3686 |
const error = error => {
|
|
|
3687 |
const outputHelper = () => output;
|
|
|
3688 |
const output = {
|
|
|
3689 |
tag: false,
|
|
|
3690 |
inner: error,
|
|
|
3691 |
fold: (onError, _onValue) => onError(error),
|
|
|
3692 |
isValue: never,
|
|
|
3693 |
isError: always,
|
|
|
3694 |
map: outputHelper,
|
|
|
3695 |
mapError: mapper => Result.error(mapper(error)),
|
|
|
3696 |
bind: outputHelper,
|
|
|
3697 |
exists: never,
|
|
|
3698 |
forall: always,
|
|
|
3699 |
getOr: identity,
|
|
|
3700 |
or: identity,
|
|
|
3701 |
getOrThunk: apply,
|
|
|
3702 |
orThunk: apply,
|
|
|
3703 |
getOrDie: die(String(error)),
|
|
|
3704 |
each: noop,
|
|
|
3705 |
toOptional: Optional.none
|
|
|
3706 |
};
|
|
|
3707 |
return output;
|
|
|
3708 |
};
|
|
|
3709 |
const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
|
|
|
3710 |
const Result = {
|
|
|
3711 |
value: value$1,
|
|
|
3712 |
error,
|
|
|
3713 |
fromOption
|
|
|
3714 |
};
|
|
|
3715 |
|
|
|
3716 |
const measure = (startAddress, gridA, gridB) => {
|
|
|
3717 |
if (startAddress.row >= gridA.length || startAddress.column > cellLength(gridA[0])) {
|
|
|
3718 |
return Result.error('invalid start address out of table bounds, row: ' + startAddress.row + ', column: ' + startAddress.column);
|
|
|
3719 |
}
|
|
|
3720 |
const rowRemainder = gridA.slice(startAddress.row);
|
|
|
3721 |
const colRemainder = rowRemainder[0].cells.slice(startAddress.column);
|
|
|
3722 |
const colRequired = cellLength(gridB[0]);
|
|
|
3723 |
const rowRequired = gridB.length;
|
|
|
3724 |
return Result.value({
|
|
|
3725 |
rowDelta: rowRemainder.length - rowRequired,
|
|
|
3726 |
colDelta: colRemainder.length - colRequired
|
|
|
3727 |
});
|
|
|
3728 |
};
|
|
|
3729 |
const measureWidth = (gridA, gridB) => {
|
|
|
3730 |
const colLengthA = cellLength(gridA[0]);
|
|
|
3731 |
const colLengthB = cellLength(gridB[0]);
|
|
|
3732 |
return {
|
|
|
3733 |
rowDelta: 0,
|
|
|
3734 |
colDelta: colLengthA - colLengthB
|
|
|
3735 |
};
|
|
|
3736 |
};
|
|
|
3737 |
const measureHeight = (gridA, gridB) => {
|
|
|
3738 |
const rowLengthA = gridA.length;
|
|
|
3739 |
const rowLengthB = gridB.length;
|
|
|
3740 |
return {
|
|
|
3741 |
rowDelta: rowLengthA - rowLengthB,
|
|
|
3742 |
colDelta: 0
|
|
|
3743 |
};
|
|
|
3744 |
};
|
|
|
3745 |
const generateElements = (amount, row, generators, isLocked) => {
|
|
|
3746 |
const generator = row.section === 'colgroup' ? generators.col : generators.cell;
|
|
|
3747 |
return range$1(amount, idx => elementnew(generator(), true, isLocked(idx)));
|
|
|
3748 |
};
|
|
|
3749 |
const rowFill = (grid, amount, generators, lockedColumns) => {
|
|
|
3750 |
const exampleRow = grid[grid.length - 1];
|
|
|
3751 |
return grid.concat(range$1(amount, () => {
|
|
|
3752 |
const generator = exampleRow.section === 'colgroup' ? generators.colgroup : generators.row;
|
|
|
3753 |
const row = clone(exampleRow, generator, identity);
|
|
|
3754 |
const elements = generateElements(row.cells.length, row, generators, idx => has$1(lockedColumns, idx.toString()));
|
|
|
3755 |
return setCells(row, elements);
|
|
|
3756 |
}));
|
|
|
3757 |
};
|
|
|
3758 |
const colFill = (grid, amount, generators, startIndex) => map$1(grid, row => {
|
|
|
3759 |
const newChildren = generateElements(amount, row, generators, never);
|
|
|
3760 |
return addCells(row, startIndex, newChildren);
|
|
|
3761 |
});
|
|
|
3762 |
const lockedColFill = (grid, generators, lockedColumns) => map$1(grid, row => {
|
|
|
3763 |
return foldl(lockedColumns, (acc, colNum) => {
|
|
|
3764 |
const newChild = generateElements(1, row, generators, always)[0];
|
|
|
3765 |
return addCell(acc, colNum, newChild);
|
|
|
3766 |
}, row);
|
|
|
3767 |
});
|
|
|
3768 |
const tailor = (gridA, delta, generators) => {
|
|
|
3769 |
const fillCols = delta.colDelta < 0 ? colFill : identity;
|
|
|
3770 |
const fillRows = delta.rowDelta < 0 ? rowFill : identity;
|
|
|
3771 |
const lockedColumns = getLockedColumnsFromGrid(gridA);
|
|
|
3772 |
const gridWidth = cellLength(gridA[0]);
|
|
|
3773 |
const isLastColLocked = exists(lockedColumns, locked => locked === gridWidth - 1);
|
|
|
3774 |
const modifiedCols = fillCols(gridA, Math.abs(delta.colDelta), generators, isLastColLocked ? gridWidth - 1 : gridWidth);
|
|
|
3775 |
const newLockedColumns = getLockedColumnsFromGrid(modifiedCols);
|
|
|
3776 |
return fillRows(modifiedCols, Math.abs(delta.rowDelta), generators, mapToObject(newLockedColumns, always));
|
|
|
3777 |
};
|
|
|
3778 |
|
|
|
3779 |
const isSpanning = (grid, row, col, comparator) => {
|
|
|
3780 |
const candidate = getCell(grid[row], col);
|
|
|
3781 |
const matching = curry(comparator, candidate.element);
|
|
|
3782 |
const currentRow = grid[row];
|
|
|
3783 |
return grid.length > 1 && cellLength(currentRow) > 1 && (col > 0 && matching(getCellElement(currentRow, col - 1)) || col < currentRow.cells.length - 1 && matching(getCellElement(currentRow, col + 1)) || row > 0 && matching(getCellElement(grid[row - 1], col)) || row < grid.length - 1 && matching(getCellElement(grid[row + 1], col)));
|
|
|
3784 |
};
|
|
|
3785 |
const mergeTables = (startAddress, gridA, gridBRows, generator, comparator, lockedColumns) => {
|
|
|
3786 |
const startRow = startAddress.row;
|
|
|
3787 |
const startCol = startAddress.column;
|
|
|
3788 |
const mergeHeight = gridBRows.length;
|
|
|
3789 |
const mergeWidth = cellLength(gridBRows[0]);
|
|
|
3790 |
const endRow = startRow + mergeHeight;
|
|
|
3791 |
const endCol = startCol + mergeWidth + lockedColumns.length;
|
|
|
3792 |
const lockedColumnObj = mapToObject(lockedColumns, always);
|
|
|
3793 |
for (let r = startRow; r < endRow; r++) {
|
|
|
3794 |
let skippedCol = 0;
|
|
|
3795 |
for (let c = startCol; c < endCol; c++) {
|
|
|
3796 |
if (lockedColumnObj[c]) {
|
|
|
3797 |
skippedCol++;
|
|
|
3798 |
continue;
|
|
|
3799 |
}
|
|
|
3800 |
if (isSpanning(gridA, r, c, comparator)) {
|
|
|
3801 |
unmerge(gridA, getCellElement(gridA[r], c), comparator, generator.cell);
|
|
|
3802 |
}
|
|
|
3803 |
const gridBColIndex = c - startCol - skippedCol;
|
|
|
3804 |
const newCell = getCell(gridBRows[r - startRow], gridBColIndex);
|
|
|
3805 |
const newCellElm = newCell.element;
|
|
|
3806 |
const replacement = generator.replace(newCellElm);
|
|
|
3807 |
mutateCell(gridA[r], c, elementnew(replacement, true, newCell.isLocked));
|
|
|
3808 |
}
|
|
|
3809 |
}
|
|
|
3810 |
return gridA;
|
|
|
3811 |
};
|
|
|
3812 |
const getValidStartAddress = (currentStartAddress, grid, lockedColumns) => {
|
|
|
3813 |
const gridColLength = cellLength(grid[0]);
|
|
|
3814 |
const adjustedRowAddress = extractGridDetails(grid).cols.length + currentStartAddress.row;
|
|
|
3815 |
const possibleColAddresses = range$1(gridColLength - currentStartAddress.column, num => num + currentStartAddress.column);
|
|
|
3816 |
const validColAddress = find$1(possibleColAddresses, num => forall(lockedColumns, col => col !== num)).getOr(gridColLength - 1);
|
|
|
3817 |
return {
|
|
|
3818 |
row: adjustedRowAddress,
|
|
|
3819 |
column: validColAddress
|
|
|
3820 |
};
|
|
|
3821 |
};
|
|
|
3822 |
const getLockedColumnsWithinBounds = (startAddress, rows, lockedColumns) => filter$2(lockedColumns, colNum => colNum >= startAddress.column && colNum <= cellLength(rows[0]) + startAddress.column);
|
|
|
3823 |
const merge$1 = (startAddress, gridA, gridB, generator, comparator) => {
|
|
|
3824 |
const lockedColumns = getLockedColumnsFromGrid(gridA);
|
|
|
3825 |
const validStartAddress = getValidStartAddress(startAddress, gridA, lockedColumns);
|
|
|
3826 |
const gridBRows = extractGridDetails(gridB).rows;
|
|
|
3827 |
const lockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, lockedColumns);
|
|
|
3828 |
const result = measure(validStartAddress, gridA, gridBRows);
|
|
|
3829 |
return result.map(diff => {
|
|
|
3830 |
const delta = {
|
|
|
3831 |
...diff,
|
|
|
3832 |
colDelta: diff.colDelta - lockedColumnsWithinBounds.length
|
|
|
3833 |
};
|
|
|
3834 |
const fittedGrid = tailor(gridA, delta, generator);
|
|
|
3835 |
const newLockedColumns = getLockedColumnsFromGrid(fittedGrid);
|
|
|
3836 |
const newLockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, newLockedColumns);
|
|
|
3837 |
return mergeTables(validStartAddress, fittedGrid, gridBRows, generator, comparator, newLockedColumnsWithinBounds);
|
|
|
3838 |
});
|
|
|
3839 |
};
|
|
|
3840 |
const insertCols = (index, gridA, gridB, generator, comparator) => {
|
|
|
3841 |
splitCols(gridA, index, comparator, generator.cell);
|
|
|
3842 |
const delta = measureHeight(gridB, gridA);
|
|
|
3843 |
const fittedNewGrid = tailor(gridB, delta, generator);
|
|
|
3844 |
const secondDelta = measureHeight(gridA, fittedNewGrid);
|
|
|
3845 |
const fittedOldGrid = tailor(gridA, secondDelta, generator);
|
|
|
3846 |
return map$1(fittedOldGrid, (gridRow, i) => {
|
|
|
3847 |
return addCells(gridRow, index, fittedNewGrid[i].cells);
|
|
|
3848 |
});
|
|
|
3849 |
};
|
|
|
3850 |
const insertRows = (index, gridA, gridB, generator, comparator) => {
|
|
|
3851 |
splitRows(gridA, index, comparator, generator.cell);
|
|
|
3852 |
const locked = getLockedColumnsFromGrid(gridA);
|
|
|
3853 |
const diff = measureWidth(gridA, gridB);
|
|
|
3854 |
const delta = {
|
|
|
3855 |
...diff,
|
|
|
3856 |
colDelta: diff.colDelta - locked.length
|
|
|
3857 |
};
|
|
|
3858 |
const fittedOldGrid = tailor(gridA, delta, generator);
|
|
|
3859 |
const {
|
|
|
3860 |
cols: oldCols,
|
|
|
3861 |
rows: oldRows
|
|
|
3862 |
} = extractGridDetails(fittedOldGrid);
|
|
|
3863 |
const newLocked = getLockedColumnsFromGrid(fittedOldGrid);
|
|
|
3864 |
const secondDiff = measureWidth(gridB, gridA);
|
|
|
3865 |
const secondDelta = {
|
|
|
3866 |
...secondDiff,
|
|
|
3867 |
colDelta: secondDiff.colDelta + newLocked.length
|
|
|
3868 |
};
|
|
|
3869 |
const fittedGridB = lockedColFill(gridB, generator, newLocked);
|
|
|
3870 |
const fittedNewGrid = tailor(fittedGridB, secondDelta, generator);
|
|
|
3871 |
return [
|
|
|
3872 |
...oldCols,
|
|
|
3873 |
...oldRows.slice(0, index),
|
|
|
3874 |
...fittedNewGrid,
|
|
|
3875 |
...oldRows.slice(index, oldRows.length)
|
|
|
3876 |
];
|
|
|
3877 |
};
|
|
|
3878 |
|
|
|
3879 |
const cloneRow = (row, cloneCell, comparator, substitution) => clone(row, elem => substitution(elem, comparator), cloneCell);
|
|
|
3880 |
const insertRowAt = (grid, index, example, comparator, substitution) => {
|
|
|
3881 |
const {rows, cols} = extractGridDetails(grid);
|
|
|
3882 |
const before = rows.slice(0, index);
|
|
|
3883 |
const after = rows.slice(index);
|
|
|
3884 |
const newRow = cloneRow(rows[example], (ex, c) => {
|
|
|
3885 |
const withinSpan = index > 0 && index < rows.length && comparator(getCellElement(rows[index - 1], c), getCellElement(rows[index], c));
|
|
|
3886 |
const ret = withinSpan ? getCell(rows[index], c) : elementnew(substitution(ex.element, comparator), true, ex.isLocked);
|
|
|
3887 |
return ret;
|
|
|
3888 |
}, comparator, substitution);
|
|
|
3889 |
return [
|
|
|
3890 |
...cols,
|
|
|
3891 |
...before,
|
|
|
3892 |
newRow,
|
|
|
3893 |
...after
|
|
|
3894 |
];
|
|
|
3895 |
};
|
|
|
3896 |
const getElementFor = (row, column, section, withinSpan, example, comparator, substitution) => {
|
|
|
3897 |
if (section === 'colgroup' || !withinSpan) {
|
|
|
3898 |
const cell = getCell(row, example);
|
|
|
3899 |
return elementnew(substitution(cell.element, comparator), true, false);
|
|
|
3900 |
} else {
|
|
|
3901 |
return getCell(row, column);
|
|
|
3902 |
}
|
|
|
3903 |
};
|
|
|
3904 |
const insertColumnAt = (grid, index, example, comparator, substitution) => map$1(grid, row => {
|
|
|
3905 |
const withinSpan = index > 0 && index < cellLength(row) && comparator(getCellElement(row, index - 1), getCellElement(row, index));
|
|
|
3906 |
const sub = getElementFor(row, index, row.section, withinSpan, example, comparator, substitution);
|
|
|
3907 |
return addCell(row, index, sub);
|
|
|
3908 |
});
|
|
|
3909 |
const deleteColumnsAt = (grid, columns) => bind$2(grid, row => {
|
|
|
3910 |
const existingCells = row.cells;
|
|
|
3911 |
const cells = foldr(columns, (acc, column) => column >= 0 && column < acc.length ? acc.slice(0, column).concat(acc.slice(column + 1)) : acc, existingCells);
|
|
|
3912 |
return cells.length > 0 ? [rowcells(row.element, cells, row.section, row.isNew)] : [];
|
|
|
3913 |
});
|
|
|
3914 |
const deleteRowsAt = (grid, start, finish) => {
|
|
|
3915 |
const {rows, cols} = extractGridDetails(grid);
|
|
|
3916 |
return [
|
|
|
3917 |
...cols,
|
|
|
3918 |
...rows.slice(0, start),
|
|
|
3919 |
...rows.slice(finish + 1)
|
|
|
3920 |
];
|
|
|
3921 |
};
|
|
|
3922 |
|
|
|
3923 |
const notInStartRow = (grid, rowIndex, colIndex, comparator) => getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(getCellElement(grid[rowIndex - 1], colIndex), getCellElement(grid[rowIndex], colIndex)));
|
|
|
3924 |
const notInStartColumn = (row, index, comparator) => index > 0 && comparator(getCellElement(row, index - 1), getCellElement(row, index));
|
|
|
3925 |
const isDuplicatedCell = (grid, rowIndex, colIndex, comparator) => notInStartRow(grid, rowIndex, colIndex, comparator) || notInStartColumn(grid[rowIndex], colIndex, comparator);
|
|
|
3926 |
const rowReplacerPredicate = (targetRow, columnHeaders) => {
|
|
|
3927 |
const entireTableIsHeader = forall(columnHeaders, identity) && isHeaderCells(targetRow.cells);
|
|
|
3928 |
return entireTableIsHeader ? always : (cell, _rowIndex, colIndex) => {
|
|
|
3929 |
const type = name(cell.element);
|
|
|
3930 |
return !(type === 'th' && columnHeaders[colIndex]);
|
|
|
3931 |
};
|
|
|
3932 |
};
|
|
|
3933 |
const columnReplacePredicate = (targetColumn, rowHeaders) => {
|
|
|
3934 |
const entireTableIsHeader = forall(rowHeaders, identity) && isHeaderCells(targetColumn);
|
|
|
3935 |
return entireTableIsHeader ? always : (cell, rowIndex, _colIndex) => {
|
|
|
3936 |
const type = name(cell.element);
|
|
|
3937 |
return !(type === 'th' && rowHeaders[rowIndex]);
|
|
|
3938 |
};
|
|
|
3939 |
};
|
|
|
3940 |
const determineScope = (applyScope, cell, newScope, isInHeader) => {
|
|
|
3941 |
const hasSpan = scope => scope === 'row' ? hasRowspan(cell) : hasColspan(cell);
|
|
|
3942 |
const getScope = scope => hasSpan(scope) ? `${ scope }group` : scope;
|
|
|
3943 |
if (applyScope) {
|
|
|
3944 |
return isHeaderCell(cell) ? getScope(newScope) : null;
|
|
|
3945 |
} else if (isInHeader && isHeaderCell(cell)) {
|
|
|
3946 |
const oppositeScope = newScope === 'row' ? 'col' : 'row';
|
|
|
3947 |
return getScope(oppositeScope);
|
|
|
3948 |
} else {
|
|
|
3949 |
return null;
|
|
|
3950 |
}
|
|
|
3951 |
};
|
|
|
3952 |
const rowScopeGenerator = (applyScope, columnHeaders) => (cell, rowIndex, columnIndex) => Optional.some(determineScope(applyScope, cell.element, 'col', columnHeaders[columnIndex]));
|
|
|
3953 |
const columnScopeGenerator = (applyScope, rowHeaders) => (cell, rowIndex) => Optional.some(determineScope(applyScope, cell.element, 'row', rowHeaders[rowIndex]));
|
|
|
3954 |
const replace = (cell, comparator, substitute) => elementnew(substitute(cell.element, comparator), true, cell.isLocked);
|
|
|
3955 |
const replaceIn = (grid, targets, comparator, substitute, replacer, genScope, shouldReplace) => {
|
|
|
3956 |
const isTarget = cell => {
|
|
|
3957 |
return exists(targets, target => {
|
|
|
3958 |
return comparator(cell.element, target.element);
|
|
|
3959 |
});
|
|
|
3960 |
};
|
|
|
3961 |
return map$1(grid, (row, rowIndex) => {
|
|
|
3962 |
return mapCells(row, (cell, colIndex) => {
|
|
|
3963 |
if (isTarget(cell)) {
|
|
|
3964 |
const newCell = shouldReplace(cell, rowIndex, colIndex) ? replacer(cell, comparator, substitute) : cell;
|
|
|
3965 |
genScope(newCell, rowIndex, colIndex).each(scope => {
|
|
|
3966 |
setOptions(newCell.element, { scope: Optional.from(scope) });
|
|
|
3967 |
});
|
|
|
3968 |
return newCell;
|
|
|
3969 |
} else {
|
|
|
3970 |
return cell;
|
|
|
3971 |
}
|
|
|
3972 |
});
|
|
|
3973 |
});
|
|
|
3974 |
};
|
|
|
3975 |
const getColumnCells = (rows, columnIndex, comparator) => bind$2(rows, (row, i) => {
|
|
|
3976 |
return isDuplicatedCell(rows, i, columnIndex, comparator) ? [] : [getCell(row, columnIndex)];
|
|
|
3977 |
});
|
|
|
3978 |
const getRowCells = (rows, rowIndex, comparator) => {
|
|
|
3979 |
const targetRow = rows[rowIndex];
|
|
|
3980 |
return bind$2(targetRow.cells, (item, i) => {
|
|
|
3981 |
return isDuplicatedCell(rows, rowIndex, i, comparator) ? [] : [item];
|
|
|
3982 |
});
|
|
|
3983 |
};
|
|
|
3984 |
const replaceColumns = (grid, indexes, applyScope, comparator, substitution) => {
|
|
|
3985 |
const rows = extractGridDetails(grid).rows;
|
|
|
3986 |
const targets = bind$2(indexes, index => getColumnCells(rows, index, comparator));
|
|
|
3987 |
const rowHeaders = map$1(rows, row => isHeaderCells(row.cells));
|
|
|
3988 |
const shouldReplaceCell = columnReplacePredicate(targets, rowHeaders);
|
|
|
3989 |
const scopeGenerator = columnScopeGenerator(applyScope, rowHeaders);
|
|
|
3990 |
return replaceIn(grid, targets, comparator, substitution, replace, scopeGenerator, shouldReplaceCell);
|
|
|
3991 |
};
|
|
|
3992 |
const replaceRows = (grid, indexes, section, applyScope, comparator, substitution, tableSection) => {
|
|
|
3993 |
const {cols, rows} = extractGridDetails(grid);
|
|
|
3994 |
const targetRow = rows[indexes[0]];
|
|
|
3995 |
const targets = bind$2(indexes, index => getRowCells(rows, index, comparator));
|
|
|
3996 |
const columnHeaders = map$1(targetRow.cells, (_cell, index) => isHeaderCells(getColumnCells(rows, index, comparator)));
|
|
|
3997 |
const newRows = [...rows];
|
|
|
3998 |
each$2(indexes, index => {
|
|
|
3999 |
newRows[index] = tableSection.transformRow(rows[index], section);
|
|
|
4000 |
});
|
|
|
4001 |
const newGrid = [
|
|
|
4002 |
...cols,
|
|
|
4003 |
...newRows
|
|
|
4004 |
];
|
|
|
4005 |
const shouldReplaceCell = rowReplacerPredicate(targetRow, columnHeaders);
|
|
|
4006 |
const scopeGenerator = rowScopeGenerator(applyScope, columnHeaders);
|
|
|
4007 |
return replaceIn(newGrid, targets, comparator, substitution, tableSection.transformCell, scopeGenerator, shouldReplaceCell);
|
|
|
4008 |
};
|
|
|
4009 |
const replaceCells = (grid, details, comparator, substitution) => {
|
|
|
4010 |
const rows = extractGridDetails(grid).rows;
|
|
|
4011 |
const targetCells = map$1(details, detail => getCell(rows[detail.row], detail.column));
|
|
|
4012 |
return replaceIn(grid, targetCells, comparator, substitution, replace, Optional.none, always);
|
|
|
4013 |
};
|
|
|
4014 |
|
|
|
4015 |
const generate = cases => {
|
|
|
4016 |
if (!isArray(cases)) {
|
|
|
4017 |
throw new Error('cases must be an array');
|
|
|
4018 |
}
|
|
|
4019 |
if (cases.length === 0) {
|
|
|
4020 |
throw new Error('there must be at least one case');
|
|
|
4021 |
}
|
|
|
4022 |
const constructors = [];
|
|
|
4023 |
const adt = {};
|
|
|
4024 |
each$2(cases, (acase, count) => {
|
|
|
4025 |
const keys$1 = keys(acase);
|
|
|
4026 |
if (keys$1.length !== 1) {
|
|
|
4027 |
throw new Error('one and only one name per case');
|
|
|
4028 |
}
|
|
|
4029 |
const key = keys$1[0];
|
|
|
4030 |
const value = acase[key];
|
|
|
4031 |
if (adt[key] !== undefined) {
|
|
|
4032 |
throw new Error('duplicate key detected:' + key);
|
|
|
4033 |
} else if (key === 'cata') {
|
|
|
4034 |
throw new Error('cannot have a case named cata (sorry)');
|
|
|
4035 |
} else if (!isArray(value)) {
|
|
|
4036 |
throw new Error('case arguments must be an array');
|
|
|
4037 |
}
|
|
|
4038 |
constructors.push(key);
|
|
|
4039 |
adt[key] = (...args) => {
|
|
|
4040 |
const argLength = args.length;
|
|
|
4041 |
if (argLength !== value.length) {
|
|
|
4042 |
throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
|
|
|
4043 |
}
|
|
|
4044 |
const match = branches => {
|
|
|
4045 |
const branchKeys = keys(branches);
|
|
|
4046 |
if (constructors.length !== branchKeys.length) {
|
|
|
4047 |
throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
|
|
|
4048 |
}
|
|
|
4049 |
const allReqd = forall(constructors, reqKey => {
|
|
|
4050 |
return contains$2(branchKeys, reqKey);
|
|
|
4051 |
});
|
|
|
4052 |
if (!allReqd) {
|
|
|
4053 |
throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
|
|
|
4054 |
}
|
|
|
4055 |
return branches[key].apply(null, args);
|
|
|
4056 |
};
|
|
|
4057 |
return {
|
|
|
4058 |
fold: (...foldArgs) => {
|
|
|
4059 |
if (foldArgs.length !== cases.length) {
|
|
|
4060 |
throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
|
|
|
4061 |
}
|
|
|
4062 |
const target = foldArgs[count];
|
|
|
4063 |
return target.apply(null, args);
|
|
|
4064 |
},
|
|
|
4065 |
match,
|
|
|
4066 |
log: label => {
|
|
|
4067 |
console.log(label, {
|
|
|
4068 |
constructors,
|
|
|
4069 |
constructor: key,
|
|
|
4070 |
params: args
|
|
|
4071 |
});
|
|
|
4072 |
}
|
|
|
4073 |
};
|
|
|
4074 |
};
|
|
|
4075 |
});
|
|
|
4076 |
return adt;
|
|
|
4077 |
};
|
|
|
4078 |
const Adt = { generate };
|
|
|
4079 |
|
|
|
4080 |
const adt$6 = Adt.generate([
|
|
|
4081 |
{ none: [] },
|
|
|
4082 |
{ only: ['index'] },
|
|
|
4083 |
{
|
|
|
4084 |
left: [
|
|
|
4085 |
'index',
|
|
|
4086 |
'next'
|
|
|
4087 |
]
|
|
|
4088 |
},
|
|
|
4089 |
{
|
|
|
4090 |
middle: [
|
|
|
4091 |
'prev',
|
|
|
4092 |
'index',
|
|
|
4093 |
'next'
|
|
|
4094 |
]
|
|
|
4095 |
},
|
|
|
4096 |
{
|
|
|
4097 |
right: [
|
|
|
4098 |
'prev',
|
|
|
4099 |
'index'
|
|
|
4100 |
]
|
|
|
4101 |
}
|
|
|
4102 |
]);
|
|
|
4103 |
const ColumnContext = { ...adt$6 };
|
|
|
4104 |
|
|
|
4105 |
const neighbours = (input, index) => {
|
|
|
4106 |
if (input.length === 0) {
|
|
|
4107 |
return ColumnContext.none();
|
|
|
4108 |
}
|
|
|
4109 |
if (input.length === 1) {
|
|
|
4110 |
return ColumnContext.only(0);
|
|
|
4111 |
}
|
|
|
4112 |
if (index === 0) {
|
|
|
4113 |
return ColumnContext.left(0, 1);
|
|
|
4114 |
}
|
|
|
4115 |
if (index === input.length - 1) {
|
|
|
4116 |
return ColumnContext.right(index - 1, index);
|
|
|
4117 |
}
|
|
|
4118 |
if (index > 0 && index < input.length - 1) {
|
|
|
4119 |
return ColumnContext.middle(index - 1, index, index + 1);
|
|
|
4120 |
}
|
|
|
4121 |
return ColumnContext.none();
|
|
|
4122 |
};
|
|
|
4123 |
const determine = (input, column, step, tableSize, resize) => {
|
|
|
4124 |
const result = input.slice(0);
|
|
|
4125 |
const context = neighbours(input, column);
|
|
|
4126 |
const onNone = constant(map$1(result, constant(0)));
|
|
|
4127 |
const onOnly = index => tableSize.singleColumnWidth(result[index], step);
|
|
|
4128 |
const onLeft = (index, next) => resize.calcLeftEdgeDeltas(result, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
|
|
|
4129 |
const onMiddle = (prev, index, next) => resize.calcMiddleDeltas(result, prev, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
|
|
|
4130 |
const onRight = (prev, index) => resize.calcRightEdgeDeltas(result, prev, index, step, tableSize.minCellWidth(), tableSize.isRelative);
|
|
|
4131 |
return context.fold(onNone, onOnly, onLeft, onMiddle, onRight);
|
|
|
4132 |
};
|
|
|
4133 |
|
|
|
4134 |
const total = (start, end, measures) => {
|
|
|
4135 |
let r = 0;
|
|
|
4136 |
for (let i = start; i < end; i++) {
|
|
|
4137 |
r += measures[i] !== undefined ? measures[i] : 0;
|
|
|
4138 |
}
|
|
|
4139 |
return r;
|
|
|
4140 |
};
|
|
|
4141 |
const recalculateWidthForCells = (warehouse, widths) => {
|
|
|
4142 |
const all = Warehouse.justCells(warehouse);
|
|
|
4143 |
return map$1(all, cell => {
|
|
|
4144 |
const width = total(cell.column, cell.column + cell.colspan, widths);
|
|
|
4145 |
return {
|
|
|
4146 |
element: cell.element,
|
|
|
4147 |
width,
|
|
|
4148 |
colspan: cell.colspan
|
|
|
4149 |
};
|
|
|
4150 |
});
|
|
|
4151 |
};
|
|
|
4152 |
const recalculateWidthForColumns = (warehouse, widths) => {
|
|
|
4153 |
const groups = Warehouse.justColumns(warehouse);
|
|
|
4154 |
return map$1(groups, (column, index) => ({
|
|
|
4155 |
element: column.element,
|
|
|
4156 |
width: widths[index],
|
|
|
4157 |
colspan: column.colspan
|
|
|
4158 |
}));
|
|
|
4159 |
};
|
|
|
4160 |
const recalculateHeightForCells = (warehouse, heights) => {
|
|
|
4161 |
const all = Warehouse.justCells(warehouse);
|
|
|
4162 |
return map$1(all, cell => {
|
|
|
4163 |
const height = total(cell.row, cell.row + cell.rowspan, heights);
|
|
|
4164 |
return {
|
|
|
4165 |
element: cell.element,
|
|
|
4166 |
height,
|
|
|
4167 |
rowspan: cell.rowspan
|
|
|
4168 |
};
|
|
|
4169 |
});
|
|
|
4170 |
};
|
|
|
4171 |
const matchRowHeight = (warehouse, heights) => {
|
|
|
4172 |
return map$1(warehouse.all, (row, i) => {
|
|
|
4173 |
return {
|
|
|
4174 |
element: row.element,
|
|
|
4175 |
height: heights[i]
|
|
|
4176 |
};
|
|
|
4177 |
});
|
|
|
4178 |
};
|
|
|
4179 |
|
|
|
4180 |
const sumUp = newSize => foldr(newSize, (b, a) => b + a, 0);
|
|
|
4181 |
const recalculate = (warehouse, widths) => {
|
|
|
4182 |
if (Warehouse.hasColumns(warehouse)) {
|
|
|
4183 |
return recalculateWidthForColumns(warehouse, widths);
|
|
|
4184 |
} else {
|
|
|
4185 |
return recalculateWidthForCells(warehouse, widths);
|
|
|
4186 |
}
|
|
|
4187 |
};
|
|
|
4188 |
const recalculateAndApply = (warehouse, widths, tableSize) => {
|
|
|
4189 |
const newSizes = recalculate(warehouse, widths);
|
|
|
4190 |
each$2(newSizes, cell => {
|
|
|
4191 |
tableSize.setElementWidth(cell.element, cell.width);
|
|
|
4192 |
});
|
|
|
4193 |
};
|
|
|
4194 |
const adjustWidth = (table, delta, index, resizing, tableSize) => {
|
|
|
4195 |
const warehouse = Warehouse.fromTable(table);
|
|
|
4196 |
const step = tableSize.getCellDelta(delta);
|
|
|
4197 |
const widths = tableSize.getWidths(warehouse, tableSize);
|
|
|
4198 |
const isLastColumn = index === warehouse.grid.columns - 1;
|
|
|
4199 |
const clampedStep = resizing.clampTableDelta(widths, index, step, tableSize.minCellWidth(), isLastColumn);
|
|
|
4200 |
const deltas = determine(widths, index, clampedStep, tableSize, resizing);
|
|
|
4201 |
const newWidths = map$1(deltas, (dx, i) => dx + widths[i]);
|
|
|
4202 |
recalculateAndApply(warehouse, newWidths, tableSize);
|
|
|
4203 |
resizing.resizeTable(tableSize.adjustTableWidth, clampedStep, isLastColumn);
|
|
|
4204 |
};
|
|
|
4205 |
const adjustHeight = (table, delta, index, direction) => {
|
|
|
4206 |
const warehouse = Warehouse.fromTable(table);
|
|
|
4207 |
const heights = getPixelHeights(warehouse, table, direction);
|
|
|
4208 |
const newHeights = map$1(heights, (dy, i) => index === i ? Math.max(delta + dy, minHeight()) : dy);
|
|
|
4209 |
const newCellSizes = recalculateHeightForCells(warehouse, newHeights);
|
|
|
4210 |
const newRowSizes = matchRowHeight(warehouse, newHeights);
|
|
|
4211 |
each$2(newRowSizes, row => {
|
|
|
4212 |
setHeight(row.element, row.height);
|
|
|
4213 |
});
|
|
|
4214 |
each$2(newCellSizes, cell => {
|
|
|
4215 |
setHeight(cell.element, cell.height);
|
|
|
4216 |
});
|
|
|
4217 |
const total = sumUp(newHeights);
|
|
|
4218 |
setHeight(table, total);
|
|
|
4219 |
};
|
|
|
4220 |
const adjustAndRedistributeWidths$1 = (_table, list, details, tableSize, resizeBehaviour) => {
|
|
|
4221 |
const warehouse = Warehouse.generate(list);
|
|
|
4222 |
const sizes = tableSize.getWidths(warehouse, tableSize);
|
|
|
4223 |
const tablePixelWidth = tableSize.pixelWidth();
|
|
|
4224 |
const {newSizes, delta} = resizeBehaviour.calcRedestributedWidths(sizes, tablePixelWidth, details.pixelDelta, tableSize.isRelative);
|
|
|
4225 |
recalculateAndApply(warehouse, newSizes, tableSize);
|
|
|
4226 |
tableSize.adjustTableWidth(delta);
|
|
|
4227 |
};
|
|
|
4228 |
const adjustWidthTo = (_table, list, _info, tableSize) => {
|
|
|
4229 |
const warehouse = Warehouse.generate(list);
|
|
|
4230 |
const widths = tableSize.getWidths(warehouse, tableSize);
|
|
|
4231 |
recalculateAndApply(warehouse, widths, tableSize);
|
|
|
4232 |
};
|
|
|
4233 |
|
|
|
4234 |
const uniqueColumns = details => {
|
|
|
4235 |
const uniqueCheck = (rest, detail) => {
|
|
|
4236 |
const columnExists = exists(rest, currentDetail => currentDetail.column === detail.column);
|
|
|
4237 |
return columnExists ? rest : rest.concat([detail]);
|
|
|
4238 |
};
|
|
|
4239 |
return foldl(details, uniqueCheck, []).sort((detailA, detailB) => detailA.column - detailB.column);
|
|
|
4240 |
};
|
|
|
4241 |
|
|
|
4242 |
const isCol = isTag('col');
|
|
|
4243 |
const isColgroup = isTag('colgroup');
|
|
|
4244 |
const isRow$1 = element => name(element) === 'tr' || isColgroup(element);
|
|
|
4245 |
const elementToData = element => {
|
|
|
4246 |
const colspan = getAttrValue(element, 'colspan', 1);
|
|
|
4247 |
const rowspan = getAttrValue(element, 'rowspan', 1);
|
|
|
4248 |
return {
|
|
|
4249 |
element,
|
|
|
4250 |
colspan,
|
|
|
4251 |
rowspan
|
|
|
4252 |
};
|
|
|
4253 |
};
|
|
|
4254 |
const modification = (generators, toData = elementToData) => {
|
|
|
4255 |
const nuCell = data => isCol(data.element) ? generators.col(data) : generators.cell(data);
|
|
|
4256 |
const nuRow = data => isColgroup(data.element) ? generators.colgroup(data) : generators.row(data);
|
|
|
4257 |
const add = element => {
|
|
|
4258 |
if (isRow$1(element)) {
|
|
|
4259 |
return nuRow({ element });
|
|
|
4260 |
} else {
|
|
|
4261 |
const cell = element;
|
|
|
4262 |
const replacement = nuCell(toData(cell));
|
|
|
4263 |
recent = Optional.some({
|
|
|
4264 |
item: cell,
|
|
|
4265 |
replacement
|
|
|
4266 |
});
|
|
|
4267 |
return replacement;
|
|
|
4268 |
}
|
|
|
4269 |
};
|
|
|
4270 |
let recent = Optional.none();
|
|
|
4271 |
const getOrInit = (element, comparator) => {
|
|
|
4272 |
return recent.fold(() => {
|
|
|
4273 |
return add(element);
|
|
|
4274 |
}, p => {
|
|
|
4275 |
return comparator(element, p.item) ? p.replacement : add(element);
|
|
|
4276 |
});
|
|
|
4277 |
};
|
|
|
4278 |
return { getOrInit };
|
|
|
4279 |
};
|
|
|
4280 |
const transform$1 = tag => {
|
|
|
4281 |
return generators => {
|
|
|
4282 |
const list = [];
|
|
|
4283 |
const find = (element, comparator) => {
|
|
|
4284 |
return find$1(list, x => {
|
|
|
4285 |
return comparator(x.item, element);
|
|
|
4286 |
});
|
|
|
4287 |
};
|
|
|
4288 |
const makeNew = element => {
|
|
|
4289 |
const attrs = tag === 'td' ? { scope: null } : {};
|
|
|
4290 |
const cell = generators.replace(element, tag, attrs);
|
|
|
4291 |
list.push({
|
|
|
4292 |
item: element,
|
|
|
4293 |
sub: cell
|
|
|
4294 |
});
|
|
|
4295 |
return cell;
|
|
|
4296 |
};
|
|
|
4297 |
const replaceOrInit = (element, comparator) => {
|
|
|
4298 |
if (isRow$1(element) || isCol(element)) {
|
|
|
4299 |
return element;
|
|
|
4300 |
} else {
|
|
|
4301 |
const cell = element;
|
|
|
4302 |
return find(cell, comparator).fold(() => {
|
|
|
4303 |
return makeNew(cell);
|
|
|
4304 |
}, p => {
|
|
|
4305 |
return comparator(element, p.item) ? p.sub : makeNew(cell);
|
|
|
4306 |
});
|
|
|
4307 |
}
|
|
|
4308 |
};
|
|
|
4309 |
return { replaceOrInit };
|
|
|
4310 |
};
|
|
|
4311 |
};
|
|
|
4312 |
const getScopeAttribute = cell => getOpt(cell, 'scope').map(attribute => attribute.substr(0, 3));
|
|
|
4313 |
const merging = generators => {
|
|
|
4314 |
const unmerge = cell => {
|
|
|
4315 |
const scope = getScopeAttribute(cell);
|
|
|
4316 |
scope.each(attribute => set$2(cell, 'scope', attribute));
|
|
|
4317 |
return () => {
|
|
|
4318 |
const raw = generators.cell({
|
|
|
4319 |
element: cell,
|
|
|
4320 |
colspan: 1,
|
|
|
4321 |
rowspan: 1
|
|
|
4322 |
});
|
|
|
4323 |
remove$5(raw, 'width');
|
|
|
4324 |
remove$5(cell, 'width');
|
|
|
4325 |
scope.each(attribute => set$2(raw, 'scope', attribute));
|
|
|
4326 |
return raw;
|
|
|
4327 |
};
|
|
|
4328 |
};
|
|
|
4329 |
const merge = cells => {
|
|
|
4330 |
const getScopeProperty = () => {
|
|
|
4331 |
const stringAttributes = cat(map$1(cells, getScopeAttribute));
|
|
|
4332 |
if (stringAttributes.length === 0) {
|
|
|
4333 |
return Optional.none();
|
|
|
4334 |
} else {
|
|
|
4335 |
const baseScope = stringAttributes[0];
|
|
|
4336 |
const scopes = [
|
|
|
4337 |
'row',
|
|
|
4338 |
'col'
|
|
|
4339 |
];
|
|
|
4340 |
const isMixed = exists(stringAttributes, attribute => {
|
|
|
4341 |
return attribute !== baseScope && contains$2(scopes, attribute);
|
|
|
4342 |
});
|
|
|
4343 |
return isMixed ? Optional.none() : Optional.from(baseScope);
|
|
|
4344 |
}
|
|
|
4345 |
};
|
|
|
4346 |
remove$5(cells[0], 'width');
|
|
|
4347 |
getScopeProperty().fold(() => remove$7(cells[0], 'scope'), attribute => set$2(cells[0], 'scope', attribute + 'group'));
|
|
|
4348 |
return constant(cells[0]);
|
|
|
4349 |
};
|
|
|
4350 |
return {
|
|
|
4351 |
unmerge,
|
|
|
4352 |
merge
|
|
|
4353 |
};
|
|
|
4354 |
};
|
|
|
4355 |
const Generators = {
|
|
|
4356 |
modification,
|
|
|
4357 |
transform: transform$1,
|
|
|
4358 |
merging
|
|
|
4359 |
};
|
|
|
4360 |
|
|
|
4361 |
const blockList = [
|
|
|
4362 |
'body',
|
|
|
4363 |
'p',
|
|
|
4364 |
'div',
|
|
|
4365 |
'article',
|
|
|
4366 |
'aside',
|
|
|
4367 |
'figcaption',
|
|
|
4368 |
'figure',
|
|
|
4369 |
'footer',
|
|
|
4370 |
'header',
|
|
|
4371 |
'nav',
|
|
|
4372 |
'section',
|
|
|
4373 |
'ol',
|
|
|
4374 |
'ul',
|
|
|
4375 |
'table',
|
|
|
4376 |
'thead',
|
|
|
4377 |
'tfoot',
|
|
|
4378 |
'tbody',
|
|
|
4379 |
'caption',
|
|
|
4380 |
'tr',
|
|
|
4381 |
'td',
|
|
|
4382 |
'th',
|
|
|
4383 |
'h1',
|
|
|
4384 |
'h2',
|
|
|
4385 |
'h3',
|
|
|
4386 |
'h4',
|
|
|
4387 |
'h5',
|
|
|
4388 |
'h6',
|
|
|
4389 |
'blockquote',
|
|
|
4390 |
'pre',
|
|
|
4391 |
'address'
|
|
|
4392 |
];
|
|
|
4393 |
const isList$1 = (universe, item) => {
|
|
|
4394 |
const tagName = universe.property().name(item);
|
|
|
4395 |
return contains$2([
|
|
|
4396 |
'ol',
|
|
|
4397 |
'ul'
|
|
|
4398 |
], tagName);
|
|
|
4399 |
};
|
|
|
4400 |
const isBlock$1 = (universe, item) => {
|
|
|
4401 |
const tagName = universe.property().name(item);
|
|
|
4402 |
return contains$2(blockList, tagName);
|
|
|
4403 |
};
|
|
|
4404 |
const isEmptyTag$1 = (universe, item) => {
|
|
|
4405 |
return contains$2([
|
|
|
4406 |
'br',
|
|
|
4407 |
'img',
|
|
|
4408 |
'hr',
|
|
|
4409 |
'input'
|
|
|
4410 |
], universe.property().name(item));
|
|
|
4411 |
};
|
|
|
4412 |
|
|
|
4413 |
const universe$1 = DomUniverse();
|
|
|
4414 |
const isBlock = element => {
|
|
|
4415 |
return isBlock$1(universe$1, element);
|
|
|
4416 |
};
|
|
|
4417 |
const isList = element => {
|
|
|
4418 |
return isList$1(universe$1, element);
|
|
|
4419 |
};
|
|
|
4420 |
const isEmptyTag = element => {
|
|
|
4421 |
return isEmptyTag$1(universe$1, element);
|
|
|
4422 |
};
|
|
|
4423 |
|
|
|
4424 |
const merge = cells => {
|
|
|
4425 |
const isBr = isTag('br');
|
|
|
4426 |
const advancedBr = children => {
|
|
|
4427 |
return forall(children, c => {
|
|
|
4428 |
return isBr(c) || isText(c) && get$6(c).trim().length === 0;
|
|
|
4429 |
});
|
|
|
4430 |
};
|
|
|
4431 |
const isListItem = el => {
|
|
|
4432 |
return name(el) === 'li' || ancestor$2(el, isList).isSome();
|
|
|
4433 |
};
|
|
|
4434 |
const siblingIsBlock = el => {
|
|
|
4435 |
return nextSibling(el).map(rightSibling => {
|
|
|
4436 |
if (isBlock(rightSibling)) {
|
|
|
4437 |
return true;
|
|
|
4438 |
}
|
|
|
4439 |
if (isEmptyTag(rightSibling)) {
|
|
|
4440 |
return name(rightSibling) === 'img' ? false : true;
|
|
|
4441 |
}
|
|
|
4442 |
return false;
|
|
|
4443 |
}).getOr(false);
|
|
|
4444 |
};
|
|
|
4445 |
const markCell = cell => {
|
|
|
4446 |
return last$1(cell).bind(rightEdge => {
|
|
|
4447 |
const rightSiblingIsBlock = siblingIsBlock(rightEdge);
|
|
|
4448 |
return parent(rightEdge).map(parent => {
|
|
|
4449 |
return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || isBlock(parent) && !eq$1(cell, parent) ? [] : [SugarElement.fromTag('br')];
|
|
|
4450 |
});
|
|
|
4451 |
}).getOr([]);
|
|
|
4452 |
};
|
|
|
4453 |
const markContent = () => {
|
|
|
4454 |
const content = bind$2(cells, cell => {
|
|
|
4455 |
const children = children$2(cell);
|
|
|
4456 |
return advancedBr(children) ? [] : children.concat(markCell(cell));
|
|
|
4457 |
});
|
|
|
4458 |
return content.length === 0 ? [SugarElement.fromTag('br')] : content;
|
|
|
4459 |
};
|
|
|
4460 |
const contents = markContent();
|
|
|
4461 |
empty(cells[0]);
|
|
|
4462 |
append(cells[0], contents);
|
|
|
4463 |
};
|
|
|
4464 |
|
|
|
4465 |
const isEditable = elem => isEditable$1(elem, true);
|
|
|
4466 |
const prune = table => {
|
|
|
4467 |
const cells = cells$1(table);
|
|
|
4468 |
if (cells.length === 0) {
|
|
|
4469 |
remove$6(table);
|
|
|
4470 |
}
|
|
|
4471 |
};
|
|
|
4472 |
const outcome = (grid, cursor) => ({
|
|
|
4473 |
grid,
|
|
|
4474 |
cursor
|
|
|
4475 |
});
|
|
|
4476 |
const findEditableCursorPosition = rows => findMap(rows, row => findMap(row.cells, cell => {
|
|
|
4477 |
const elem = cell.element;
|
|
|
4478 |
return someIf(isEditable(elem), elem);
|
|
|
4479 |
}));
|
|
|
4480 |
const elementFromGrid = (grid, row, column) => {
|
|
|
4481 |
var _a, _b;
|
|
|
4482 |
const rows = extractGridDetails(grid).rows;
|
|
|
4483 |
return Optional.from((_b = (_a = rows[row]) === null || _a === void 0 ? void 0 : _a.cells[column]) === null || _b === void 0 ? void 0 : _b.element).filter(isEditable).orThunk(() => findEditableCursorPosition(rows));
|
|
|
4484 |
};
|
|
|
4485 |
const bundle = (grid, row, column) => {
|
|
|
4486 |
const cursorElement = elementFromGrid(grid, row, column);
|
|
|
4487 |
return outcome(grid, cursorElement);
|
|
|
4488 |
};
|
|
|
4489 |
const uniqueRows = details => {
|
|
|
4490 |
const rowCompilation = (rest, detail) => {
|
|
|
4491 |
const rowExists = exists(rest, currentDetail => currentDetail.row === detail.row);
|
|
|
4492 |
return rowExists ? rest : rest.concat([detail]);
|
|
|
4493 |
};
|
|
|
4494 |
return foldl(details, rowCompilation, []).sort((detailA, detailB) => detailA.row - detailB.row);
|
|
|
4495 |
};
|
|
|
4496 |
const opInsertRowsBefore = (grid, details, comparator, genWrappers) => {
|
|
|
4497 |
const targetIndex = details[0].row;
|
|
|
4498 |
const rows = uniqueRows(details);
|
|
|
4499 |
const newGrid = foldr(rows, (acc, row) => {
|
|
|
4500 |
const newG = insertRowAt(acc.grid, targetIndex, row.row + acc.delta, comparator, genWrappers.getOrInit);
|
|
|
4501 |
return {
|
|
|
4502 |
grid: newG,
|
|
|
4503 |
delta: acc.delta + 1
|
|
|
4504 |
};
|
|
|
4505 |
}, {
|
|
|
4506 |
grid,
|
|
|
4507 |
delta: 0
|
|
|
4508 |
}).grid;
|
|
|
4509 |
return bundle(newGrid, targetIndex, details[0].column);
|
|
|
4510 |
};
|
|
|
4511 |
const opInsertRowsAfter = (grid, details, comparator, genWrappers) => {
|
|
|
4512 |
const rows = uniqueRows(details);
|
|
|
4513 |
const target = rows[rows.length - 1];
|
|
|
4514 |
const targetIndex = target.row + target.rowspan;
|
|
|
4515 |
const newGrid = foldr(rows, (newG, row) => {
|
|
|
4516 |
return insertRowAt(newG, targetIndex, row.row, comparator, genWrappers.getOrInit);
|
|
|
4517 |
}, grid);
|
|
|
4518 |
return bundle(newGrid, targetIndex, details[0].column);
|
|
|
4519 |
};
|
|
|
4520 |
const opInsertColumnsBefore = (grid, extractDetail, comparator, genWrappers) => {
|
|
|
4521 |
const details = extractDetail.details;
|
|
|
4522 |
const columns = uniqueColumns(details);
|
|
|
4523 |
const targetIndex = columns[0].column;
|
|
|
4524 |
const newGrid = foldr(columns, (acc, col) => {
|
|
|
4525 |
const newG = insertColumnAt(acc.grid, targetIndex, col.column + acc.delta, comparator, genWrappers.getOrInit);
|
|
|
4526 |
return {
|
|
|
4527 |
grid: newG,
|
|
|
4528 |
delta: acc.delta + 1
|
|
|
4529 |
};
|
|
|
4530 |
}, {
|
|
|
4531 |
grid,
|
|
|
4532 |
delta: 0
|
|
|
4533 |
}).grid;
|
|
|
4534 |
return bundle(newGrid, details[0].row, targetIndex);
|
|
|
4535 |
};
|
|
|
4536 |
const opInsertColumnsAfter = (grid, extractDetail, comparator, genWrappers) => {
|
|
|
4537 |
const details = extractDetail.details;
|
|
|
4538 |
const target = details[details.length - 1];
|
|
|
4539 |
const targetIndex = target.column + target.colspan;
|
|
|
4540 |
const columns = uniqueColumns(details);
|
|
|
4541 |
const newGrid = foldr(columns, (newG, col) => {
|
|
|
4542 |
return insertColumnAt(newG, targetIndex, col.column, comparator, genWrappers.getOrInit);
|
|
|
4543 |
}, grid);
|
|
|
4544 |
return bundle(newGrid, details[0].row, targetIndex);
|
|
|
4545 |
};
|
|
|
4546 |
const opMakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
|
|
|
4547 |
const columns = uniqueColumns(details);
|
|
|
4548 |
const columnIndexes = map$1(columns, detail => detail.column);
|
|
|
4549 |
const newGrid = replaceColumns(initialGrid, columnIndexes, true, comparator, genWrappers.replaceOrInit);
|
|
|
4550 |
return bundle(newGrid, details[0].row, details[0].column);
|
|
|
4551 |
};
|
|
|
4552 |
const opMakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
|
|
|
4553 |
const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
|
|
|
4554 |
return bundle(newGrid, details[0].row, details[0].column);
|
|
|
4555 |
};
|
|
|
4556 |
const opUnmakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
|
|
|
4557 |
const columns = uniqueColumns(details);
|
|
|
4558 |
const columnIndexes = map$1(columns, detail => detail.column);
|
|
|
4559 |
const newGrid = replaceColumns(initialGrid, columnIndexes, false, comparator, genWrappers.replaceOrInit);
|
|
|
4560 |
return bundle(newGrid, details[0].row, details[0].column);
|
|
|
4561 |
};
|
|
|
4562 |
const opUnmakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
|
|
|
4563 |
const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
|
|
|
4564 |
return bundle(newGrid, details[0].row, details[0].column);
|
|
|
4565 |
};
|
|
|
4566 |
const makeRowsSection = (section, applyScope) => (initialGrid, details, comparator, genWrappers, tableSection) => {
|
|
|
4567 |
const rows = uniqueRows(details);
|
|
|
4568 |
const rowIndexes = map$1(rows, detail => detail.row);
|
|
|
4569 |
const newGrid = replaceRows(initialGrid, rowIndexes, section, applyScope, comparator, genWrappers.replaceOrInit, tableSection);
|
|
|
4570 |
return bundle(newGrid, details[0].row, details[0].column);
|
|
|
4571 |
};
|
|
|
4572 |
const opMakeRowsHeader = makeRowsSection('thead', true);
|
|
|
4573 |
const opMakeRowsBody = makeRowsSection('tbody', false);
|
|
|
4574 |
const opMakeRowsFooter = makeRowsSection('tfoot', false);
|
|
|
4575 |
const opEraseColumns = (grid, extractDetail, _comparator, _genWrappers) => {
|
|
|
4576 |
const columns = uniqueColumns(extractDetail.details);
|
|
|
4577 |
const newGrid = deleteColumnsAt(grid, map$1(columns, column => column.column));
|
|
|
4578 |
const maxColIndex = newGrid.length > 0 ? newGrid[0].cells.length - 1 : 0;
|
|
|
4579 |
return bundle(newGrid, columns[0].row, Math.min(columns[0].column, maxColIndex));
|
|
|
4580 |
};
|
|
|
4581 |
const opEraseRows = (grid, details, _comparator, _genWrappers) => {
|
|
|
4582 |
const rows = uniqueRows(details);
|
|
|
4583 |
const newGrid = deleteRowsAt(grid, rows[0].row, rows[rows.length - 1].row);
|
|
|
4584 |
const maxRowIndex = newGrid.length > 0 ? newGrid.length - 1 : 0;
|
|
|
4585 |
return bundle(newGrid, Math.min(details[0].row, maxRowIndex), details[0].column);
|
|
|
4586 |
};
|
|
|
4587 |
const opMergeCells = (grid, mergable, comparator, genWrappers) => {
|
|
|
4588 |
const cells = mergable.cells;
|
|
|
4589 |
merge(cells);
|
|
|
4590 |
const newGrid = merge$2(grid, mergable.bounds, comparator, genWrappers.merge(cells));
|
|
|
4591 |
return outcome(newGrid, Optional.from(cells[0]));
|
|
|
4592 |
};
|
|
|
4593 |
const opUnmergeCells = (grid, unmergable, comparator, genWrappers) => {
|
|
|
4594 |
const unmerge$1 = (b, cell) => unmerge(b, cell, comparator, genWrappers.unmerge(cell));
|
|
|
4595 |
const newGrid = foldr(unmergable, unmerge$1, grid);
|
|
|
4596 |
return outcome(newGrid, Optional.from(unmergable[0]));
|
|
|
4597 |
};
|
|
|
4598 |
const opPasteCells = (grid, pasteDetails, comparator, _genWrappers) => {
|
|
|
4599 |
const gridify = (table, generators) => {
|
|
|
4600 |
const wh = Warehouse.fromTable(table);
|
|
|
4601 |
return toGrid(wh, generators, true);
|
|
|
4602 |
};
|
|
|
4603 |
const gridB = gridify(pasteDetails.clipboard, pasteDetails.generators);
|
|
|
4604 |
const startAddress = address(pasteDetails.row, pasteDetails.column);
|
|
|
4605 |
const mergedGrid = merge$1(startAddress, grid, gridB, pasteDetails.generators, comparator);
|
|
|
4606 |
return mergedGrid.fold(() => outcome(grid, Optional.some(pasteDetails.element)), newGrid => {
|
|
|
4607 |
return bundle(newGrid, pasteDetails.row, pasteDetails.column);
|
|
|
4608 |
});
|
|
|
4609 |
};
|
|
|
4610 |
const gridifyRows = (rows, generators, context) => {
|
|
|
4611 |
const pasteDetails = fromPastedRows(rows, context.section);
|
|
|
4612 |
const wh = Warehouse.generate(pasteDetails);
|
|
|
4613 |
return toGrid(wh, generators, true);
|
|
|
4614 |
};
|
|
|
4615 |
const opPasteColsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
|
|
|
4616 |
const rows = extractGridDetails(grid).rows;
|
|
|
4617 |
const index = pasteDetails.cells[0].column;
|
|
|
4618 |
const context = rows[pasteDetails.cells[0].row];
|
|
|
4619 |
const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
|
|
|
4620 |
const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
|
|
|
4621 |
return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
|
|
|
4622 |
};
|
|
|
4623 |
const opPasteColsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
|
|
|
4624 |
const rows = extractGridDetails(grid).rows;
|
|
|
4625 |
const index = pasteDetails.cells[pasteDetails.cells.length - 1].column + pasteDetails.cells[pasteDetails.cells.length - 1].colspan;
|
|
|
4626 |
const context = rows[pasteDetails.cells[0].row];
|
|
|
4627 |
const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
|
|
|
4628 |
const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
|
|
|
4629 |
return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
|
|
|
4630 |
};
|
|
|
4631 |
const opPasteRowsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
|
|
|
4632 |
const rows = extractGridDetails(grid).rows;
|
|
|
4633 |
const index = pasteDetails.cells[0].row;
|
|
|
4634 |
const context = rows[index];
|
|
|
4635 |
const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
|
|
|
4636 |
const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
|
|
|
4637 |
return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
|
|
|
4638 |
};
|
|
|
4639 |
const opPasteRowsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
|
|
|
4640 |
const rows = extractGridDetails(grid).rows;
|
|
|
4641 |
const index = pasteDetails.cells[pasteDetails.cells.length - 1].row + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan;
|
|
|
4642 |
const context = rows[pasteDetails.cells[0].row];
|
|
|
4643 |
const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
|
|
|
4644 |
const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
|
|
|
4645 |
return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
|
|
|
4646 |
};
|
|
|
4647 |
const opGetColumnsType = (table, target) => {
|
|
|
4648 |
const house = Warehouse.fromTable(table);
|
|
|
4649 |
const details = onCells(house, target);
|
|
|
4650 |
return details.bind(selectedCells => {
|
|
|
4651 |
const lastSelectedCell = selectedCells[selectedCells.length - 1];
|
|
|
4652 |
const minColRange = selectedCells[0].column;
|
|
|
4653 |
const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
|
|
|
4654 |
const selectedColumnCells = flatten(map$1(house.all, row => filter$2(row.cells, cell => cell.column >= minColRange && cell.column < maxColRange)));
|
|
|
4655 |
return findCommonCellType(selectedColumnCells);
|
|
|
4656 |
}).getOr('');
|
|
|
4657 |
};
|
|
|
4658 |
const opGetCellsType = (table, target) => {
|
|
|
4659 |
const house = Warehouse.fromTable(table);
|
|
|
4660 |
const details = onCells(house, target);
|
|
|
4661 |
return details.bind(findCommonCellType).getOr('');
|
|
|
4662 |
};
|
|
|
4663 |
const opGetRowsType = (table, target) => {
|
|
|
4664 |
const house = Warehouse.fromTable(table);
|
|
|
4665 |
const details = onCells(house, target);
|
|
|
4666 |
return details.bind(selectedCells => {
|
|
|
4667 |
const lastSelectedCell = selectedCells[selectedCells.length - 1];
|
|
|
4668 |
const minRowRange = selectedCells[0].row;
|
|
|
4669 |
const maxRowRange = lastSelectedCell.row + lastSelectedCell.rowspan;
|
|
|
4670 |
const selectedRows = house.all.slice(minRowRange, maxRowRange);
|
|
|
4671 |
return findCommonRowType(selectedRows);
|
|
|
4672 |
}).getOr('');
|
|
|
4673 |
};
|
|
|
4674 |
const resize = (table, list, details, behaviours) => adjustWidthTo(table, list, details, behaviours.sizing);
|
|
|
4675 |
const adjustAndRedistributeWidths = (table, list, details, behaviours) => adjustAndRedistributeWidths$1(table, list, details, behaviours.sizing, behaviours.resize);
|
|
|
4676 |
const firstColumnIsLocked = (_warehouse, details) => exists(details, detail => detail.column === 0 && detail.isLocked);
|
|
|
4677 |
const lastColumnIsLocked = (warehouse, details) => exists(details, detail => detail.column + detail.colspan >= warehouse.grid.columns && detail.isLocked);
|
|
|
4678 |
const getColumnsWidth = (warehouse, details) => {
|
|
|
4679 |
const columns$1 = columns(warehouse);
|
|
|
4680 |
const uniqueCols = uniqueColumns(details);
|
|
|
4681 |
return foldl(uniqueCols, (acc, detail) => {
|
|
|
4682 |
const column = columns$1[detail.column];
|
|
|
4683 |
const colWidth = column.map(getOuter$2).getOr(0);
|
|
|
4684 |
return acc + colWidth;
|
|
|
4685 |
}, 0);
|
|
|
4686 |
};
|
|
|
4687 |
const insertColumnsExtractor = before => (warehouse, target) => onCells(warehouse, target).filter(details => {
|
|
|
4688 |
const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
|
|
|
4689 |
return !checkLocked(warehouse, details);
|
|
|
4690 |
}).map(details => ({
|
|
|
4691 |
details,
|
|
|
4692 |
pixelDelta: getColumnsWidth(warehouse, details)
|
|
|
4693 |
}));
|
|
|
4694 |
const eraseColumnsExtractor = (warehouse, target) => onUnlockedCells(warehouse, target).map(details => ({
|
|
|
4695 |
details,
|
|
|
4696 |
pixelDelta: -getColumnsWidth(warehouse, details)
|
|
|
4697 |
}));
|
|
|
4698 |
const pasteColumnsExtractor = before => (warehouse, target) => onPasteByEditor(warehouse, target).filter(details => {
|
|
|
4699 |
const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
|
|
|
4700 |
return !checkLocked(warehouse, details.cells);
|
|
|
4701 |
});
|
|
|
4702 |
const headerCellGenerator = Generators.transform('th');
|
|
|
4703 |
const bodyCellGenerator = Generators.transform('td');
|
|
|
4704 |
const insertRowsBefore = run(opInsertRowsBefore, onCells, noop, noop, Generators.modification);
|
|
|
4705 |
const insertRowsAfter = run(opInsertRowsAfter, onCells, noop, noop, Generators.modification);
|
|
|
4706 |
const insertColumnsBefore = run(opInsertColumnsBefore, insertColumnsExtractor(true), adjustAndRedistributeWidths, noop, Generators.modification);
|
|
|
4707 |
const insertColumnsAfter = run(opInsertColumnsAfter, insertColumnsExtractor(false), adjustAndRedistributeWidths, noop, Generators.modification);
|
|
|
4708 |
const eraseColumns = run(opEraseColumns, eraseColumnsExtractor, adjustAndRedistributeWidths, prune, Generators.modification);
|
|
|
4709 |
const eraseRows = run(opEraseRows, onCells, noop, prune, Generators.modification);
|
|
|
4710 |
const makeColumnsHeader = run(opMakeColumnsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
|
|
|
4711 |
const unmakeColumnsHeader = run(opUnmakeColumnsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
|
|
|
4712 |
const makeRowsHeader = run(opMakeRowsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
|
|
|
4713 |
const makeRowsBody = run(opMakeRowsBody, onUnlockedCells, noop, noop, bodyCellGenerator);
|
|
|
4714 |
const makeRowsFooter = run(opMakeRowsFooter, onUnlockedCells, noop, noop, bodyCellGenerator);
|
|
|
4715 |
const makeCellsHeader = run(opMakeCellsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
|
|
|
4716 |
const unmakeCellsHeader = run(opUnmakeCellsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
|
|
|
4717 |
const mergeCells = run(opMergeCells, onUnlockedMergable, resize, noop, Generators.merging);
|
|
|
4718 |
const unmergeCells = run(opUnmergeCells, onUnlockedUnmergable, resize, noop, Generators.merging);
|
|
|
4719 |
const pasteCells = run(opPasteCells, onPaste, resize, noop, Generators.modification);
|
|
|
4720 |
const pasteColsBefore = run(opPasteColsBefore, pasteColumnsExtractor(true), noop, noop, Generators.modification);
|
|
|
4721 |
const pasteColsAfter = run(opPasteColsAfter, pasteColumnsExtractor(false), noop, noop, Generators.modification);
|
|
|
4722 |
const pasteRowsBefore = run(opPasteRowsBefore, onPasteByEditor, noop, noop, Generators.modification);
|
|
|
4723 |
const pasteRowsAfter = run(opPasteRowsAfter, onPasteByEditor, noop, noop, Generators.modification);
|
|
|
4724 |
const getColumnsType = opGetColumnsType;
|
|
|
4725 |
const getCellsType = opGetCellsType;
|
|
|
4726 |
const getRowsType = opGetRowsType;
|
|
|
4727 |
|
|
|
4728 |
const fireNewRow = (editor, row) => editor.dispatch('NewRow', { node: row });
|
|
|
4729 |
const fireNewCell = (editor, cell) => editor.dispatch('NewCell', { node: cell });
|
|
|
4730 |
const fireTableModified = (editor, table, data) => {
|
|
|
4731 |
editor.dispatch('TableModified', {
|
|
|
4732 |
...data,
|
|
|
4733 |
table
|
|
|
4734 |
});
|
|
|
4735 |
};
|
|
|
4736 |
const fireTableSelectionChange = (editor, cells, start, finish, otherCells) => {
|
|
|
4737 |
editor.dispatch('TableSelectionChange', {
|
|
|
4738 |
cells,
|
|
|
4739 |
start,
|
|
|
4740 |
finish,
|
|
|
4741 |
otherCells
|
|
|
4742 |
});
|
|
|
4743 |
};
|
|
|
4744 |
const fireTableSelectionClear = editor => {
|
|
|
4745 |
editor.dispatch('TableSelectionClear');
|
|
|
4746 |
};
|
|
|
4747 |
const fireObjectResizeStart = (editor, target, width, height, origin) => {
|
|
|
4748 |
editor.dispatch('ObjectResizeStart', {
|
|
|
4749 |
target,
|
|
|
4750 |
width,
|
|
|
4751 |
height,
|
|
|
4752 |
origin
|
|
|
4753 |
});
|
|
|
4754 |
};
|
|
|
4755 |
const fireObjectResized = (editor, target, width, height, origin) => {
|
|
|
4756 |
editor.dispatch('ObjectResized', {
|
|
|
4757 |
target,
|
|
|
4758 |
width,
|
|
|
4759 |
height,
|
|
|
4760 |
origin
|
|
|
4761 |
});
|
|
|
4762 |
};
|
|
|
4763 |
const styleModified = {
|
|
|
4764 |
structure: false,
|
|
|
4765 |
style: true
|
|
|
4766 |
};
|
|
|
4767 |
const structureModified = {
|
|
|
4768 |
structure: true,
|
|
|
4769 |
style: false
|
|
|
4770 |
};
|
|
|
4771 |
const styleAndStructureModified = {
|
|
|
4772 |
structure: true,
|
|
|
4773 |
style: true
|
|
|
4774 |
};
|
|
|
4775 |
|
|
|
4776 |
const get$5 = (editor, table) => {
|
|
|
4777 |
if (isTablePercentagesForced(editor)) {
|
|
|
4778 |
return TableSize.percentageSize(table);
|
|
|
4779 |
} else if (isTablePixelsForced(editor)) {
|
|
|
4780 |
return TableSize.pixelSize(table);
|
|
|
4781 |
} else {
|
|
|
4782 |
return TableSize.getTableSize(table);
|
|
|
4783 |
}
|
|
|
4784 |
};
|
|
|
4785 |
|
|
|
4786 |
const TableActions = (editor, resizeHandler, cellSelectionHandler) => {
|
|
|
4787 |
const isTableBody = editor => name(getBody(editor)) === 'table';
|
|
|
4788 |
const lastRowGuard = table => !isTableBody(editor) || getGridSize(table).rows > 1;
|
|
|
4789 |
const lastColumnGuard = table => !isTableBody(editor) || getGridSize(table).columns > 1;
|
|
|
4790 |
const cloneFormats = getTableCloneElements(editor);
|
|
|
4791 |
const colMutationOp = isResizeTableColumnResizing(editor) ? noop : halve;
|
|
|
4792 |
const getTableSectionType = table => {
|
|
|
4793 |
switch (getTableHeaderType(editor)) {
|
|
|
4794 |
case 'section':
|
|
|
4795 |
return TableSection.section();
|
|
|
4796 |
case 'sectionCells':
|
|
|
4797 |
return TableSection.sectionCells();
|
|
|
4798 |
case 'cells':
|
|
|
4799 |
return TableSection.cells();
|
|
|
4800 |
default:
|
|
|
4801 |
return TableSection.getTableSectionType(table, 'section');
|
|
|
4802 |
}
|
|
|
4803 |
};
|
|
|
4804 |
const setSelectionFromAction = (table, result) => result.cursor.fold(() => {
|
|
|
4805 |
const cells = cells$1(table);
|
|
|
4806 |
return head(cells).filter(inBody).map(firstCell => {
|
|
|
4807 |
cellSelectionHandler.clearSelectedCells(table.dom);
|
|
|
4808 |
const rng = editor.dom.createRng();
|
|
|
4809 |
rng.selectNode(firstCell.dom);
|
|
|
4810 |
editor.selection.setRng(rng);
|
|
|
4811 |
set$2(firstCell, 'data-mce-selected', '1');
|
|
|
4812 |
return rng;
|
|
|
4813 |
});
|
|
|
4814 |
}, cell => {
|
|
|
4815 |
const des = freefallRtl(cell);
|
|
|
4816 |
const rng = editor.dom.createRng();
|
|
|
4817 |
rng.setStart(des.element.dom, des.offset);
|
|
|
4818 |
rng.setEnd(des.element.dom, des.offset);
|
|
|
4819 |
editor.selection.setRng(rng);
|
|
|
4820 |
cellSelectionHandler.clearSelectedCells(table.dom);
|
|
|
4821 |
return Optional.some(rng);
|
|
|
4822 |
});
|
|
|
4823 |
const execute = (operation, guard, mutate, effect) => (table, target, noEvents = false) => {
|
|
|
4824 |
removeDataStyle(table);
|
|
|
4825 |
const doc = SugarElement.fromDom(editor.getDoc());
|
|
|
4826 |
const generators = cellOperations(mutate, doc, cloneFormats);
|
|
|
4827 |
const behaviours = {
|
|
|
4828 |
sizing: get$5(editor, table),
|
|
|
4829 |
resize: isResizeTableColumnResizing(editor) ? resizeTable() : preserveTable(),
|
|
|
4830 |
section: getTableSectionType(table)
|
|
|
4831 |
};
|
|
|
4832 |
return guard(table) ? operation(table, target, generators, behaviours).bind(result => {
|
|
|
4833 |
resizeHandler.refresh(table.dom);
|
|
|
4834 |
each$2(result.newRows, row => {
|
|
|
4835 |
fireNewRow(editor, row.dom);
|
|
|
4836 |
});
|
|
|
4837 |
each$2(result.newCells, cell => {
|
|
|
4838 |
fireNewCell(editor, cell.dom);
|
|
|
4839 |
});
|
|
|
4840 |
const range = setSelectionFromAction(table, result);
|
|
|
4841 |
if (inBody(table)) {
|
|
|
4842 |
removeDataStyle(table);
|
|
|
4843 |
if (!noEvents) {
|
|
|
4844 |
fireTableModified(editor, table.dom, effect);
|
|
|
4845 |
}
|
|
|
4846 |
}
|
|
|
4847 |
return range.map(rng => ({
|
|
|
4848 |
rng,
|
|
|
4849 |
effect
|
|
|
4850 |
}));
|
|
|
4851 |
}) : Optional.none();
|
|
|
4852 |
};
|
|
|
4853 |
const deleteRow = execute(eraseRows, lastRowGuard, noop, structureModified);
|
|
|
4854 |
const deleteColumn = execute(eraseColumns, lastColumnGuard, noop, structureModified);
|
|
|
4855 |
const insertRowsBefore$1 = execute(insertRowsBefore, always, noop, structureModified);
|
|
|
4856 |
const insertRowsAfter$1 = execute(insertRowsAfter, always, noop, structureModified);
|
|
|
4857 |
const insertColumnsBefore$1 = execute(insertColumnsBefore, always, colMutationOp, structureModified);
|
|
|
4858 |
const insertColumnsAfter$1 = execute(insertColumnsAfter, always, colMutationOp, structureModified);
|
|
|
4859 |
const mergeCells$1 = execute(mergeCells, always, noop, structureModified);
|
|
|
4860 |
const unmergeCells$1 = execute(unmergeCells, always, noop, structureModified);
|
|
|
4861 |
const pasteColsBefore$1 = execute(pasteColsBefore, always, noop, structureModified);
|
|
|
4862 |
const pasteColsAfter$1 = execute(pasteColsAfter, always, noop, structureModified);
|
|
|
4863 |
const pasteRowsBefore$1 = execute(pasteRowsBefore, always, noop, structureModified);
|
|
|
4864 |
const pasteRowsAfter$1 = execute(pasteRowsAfter, always, noop, structureModified);
|
|
|
4865 |
const pasteCells$1 = execute(pasteCells, always, noop, styleAndStructureModified);
|
|
|
4866 |
const makeCellsHeader$1 = execute(makeCellsHeader, always, noop, structureModified);
|
|
|
4867 |
const unmakeCellsHeader$1 = execute(unmakeCellsHeader, always, noop, structureModified);
|
|
|
4868 |
const makeColumnsHeader$1 = execute(makeColumnsHeader, always, noop, structureModified);
|
|
|
4869 |
const unmakeColumnsHeader$1 = execute(unmakeColumnsHeader, always, noop, structureModified);
|
|
|
4870 |
const makeRowsHeader$1 = execute(makeRowsHeader, always, noop, structureModified);
|
|
|
4871 |
const makeRowsBody$1 = execute(makeRowsBody, always, noop, structureModified);
|
|
|
4872 |
const makeRowsFooter$1 = execute(makeRowsFooter, always, noop, structureModified);
|
|
|
4873 |
const getTableCellType = getCellsType;
|
|
|
4874 |
const getTableColType = getColumnsType;
|
|
|
4875 |
const getTableRowType = getRowsType;
|
|
|
4876 |
return {
|
|
|
4877 |
deleteRow,
|
|
|
4878 |
deleteColumn,
|
|
|
4879 |
insertRowsBefore: insertRowsBefore$1,
|
|
|
4880 |
insertRowsAfter: insertRowsAfter$1,
|
|
|
4881 |
insertColumnsBefore: insertColumnsBefore$1,
|
|
|
4882 |
insertColumnsAfter: insertColumnsAfter$1,
|
|
|
4883 |
mergeCells: mergeCells$1,
|
|
|
4884 |
unmergeCells: unmergeCells$1,
|
|
|
4885 |
pasteColsBefore: pasteColsBefore$1,
|
|
|
4886 |
pasteColsAfter: pasteColsAfter$1,
|
|
|
4887 |
pasteRowsBefore: pasteRowsBefore$1,
|
|
|
4888 |
pasteRowsAfter: pasteRowsAfter$1,
|
|
|
4889 |
pasteCells: pasteCells$1,
|
|
|
4890 |
makeCellsHeader: makeCellsHeader$1,
|
|
|
4891 |
unmakeCellsHeader: unmakeCellsHeader$1,
|
|
|
4892 |
makeColumnsHeader: makeColumnsHeader$1,
|
|
|
4893 |
unmakeColumnsHeader: unmakeColumnsHeader$1,
|
|
|
4894 |
makeRowsHeader: makeRowsHeader$1,
|
|
|
4895 |
makeRowsBody: makeRowsBody$1,
|
|
|
4896 |
makeRowsFooter: makeRowsFooter$1,
|
|
|
4897 |
getTableRowType,
|
|
|
4898 |
getTableCellType,
|
|
|
4899 |
getTableColType
|
|
|
4900 |
};
|
|
|
4901 |
};
|
|
|
4902 |
|
|
|
4903 |
const constrainSpan = (element, property, value) => {
|
|
|
4904 |
const currentColspan = getAttrValue(element, property, 1);
|
|
|
4905 |
if (value === 1 || currentColspan <= 1) {
|
|
|
4906 |
remove$7(element, property);
|
|
|
4907 |
} else {
|
|
|
4908 |
set$2(element, property, Math.min(value, currentColspan));
|
|
|
4909 |
}
|
|
|
4910 |
};
|
|
|
4911 |
const isColInRange = (minColRange, maxColRange) => cell => {
|
|
|
4912 |
const endCol = cell.column + cell.colspan - 1;
|
|
|
4913 |
const startCol = cell.column;
|
|
|
4914 |
return endCol >= minColRange && startCol < maxColRange;
|
|
|
4915 |
};
|
|
|
4916 |
const generateColGroup = (house, minColRange, maxColRange) => {
|
|
|
4917 |
if (Warehouse.hasColumns(house)) {
|
|
|
4918 |
const colsToCopy = filter$2(Warehouse.justColumns(house), isColInRange(minColRange, maxColRange));
|
|
|
4919 |
const copiedCols = map$1(colsToCopy, c => {
|
|
|
4920 |
const clonedCol = deep(c.element);
|
|
|
4921 |
constrainSpan(clonedCol, 'span', maxColRange - minColRange);
|
|
|
4922 |
return clonedCol;
|
|
|
4923 |
});
|
|
|
4924 |
const fakeColgroup = SugarElement.fromTag('colgroup');
|
|
|
4925 |
append(fakeColgroup, copiedCols);
|
|
|
4926 |
return [fakeColgroup];
|
|
|
4927 |
} else {
|
|
|
4928 |
return [];
|
|
|
4929 |
}
|
|
|
4930 |
};
|
|
|
4931 |
const generateRows = (house, minColRange, maxColRange) => map$1(house.all, row => {
|
|
|
4932 |
const cellsToCopy = filter$2(row.cells, isColInRange(minColRange, maxColRange));
|
|
|
4933 |
const copiedCells = map$1(cellsToCopy, cell => {
|
|
|
4934 |
const clonedCell = deep(cell.element);
|
|
|
4935 |
constrainSpan(clonedCell, 'colspan', maxColRange - minColRange);
|
|
|
4936 |
return clonedCell;
|
|
|
4937 |
});
|
|
|
4938 |
const fakeTR = SugarElement.fromTag('tr');
|
|
|
4939 |
append(fakeTR, copiedCells);
|
|
|
4940 |
return fakeTR;
|
|
|
4941 |
});
|
|
|
4942 |
const copyCols = (table, target) => {
|
|
|
4943 |
const house = Warehouse.fromTable(table);
|
|
|
4944 |
const details = onUnlockedCells(house, target);
|
|
|
4945 |
return details.map(selectedCells => {
|
|
|
4946 |
const lastSelectedCell = selectedCells[selectedCells.length - 1];
|
|
|
4947 |
const minColRange = selectedCells[0].column;
|
|
|
4948 |
const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
|
|
|
4949 |
const fakeColGroups = generateColGroup(house, minColRange, maxColRange);
|
|
|
4950 |
const fakeRows = generateRows(house, minColRange, maxColRange);
|
|
|
4951 |
return [
|
|
|
4952 |
...fakeColGroups,
|
|
|
4953 |
...fakeRows
|
|
|
4954 |
];
|
|
|
4955 |
});
|
|
|
4956 |
};
|
|
|
4957 |
|
|
|
4958 |
const copyRows = (table, target, generators) => {
|
|
|
4959 |
const warehouse = Warehouse.fromTable(table);
|
|
|
4960 |
const details = onCells(warehouse, target);
|
|
|
4961 |
return details.bind(selectedCells => {
|
|
|
4962 |
const grid = toGrid(warehouse, generators, false);
|
|
|
4963 |
const rows = extractGridDetails(grid).rows;
|
|
|
4964 |
const slicedGrid = rows.slice(selectedCells[0].row, selectedCells[selectedCells.length - 1].row + selectedCells[selectedCells.length - 1].rowspan);
|
|
|
4965 |
const filteredGrid = bind$2(slicedGrid, row => {
|
|
|
4966 |
const newCells = filter$2(row.cells, cell => !cell.isLocked);
|
|
|
4967 |
return newCells.length > 0 ? [{
|
|
|
4968 |
...row,
|
|
|
4969 |
cells: newCells
|
|
|
4970 |
}] : [];
|
|
|
4971 |
});
|
|
|
4972 |
const slicedDetails = toDetailList(filteredGrid);
|
|
|
4973 |
return someIf(slicedDetails.length > 0, slicedDetails);
|
|
|
4974 |
}).map(slicedDetails => copy(slicedDetails));
|
|
|
4975 |
};
|
|
|
4976 |
|
|
|
4977 |
const adt$5 = Adt.generate([
|
|
|
4978 |
{ invalid: ['raw'] },
|
|
|
4979 |
{ pixels: ['value'] },
|
|
|
4980 |
{ percent: ['value'] }
|
|
|
4981 |
]);
|
|
|
4982 |
const validateFor = (suffix, type, value) => {
|
|
|
4983 |
const rawAmount = value.substring(0, value.length - suffix.length);
|
|
|
4984 |
const amount = parseFloat(rawAmount);
|
|
|
4985 |
return rawAmount === amount.toString() ? type(amount) : adt$5.invalid(value);
|
|
|
4986 |
};
|
|
|
4987 |
const from = value => {
|
|
|
4988 |
if (endsWith(value, '%')) {
|
|
|
4989 |
return validateFor('%', adt$5.percent, value);
|
|
|
4990 |
}
|
|
|
4991 |
if (endsWith(value, 'px')) {
|
|
|
4992 |
return validateFor('px', adt$5.pixels, value);
|
|
|
4993 |
}
|
|
|
4994 |
return adt$5.invalid(value);
|
|
|
4995 |
};
|
|
|
4996 |
const Size = {
|
|
|
4997 |
...adt$5,
|
|
|
4998 |
from
|
|
|
4999 |
};
|
|
|
5000 |
|
|
|
5001 |
const redistributeToPercent = (widths, totalWidth) => {
|
|
|
5002 |
return map$1(widths, w => {
|
|
|
5003 |
const colType = Size.from(w);
|
|
|
5004 |
return colType.fold(() => {
|
|
|
5005 |
return w;
|
|
|
5006 |
}, px => {
|
|
|
5007 |
const ratio = px / totalWidth * 100;
|
|
|
5008 |
return ratio + '%';
|
|
|
5009 |
}, pc => {
|
|
|
5010 |
return pc + '%';
|
|
|
5011 |
});
|
|
|
5012 |
});
|
|
|
5013 |
};
|
|
|
5014 |
const redistributeToPx = (widths, totalWidth, newTotalWidth) => {
|
|
|
5015 |
const scale = newTotalWidth / totalWidth;
|
|
|
5016 |
return map$1(widths, w => {
|
|
|
5017 |
const colType = Size.from(w);
|
|
|
5018 |
return colType.fold(() => {
|
|
|
5019 |
return w;
|
|
|
5020 |
}, px => {
|
|
|
5021 |
return px * scale + 'px';
|
|
|
5022 |
}, pc => {
|
|
|
5023 |
return pc / 100 * newTotalWidth + 'px';
|
|
|
5024 |
});
|
|
|
5025 |
});
|
|
|
5026 |
};
|
|
|
5027 |
const redistributeEmpty = (newWidthType, columns) => {
|
|
|
5028 |
const f = newWidthType.fold(() => constant(''), pixels => {
|
|
|
5029 |
const num = pixels / columns;
|
|
|
5030 |
return constant(num + 'px');
|
|
|
5031 |
}, () => {
|
|
|
5032 |
const num = 100 / columns;
|
|
|
5033 |
return constant(num + '%');
|
|
|
5034 |
});
|
|
|
5035 |
return range$1(columns, f);
|
|
|
5036 |
};
|
|
|
5037 |
const redistributeValues = (newWidthType, widths, totalWidth) => {
|
|
|
5038 |
return newWidthType.fold(() => {
|
|
|
5039 |
return widths;
|
|
|
5040 |
}, px => {
|
|
|
5041 |
return redistributeToPx(widths, totalWidth, px);
|
|
|
5042 |
}, _pc => {
|
|
|
5043 |
return redistributeToPercent(widths, totalWidth);
|
|
|
5044 |
});
|
|
|
5045 |
};
|
|
|
5046 |
const redistribute$1 = (widths, totalWidth, newWidth) => {
|
|
|
5047 |
const newType = Size.from(newWidth);
|
|
|
5048 |
const floats = forall(widths, s => {
|
|
|
5049 |
return s === '0px';
|
|
|
5050 |
}) ? redistributeEmpty(newType, widths.length) : redistributeValues(newType, widths, totalWidth);
|
|
|
5051 |
return normalize(floats);
|
|
|
5052 |
};
|
|
|
5053 |
const sum = (values, fallback) => {
|
|
|
5054 |
if (values.length === 0) {
|
|
|
5055 |
return fallback;
|
|
|
5056 |
}
|
|
|
5057 |
return foldr(values, (rest, v) => {
|
|
|
5058 |
return Size.from(v).fold(constant(0), identity, identity) + rest;
|
|
|
5059 |
}, 0);
|
|
|
5060 |
};
|
|
|
5061 |
const roundDown = (num, unit) => {
|
|
|
5062 |
const floored = Math.floor(num);
|
|
|
5063 |
return {
|
|
|
5064 |
value: floored + unit,
|
|
|
5065 |
remainder: num - floored
|
|
|
5066 |
};
|
|
|
5067 |
};
|
|
|
5068 |
const add$3 = (value, amount) => {
|
|
|
5069 |
return Size.from(value).fold(constant(value), px => {
|
|
|
5070 |
return px + amount + 'px';
|
|
|
5071 |
}, pc => {
|
|
|
5072 |
return pc + amount + '%';
|
|
|
5073 |
});
|
|
|
5074 |
};
|
|
|
5075 |
const normalize = values => {
|
|
|
5076 |
if (values.length === 0) {
|
|
|
5077 |
return values;
|
|
|
5078 |
}
|
|
|
5079 |
const scan = foldr(values, (rest, value) => {
|
|
|
5080 |
const info = Size.from(value).fold(() => ({
|
|
|
5081 |
value,
|
|
|
5082 |
remainder: 0
|
|
|
5083 |
}), num => roundDown(num, 'px'), num => ({
|
|
|
5084 |
value: num + '%',
|
|
|
5085 |
remainder: 0
|
|
|
5086 |
}));
|
|
|
5087 |
return {
|
|
|
5088 |
output: [info.value].concat(rest.output),
|
|
|
5089 |
remainder: rest.remainder + info.remainder
|
|
|
5090 |
};
|
|
|
5091 |
}, {
|
|
|
5092 |
output: [],
|
|
|
5093 |
remainder: 0
|
|
|
5094 |
});
|
|
|
5095 |
const r = scan.output;
|
|
|
5096 |
return r.slice(0, r.length - 1).concat([add$3(r[r.length - 1], Math.round(scan.remainder))]);
|
|
|
5097 |
};
|
|
|
5098 |
const validate = Size.from;
|
|
|
5099 |
|
|
|
5100 |
const redistributeToW = (newWidths, cells, unit) => {
|
|
|
5101 |
each$2(cells, cell => {
|
|
|
5102 |
const widths = newWidths.slice(cell.column, cell.colspan + cell.column);
|
|
|
5103 |
const w = sum(widths, minWidth());
|
|
|
5104 |
set$1(cell.element, 'width', w + unit);
|
|
|
5105 |
});
|
|
|
5106 |
};
|
|
|
5107 |
const redistributeToColumns = (newWidths, columns, unit) => {
|
|
|
5108 |
each$2(columns, (column, index) => {
|
|
|
5109 |
const width = sum([newWidths[index]], minWidth());
|
|
|
5110 |
set$1(column.element, 'width', width + unit);
|
|
|
5111 |
});
|
|
|
5112 |
};
|
|
|
5113 |
const redistributeToH = (newHeights, rows, cells, unit) => {
|
|
|
5114 |
each$2(cells, cell => {
|
|
|
5115 |
const heights = newHeights.slice(cell.row, cell.rowspan + cell.row);
|
|
|
5116 |
const h = sum(heights, minHeight());
|
|
|
5117 |
set$1(cell.element, 'height', h + unit);
|
|
|
5118 |
});
|
|
|
5119 |
each$2(rows, (row, i) => {
|
|
|
5120 |
set$1(row.element, 'height', newHeights[i]);
|
|
|
5121 |
});
|
|
|
5122 |
};
|
|
|
5123 |
const getUnit = newSize => {
|
|
|
5124 |
return validate(newSize).fold(constant('px'), constant('px'), constant('%'));
|
|
|
5125 |
};
|
|
|
5126 |
const redistribute = (table, optWidth, optHeight) => {
|
|
|
5127 |
const warehouse = Warehouse.fromTable(table);
|
|
|
5128 |
const rows = warehouse.all;
|
|
|
5129 |
const cells = Warehouse.justCells(warehouse);
|
|
|
5130 |
const columns = Warehouse.justColumns(warehouse);
|
|
|
5131 |
optWidth.each(newWidth => {
|
|
|
5132 |
const widthUnit = getUnit(newWidth);
|
|
|
5133 |
const totalWidth = get$9(table);
|
|
|
5134 |
const oldWidths = getRawWidths(warehouse, table);
|
|
|
5135 |
const nuWidths = redistribute$1(oldWidths, totalWidth, newWidth);
|
|
|
5136 |
if (Warehouse.hasColumns(warehouse)) {
|
|
|
5137 |
redistributeToColumns(nuWidths, columns, widthUnit);
|
|
|
5138 |
} else {
|
|
|
5139 |
redistributeToW(nuWidths, cells, widthUnit);
|
|
|
5140 |
}
|
|
|
5141 |
set$1(table, 'width', newWidth);
|
|
|
5142 |
});
|
|
|
5143 |
optHeight.each(newHeight => {
|
|
|
5144 |
const hUnit = getUnit(newHeight);
|
|
|
5145 |
const totalHeight = get$8(table);
|
|
|
5146 |
const oldHeights = getRawHeights(warehouse, table, height);
|
|
|
5147 |
const nuHeights = redistribute$1(oldHeights, totalHeight, newHeight);
|
|
|
5148 |
redistributeToH(nuHeights, rows, cells, hUnit);
|
|
|
5149 |
set$1(table, 'height', newHeight);
|
|
|
5150 |
});
|
|
|
5151 |
};
|
|
|
5152 |
const isPercentSizing = isPercentSizing$1;
|
|
|
5153 |
const isPixelSizing = isPixelSizing$1;
|
|
|
5154 |
const isNoneSizing = isNoneSizing$1;
|
|
|
5155 |
|
|
|
5156 |
const cleanupLegacyAttributes = element => {
|
|
|
5157 |
remove$7(element, 'width');
|
|
|
5158 |
};
|
|
|
5159 |
const convertToPercentSize = table => {
|
|
|
5160 |
const newWidth = getPercentTableWidth(table);
|
|
|
5161 |
redistribute(table, Optional.some(newWidth), Optional.none());
|
|
|
5162 |
cleanupLegacyAttributes(table);
|
|
|
5163 |
};
|
|
|
5164 |
const convertToPixelSize = table => {
|
|
|
5165 |
const newWidth = getPixelTableWidth(table);
|
|
|
5166 |
redistribute(table, Optional.some(newWidth), Optional.none());
|
|
|
5167 |
cleanupLegacyAttributes(table);
|
|
|
5168 |
};
|
|
|
5169 |
const convertToNoneSize = table => {
|
|
|
5170 |
remove$5(table, 'width');
|
|
|
5171 |
const columns = columns$1(table);
|
|
|
5172 |
const rowElements = columns.length > 0 ? columns : cells$1(table);
|
|
|
5173 |
each$2(rowElements, cell => {
|
|
|
5174 |
remove$5(cell, 'width');
|
|
|
5175 |
cleanupLegacyAttributes(cell);
|
|
|
5176 |
});
|
|
|
5177 |
cleanupLegacyAttributes(table);
|
|
|
5178 |
};
|
|
|
5179 |
|
|
|
5180 |
const DefaultRenderOptions = {
|
|
|
5181 |
styles: {
|
|
|
5182 |
'border-collapse': 'collapse',
|
|
|
5183 |
'width': '100%'
|
|
|
5184 |
},
|
|
|
5185 |
attributes: { border: '1' },
|
|
|
5186 |
colGroups: false
|
|
|
5187 |
};
|
|
|
5188 |
const tableHeaderCell = () => SugarElement.fromTag('th');
|
|
|
5189 |
const tableCell = () => SugarElement.fromTag('td');
|
|
|
5190 |
const tableColumn = () => SugarElement.fromTag('col');
|
|
|
5191 |
const createRow = (columns, rowHeaders, columnHeaders, rowIndex) => {
|
|
|
5192 |
const tr = SugarElement.fromTag('tr');
|
|
|
5193 |
for (let j = 0; j < columns; j++) {
|
|
|
5194 |
const td = rowIndex < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell();
|
|
|
5195 |
if (j < columnHeaders) {
|
|
|
5196 |
set$2(td, 'scope', 'row');
|
|
|
5197 |
}
|
|
|
5198 |
if (rowIndex < rowHeaders) {
|
|
|
5199 |
set$2(td, 'scope', 'col');
|
|
|
5200 |
}
|
|
|
5201 |
append$1(td, SugarElement.fromTag('br'));
|
|
|
5202 |
append$1(tr, td);
|
|
|
5203 |
}
|
|
|
5204 |
return tr;
|
|
|
5205 |
};
|
|
|
5206 |
const createGroupRow = columns => {
|
|
|
5207 |
const columnGroup = SugarElement.fromTag('colgroup');
|
|
|
5208 |
range$1(columns, () => append$1(columnGroup, tableColumn()));
|
|
|
5209 |
return columnGroup;
|
|
|
5210 |
};
|
|
|
5211 |
const createRows = (rows, columns, rowHeaders, columnHeaders) => range$1(rows, r => createRow(columns, rowHeaders, columnHeaders, r));
|
|
|
5212 |
const render = (rows, columns, rowHeaders, columnHeaders, headerType, renderOpts = DefaultRenderOptions) => {
|
|
|
5213 |
const table = SugarElement.fromTag('table');
|
|
|
5214 |
const rowHeadersGoInThead = headerType !== 'cells';
|
|
|
5215 |
setAll(table, renderOpts.styles);
|
|
|
5216 |
setAll$1(table, renderOpts.attributes);
|
|
|
5217 |
if (renderOpts.colGroups) {
|
|
|
5218 |
append$1(table, createGroupRow(columns));
|
|
|
5219 |
}
|
|
|
5220 |
const actualRowHeaders = Math.min(rows, rowHeaders);
|
|
|
5221 |
if (rowHeadersGoInThead && rowHeaders > 0) {
|
|
|
5222 |
const thead = SugarElement.fromTag('thead');
|
|
|
5223 |
append$1(table, thead);
|
|
|
5224 |
const theadRowHeaders = headerType === 'sectionCells' ? actualRowHeaders : 0;
|
|
|
5225 |
const theadRows = createRows(rowHeaders, columns, theadRowHeaders, columnHeaders);
|
|
|
5226 |
append(thead, theadRows);
|
|
|
5227 |
}
|
|
|
5228 |
const tbody = SugarElement.fromTag('tbody');
|
|
|
5229 |
append$1(table, tbody);
|
|
|
5230 |
const numRows = rowHeadersGoInThead ? rows - actualRowHeaders : rows;
|
|
|
5231 |
const numRowHeaders = rowHeadersGoInThead ? 0 : rowHeaders;
|
|
|
5232 |
const tbodyRows = createRows(numRows, columns, numRowHeaders, columnHeaders);
|
|
|
5233 |
append(tbody, tbodyRows);
|
|
|
5234 |
return table;
|
|
|
5235 |
};
|
|
|
5236 |
|
|
|
5237 |
const get$4 = element => element.dom.innerHTML;
|
|
|
5238 |
const getOuter = element => {
|
|
|
5239 |
const container = SugarElement.fromTag('div');
|
|
|
5240 |
const clone = SugarElement.fromDom(element.dom.cloneNode(true));
|
|
|
5241 |
append$1(container, clone);
|
|
|
5242 |
return get$4(container);
|
|
|
5243 |
};
|
|
|
5244 |
|
|
|
5245 |
const placeCaretInCell = (editor, cell) => {
|
|
|
5246 |
editor.selection.select(cell.dom, true);
|
|
|
5247 |
editor.selection.collapse(true);
|
|
|
5248 |
};
|
|
|
5249 |
const selectFirstCellInTable = (editor, tableElm) => {
|
|
|
5250 |
descendant(tableElm, 'td,th').each(curry(placeCaretInCell, editor));
|
|
|
5251 |
};
|
|
|
5252 |
const fireEvents = (editor, table) => {
|
|
|
5253 |
each$2(descendants(table, 'tr'), row => {
|
|
|
5254 |
fireNewRow(editor, row.dom);
|
|
|
5255 |
each$2(descendants(row, 'th,td'), cell => {
|
|
|
5256 |
fireNewCell(editor, cell.dom);
|
|
|
5257 |
});
|
|
|
5258 |
});
|
|
|
5259 |
};
|
|
|
5260 |
const isPercentage = width => isString(width) && width.indexOf('%') !== -1;
|
|
|
5261 |
const insert = (editor, columns, rows, colHeaders, rowHeaders) => {
|
|
|
5262 |
const defaultStyles = getTableDefaultStyles(editor);
|
|
|
5263 |
const options = {
|
|
|
5264 |
styles: defaultStyles,
|
|
|
5265 |
attributes: getTableDefaultAttributes(editor),
|
|
|
5266 |
colGroups: tableUseColumnGroup(editor)
|
|
|
5267 |
};
|
|
|
5268 |
editor.undoManager.ignore(() => {
|
|
|
5269 |
const table = render(rows, columns, rowHeaders, colHeaders, getTableHeaderType(editor), options);
|
|
|
5270 |
set$2(table, 'data-mce-id', '__mce');
|
|
|
5271 |
const html = getOuter(table);
|
|
|
5272 |
editor.insertContent(html);
|
|
|
5273 |
editor.addVisual();
|
|
|
5274 |
});
|
|
|
5275 |
return descendant(getBody(editor), 'table[data-mce-id="__mce"]').map(table => {
|
|
|
5276 |
if (isTablePixelsForced(editor)) {
|
|
|
5277 |
convertToPixelSize(table);
|
|
|
5278 |
} else if (isTableResponsiveForced(editor)) {
|
|
|
5279 |
convertToNoneSize(table);
|
|
|
5280 |
} else if (isTablePercentagesForced(editor) || isPercentage(defaultStyles.width)) {
|
|
|
5281 |
convertToPercentSize(table);
|
|
|
5282 |
}
|
|
|
5283 |
removeDataStyle(table);
|
|
|
5284 |
remove$7(table, 'data-mce-id');
|
|
|
5285 |
fireEvents(editor, table);
|
|
|
5286 |
selectFirstCellInTable(editor, table);
|
|
|
5287 |
return table.dom;
|
|
|
5288 |
}).getOrNull();
|
|
|
5289 |
};
|
|
|
5290 |
const insertTable = (editor, rows, columns, options = {}) => {
|
|
|
5291 |
const checkInput = val => isNumber(val) && val > 0;
|
|
|
5292 |
if (checkInput(rows) && checkInput(columns)) {
|
|
|
5293 |
const headerRows = options.headerRows || 0;
|
|
|
5294 |
const headerColumns = options.headerColumns || 0;
|
|
|
5295 |
return insert(editor, columns, rows, headerColumns, headerRows);
|
|
|
5296 |
} else {
|
|
|
5297 |
console.error('Invalid values for mceInsertTable - rows and columns values are required to insert a table.');
|
|
|
5298 |
return null;
|
|
|
5299 |
}
|
|
|
5300 |
};
|
|
|
5301 |
|
|
|
5302 |
var global = tinymce.util.Tools.resolve('tinymce.FakeClipboard');
|
|
|
5303 |
|
|
|
5304 |
const tableTypeBase = 'x-tinymce/dom-table-';
|
|
|
5305 |
const tableTypeRow = tableTypeBase + 'rows';
|
|
|
5306 |
const tableTypeColumn = tableTypeBase + 'columns';
|
|
|
5307 |
const setData = items => {
|
|
|
5308 |
const fakeClipboardItem = global.FakeClipboardItem(items);
|
|
|
5309 |
global.write([fakeClipboardItem]);
|
|
|
5310 |
};
|
|
|
5311 |
const getData = type => {
|
|
|
5312 |
var _a;
|
|
|
5313 |
const items = (_a = global.read()) !== null && _a !== void 0 ? _a : [];
|
|
|
5314 |
return findMap(items, item => Optional.from(item.getType(type)));
|
|
|
5315 |
};
|
|
|
5316 |
const clearData = type => {
|
|
|
5317 |
if (getData(type).isSome()) {
|
|
|
5318 |
global.clear();
|
|
|
5319 |
}
|
|
|
5320 |
};
|
|
|
5321 |
const setRows = rowsOpt => {
|
|
|
5322 |
rowsOpt.fold(clearRows, rows => setData({ [tableTypeRow]: rows }));
|
|
|
5323 |
};
|
|
|
5324 |
const getRows = () => getData(tableTypeRow);
|
|
|
5325 |
const clearRows = () => clearData(tableTypeRow);
|
|
|
5326 |
const setColumns = columnsOpt => {
|
|
|
5327 |
columnsOpt.fold(clearColumns, columns => setData({ [tableTypeColumn]: columns }));
|
|
|
5328 |
};
|
|
|
5329 |
const getColumns = () => getData(tableTypeColumn);
|
|
|
5330 |
const clearColumns = () => clearData(tableTypeColumn);
|
|
|
5331 |
|
|
|
5332 |
const getSelectionStartCellOrCaption = editor => getSelectionCellOrCaption(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
|
|
|
5333 |
const getSelectionStartCell = editor => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
|
|
|
5334 |
const registerCommands = (editor, actions) => {
|
|
|
5335 |
const isRoot = getIsRoot(editor);
|
|
|
5336 |
const eraseTable = () => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
|
|
|
5337 |
table(cellOrCaption, isRoot).filter(not(isRoot)).each(table => {
|
|
|
5338 |
const cursor = SugarElement.fromText('');
|
|
|
5339 |
after$5(table, cursor);
|
|
|
5340 |
remove$6(table);
|
|
|
5341 |
if (editor.dom.isEmpty(editor.getBody())) {
|
|
|
5342 |
editor.setContent('');
|
|
|
5343 |
editor.selection.setCursorLocation();
|
|
|
5344 |
} else {
|
|
|
5345 |
const rng = editor.dom.createRng();
|
|
|
5346 |
rng.setStart(cursor.dom, 0);
|
|
|
5347 |
rng.setEnd(cursor.dom, 0);
|
|
|
5348 |
editor.selection.setRng(rng);
|
|
|
5349 |
editor.nodeChanged();
|
|
|
5350 |
}
|
|
|
5351 |
});
|
|
|
5352 |
});
|
|
|
5353 |
const setSizingMode = sizing => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
|
|
|
5354 |
const isForcedSizing = isTableResponsiveForced(editor) || isTablePixelsForced(editor) || isTablePercentagesForced(editor);
|
|
|
5355 |
if (!isForcedSizing) {
|
|
|
5356 |
table(cellOrCaption, isRoot).each(table => {
|
|
|
5357 |
if (sizing === 'relative' && !isPercentSizing(table)) {
|
|
|
5358 |
convertToPercentSize(table);
|
|
|
5359 |
} else if (sizing === 'fixed' && !isPixelSizing(table)) {
|
|
|
5360 |
convertToPixelSize(table);
|
|
|
5361 |
} else if (sizing === 'responsive' && !isNoneSizing(table)) {
|
|
|
5362 |
convertToNoneSize(table);
|
|
|
5363 |
}
|
|
|
5364 |
removeDataStyle(table);
|
|
|
5365 |
fireTableModified(editor, table.dom, structureModified);
|
|
|
5366 |
});
|
|
|
5367 |
}
|
|
|
5368 |
});
|
|
|
5369 |
const getTableFromCell = cell => table(cell, isRoot);
|
|
|
5370 |
const performActionOnSelection = action => getSelectionStartCell(editor).bind(cell => getTableFromCell(cell).map(table => action(table, cell)));
|
|
|
5371 |
const toggleTableClass = (_ui, clazz) => {
|
|
|
5372 |
performActionOnSelection(table => {
|
|
|
5373 |
editor.formatter.toggle('tableclass', { value: clazz }, table.dom);
|
|
|
5374 |
fireTableModified(editor, table.dom, styleModified);
|
|
|
5375 |
});
|
|
|
5376 |
};
|
|
|
5377 |
const toggleTableCellClass = (_ui, clazz) => {
|
|
|
5378 |
performActionOnSelection(table => {
|
|
|
5379 |
const selectedCells = getCellsFromSelection(editor);
|
|
|
5380 |
const allHaveClass = forall(selectedCells, cell => editor.formatter.match('tablecellclass', { value: clazz }, cell.dom));
|
|
|
5381 |
const formatterAction = allHaveClass ? editor.formatter.remove : editor.formatter.apply;
|
|
|
5382 |
each$2(selectedCells, cell => formatterAction('tablecellclass', { value: clazz }, cell.dom));
|
|
|
5383 |
fireTableModified(editor, table.dom, styleModified);
|
|
|
5384 |
});
|
|
|
5385 |
};
|
|
|
5386 |
const toggleCaption = () => {
|
|
|
5387 |
getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
|
|
|
5388 |
table(cellOrCaption, isRoot).each(table => {
|
|
|
5389 |
child(table, 'caption').fold(() => {
|
|
|
5390 |
const caption = SugarElement.fromTag('caption');
|
|
|
5391 |
append$1(caption, SugarElement.fromText('Caption'));
|
|
|
5392 |
appendAt(table, caption, 0);
|
|
|
5393 |
editor.selection.setCursorLocation(caption.dom, 0);
|
|
|
5394 |
}, caption => {
|
|
|
5395 |
if (isTag('caption')(cellOrCaption)) {
|
|
|
5396 |
one('td', table).each(td => editor.selection.setCursorLocation(td.dom, 0));
|
|
|
5397 |
}
|
|
|
5398 |
remove$6(caption);
|
|
|
5399 |
});
|
|
|
5400 |
fireTableModified(editor, table.dom, structureModified);
|
|
|
5401 |
});
|
|
|
5402 |
});
|
|
|
5403 |
};
|
|
|
5404 |
const postExecute = _data => {
|
|
|
5405 |
editor.focus();
|
|
|
5406 |
};
|
|
|
5407 |
const actOnSelection = (execute, noEvents = false) => performActionOnSelection((table, startCell) => {
|
|
|
5408 |
const targets = forMenu(getCellsFromSelection(editor), table, startCell);
|
|
|
5409 |
execute(table, targets, noEvents).each(postExecute);
|
|
|
5410 |
});
|
|
|
5411 |
const copyRowSelection = () => performActionOnSelection((table, startCell) => {
|
|
|
5412 |
const targets = forMenu(getCellsFromSelection(editor), table, startCell);
|
|
|
5413 |
const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), Optional.none());
|
|
|
5414 |
return copyRows(table, targets, generators);
|
|
|
5415 |
});
|
|
|
5416 |
const copyColSelection = () => performActionOnSelection((table, startCell) => {
|
|
|
5417 |
const targets = forMenu(getCellsFromSelection(editor), table, startCell);
|
|
|
5418 |
return copyCols(table, targets);
|
|
|
5419 |
});
|
|
|
5420 |
const pasteOnSelection = (execute, getRows) => getRows().each(rows => {
|
|
|
5421 |
const clonedRows = map$1(rows, row => deep(row));
|
|
|
5422 |
performActionOnSelection((table, startCell) => {
|
|
|
5423 |
const generators = paste$1(SugarElement.fromDom(editor.getDoc()));
|
|
|
5424 |
const targets = pasteRows(getCellsFromSelection(editor), startCell, clonedRows, generators);
|
|
|
5425 |
execute(table, targets).each(postExecute);
|
|
|
5426 |
});
|
|
|
5427 |
});
|
|
|
5428 |
const actOnType = getAction => (_ui, args) => get$c(args, 'type').each(type => {
|
|
|
5429 |
actOnSelection(getAction(type), args.no_events);
|
|
|
5430 |
});
|
|
|
5431 |
each$1({
|
|
|
5432 |
mceTableSplitCells: () => actOnSelection(actions.unmergeCells),
|
|
|
5433 |
mceTableMergeCells: () => actOnSelection(actions.mergeCells),
|
|
|
5434 |
mceTableInsertRowBefore: () => actOnSelection(actions.insertRowsBefore),
|
|
|
5435 |
mceTableInsertRowAfter: () => actOnSelection(actions.insertRowsAfter),
|
|
|
5436 |
mceTableInsertColBefore: () => actOnSelection(actions.insertColumnsBefore),
|
|
|
5437 |
mceTableInsertColAfter: () => actOnSelection(actions.insertColumnsAfter),
|
|
|
5438 |
mceTableDeleteCol: () => actOnSelection(actions.deleteColumn),
|
|
|
5439 |
mceTableDeleteRow: () => actOnSelection(actions.deleteRow),
|
|
|
5440 |
mceTableCutCol: () => copyColSelection().each(selection => {
|
|
|
5441 |
setColumns(selection);
|
|
|
5442 |
actOnSelection(actions.deleteColumn);
|
|
|
5443 |
}),
|
|
|
5444 |
mceTableCutRow: () => copyRowSelection().each(selection => {
|
|
|
5445 |
setRows(selection);
|
|
|
5446 |
actOnSelection(actions.deleteRow);
|
|
|
5447 |
}),
|
|
|
5448 |
mceTableCopyCol: () => copyColSelection().each(selection => setColumns(selection)),
|
|
|
5449 |
mceTableCopyRow: () => copyRowSelection().each(selection => setRows(selection)),
|
|
|
5450 |
mceTablePasteColBefore: () => pasteOnSelection(actions.pasteColsBefore, getColumns),
|
|
|
5451 |
mceTablePasteColAfter: () => pasteOnSelection(actions.pasteColsAfter, getColumns),
|
|
|
5452 |
mceTablePasteRowBefore: () => pasteOnSelection(actions.pasteRowsBefore, getRows),
|
|
|
5453 |
mceTablePasteRowAfter: () => pasteOnSelection(actions.pasteRowsAfter, getRows),
|
|
|
5454 |
mceTableDelete: eraseTable,
|
|
|
5455 |
mceTableCellToggleClass: toggleTableCellClass,
|
|
|
5456 |
mceTableToggleClass: toggleTableClass,
|
|
|
5457 |
mceTableToggleCaption: toggleCaption,
|
|
|
5458 |
mceTableSizingMode: (_ui, sizing) => setSizingMode(sizing),
|
|
|
5459 |
mceTableCellType: actOnType(type => type === 'th' ? actions.makeCellsHeader : actions.unmakeCellsHeader),
|
|
|
5460 |
mceTableColType: actOnType(type => type === 'th' ? actions.makeColumnsHeader : actions.unmakeColumnsHeader),
|
|
|
5461 |
mceTableRowType: actOnType(type => {
|
|
|
5462 |
switch (type) {
|
|
|
5463 |
case 'header':
|
|
|
5464 |
return actions.makeRowsHeader;
|
|
|
5465 |
case 'footer':
|
|
|
5466 |
return actions.makeRowsFooter;
|
|
|
5467 |
default:
|
|
|
5468 |
return actions.makeRowsBody;
|
|
|
5469 |
}
|
|
|
5470 |
})
|
|
|
5471 |
}, (func, name) => editor.addCommand(name, func));
|
|
|
5472 |
editor.addCommand('mceInsertTable', (_ui, args) => {
|
|
|
5473 |
insertTable(editor, args.rows, args.columns, args.options);
|
|
|
5474 |
});
|
|
|
5475 |
editor.addCommand('mceTableApplyCellStyle', (_ui, args) => {
|
|
|
5476 |
const getFormatName = style => 'tablecell' + style.toLowerCase().replace('-', '');
|
|
|
5477 |
if (!isObject(args)) {
|
|
|
5478 |
return;
|
|
|
5479 |
}
|
|
|
5480 |
const cells = filter$2(getCellsFromSelection(editor), isInEditableContext$1);
|
|
|
5481 |
if (cells.length === 0) {
|
|
|
5482 |
return;
|
|
|
5483 |
}
|
|
|
5484 |
const validArgs = filter$1(args, (value, style) => editor.formatter.has(getFormatName(style)) && isString(value));
|
|
|
5485 |
if (isEmpty(validArgs)) {
|
|
|
5486 |
return;
|
|
|
5487 |
}
|
|
|
5488 |
each$1(validArgs, (value, style) => {
|
|
|
5489 |
const formatName = getFormatName(style);
|
|
|
5490 |
each$2(cells, cell => {
|
|
|
5491 |
if (value === '') {
|
|
|
5492 |
editor.formatter.remove(formatName, { value: null }, cell.dom, true);
|
|
|
5493 |
} else {
|
|
|
5494 |
editor.formatter.apply(formatName, { value }, cell.dom);
|
|
|
5495 |
}
|
|
|
5496 |
});
|
|
|
5497 |
});
|
|
|
5498 |
getTableFromCell(cells[0]).each(table => fireTableModified(editor, table.dom, styleModified));
|
|
|
5499 |
});
|
|
|
5500 |
};
|
|
|
5501 |
|
|
|
5502 |
const registerQueryCommands = (editor, actions) => {
|
|
|
5503 |
const isRoot = getIsRoot(editor);
|
|
|
5504 |
const lookupOnSelection = action => getSelectionCell(getSelectionStart(editor)).bind(cell => table(cell, isRoot).map(table => {
|
|
|
5505 |
const targets = forMenu(getCellsFromSelection(editor), table, cell);
|
|
|
5506 |
return action(table, targets);
|
|
|
5507 |
})).getOr('');
|
|
|
5508 |
each$1({
|
|
|
5509 |
mceTableRowType: () => lookupOnSelection(actions.getTableRowType),
|
|
|
5510 |
mceTableCellType: () => lookupOnSelection(actions.getTableCellType),
|
|
|
5511 |
mceTableColType: () => lookupOnSelection(actions.getTableColType)
|
|
|
5512 |
}, (func, name) => editor.addQueryValueHandler(name, func));
|
|
|
5513 |
};
|
|
|
5514 |
|
|
|
5515 |
const adt$4 = Adt.generate([
|
|
|
5516 |
{ before: ['element'] },
|
|
|
5517 |
{
|
|
|
5518 |
on: [
|
|
|
5519 |
'element',
|
|
|
5520 |
'offset'
|
|
|
5521 |
]
|
|
|
5522 |
},
|
|
|
5523 |
{ after: ['element'] }
|
|
|
5524 |
]);
|
|
|
5525 |
const cata$1 = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
|
|
|
5526 |
const getStart$1 = situ => situ.fold(identity, identity, identity);
|
|
|
5527 |
const before$2 = adt$4.before;
|
|
|
5528 |
const on = adt$4.on;
|
|
|
5529 |
const after$3 = adt$4.after;
|
|
|
5530 |
const Situ = {
|
|
|
5531 |
before: before$2,
|
|
|
5532 |
on,
|
|
|
5533 |
after: after$3,
|
|
|
5534 |
cata: cata$1,
|
|
|
5535 |
getStart: getStart$1
|
|
|
5536 |
};
|
|
|
5537 |
|
|
|
5538 |
const create$4 = (selection, kill) => ({
|
|
|
5539 |
selection,
|
|
|
5540 |
kill
|
|
|
5541 |
});
|
|
|
5542 |
const Response = { create: create$4 };
|
|
|
5543 |
|
|
|
5544 |
const selectNode = (win, element) => {
|
|
|
5545 |
const rng = win.document.createRange();
|
|
|
5546 |
rng.selectNode(element.dom);
|
|
|
5547 |
return rng;
|
|
|
5548 |
};
|
|
|
5549 |
const selectNodeContents = (win, element) => {
|
|
|
5550 |
const rng = win.document.createRange();
|
|
|
5551 |
selectNodeContentsUsing(rng, element);
|
|
|
5552 |
return rng;
|
|
|
5553 |
};
|
|
|
5554 |
const selectNodeContentsUsing = (rng, element) => rng.selectNodeContents(element.dom);
|
|
|
5555 |
const setStart = (rng, situ) => {
|
|
|
5556 |
situ.fold(e => {
|
|
|
5557 |
rng.setStartBefore(e.dom);
|
|
|
5558 |
}, (e, o) => {
|
|
|
5559 |
rng.setStart(e.dom, o);
|
|
|
5560 |
}, e => {
|
|
|
5561 |
rng.setStartAfter(e.dom);
|
|
|
5562 |
});
|
|
|
5563 |
};
|
|
|
5564 |
const setFinish = (rng, situ) => {
|
|
|
5565 |
situ.fold(e => {
|
|
|
5566 |
rng.setEndBefore(e.dom);
|
|
|
5567 |
}, (e, o) => {
|
|
|
5568 |
rng.setEnd(e.dom, o);
|
|
|
5569 |
}, e => {
|
|
|
5570 |
rng.setEndAfter(e.dom);
|
|
|
5571 |
});
|
|
|
5572 |
};
|
|
|
5573 |
const relativeToNative = (win, startSitu, finishSitu) => {
|
|
|
5574 |
const range = win.document.createRange();
|
|
|
5575 |
setStart(range, startSitu);
|
|
|
5576 |
setFinish(range, finishSitu);
|
|
|
5577 |
return range;
|
|
|
5578 |
};
|
|
|
5579 |
const exactToNative = (win, start, soffset, finish, foffset) => {
|
|
|
5580 |
const rng = win.document.createRange();
|
|
|
5581 |
rng.setStart(start.dom, soffset);
|
|
|
5582 |
rng.setEnd(finish.dom, foffset);
|
|
|
5583 |
return rng;
|
|
|
5584 |
};
|
|
|
5585 |
const toRect = rect => ({
|
|
|
5586 |
left: rect.left,
|
|
|
5587 |
top: rect.top,
|
|
|
5588 |
right: rect.right,
|
|
|
5589 |
bottom: rect.bottom,
|
|
|
5590 |
width: rect.width,
|
|
|
5591 |
height: rect.height
|
|
|
5592 |
});
|
|
|
5593 |
const getFirstRect$1 = rng => {
|
|
|
5594 |
const rects = rng.getClientRects();
|
|
|
5595 |
const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
|
|
|
5596 |
return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
|
|
|
5597 |
};
|
|
|
5598 |
|
|
|
5599 |
const adt$3 = Adt.generate([
|
|
|
5600 |
{
|
|
|
5601 |
ltr: [
|
|
|
5602 |
'start',
|
|
|
5603 |
'soffset',
|
|
|
5604 |
'finish',
|
|
|
5605 |
'foffset'
|
|
|
5606 |
]
|
|
|
5607 |
},
|
|
|
5608 |
{
|
|
|
5609 |
rtl: [
|
|
|
5610 |
'start',
|
|
|
5611 |
'soffset',
|
|
|
5612 |
'finish',
|
|
|
5613 |
'foffset'
|
|
|
5614 |
]
|
|
|
5615 |
}
|
|
|
5616 |
]);
|
|
|
5617 |
const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
|
|
|
5618 |
const getRanges = (win, selection) => selection.match({
|
|
|
5619 |
domRange: rng => {
|
|
|
5620 |
return {
|
|
|
5621 |
ltr: constant(rng),
|
|
|
5622 |
rtl: Optional.none
|
|
|
5623 |
};
|
|
|
5624 |
},
|
|
|
5625 |
relative: (startSitu, finishSitu) => {
|
|
|
5626 |
return {
|
|
|
5627 |
ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
|
|
|
5628 |
rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
|
|
|
5629 |
};
|
|
|
5630 |
},
|
|
|
5631 |
exact: (start, soffset, finish, foffset) => {
|
|
|
5632 |
return {
|
|
|
5633 |
ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
|
|
|
5634 |
rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
|
|
|
5635 |
};
|
|
|
5636 |
}
|
|
|
5637 |
});
|
|
|
5638 |
const doDiagnose = (win, ranges) => {
|
|
|
5639 |
const rng = ranges.ltr();
|
|
|
5640 |
if (rng.collapsed) {
|
|
|
5641 |
const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
|
|
|
5642 |
return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng));
|
|
|
5643 |
} else {
|
|
|
5644 |
return fromRange(win, adt$3.ltr, rng);
|
|
|
5645 |
}
|
|
|
5646 |
};
|
|
|
5647 |
const diagnose = (win, selection) => {
|
|
|
5648 |
const ranges = getRanges(win, selection);
|
|
|
5649 |
return doDiagnose(win, ranges);
|
|
|
5650 |
};
|
|
|
5651 |
const asLtrRange = (win, selection) => {
|
|
|
5652 |
const diagnosis = diagnose(win, selection);
|
|
|
5653 |
return diagnosis.match({
|
|
|
5654 |
ltr: (start, soffset, finish, foffset) => {
|
|
|
5655 |
const rng = win.document.createRange();
|
|
|
5656 |
rng.setStart(start.dom, soffset);
|
|
|
5657 |
rng.setEnd(finish.dom, foffset);
|
|
|
5658 |
return rng;
|
|
|
5659 |
},
|
|
|
5660 |
rtl: (start, soffset, finish, foffset) => {
|
|
|
5661 |
const rng = win.document.createRange();
|
|
|
5662 |
rng.setStart(finish.dom, foffset);
|
|
|
5663 |
rng.setEnd(start.dom, soffset);
|
|
|
5664 |
return rng;
|
|
|
5665 |
}
|
|
|
5666 |
});
|
|
|
5667 |
};
|
|
|
5668 |
adt$3.ltr;
|
|
|
5669 |
adt$3.rtl;
|
|
|
5670 |
|
|
|
5671 |
const create$3 = (start, soffset, finish, foffset) => ({
|
|
|
5672 |
start,
|
|
|
5673 |
soffset,
|
|
|
5674 |
finish,
|
|
|
5675 |
foffset
|
|
|
5676 |
});
|
|
|
5677 |
const SimRange = { create: create$3 };
|
|
|
5678 |
|
|
|
5679 |
const create$2 = (start, soffset, finish, foffset) => {
|
|
|
5680 |
return {
|
|
|
5681 |
start: Situ.on(start, soffset),
|
|
|
5682 |
finish: Situ.on(finish, foffset)
|
|
|
5683 |
};
|
|
|
5684 |
};
|
|
|
5685 |
const Situs = { create: create$2 };
|
|
|
5686 |
|
|
|
5687 |
const convertToRange = (win, selection) => {
|
|
|
5688 |
const rng = asLtrRange(win, selection);
|
|
|
5689 |
return SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset);
|
|
|
5690 |
};
|
|
|
5691 |
const makeSitus = Situs.create;
|
|
|
5692 |
|
|
|
5693 |
const sync = (container, isRoot, start, soffset, finish, foffset, selectRange) => {
|
|
|
5694 |
if (!(eq$1(start, finish) && soffset === foffset)) {
|
|
|
5695 |
return closest$1(start, 'td,th', isRoot).bind(s => {
|
|
|
5696 |
return closest$1(finish, 'td,th', isRoot).bind(f => {
|
|
|
5697 |
return detect(container, isRoot, s, f, selectRange);
|
|
|
5698 |
});
|
|
|
5699 |
});
|
|
|
5700 |
} else {
|
|
|
5701 |
return Optional.none();
|
|
|
5702 |
}
|
|
|
5703 |
};
|
|
|
5704 |
const detect = (container, isRoot, start, finish, selectRange) => {
|
|
|
5705 |
if (!eq$1(start, finish)) {
|
|
|
5706 |
return identify(start, finish, isRoot).bind(cellSel => {
|
|
|
5707 |
const boxes = cellSel.boxes.getOr([]);
|
|
|
5708 |
if (boxes.length > 1) {
|
|
|
5709 |
selectRange(container, boxes, cellSel.start, cellSel.finish);
|
|
|
5710 |
return Optional.some(Response.create(Optional.some(makeSitus(start, 0, start, getEnd(start))), true));
|
|
|
5711 |
} else {
|
|
|
5712 |
return Optional.none();
|
|
|
5713 |
}
|
|
|
5714 |
});
|
|
|
5715 |
} else {
|
|
|
5716 |
return Optional.none();
|
|
|
5717 |
}
|
|
|
5718 |
};
|
|
|
5719 |
const update = (rows, columns, container, selected, annotations) => {
|
|
|
5720 |
const updateSelection = newSels => {
|
|
|
5721 |
annotations.clearBeforeUpdate(container);
|
|
|
5722 |
annotations.selectRange(container, newSels.boxes, newSels.start, newSels.finish);
|
|
|
5723 |
return newSels.boxes;
|
|
|
5724 |
};
|
|
|
5725 |
return shiftSelection(selected, rows, columns, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(updateSelection);
|
|
|
5726 |
};
|
|
|
5727 |
|
|
|
5728 |
const traverse = (item, mode) => ({
|
|
|
5729 |
item,
|
|
|
5730 |
mode
|
|
|
5731 |
});
|
|
|
5732 |
const backtrack = (universe, item, _direction, transition = sidestep) => {
|
|
|
5733 |
return universe.property().parent(item).map(p => {
|
|
|
5734 |
return traverse(p, transition);
|
|
|
5735 |
});
|
|
|
5736 |
};
|
|
|
5737 |
const sidestep = (universe, item, direction, transition = advance) => {
|
|
|
5738 |
return direction.sibling(universe, item).map(p => {
|
|
|
5739 |
return traverse(p, transition);
|
|
|
5740 |
});
|
|
|
5741 |
};
|
|
|
5742 |
const advance = (universe, item, direction, transition = advance) => {
|
|
|
5743 |
const children = universe.property().children(item);
|
|
|
5744 |
const result = direction.first(children);
|
|
|
5745 |
return result.map(r => {
|
|
|
5746 |
return traverse(r, transition);
|
|
|
5747 |
});
|
|
|
5748 |
};
|
|
|
5749 |
const successors = [
|
|
|
5750 |
{
|
|
|
5751 |
current: backtrack,
|
|
|
5752 |
next: sidestep,
|
|
|
5753 |
fallback: Optional.none()
|
|
|
5754 |
},
|
|
|
5755 |
{
|
|
|
5756 |
current: sidestep,
|
|
|
5757 |
next: advance,
|
|
|
5758 |
fallback: Optional.some(backtrack)
|
|
|
5759 |
},
|
|
|
5760 |
{
|
|
|
5761 |
current: advance,
|
|
|
5762 |
next: advance,
|
|
|
5763 |
fallback: Optional.some(sidestep)
|
|
|
5764 |
}
|
|
|
5765 |
];
|
|
|
5766 |
const go = (universe, item, mode, direction, rules = successors) => {
|
|
|
5767 |
const ruleOpt = find$1(rules, succ => {
|
|
|
5768 |
return succ.current === mode;
|
|
|
5769 |
});
|
|
|
5770 |
return ruleOpt.bind(rule => {
|
|
|
5771 |
return rule.current(universe, item, direction, rule.next).orThunk(() => {
|
|
|
5772 |
return rule.fallback.bind(fb => {
|
|
|
5773 |
return go(universe, item, fb, direction);
|
|
|
5774 |
});
|
|
|
5775 |
});
|
|
|
5776 |
});
|
|
|
5777 |
};
|
|
|
5778 |
|
|
|
5779 |
const left$1 = () => {
|
|
|
5780 |
const sibling = (universe, item) => {
|
|
|
5781 |
return universe.query().prevSibling(item);
|
|
|
5782 |
};
|
|
|
5783 |
const first = children => {
|
|
|
5784 |
return children.length > 0 ? Optional.some(children[children.length - 1]) : Optional.none();
|
|
|
5785 |
};
|
|
|
5786 |
return {
|
|
|
5787 |
sibling,
|
|
|
5788 |
first
|
|
|
5789 |
};
|
|
|
5790 |
};
|
|
|
5791 |
const right$1 = () => {
|
|
|
5792 |
const sibling = (universe, item) => {
|
|
|
5793 |
return universe.query().nextSibling(item);
|
|
|
5794 |
};
|
|
|
5795 |
const first = children => {
|
|
|
5796 |
return children.length > 0 ? Optional.some(children[0]) : Optional.none();
|
|
|
5797 |
};
|
|
|
5798 |
return {
|
|
|
5799 |
sibling,
|
|
|
5800 |
first
|
|
|
5801 |
};
|
|
|
5802 |
};
|
|
|
5803 |
const Walkers = {
|
|
|
5804 |
left: left$1,
|
|
|
5805 |
right: right$1
|
|
|
5806 |
};
|
|
|
5807 |
|
|
|
5808 |
const hone = (universe, item, predicate, mode, direction, isRoot) => {
|
|
|
5809 |
const next = go(universe, item, mode, direction);
|
|
|
5810 |
return next.bind(n => {
|
|
|
5811 |
if (isRoot(n.item)) {
|
|
|
5812 |
return Optional.none();
|
|
|
5813 |
} else {
|
|
|
5814 |
return predicate(n.item) ? Optional.some(n.item) : hone(universe, n.item, predicate, n.mode, direction, isRoot);
|
|
|
5815 |
}
|
|
|
5816 |
});
|
|
|
5817 |
};
|
|
|
5818 |
const left = (universe, item, predicate, isRoot) => {
|
|
|
5819 |
return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot);
|
|
|
5820 |
};
|
|
|
5821 |
const right = (universe, item, predicate, isRoot) => {
|
|
|
5822 |
return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot);
|
|
|
5823 |
};
|
|
|
5824 |
|
|
|
5825 |
const isLeaf = universe => element => universe.property().children(element).length === 0;
|
|
|
5826 |
const before$1 = (universe, item, isRoot) => {
|
|
|
5827 |
return seekLeft$1(universe, item, isLeaf(universe), isRoot);
|
|
|
5828 |
};
|
|
|
5829 |
const after$2 = (universe, item, isRoot) => {
|
|
|
5830 |
return seekRight$1(universe, item, isLeaf(universe), isRoot);
|
|
|
5831 |
};
|
|
|
5832 |
const seekLeft$1 = left;
|
|
|
5833 |
const seekRight$1 = right;
|
|
|
5834 |
|
|
|
5835 |
const universe = DomUniverse();
|
|
|
5836 |
const before = (element, isRoot) => {
|
|
|
5837 |
return before$1(universe, element, isRoot);
|
|
|
5838 |
};
|
|
|
5839 |
const after$1 = (element, isRoot) => {
|
|
|
5840 |
return after$2(universe, element, isRoot);
|
|
|
5841 |
};
|
|
|
5842 |
const seekLeft = (element, predicate, isRoot) => {
|
|
|
5843 |
return seekLeft$1(universe, element, predicate, isRoot);
|
|
|
5844 |
};
|
|
|
5845 |
const seekRight = (element, predicate, isRoot) => {
|
|
|
5846 |
return seekRight$1(universe, element, predicate, isRoot);
|
|
|
5847 |
};
|
|
|
5848 |
|
|
|
5849 |
const ancestor = (scope, predicate, isRoot) => ancestor$2(scope, predicate, isRoot).isSome();
|
|
|
5850 |
|
|
|
5851 |
const adt$2 = Adt.generate([
|
|
|
5852 |
{ none: ['message'] },
|
|
|
5853 |
{ success: [] },
|
|
|
5854 |
{ failedUp: ['cell'] },
|
|
|
5855 |
{ failedDown: ['cell'] }
|
|
|
5856 |
]);
|
|
|
5857 |
const isOverlapping = (bridge, before, after) => {
|
|
|
5858 |
const beforeBounds = bridge.getRect(before);
|
|
|
5859 |
const afterBounds = bridge.getRect(after);
|
|
|
5860 |
return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right;
|
|
|
5861 |
};
|
|
|
5862 |
const isRow = elem => {
|
|
|
5863 |
return closest$1(elem, 'tr');
|
|
|
5864 |
};
|
|
|
5865 |
const verify = (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) => {
|
|
|
5866 |
return closest$1(after, 'td,th', isRoot).bind(afterCell => {
|
|
|
5867 |
return closest$1(before, 'td,th', isRoot).map(beforeCell => {
|
|
|
5868 |
if (!eq$1(afterCell, beforeCell)) {
|
|
|
5869 |
return sharedOne(isRow, [
|
|
|
5870 |
afterCell,
|
|
|
5871 |
beforeCell
|
|
|
5872 |
]).fold(() => {
|
|
|
5873 |
return isOverlapping(bridge, beforeCell, afterCell) ? adt$2.success() : failure(beforeCell);
|
|
|
5874 |
}, _sharedRow => {
|
|
|
5875 |
return failure(beforeCell);
|
|
|
5876 |
});
|
|
|
5877 |
} else {
|
|
|
5878 |
return eq$1(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$2.none('in same cell');
|
|
|
5879 |
}
|
|
|
5880 |
});
|
|
|
5881 |
}).getOr(adt$2.none('default'));
|
|
|
5882 |
};
|
|
|
5883 |
const cata = (subject, onNone, onSuccess, onFailedUp, onFailedDown) => {
|
|
|
5884 |
return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown);
|
|
|
5885 |
};
|
|
|
5886 |
const BeforeAfter = {
|
|
|
5887 |
...adt$2,
|
|
|
5888 |
verify,
|
|
|
5889 |
cata
|
|
|
5890 |
};
|
|
|
5891 |
|
|
|
5892 |
const inParent = (parent, children, element, index) => ({
|
|
|
5893 |
parent,
|
|
|
5894 |
children,
|
|
|
5895 |
element,
|
|
|
5896 |
index
|
|
|
5897 |
});
|
|
|
5898 |
const indexInParent = element => parent(element).bind(parent => {
|
|
|
5899 |
const children = children$2(parent);
|
|
|
5900 |
return indexOf(children, element).map(index => inParent(parent, children, element, index));
|
|
|
5901 |
});
|
|
|
5902 |
const indexOf = (elements, element) => findIndex(elements, curry(eq$1, element));
|
|
|
5903 |
|
|
|
5904 |
const isBr = isTag('br');
|
|
|
5905 |
const gatherer = (cand, gather, isRoot) => {
|
|
|
5906 |
return gather(cand, isRoot).bind(target => {
|
|
|
5907 |
return isText(target) && get$6(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Optional.some(target);
|
|
|
5908 |
});
|
|
|
5909 |
};
|
|
|
5910 |
const handleBr = (isRoot, element, direction) => {
|
|
|
5911 |
return direction.traverse(element).orThunk(() => {
|
|
|
5912 |
return gatherer(element, direction.gather, isRoot);
|
|
|
5913 |
}).map(direction.relative);
|
|
|
5914 |
};
|
|
|
5915 |
const findBr = (element, offset) => {
|
|
|
5916 |
return child$2(element, offset).filter(isBr).orThunk(() => {
|
|
|
5917 |
return child$2(element, offset - 1).filter(isBr);
|
|
|
5918 |
});
|
|
|
5919 |
};
|
|
|
5920 |
const handleParent = (isRoot, element, offset, direction) => {
|
|
|
5921 |
return findBr(element, offset).bind(br => {
|
|
|
5922 |
return direction.traverse(br).fold(() => {
|
|
|
5923 |
return gatherer(br, direction.gather, isRoot).map(direction.relative);
|
|
|
5924 |
}, adjacent => {
|
|
|
5925 |
return indexInParent(adjacent).map(info => {
|
|
|
5926 |
return Situ.on(info.parent, info.index);
|
|
|
5927 |
});
|
|
|
5928 |
});
|
|
|
5929 |
});
|
|
|
5930 |
};
|
|
|
5931 |
const tryBr = (isRoot, element, offset, direction) => {
|
|
|
5932 |
const target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction);
|
|
|
5933 |
return target.map(tgt => {
|
|
|
5934 |
return {
|
|
|
5935 |
start: tgt,
|
|
|
5936 |
finish: tgt
|
|
|
5937 |
};
|
|
|
5938 |
});
|
|
|
5939 |
};
|
|
|
5940 |
const process = analysis => {
|
|
|
5941 |
return BeforeAfter.cata(analysis, _message => {
|
|
|
5942 |
return Optional.none();
|
|
|
5943 |
}, () => {
|
|
|
5944 |
return Optional.none();
|
|
|
5945 |
}, cell => {
|
|
|
5946 |
return Optional.some(point(cell, 0));
|
|
|
5947 |
}, cell => {
|
|
|
5948 |
return Optional.some(point(cell, getEnd(cell)));
|
|
|
5949 |
});
|
|
|
5950 |
};
|
|
|
5951 |
|
|
|
5952 |
const moveDown = (caret, amount) => {
|
|
|
5953 |
return {
|
|
|
5954 |
left: caret.left,
|
|
|
5955 |
top: caret.top + amount,
|
|
|
5956 |
right: caret.right,
|
|
|
5957 |
bottom: caret.bottom + amount
|
|
|
5958 |
};
|
|
|
5959 |
};
|
|
|
5960 |
const moveUp = (caret, amount) => {
|
|
|
5961 |
return {
|
|
|
5962 |
left: caret.left,
|
|
|
5963 |
top: caret.top - amount,
|
|
|
5964 |
right: caret.right,
|
|
|
5965 |
bottom: caret.bottom - amount
|
|
|
5966 |
};
|
|
|
5967 |
};
|
|
|
5968 |
const translate = (caret, xDelta, yDelta) => {
|
|
|
5969 |
return {
|
|
|
5970 |
left: caret.left + xDelta,
|
|
|
5971 |
top: caret.top + yDelta,
|
|
|
5972 |
right: caret.right + xDelta,
|
|
|
5973 |
bottom: caret.bottom + yDelta
|
|
|
5974 |
};
|
|
|
5975 |
};
|
|
|
5976 |
const getTop = caret => {
|
|
|
5977 |
return caret.top;
|
|
|
5978 |
};
|
|
|
5979 |
const getBottom = caret => {
|
|
|
5980 |
return caret.bottom;
|
|
|
5981 |
};
|
|
|
5982 |
|
|
|
5983 |
const getPartialBox = (bridge, element, offset) => {
|
|
|
5984 |
if (offset >= 0 && offset < getEnd(element)) {
|
|
|
5985 |
return bridge.getRangedRect(element, offset, element, offset + 1);
|
|
|
5986 |
} else if (offset > 0) {
|
|
|
5987 |
return bridge.getRangedRect(element, offset - 1, element, offset);
|
|
|
5988 |
}
|
|
|
5989 |
return Optional.none();
|
|
|
5990 |
};
|
|
|
5991 |
const toCaret = rect => ({
|
|
|
5992 |
left: rect.left,
|
|
|
5993 |
top: rect.top,
|
|
|
5994 |
right: rect.right,
|
|
|
5995 |
bottom: rect.bottom
|
|
|
5996 |
});
|
|
|
5997 |
const getElemBox = (bridge, element) => {
|
|
|
5998 |
return Optional.some(bridge.getRect(element));
|
|
|
5999 |
};
|
|
|
6000 |
const getBoxAt = (bridge, element, offset) => {
|
|
|
6001 |
if (isElement(element)) {
|
|
|
6002 |
return getElemBox(bridge, element).map(toCaret);
|
|
|
6003 |
} else if (isText(element)) {
|
|
|
6004 |
return getPartialBox(bridge, element, offset).map(toCaret);
|
|
|
6005 |
} else {
|
|
|
6006 |
return Optional.none();
|
|
|
6007 |
}
|
|
|
6008 |
};
|
|
|
6009 |
const getEntireBox = (bridge, element) => {
|
|
|
6010 |
if (isElement(element)) {
|
|
|
6011 |
return getElemBox(bridge, element).map(toCaret);
|
|
|
6012 |
} else if (isText(element)) {
|
|
|
6013 |
return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret);
|
|
|
6014 |
} else {
|
|
|
6015 |
return Optional.none();
|
|
|
6016 |
}
|
|
|
6017 |
};
|
|
|
6018 |
|
|
|
6019 |
const JUMP_SIZE = 5;
|
|
|
6020 |
const NUM_RETRIES = 100;
|
|
|
6021 |
const adt$1 = Adt.generate([
|
|
|
6022 |
{ none: [] },
|
|
|
6023 |
{ retry: ['caret'] }
|
|
|
6024 |
]);
|
|
|
6025 |
const isOutside = (caret, box) => {
|
|
|
6026 |
return caret.left < box.left || Math.abs(box.right - caret.left) < 1 || caret.left > box.right;
|
|
|
6027 |
};
|
|
|
6028 |
const inOutsideBlock = (bridge, element, caret) => {
|
|
|
6029 |
return closest$2(element, isBlock).fold(never, cell => {
|
|
|
6030 |
return getEntireBox(bridge, cell).exists(box => {
|
|
|
6031 |
return isOutside(caret, box);
|
|
|
6032 |
});
|
|
|
6033 |
});
|
|
|
6034 |
};
|
|
|
6035 |
const adjustDown = (bridge, element, guessBox, original, caret) => {
|
|
|
6036 |
const lowerCaret = moveDown(caret, JUMP_SIZE);
|
|
|
6037 |
if (Math.abs(guessBox.bottom - original.bottom) < 1) {
|
|
|
6038 |
return adt$1.retry(lowerCaret);
|
|
|
6039 |
} else if (guessBox.top > caret.bottom) {
|
|
|
6040 |
return adt$1.retry(lowerCaret);
|
|
|
6041 |
} else if (guessBox.top === caret.bottom) {
|
|
|
6042 |
return adt$1.retry(moveDown(caret, 1));
|
|
|
6043 |
} else {
|
|
|
6044 |
return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(lowerCaret, JUMP_SIZE, 0)) : adt$1.none();
|
|
|
6045 |
}
|
|
|
6046 |
};
|
|
|
6047 |
const adjustUp = (bridge, element, guessBox, original, caret) => {
|
|
|
6048 |
const higherCaret = moveUp(caret, JUMP_SIZE);
|
|
|
6049 |
if (Math.abs(guessBox.top - original.top) < 1) {
|
|
|
6050 |
return adt$1.retry(higherCaret);
|
|
|
6051 |
} else if (guessBox.bottom < caret.top) {
|
|
|
6052 |
return adt$1.retry(higherCaret);
|
|
|
6053 |
} else if (guessBox.bottom === caret.top) {
|
|
|
6054 |
return adt$1.retry(moveUp(caret, 1));
|
|
|
6055 |
} else {
|
|
|
6056 |
return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(higherCaret, JUMP_SIZE, 0)) : adt$1.none();
|
|
|
6057 |
}
|
|
|
6058 |
};
|
|
|
6059 |
const upMovement = {
|
|
|
6060 |
point: getTop,
|
|
|
6061 |
adjuster: adjustUp,
|
|
|
6062 |
move: moveUp,
|
|
|
6063 |
gather: before
|
|
|
6064 |
};
|
|
|
6065 |
const downMovement = {
|
|
|
6066 |
point: getBottom,
|
|
|
6067 |
adjuster: adjustDown,
|
|
|
6068 |
move: moveDown,
|
|
|
6069 |
gather: after$1
|
|
|
6070 |
};
|
|
|
6071 |
const isAtTable = (bridge, x, y) => {
|
|
|
6072 |
return bridge.elementFromPoint(x, y).filter(elm => {
|
|
|
6073 |
return name(elm) === 'table';
|
|
|
6074 |
}).isSome();
|
|
|
6075 |
};
|
|
|
6076 |
const adjustForTable = (bridge, movement, original, caret, numRetries) => {
|
|
|
6077 |
return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries);
|
|
|
6078 |
};
|
|
|
6079 |
const adjustTil = (bridge, movement, original, caret, numRetries) => {
|
|
|
6080 |
if (numRetries === 0) {
|
|
|
6081 |
return Optional.some(caret);
|
|
|
6082 |
}
|
|
|
6083 |
if (isAtTable(bridge, caret.left, movement.point(caret))) {
|
|
|
6084 |
return adjustForTable(bridge, movement, original, caret, numRetries - 1);
|
|
|
6085 |
}
|
|
|
6086 |
return bridge.situsFromPoint(caret.left, movement.point(caret)).bind(guess => {
|
|
|
6087 |
return guess.start.fold(Optional.none, element => {
|
|
|
6088 |
return getEntireBox(bridge, element).bind(guessBox => {
|
|
|
6089 |
return movement.adjuster(bridge, element, guessBox, original, caret).fold(Optional.none, newCaret => {
|
|
|
6090 |
return adjustTil(bridge, movement, original, newCaret, numRetries - 1);
|
|
|
6091 |
});
|
|
|
6092 |
}).orThunk(() => {
|
|
|
6093 |
return Optional.some(caret);
|
|
|
6094 |
});
|
|
|
6095 |
}, Optional.none);
|
|
|
6096 |
});
|
|
|
6097 |
};
|
|
|
6098 |
const checkScroll = (movement, adjusted, bridge) => {
|
|
|
6099 |
if (movement.point(adjusted) > bridge.getInnerHeight()) {
|
|
|
6100 |
return Optional.some(movement.point(adjusted) - bridge.getInnerHeight());
|
|
|
6101 |
} else if (movement.point(adjusted) < 0) {
|
|
|
6102 |
return Optional.some(-movement.point(adjusted));
|
|
|
6103 |
} else {
|
|
|
6104 |
return Optional.none();
|
|
|
6105 |
}
|
|
|
6106 |
};
|
|
|
6107 |
const retry = (movement, bridge, caret) => {
|
|
|
6108 |
const moved = movement.move(caret, JUMP_SIZE);
|
|
|
6109 |
const adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved);
|
|
|
6110 |
return checkScroll(movement, adjusted, bridge).fold(() => {
|
|
|
6111 |
return bridge.situsFromPoint(adjusted.left, movement.point(adjusted));
|
|
|
6112 |
}, delta => {
|
|
|
6113 |
bridge.scrollBy(0, delta);
|
|
|
6114 |
return bridge.situsFromPoint(adjusted.left, movement.point(adjusted) - delta);
|
|
|
6115 |
});
|
|
|
6116 |
};
|
|
|
6117 |
const Retries = {
|
|
|
6118 |
tryUp: curry(retry, upMovement),
|
|
|
6119 |
tryDown: curry(retry, downMovement),
|
|
|
6120 |
getJumpSize: constant(JUMP_SIZE)
|
|
|
6121 |
};
|
|
|
6122 |
|
|
|
6123 |
const MAX_RETRIES = 20;
|
|
|
6124 |
const findSpot = (bridge, isRoot, direction) => {
|
|
|
6125 |
return bridge.getSelection().bind(sel => {
|
|
|
6126 |
return tryBr(isRoot, sel.finish, sel.foffset, direction).fold(() => {
|
|
|
6127 |
return Optional.some(point(sel.finish, sel.foffset));
|
|
|
6128 |
}, brNeighbour => {
|
|
|
6129 |
const range = bridge.fromSitus(brNeighbour);
|
|
|
6130 |
const analysis = BeforeAfter.verify(bridge, sel.finish, sel.foffset, range.finish, range.foffset, direction.failure, isRoot);
|
|
|
6131 |
return process(analysis);
|
|
|
6132 |
});
|
|
|
6133 |
});
|
|
|
6134 |
};
|
|
|
6135 |
const scan = (bridge, isRoot, element, offset, direction, numRetries) => {
|
|
|
6136 |
if (numRetries === 0) {
|
|
|
6137 |
return Optional.none();
|
|
|
6138 |
}
|
|
|
6139 |
return tryCursor(bridge, isRoot, element, offset, direction).bind(situs => {
|
|
|
6140 |
const range = bridge.fromSitus(situs);
|
|
|
6141 |
const analysis = BeforeAfter.verify(bridge, element, offset, range.finish, range.foffset, direction.failure, isRoot);
|
|
|
6142 |
return BeforeAfter.cata(analysis, () => {
|
|
|
6143 |
return Optional.none();
|
|
|
6144 |
}, () => {
|
|
|
6145 |
return Optional.some(situs);
|
|
|
6146 |
}, cell => {
|
|
|
6147 |
if (eq$1(element, cell) && offset === 0) {
|
|
|
6148 |
return tryAgain(bridge, element, offset, moveUp, direction);
|
|
|
6149 |
} else {
|
|
|
6150 |
return scan(bridge, isRoot, cell, 0, direction, numRetries - 1);
|
|
|
6151 |
}
|
|
|
6152 |
}, cell => {
|
|
|
6153 |
if (eq$1(element, cell) && offset === getEnd(cell)) {
|
|
|
6154 |
return tryAgain(bridge, element, offset, moveDown, direction);
|
|
|
6155 |
} else {
|
|
|
6156 |
return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1);
|
|
|
6157 |
}
|
|
|
6158 |
});
|
|
|
6159 |
});
|
|
|
6160 |
};
|
|
|
6161 |
const tryAgain = (bridge, element, offset, move, direction) => {
|
|
|
6162 |
return getBoxAt(bridge, element, offset).bind(box => {
|
|
|
6163 |
return tryAt(bridge, direction, move(box, Retries.getJumpSize()));
|
|
|
6164 |
});
|
|
|
6165 |
};
|
|
|
6166 |
const tryAt = (bridge, direction, box) => {
|
|
|
6167 |
const browser = detect$2().browser;
|
|
|
6168 |
if (browser.isChromium() || browser.isSafari() || browser.isFirefox()) {
|
|
|
6169 |
return direction.retry(bridge, box);
|
|
|
6170 |
} else {
|
|
|
6171 |
return Optional.none();
|
|
|
6172 |
}
|
|
|
6173 |
};
|
|
|
6174 |
const tryCursor = (bridge, isRoot, element, offset, direction) => {
|
|
|
6175 |
return getBoxAt(bridge, element, offset).bind(box => {
|
|
|
6176 |
return tryAt(bridge, direction, box);
|
|
|
6177 |
});
|
|
|
6178 |
};
|
|
|
6179 |
const handle$1 = (bridge, isRoot, direction) => {
|
|
|
6180 |
return findSpot(bridge, isRoot, direction).bind(spot => {
|
|
|
6181 |
return scan(bridge, isRoot, spot.element, spot.offset, direction, MAX_RETRIES).map(bridge.fromSitus);
|
|
|
6182 |
});
|
|
|
6183 |
};
|
|
|
6184 |
|
|
|
6185 |
const inSameTable = (elem, table) => {
|
|
|
6186 |
return ancestor(elem, e => {
|
|
|
6187 |
return parent(e).exists(p => {
|
|
|
6188 |
return eq$1(p, table);
|
|
|
6189 |
});
|
|
|
6190 |
});
|
|
|
6191 |
};
|
|
|
6192 |
const simulate = (bridge, isRoot, direction, initial, anchor) => {
|
|
|
6193 |
return closest$1(initial, 'td,th', isRoot).bind(start => {
|
|
|
6194 |
return closest$1(start, 'table', isRoot).bind(table => {
|
|
|
6195 |
if (!inSameTable(anchor, table)) {
|
|
|
6196 |
return Optional.none();
|
|
|
6197 |
}
|
|
|
6198 |
return handle$1(bridge, isRoot, direction).bind(range => {
|
|
|
6199 |
return closest$1(range.finish, 'td,th', isRoot).map(finish => {
|
|
|
6200 |
return {
|
|
|
6201 |
start,
|
|
|
6202 |
finish,
|
|
|
6203 |
range
|
|
|
6204 |
};
|
|
|
6205 |
});
|
|
|
6206 |
});
|
|
|
6207 |
});
|
|
|
6208 |
});
|
|
|
6209 |
};
|
|
|
6210 |
const navigate = (bridge, isRoot, direction, initial, anchor, precheck) => {
|
|
|
6211 |
return precheck(initial, isRoot).orThunk(() => {
|
|
|
6212 |
return simulate(bridge, isRoot, direction, initial, anchor).map(info => {
|
|
|
6213 |
const range = info.range;
|
|
|
6214 |
return Response.create(Optional.some(makeSitus(range.start, range.soffset, range.finish, range.foffset)), true);
|
|
|
6215 |
});
|
|
|
6216 |
});
|
|
|
6217 |
};
|
|
|
6218 |
const firstUpCheck = (initial, isRoot) => {
|
|
|
6219 |
return closest$1(initial, 'tr', isRoot).bind(startRow => {
|
|
|
6220 |
return closest$1(startRow, 'table', isRoot).bind(table => {
|
|
|
6221 |
const rows = descendants(table, 'tr');
|
|
|
6222 |
if (eq$1(startRow, rows[0])) {
|
|
|
6223 |
return seekLeft(table, element => {
|
|
|
6224 |
return last$1(element).isSome();
|
|
|
6225 |
}, isRoot).map(last => {
|
|
|
6226 |
const lastOffset = getEnd(last);
|
|
|
6227 |
return Response.create(Optional.some(makeSitus(last, lastOffset, last, lastOffset)), true);
|
|
|
6228 |
});
|
|
|
6229 |
} else {
|
|
|
6230 |
return Optional.none();
|
|
|
6231 |
}
|
|
|
6232 |
});
|
|
|
6233 |
});
|
|
|
6234 |
};
|
|
|
6235 |
const lastDownCheck = (initial, isRoot) => {
|
|
|
6236 |
return closest$1(initial, 'tr', isRoot).bind(startRow => {
|
|
|
6237 |
return closest$1(startRow, 'table', isRoot).bind(table => {
|
|
|
6238 |
const rows = descendants(table, 'tr');
|
|
|
6239 |
if (eq$1(startRow, rows[rows.length - 1])) {
|
|
|
6240 |
return seekRight(table, element => {
|
|
|
6241 |
return first(element).isSome();
|
|
|
6242 |
}, isRoot).map(first => {
|
|
|
6243 |
return Response.create(Optional.some(makeSitus(first, 0, first, 0)), true);
|
|
|
6244 |
});
|
|
|
6245 |
} else {
|
|
|
6246 |
return Optional.none();
|
|
|
6247 |
}
|
|
|
6248 |
});
|
|
|
6249 |
});
|
|
|
6250 |
};
|
|
|
6251 |
const select = (bridge, container, isRoot, direction, initial, anchor, selectRange) => {
|
|
|
6252 |
return simulate(bridge, isRoot, direction, initial, anchor).bind(info => {
|
|
|
6253 |
return detect(container, isRoot, info.start, info.finish, selectRange);
|
|
|
6254 |
});
|
|
|
6255 |
};
|
|
|
6256 |
|
|
|
6257 |
const Cell = initial => {
|
|
|
6258 |
let value = initial;
|
|
|
6259 |
const get = () => {
|
|
|
6260 |
return value;
|
|
|
6261 |
};
|
|
|
6262 |
const set = v => {
|
|
|
6263 |
value = v;
|
|
|
6264 |
};
|
|
|
6265 |
return {
|
|
|
6266 |
get,
|
|
|
6267 |
set
|
|
|
6268 |
};
|
|
|
6269 |
};
|
|
|
6270 |
|
|
|
6271 |
const singleton = doRevoke => {
|
|
|
6272 |
const subject = Cell(Optional.none());
|
|
|
6273 |
const revoke = () => subject.get().each(doRevoke);
|
|
|
6274 |
const clear = () => {
|
|
|
6275 |
revoke();
|
|
|
6276 |
subject.set(Optional.none());
|
|
|
6277 |
};
|
|
|
6278 |
const isSet = () => subject.get().isSome();
|
|
|
6279 |
const get = () => subject.get();
|
|
|
6280 |
const set = s => {
|
|
|
6281 |
revoke();
|
|
|
6282 |
subject.set(Optional.some(s));
|
|
|
6283 |
};
|
|
|
6284 |
return {
|
|
|
6285 |
clear,
|
|
|
6286 |
isSet,
|
|
|
6287 |
get,
|
|
|
6288 |
set
|
|
|
6289 |
};
|
|
|
6290 |
};
|
|
|
6291 |
const value = () => {
|
|
|
6292 |
const subject = singleton(noop);
|
|
|
6293 |
const on = f => subject.get().each(f);
|
|
|
6294 |
return {
|
|
|
6295 |
...subject,
|
|
|
6296 |
on
|
|
|
6297 |
};
|
|
|
6298 |
};
|
|
|
6299 |
|
|
|
6300 |
const findCell = (target, isRoot) => closest$1(target, 'td,th', isRoot);
|
|
|
6301 |
const isInEditableContext = cell => parentElement(cell).exists(isEditable$1);
|
|
|
6302 |
const MouseSelection = (bridge, container, isRoot, annotations) => {
|
|
|
6303 |
const cursor = value();
|
|
|
6304 |
const clearstate = cursor.clear;
|
|
|
6305 |
const applySelection = event => {
|
|
|
6306 |
cursor.on(start => {
|
|
|
6307 |
annotations.clearBeforeUpdate(container);
|
|
|
6308 |
findCell(event.target, isRoot).each(finish => {
|
|
|
6309 |
identify(start, finish, isRoot).each(cellSel => {
|
|
|
6310 |
const boxes = cellSel.boxes.getOr([]);
|
|
|
6311 |
if (boxes.length === 1) {
|
|
|
6312 |
const singleCell = boxes[0];
|
|
|
6313 |
const isNonEditableCell = getRaw(singleCell) === 'false';
|
|
|
6314 |
const isCellClosestContentEditable = is(closest(event.target), singleCell, eq$1);
|
|
|
6315 |
if (isNonEditableCell && isCellClosestContentEditable) {
|
|
|
6316 |
annotations.selectRange(container, boxes, singleCell, singleCell);
|
|
|
6317 |
bridge.selectContents(singleCell);
|
|
|
6318 |
}
|
|
|
6319 |
} else if (boxes.length > 1) {
|
|
|
6320 |
annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
|
|
|
6321 |
bridge.selectContents(finish);
|
|
|
6322 |
}
|
|
|
6323 |
});
|
|
|
6324 |
});
|
|
|
6325 |
});
|
|
|
6326 |
};
|
|
|
6327 |
const mousedown = event => {
|
|
|
6328 |
annotations.clear(container);
|
|
|
6329 |
findCell(event.target, isRoot).filter(isInEditableContext).each(cursor.set);
|
|
|
6330 |
};
|
|
|
6331 |
const mouseover = event => {
|
|
|
6332 |
applySelection(event);
|
|
|
6333 |
};
|
|
|
6334 |
const mouseup = event => {
|
|
|
6335 |
applySelection(event);
|
|
|
6336 |
clearstate();
|
|
|
6337 |
};
|
|
|
6338 |
return {
|
|
|
6339 |
clearstate,
|
|
|
6340 |
mousedown,
|
|
|
6341 |
mouseover,
|
|
|
6342 |
mouseup
|
|
|
6343 |
};
|
|
|
6344 |
};
|
|
|
6345 |
|
|
|
6346 |
const down = {
|
|
|
6347 |
traverse: nextSibling,
|
|
|
6348 |
gather: after$1,
|
|
|
6349 |
relative: Situ.before,
|
|
|
6350 |
retry: Retries.tryDown,
|
|
|
6351 |
failure: BeforeAfter.failedDown
|
|
|
6352 |
};
|
|
|
6353 |
const up = {
|
|
|
6354 |
traverse: prevSibling,
|
|
|
6355 |
gather: before,
|
|
|
6356 |
relative: Situ.before,
|
|
|
6357 |
retry: Retries.tryUp,
|
|
|
6358 |
failure: BeforeAfter.failedUp
|
|
|
6359 |
};
|
|
|
6360 |
|
|
|
6361 |
const isKey = key => {
|
|
|
6362 |
return keycode => {
|
|
|
6363 |
return keycode === key;
|
|
|
6364 |
};
|
|
|
6365 |
};
|
|
|
6366 |
const isUp = isKey(38);
|
|
|
6367 |
const isDown = isKey(40);
|
|
|
6368 |
const isNavigation = keycode => {
|
|
|
6369 |
return keycode >= 37 && keycode <= 40;
|
|
|
6370 |
};
|
|
|
6371 |
const ltr = {
|
|
|
6372 |
isBackward: isKey(37),
|
|
|
6373 |
isForward: isKey(39)
|
|
|
6374 |
};
|
|
|
6375 |
const rtl = {
|
|
|
6376 |
isBackward: isKey(39),
|
|
|
6377 |
isForward: isKey(37)
|
|
|
6378 |
};
|
|
|
6379 |
|
|
|
6380 |
const get$3 = _DOC => {
|
|
|
6381 |
const doc = _DOC !== undefined ? _DOC.dom : document;
|
|
|
6382 |
const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
|
|
|
6383 |
const y = doc.body.scrollTop || doc.documentElement.scrollTop;
|
|
|
6384 |
return SugarPosition(x, y);
|
|
|
6385 |
};
|
|
|
6386 |
const by = (x, y, _DOC) => {
|
|
|
6387 |
const doc = _DOC !== undefined ? _DOC.dom : document;
|
|
|
6388 |
const win = doc.defaultView;
|
|
|
6389 |
if (win) {
|
|
|
6390 |
win.scrollBy(x, y);
|
|
|
6391 |
}
|
|
|
6392 |
};
|
|
|
6393 |
|
|
|
6394 |
const adt = Adt.generate([
|
|
|
6395 |
{ domRange: ['rng'] },
|
|
|
6396 |
{
|
|
|
6397 |
relative: [
|
|
|
6398 |
'startSitu',
|
|
|
6399 |
'finishSitu'
|
|
|
6400 |
]
|
|
|
6401 |
},
|
|
|
6402 |
{
|
|
|
6403 |
exact: [
|
|
|
6404 |
'start',
|
|
|
6405 |
'soffset',
|
|
|
6406 |
'finish',
|
|
|
6407 |
'foffset'
|
|
|
6408 |
]
|
|
|
6409 |
}
|
|
|
6410 |
]);
|
|
|
6411 |
const exactFromRange = simRange => adt.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
|
|
|
6412 |
const getStart = selection => selection.match({
|
|
|
6413 |
domRange: rng => SugarElement.fromDom(rng.startContainer),
|
|
|
6414 |
relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
|
|
|
6415 |
exact: (start, _soffset, _finish, _foffset) => start
|
|
|
6416 |
});
|
|
|
6417 |
const domRange = adt.domRange;
|
|
|
6418 |
const relative = adt.relative;
|
|
|
6419 |
const exact = adt.exact;
|
|
|
6420 |
const getWin = selection => {
|
|
|
6421 |
const start = getStart(selection);
|
|
|
6422 |
return defaultView(start);
|
|
|
6423 |
};
|
|
|
6424 |
const range = SimRange.create;
|
|
|
6425 |
const SimSelection = {
|
|
|
6426 |
domRange,
|
|
|
6427 |
relative,
|
|
|
6428 |
exact,
|
|
|
6429 |
exactFromRange,
|
|
|
6430 |
getWin,
|
|
|
6431 |
range
|
|
|
6432 |
};
|
|
|
6433 |
|
|
|
6434 |
const caretPositionFromPoint = (doc, x, y) => {
|
|
|
6435 |
var _a, _b;
|
|
|
6436 |
return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => {
|
|
|
6437 |
if (pos.offsetNode === null) {
|
|
|
6438 |
return Optional.none();
|
|
|
6439 |
}
|
|
|
6440 |
const r = doc.dom.createRange();
|
|
|
6441 |
r.setStart(pos.offsetNode, pos.offset);
|
|
|
6442 |
r.collapse();
|
|
|
6443 |
return Optional.some(r);
|
|
|
6444 |
});
|
|
|
6445 |
};
|
|
|
6446 |
const caretRangeFromPoint = (doc, x, y) => {
|
|
|
6447 |
var _a, _b;
|
|
|
6448 |
return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y));
|
|
|
6449 |
};
|
|
|
6450 |
const availableSearch = (() => {
|
|
|
6451 |
if (document.caretPositionFromPoint) {
|
|
|
6452 |
return caretPositionFromPoint;
|
|
|
6453 |
} else if (document.caretRangeFromPoint) {
|
|
|
6454 |
return caretRangeFromPoint;
|
|
|
6455 |
} else {
|
|
|
6456 |
return Optional.none;
|
|
|
6457 |
}
|
|
|
6458 |
})();
|
|
|
6459 |
const fromPoint = (win, x, y) => {
|
|
|
6460 |
const doc = SugarElement.fromDom(win.document);
|
|
|
6461 |
return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
|
|
|
6462 |
};
|
|
|
6463 |
|
|
|
6464 |
const beforeSpecial = (element, offset) => {
|
|
|
6465 |
const name$1 = name(element);
|
|
|
6466 |
if ('input' === name$1) {
|
|
|
6467 |
return Situ.after(element);
|
|
|
6468 |
} else if (!contains$2([
|
|
|
6469 |
'br',
|
|
|
6470 |
'img'
|
|
|
6471 |
], name$1)) {
|
|
|
6472 |
return Situ.on(element, offset);
|
|
|
6473 |
} else {
|
|
|
6474 |
return offset === 0 ? Situ.before(element) : Situ.after(element);
|
|
|
6475 |
}
|
|
|
6476 |
};
|
|
|
6477 |
const preprocessRelative = (startSitu, finishSitu) => {
|
|
|
6478 |
const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
|
|
|
6479 |
const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
|
|
|
6480 |
return SimSelection.relative(start, finish);
|
|
|
6481 |
};
|
|
|
6482 |
const preprocessExact = (start, soffset, finish, foffset) => {
|
|
|
6483 |
const startSitu = beforeSpecial(start, soffset);
|
|
|
6484 |
const finishSitu = beforeSpecial(finish, foffset);
|
|
|
6485 |
return SimSelection.relative(startSitu, finishSitu);
|
|
|
6486 |
};
|
|
|
6487 |
|
|
|
6488 |
const makeRange = (start, soffset, finish, foffset) => {
|
|
|
6489 |
const doc = owner(start);
|
|
|
6490 |
const rng = doc.dom.createRange();
|
|
|
6491 |
rng.setStart(start.dom, soffset);
|
|
|
6492 |
rng.setEnd(finish.dom, foffset);
|
|
|
6493 |
return rng;
|
|
|
6494 |
};
|
|
|
6495 |
const after = (start, soffset, finish, foffset) => {
|
|
|
6496 |
const r = makeRange(start, soffset, finish, foffset);
|
|
|
6497 |
const same = eq$1(start, finish) && soffset === foffset;
|
|
|
6498 |
return r.collapsed && !same;
|
|
|
6499 |
};
|
|
|
6500 |
|
|
|
6501 |
const getNativeSelection = win => Optional.from(win.getSelection());
|
|
|
6502 |
const doSetNativeRange = (win, rng) => {
|
|
|
6503 |
getNativeSelection(win).each(selection => {
|
|
|
6504 |
selection.removeAllRanges();
|
|
|
6505 |
selection.addRange(rng);
|
|
|
6506 |
});
|
|
|
6507 |
};
|
|
|
6508 |
const doSetRange = (win, start, soffset, finish, foffset) => {
|
|
|
6509 |
const rng = exactToNative(win, start, soffset, finish, foffset);
|
|
|
6510 |
doSetNativeRange(win, rng);
|
|
|
6511 |
};
|
|
|
6512 |
const setLegacyRtlRange = (win, selection, start, soffset, finish, foffset) => {
|
|
|
6513 |
selection.collapse(start.dom, soffset);
|
|
|
6514 |
selection.extend(finish.dom, foffset);
|
|
|
6515 |
};
|
|
|
6516 |
const setRangeFromRelative = (win, relative) => diagnose(win, relative).match({
|
|
|
6517 |
ltr: (start, soffset, finish, foffset) => {
|
|
|
6518 |
doSetRange(win, start, soffset, finish, foffset);
|
|
|
6519 |
},
|
|
|
6520 |
rtl: (start, soffset, finish, foffset) => {
|
|
|
6521 |
getNativeSelection(win).each(selection => {
|
|
|
6522 |
if (selection.setBaseAndExtent) {
|
|
|
6523 |
selection.setBaseAndExtent(start.dom, soffset, finish.dom, foffset);
|
|
|
6524 |
} else if (selection.extend) {
|
|
|
6525 |
try {
|
|
|
6526 |
setLegacyRtlRange(win, selection, start, soffset, finish, foffset);
|
|
|
6527 |
} catch (e) {
|
|
|
6528 |
doSetRange(win, finish, foffset, start, soffset);
|
|
|
6529 |
}
|
|
|
6530 |
} else {
|
|
|
6531 |
doSetRange(win, finish, foffset, start, soffset);
|
|
|
6532 |
}
|
|
|
6533 |
});
|
|
|
6534 |
}
|
|
|
6535 |
});
|
|
|
6536 |
const setExact = (win, start, soffset, finish, foffset) => {
|
|
|
6537 |
const relative = preprocessExact(start, soffset, finish, foffset);
|
|
|
6538 |
setRangeFromRelative(win, relative);
|
|
|
6539 |
};
|
|
|
6540 |
const setRelative = (win, startSitu, finishSitu) => {
|
|
|
6541 |
const relative = preprocessRelative(startSitu, finishSitu);
|
|
|
6542 |
setRangeFromRelative(win, relative);
|
|
|
6543 |
};
|
|
|
6544 |
const readRange = selection => {
|
|
|
6545 |
if (selection.rangeCount > 0) {
|
|
|
6546 |
const firstRng = selection.getRangeAt(0);
|
|
|
6547 |
const lastRng = selection.getRangeAt(selection.rangeCount - 1);
|
|
|
6548 |
return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
|
|
|
6549 |
} else {
|
|
|
6550 |
return Optional.none();
|
|
|
6551 |
}
|
|
|
6552 |
};
|
|
|
6553 |
const doGetExact = selection => {
|
|
|
6554 |
if (selection.anchorNode === null || selection.focusNode === null) {
|
|
|
6555 |
return readRange(selection);
|
|
|
6556 |
} else {
|
|
|
6557 |
const anchor = SugarElement.fromDom(selection.anchorNode);
|
|
|
6558 |
const focus = SugarElement.fromDom(selection.focusNode);
|
|
|
6559 |
return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
|
|
|
6560 |
}
|
|
|
6561 |
};
|
|
|
6562 |
const setToElement = (win, element, selectNodeContents$1 = true) => {
|
|
|
6563 |
const rngGetter = selectNodeContents$1 ? selectNodeContents : selectNode;
|
|
|
6564 |
const rng = rngGetter(win, element);
|
|
|
6565 |
doSetNativeRange(win, rng);
|
|
|
6566 |
};
|
|
|
6567 |
const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
|
|
|
6568 |
const get$2 = win => getExact(win).map(range => SimSelection.exact(range.start, range.soffset, range.finish, range.foffset));
|
|
|
6569 |
const getFirstRect = (win, selection) => {
|
|
|
6570 |
const rng = asLtrRange(win, selection);
|
|
|
6571 |
return getFirstRect$1(rng);
|
|
|
6572 |
};
|
|
|
6573 |
const getAtPoint = (win, x, y) => fromPoint(win, x, y);
|
|
|
6574 |
const clear = win => {
|
|
|
6575 |
getNativeSelection(win).each(selection => selection.removeAllRanges());
|
|
|
6576 |
};
|
|
|
6577 |
|
|
|
6578 |
const WindowBridge = win => {
|
|
|
6579 |
const elementFromPoint = (x, y) => {
|
|
|
6580 |
return SugarElement.fromPoint(SugarElement.fromDom(win.document), x, y);
|
|
|
6581 |
};
|
|
|
6582 |
const getRect = element => {
|
|
|
6583 |
return element.dom.getBoundingClientRect();
|
|
|
6584 |
};
|
|
|
6585 |
const getRangedRect = (start, soffset, finish, foffset) => {
|
|
|
6586 |
const sel = SimSelection.exact(start, soffset, finish, foffset);
|
|
|
6587 |
return getFirstRect(win, sel);
|
|
|
6588 |
};
|
|
|
6589 |
const getSelection = () => {
|
|
|
6590 |
return get$2(win).map(exactAdt => {
|
|
|
6591 |
return convertToRange(win, exactAdt);
|
|
|
6592 |
});
|
|
|
6593 |
};
|
|
|
6594 |
const fromSitus = situs => {
|
|
|
6595 |
const relative = SimSelection.relative(situs.start, situs.finish);
|
|
|
6596 |
return convertToRange(win, relative);
|
|
|
6597 |
};
|
|
|
6598 |
const situsFromPoint = (x, y) => {
|
|
|
6599 |
return getAtPoint(win, x, y).map(exact => {
|
|
|
6600 |
return Situs.create(exact.start, exact.soffset, exact.finish, exact.foffset);
|
|
|
6601 |
});
|
|
|
6602 |
};
|
|
|
6603 |
const clearSelection = () => {
|
|
|
6604 |
clear(win);
|
|
|
6605 |
};
|
|
|
6606 |
const collapseSelection = (toStart = false) => {
|
|
|
6607 |
get$2(win).each(sel => sel.fold(rng => rng.collapse(toStart), (startSitu, finishSitu) => {
|
|
|
6608 |
const situ = toStart ? startSitu : finishSitu;
|
|
|
6609 |
setRelative(win, situ, situ);
|
|
|
6610 |
}, (start, soffset, finish, foffset) => {
|
|
|
6611 |
const node = toStart ? start : finish;
|
|
|
6612 |
const offset = toStart ? soffset : foffset;
|
|
|
6613 |
setExact(win, node, offset, node, offset);
|
|
|
6614 |
}));
|
|
|
6615 |
};
|
|
|
6616 |
const selectNode = element => {
|
|
|
6617 |
setToElement(win, element, false);
|
|
|
6618 |
};
|
|
|
6619 |
const selectContents = element => {
|
|
|
6620 |
setToElement(win, element);
|
|
|
6621 |
};
|
|
|
6622 |
const setSelection = sel => {
|
|
|
6623 |
setExact(win, sel.start, sel.soffset, sel.finish, sel.foffset);
|
|
|
6624 |
};
|
|
|
6625 |
const setRelativeSelection = (start, finish) => {
|
|
|
6626 |
setRelative(win, start, finish);
|
|
|
6627 |
};
|
|
|
6628 |
const getInnerHeight = () => {
|
|
|
6629 |
return win.innerHeight;
|
|
|
6630 |
};
|
|
|
6631 |
const getScrollY = () => {
|
|
|
6632 |
const pos = get$3(SugarElement.fromDom(win.document));
|
|
|
6633 |
return pos.top;
|
|
|
6634 |
};
|
|
|
6635 |
const scrollBy = (x, y) => {
|
|
|
6636 |
by(x, y, SugarElement.fromDom(win.document));
|
|
|
6637 |
};
|
|
|
6638 |
return {
|
|
|
6639 |
elementFromPoint,
|
|
|
6640 |
getRect,
|
|
|
6641 |
getRangedRect,
|
|
|
6642 |
getSelection,
|
|
|
6643 |
fromSitus,
|
|
|
6644 |
situsFromPoint,
|
|
|
6645 |
clearSelection,
|
|
|
6646 |
collapseSelection,
|
|
|
6647 |
setSelection,
|
|
|
6648 |
setRelativeSelection,
|
|
|
6649 |
selectNode,
|
|
|
6650 |
selectContents,
|
|
|
6651 |
getInnerHeight,
|
|
|
6652 |
getScrollY,
|
|
|
6653 |
scrollBy
|
|
|
6654 |
};
|
|
|
6655 |
};
|
|
|
6656 |
|
|
|
6657 |
const rc = (rows, cols) => ({
|
|
|
6658 |
rows,
|
|
|
6659 |
cols
|
|
|
6660 |
});
|
|
|
6661 |
const mouse = (win, container, isRoot, annotations) => {
|
|
|
6662 |
const bridge = WindowBridge(win);
|
|
|
6663 |
const handlers = MouseSelection(bridge, container, isRoot, annotations);
|
|
|
6664 |
return {
|
|
|
6665 |
clearstate: handlers.clearstate,
|
|
|
6666 |
mousedown: handlers.mousedown,
|
|
|
6667 |
mouseover: handlers.mouseover,
|
|
|
6668 |
mouseup: handlers.mouseup
|
|
|
6669 |
};
|
|
|
6670 |
};
|
|
|
6671 |
const isEditableNode = node => closest$2(node, isHTMLElement).exists(isEditable$1);
|
|
|
6672 |
const isEditableSelection = (start, finish) => isEditableNode(start) || isEditableNode(finish);
|
|
|
6673 |
const keyboard = (win, container, isRoot, annotations) => {
|
|
|
6674 |
const bridge = WindowBridge(win);
|
|
|
6675 |
const clearToNavigate = () => {
|
|
|
6676 |
annotations.clear(container);
|
|
|
6677 |
return Optional.none();
|
|
|
6678 |
};
|
|
|
6679 |
const keydown = (event, start, soffset, finish, foffset, direction) => {
|
|
|
6680 |
const realEvent = event.raw;
|
|
|
6681 |
const keycode = realEvent.which;
|
|
|
6682 |
const shiftKey = realEvent.shiftKey === true;
|
|
|
6683 |
const handler = retrieve$1(container, annotations.selectedSelector).fold(() => {
|
|
|
6684 |
if (isNavigation(keycode) && !shiftKey) {
|
|
|
6685 |
annotations.clearBeforeUpdate(container);
|
|
|
6686 |
}
|
|
|
6687 |
if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
|
|
|
6688 |
return Optional.none;
|
|
|
6689 |
} else if (isDown(keycode) && shiftKey) {
|
|
|
6690 |
return curry(select, bridge, container, isRoot, down, finish, start, annotations.selectRange);
|
|
|
6691 |
} else if (isUp(keycode) && shiftKey) {
|
|
|
6692 |
return curry(select, bridge, container, isRoot, up, finish, start, annotations.selectRange);
|
|
|
6693 |
} else if (isDown(keycode)) {
|
|
|
6694 |
return curry(navigate, bridge, isRoot, down, finish, start, lastDownCheck);
|
|
|
6695 |
} else if (isUp(keycode)) {
|
|
|
6696 |
return curry(navigate, bridge, isRoot, up, finish, start, firstUpCheck);
|
|
|
6697 |
} else {
|
|
|
6698 |
return Optional.none;
|
|
|
6699 |
}
|
|
|
6700 |
}, selected => {
|
|
|
6701 |
const update$1 = attempts => {
|
|
|
6702 |
return () => {
|
|
|
6703 |
const navigation = findMap(attempts, delta => {
|
|
|
6704 |
return update(delta.rows, delta.cols, container, selected, annotations);
|
|
|
6705 |
});
|
|
|
6706 |
return navigation.fold(() => {
|
|
|
6707 |
return getEdges(container, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(edges => {
|
|
|
6708 |
const relative = isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before;
|
|
|
6709 |
bridge.setRelativeSelection(Situ.on(edges.first, 0), relative(edges.table));
|
|
|
6710 |
annotations.clear(container);
|
|
|
6711 |
return Response.create(Optional.none(), true);
|
|
|
6712 |
});
|
|
|
6713 |
}, _ => {
|
|
|
6714 |
return Optional.some(Response.create(Optional.none(), true));
|
|
|
6715 |
});
|
|
|
6716 |
};
|
|
|
6717 |
};
|
|
|
6718 |
if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
|
|
|
6719 |
return Optional.none;
|
|
|
6720 |
} else if (isDown(keycode) && shiftKey) {
|
|
|
6721 |
return update$1([rc(+1, 0)]);
|
|
|
6722 |
} else if (isUp(keycode) && shiftKey) {
|
|
|
6723 |
return update$1([rc(-1, 0)]);
|
|
|
6724 |
} else if (direction.isBackward(keycode) && shiftKey) {
|
|
|
6725 |
return update$1([
|
|
|
6726 |
rc(0, -1),
|
|
|
6727 |
rc(-1, 0)
|
|
|
6728 |
]);
|
|
|
6729 |
} else if (direction.isForward(keycode) && shiftKey) {
|
|
|
6730 |
return update$1([
|
|
|
6731 |
rc(0, +1),
|
|
|
6732 |
rc(+1, 0)
|
|
|
6733 |
]);
|
|
|
6734 |
} else if (isNavigation(keycode) && !shiftKey) {
|
|
|
6735 |
return clearToNavigate;
|
|
|
6736 |
} else {
|
|
|
6737 |
return Optional.none;
|
|
|
6738 |
}
|
|
|
6739 |
});
|
|
|
6740 |
return handler();
|
|
|
6741 |
};
|
|
|
6742 |
const keyup = (event, start, soffset, finish, foffset) => {
|
|
|
6743 |
return retrieve$1(container, annotations.selectedSelector).fold(() => {
|
|
|
6744 |
const realEvent = event.raw;
|
|
|
6745 |
const keycode = realEvent.which;
|
|
|
6746 |
const shiftKey = realEvent.shiftKey === true;
|
|
|
6747 |
if (!shiftKey) {
|
|
|
6748 |
return Optional.none();
|
|
|
6749 |
}
|
|
|
6750 |
if (isNavigation(keycode) && isEditableSelection(start, finish)) {
|
|
|
6751 |
return sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange);
|
|
|
6752 |
} else {
|
|
|
6753 |
return Optional.none();
|
|
|
6754 |
}
|
|
|
6755 |
}, Optional.none);
|
|
|
6756 |
};
|
|
|
6757 |
return {
|
|
|
6758 |
keydown,
|
|
|
6759 |
keyup
|
|
|
6760 |
};
|
|
|
6761 |
};
|
|
|
6762 |
const external = (win, container, isRoot, annotations) => {
|
|
|
6763 |
const bridge = WindowBridge(win);
|
|
|
6764 |
return (start, finish) => {
|
|
|
6765 |
annotations.clearBeforeUpdate(container);
|
|
|
6766 |
identify(start, finish, isRoot).each(cellSel => {
|
|
|
6767 |
const boxes = cellSel.boxes.getOr([]);
|
|
|
6768 |
annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
|
|
|
6769 |
bridge.selectContents(finish);
|
|
|
6770 |
bridge.collapseSelection();
|
|
|
6771 |
});
|
|
|
6772 |
};
|
|
|
6773 |
};
|
|
|
6774 |
|
|
|
6775 |
const read = (element, attr) => {
|
|
|
6776 |
const value = get$b(element, attr);
|
|
|
6777 |
return value === undefined || value === '' ? [] : value.split(' ');
|
|
|
6778 |
};
|
|
|
6779 |
const add$2 = (element, attr, id) => {
|
|
|
6780 |
const old = read(element, attr);
|
|
|
6781 |
const nu = old.concat([id]);
|
|
|
6782 |
set$2(element, attr, nu.join(' '));
|
|
|
6783 |
return true;
|
|
|
6784 |
};
|
|
|
6785 |
const remove$4 = (element, attr, id) => {
|
|
|
6786 |
const nu = filter$2(read(element, attr), v => v !== id);
|
|
|
6787 |
if (nu.length > 0) {
|
|
|
6788 |
set$2(element, attr, nu.join(' '));
|
|
|
6789 |
} else {
|
|
|
6790 |
remove$7(element, attr);
|
|
|
6791 |
}
|
|
|
6792 |
return false;
|
|
|
6793 |
};
|
|
|
6794 |
|
|
|
6795 |
const supports = element => element.dom.classList !== undefined;
|
|
|
6796 |
const get$1 = element => read(element, 'class');
|
|
|
6797 |
const add$1 = (element, clazz) => add$2(element, 'class', clazz);
|
|
|
6798 |
const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
|
|
|
6799 |
|
|
|
6800 |
const add = (element, clazz) => {
|
|
|
6801 |
if (supports(element)) {
|
|
|
6802 |
element.dom.classList.add(clazz);
|
|
|
6803 |
} else {
|
|
|
6804 |
add$1(element, clazz);
|
|
|
6805 |
}
|
|
|
6806 |
};
|
|
|
6807 |
const cleanClass = element => {
|
|
|
6808 |
const classList = supports(element) ? element.dom.classList : get$1(element);
|
|
|
6809 |
if (classList.length === 0) {
|
|
|
6810 |
remove$7(element, 'class');
|
|
|
6811 |
}
|
|
|
6812 |
};
|
|
|
6813 |
const remove$2 = (element, clazz) => {
|
|
|
6814 |
if (supports(element)) {
|
|
|
6815 |
const classList = element.dom.classList;
|
|
|
6816 |
classList.remove(clazz);
|
|
|
6817 |
} else {
|
|
|
6818 |
remove$3(element, clazz);
|
|
|
6819 |
}
|
|
|
6820 |
cleanClass(element);
|
|
|
6821 |
};
|
|
|
6822 |
const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
|
|
|
6823 |
|
|
|
6824 |
const remove$1 = (element, classes) => {
|
|
|
6825 |
each$2(classes, x => {
|
|
|
6826 |
remove$2(element, x);
|
|
|
6827 |
});
|
|
|
6828 |
};
|
|
|
6829 |
|
|
|
6830 |
const addClass = clazz => element => {
|
|
|
6831 |
add(element, clazz);
|
|
|
6832 |
};
|
|
|
6833 |
const removeClasses = classes => element => {
|
|
|
6834 |
remove$1(element, classes);
|
|
|
6835 |
};
|
|
|
6836 |
|
|
|
6837 |
const byClass = ephemera => {
|
|
|
6838 |
const addSelectionClass = addClass(ephemera.selected);
|
|
|
6839 |
const removeSelectionClasses = removeClasses([
|
|
|
6840 |
ephemera.selected,
|
|
|
6841 |
ephemera.lastSelected,
|
|
|
6842 |
ephemera.firstSelected
|
|
|
6843 |
]);
|
|
|
6844 |
const clear = container => {
|
|
|
6845 |
const sels = descendants(container, ephemera.selectedSelector);
|
|
|
6846 |
each$2(sels, removeSelectionClasses);
|
|
|
6847 |
};
|
|
|
6848 |
const selectRange = (container, cells, start, finish) => {
|
|
|
6849 |
clear(container);
|
|
|
6850 |
each$2(cells, addSelectionClass);
|
|
|
6851 |
add(start, ephemera.firstSelected);
|
|
|
6852 |
add(finish, ephemera.lastSelected);
|
|
|
6853 |
};
|
|
|
6854 |
return {
|
|
|
6855 |
clearBeforeUpdate: clear,
|
|
|
6856 |
clear,
|
|
|
6857 |
selectRange,
|
|
|
6858 |
selectedSelector: ephemera.selectedSelector,
|
|
|
6859 |
firstSelectedSelector: ephemera.firstSelectedSelector,
|
|
|
6860 |
lastSelectedSelector: ephemera.lastSelectedSelector
|
|
|
6861 |
};
|
|
|
6862 |
};
|
|
|
6863 |
const byAttr = (ephemera, onSelection, onClear) => {
|
|
|
6864 |
const removeSelectionAttributes = element => {
|
|
|
6865 |
remove$7(element, ephemera.selected);
|
|
|
6866 |
remove$7(element, ephemera.firstSelected);
|
|
|
6867 |
remove$7(element, ephemera.lastSelected);
|
|
|
6868 |
};
|
|
|
6869 |
const addSelectionAttribute = element => {
|
|
|
6870 |
set$2(element, ephemera.selected, '1');
|
|
|
6871 |
};
|
|
|
6872 |
const clear = container => {
|
|
|
6873 |
clearBeforeUpdate(container);
|
|
|
6874 |
onClear();
|
|
|
6875 |
};
|
|
|
6876 |
const clearBeforeUpdate = container => {
|
|
|
6877 |
const sels = descendants(container, `${ ephemera.selectedSelector },${ ephemera.firstSelectedSelector },${ ephemera.lastSelectedSelector }`);
|
|
|
6878 |
each$2(sels, removeSelectionAttributes);
|
|
|
6879 |
};
|
|
|
6880 |
const selectRange = (container, cells, start, finish) => {
|
|
|
6881 |
clear(container);
|
|
|
6882 |
each$2(cells, addSelectionAttribute);
|
|
|
6883 |
set$2(start, ephemera.firstSelected, '1');
|
|
|
6884 |
set$2(finish, ephemera.lastSelected, '1');
|
|
|
6885 |
onSelection(cells, start, finish);
|
|
|
6886 |
};
|
|
|
6887 |
return {
|
|
|
6888 |
clearBeforeUpdate,
|
|
|
6889 |
clear,
|
|
|
6890 |
selectRange,
|
|
|
6891 |
selectedSelector: ephemera.selectedSelector,
|
|
|
6892 |
firstSelectedSelector: ephemera.firstSelectedSelector,
|
|
|
6893 |
lastSelectedSelector: ephemera.lastSelectedSelector
|
|
|
6894 |
};
|
|
|
6895 |
};
|
|
|
6896 |
const SelectionAnnotation = {
|
|
|
6897 |
byClass,
|
|
|
6898 |
byAttr
|
|
|
6899 |
};
|
|
|
6900 |
|
|
|
6901 |
const fold = (subject, onNone, onMultiple, onSingle) => {
|
|
|
6902 |
switch (subject.tag) {
|
|
|
6903 |
case 'none':
|
|
|
6904 |
return onNone();
|
|
|
6905 |
case 'single':
|
|
|
6906 |
return onSingle(subject.element);
|
|
|
6907 |
case 'multiple':
|
|
|
6908 |
return onMultiple(subject.elements);
|
|
|
6909 |
}
|
|
|
6910 |
};
|
|
|
6911 |
const none = () => ({ tag: 'none' });
|
|
|
6912 |
const multiple = elements => ({
|
|
|
6913 |
tag: 'multiple',
|
|
|
6914 |
elements
|
|
|
6915 |
});
|
|
|
6916 |
const single = element => ({
|
|
|
6917 |
tag: 'single',
|
|
|
6918 |
element
|
|
|
6919 |
});
|
|
|
6920 |
|
|
|
6921 |
const Selections = (lazyRoot, getStart, selectedSelector) => {
|
|
|
6922 |
const get = () => retrieve(lazyRoot(), selectedSelector).fold(() => getStart().fold(none, single), multiple);
|
|
|
6923 |
return { get };
|
|
|
6924 |
};
|
|
|
6925 |
|
|
|
6926 |
const getUpOrLeftCells = (grid, selectedCells) => {
|
|
|
6927 |
const upGrid = grid.slice(0, selectedCells[selectedCells.length - 1].row + 1);
|
|
|
6928 |
const upDetails = toDetailList(upGrid);
|
|
|
6929 |
return bind$2(upDetails, detail => {
|
|
|
6930 |
const slicedCells = detail.cells.slice(0, selectedCells[selectedCells.length - 1].column + 1);
|
|
|
6931 |
return map$1(slicedCells, cell => cell.element);
|
|
|
6932 |
});
|
|
|
6933 |
};
|
|
|
6934 |
const getDownOrRightCells = (grid, selectedCells) => {
|
|
|
6935 |
const downGrid = grid.slice(selectedCells[0].row + selectedCells[0].rowspan - 1, grid.length);
|
|
|
6936 |
const downDetails = toDetailList(downGrid);
|
|
|
6937 |
return bind$2(downDetails, detail => {
|
|
|
6938 |
const slicedCells = detail.cells.slice(selectedCells[0].column + selectedCells[0].colspan - 1, detail.cells.length);
|
|
|
6939 |
return map$1(slicedCells, cell => cell.element);
|
|
|
6940 |
});
|
|
|
6941 |
};
|
|
|
6942 |
const getOtherCells = (table, target, generators) => {
|
|
|
6943 |
const warehouse = Warehouse.fromTable(table);
|
|
|
6944 |
const details = onCells(warehouse, target);
|
|
|
6945 |
return details.map(selectedCells => {
|
|
|
6946 |
const grid = toGrid(warehouse, generators, false);
|
|
|
6947 |
const {rows} = extractGridDetails(grid);
|
|
|
6948 |
const upOrLeftCells = getUpOrLeftCells(rows, selectedCells);
|
|
|
6949 |
const downOrRightCells = getDownOrRightCells(rows, selectedCells);
|
|
|
6950 |
return {
|
|
|
6951 |
upOrLeftCells,
|
|
|
6952 |
downOrRightCells
|
|
|
6953 |
};
|
|
|
6954 |
});
|
|
|
6955 |
};
|
|
|
6956 |
|
|
|
6957 |
const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
|
|
|
6958 |
target,
|
|
|
6959 |
x,
|
|
|
6960 |
y,
|
|
|
6961 |
stop,
|
|
|
6962 |
prevent,
|
|
|
6963 |
kill,
|
|
|
6964 |
raw
|
|
|
6965 |
});
|
|
|
6966 |
const fromRawEvent$1 = rawEvent => {
|
|
|
6967 |
const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
|
|
|
6968 |
const stop = () => rawEvent.stopPropagation();
|
|
|
6969 |
const prevent = () => rawEvent.preventDefault();
|
|
|
6970 |
const kill = compose(prevent, stop);
|
|
|
6971 |
return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
|
|
|
6972 |
};
|
|
|
6973 |
const handle = (filter, handler) => rawEvent => {
|
|
|
6974 |
if (filter(rawEvent)) {
|
|
|
6975 |
handler(fromRawEvent$1(rawEvent));
|
|
|
6976 |
}
|
|
|
6977 |
};
|
|
|
6978 |
const binder = (element, event, filter, handler, useCapture) => {
|
|
|
6979 |
const wrapped = handle(filter, handler);
|
|
|
6980 |
element.dom.addEventListener(event, wrapped, useCapture);
|
|
|
6981 |
return { unbind: curry(unbind, element, event, wrapped, useCapture) };
|
|
|
6982 |
};
|
|
|
6983 |
const bind$1 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
|
|
|
6984 |
const unbind = (element, event, handler, useCapture) => {
|
|
|
6985 |
element.dom.removeEventListener(event, handler, useCapture);
|
|
|
6986 |
};
|
|
|
6987 |
|
|
|
6988 |
const filter = always;
|
|
|
6989 |
const bind = (element, event, handler) => bind$1(element, event, filter, handler);
|
|
|
6990 |
const fromRawEvent = fromRawEvent$1;
|
|
|
6991 |
|
|
|
6992 |
const hasInternalTarget = e => !has(SugarElement.fromDom(e.target), 'ephox-snooker-resizer-bar');
|
|
|
6993 |
const TableCellSelectionHandler = (editor, resizeHandler) => {
|
|
|
6994 |
const cellSelection = Selections(() => SugarElement.fromDom(editor.getBody()), () => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)), ephemera.selectedSelector);
|
|
|
6995 |
const onSelection = (cells, start, finish) => {
|
|
|
6996 |
const tableOpt = table(start);
|
|
|
6997 |
tableOpt.each(table => {
|
|
|
6998 |
const cloneFormats = getTableCloneElements(editor);
|
|
|
6999 |
const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), cloneFormats);
|
|
|
7000 |
const selectedCells = getCellsFromSelection(editor);
|
|
|
7001 |
const otherCells = getOtherCells(table, { selection: selectedCells }, generators);
|
|
|
7002 |
fireTableSelectionChange(editor, cells, start, finish, otherCells);
|
|
|
7003 |
});
|
|
|
7004 |
};
|
|
|
7005 |
const onClear = () => fireTableSelectionClear(editor);
|
|
|
7006 |
const annotations = SelectionAnnotation.byAttr(ephemera, onSelection, onClear);
|
|
|
7007 |
editor.on('init', _e => {
|
|
|
7008 |
const win = editor.getWin();
|
|
|
7009 |
const body = getBody(editor);
|
|
|
7010 |
const isRoot = getIsRoot(editor);
|
|
|
7011 |
const syncSelection = () => {
|
|
|
7012 |
const sel = editor.selection;
|
|
|
7013 |
const start = SugarElement.fromDom(sel.getStart());
|
|
|
7014 |
const end = SugarElement.fromDom(sel.getEnd());
|
|
|
7015 |
const shared = sharedOne(table, [
|
|
|
7016 |
start,
|
|
|
7017 |
end
|
|
|
7018 |
]);
|
|
|
7019 |
shared.fold(() => annotations.clear(body), noop);
|
|
|
7020 |
};
|
|
|
7021 |
const mouseHandlers = mouse(win, body, isRoot, annotations);
|
|
|
7022 |
const keyHandlers = keyboard(win, body, isRoot, annotations);
|
|
|
7023 |
const external$1 = external(win, body, isRoot, annotations);
|
|
|
7024 |
const hasShiftKey = event => event.raw.shiftKey === true;
|
|
|
7025 |
editor.on('TableSelectorChange', e => external$1(e.start, e.finish));
|
|
|
7026 |
const handleResponse = (event, response) => {
|
|
|
7027 |
if (!hasShiftKey(event)) {
|
|
|
7028 |
return;
|
|
|
7029 |
}
|
|
|
7030 |
if (response.kill) {
|
|
|
7031 |
event.kill();
|
|
|
7032 |
}
|
|
|
7033 |
response.selection.each(ns => {
|
|
|
7034 |
const relative = SimSelection.relative(ns.start, ns.finish);
|
|
|
7035 |
const rng = asLtrRange(win, relative);
|
|
|
7036 |
editor.selection.setRng(rng);
|
|
|
7037 |
});
|
|
|
7038 |
};
|
|
|
7039 |
const keyup = event => {
|
|
|
7040 |
const wrappedEvent = fromRawEvent(event);
|
|
|
7041 |
if (wrappedEvent.raw.shiftKey && isNavigation(wrappedEvent.raw.which)) {
|
|
|
7042 |
const rng = editor.selection.getRng();
|
|
|
7043 |
const start = SugarElement.fromDom(rng.startContainer);
|
|
|
7044 |
const end = SugarElement.fromDom(rng.endContainer);
|
|
|
7045 |
keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(response => {
|
|
|
7046 |
handleResponse(wrappedEvent, response);
|
|
|
7047 |
});
|
|
|
7048 |
}
|
|
|
7049 |
};
|
|
|
7050 |
const keydown = event => {
|
|
|
7051 |
const wrappedEvent = fromRawEvent(event);
|
|
|
7052 |
resizeHandler.hide();
|
|
|
7053 |
const rng = editor.selection.getRng();
|
|
|
7054 |
const start = SugarElement.fromDom(rng.startContainer);
|
|
|
7055 |
const end = SugarElement.fromDom(rng.endContainer);
|
|
|
7056 |
const direction = onDirection(ltr, rtl)(SugarElement.fromDom(editor.selection.getStart()));
|
|
|
7057 |
keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(response => {
|
|
|
7058 |
handleResponse(wrappedEvent, response);
|
|
|
7059 |
});
|
|
|
7060 |
resizeHandler.show();
|
|
|
7061 |
};
|
|
|
7062 |
const isLeftMouse = raw => raw.button === 0;
|
|
|
7063 |
const isLeftButtonPressed = raw => {
|
|
|
7064 |
if (raw.buttons === undefined) {
|
|
|
7065 |
return true;
|
|
|
7066 |
}
|
|
|
7067 |
return (raw.buttons & 1) !== 0;
|
|
|
7068 |
};
|
|
|
7069 |
const dragStart = _e => {
|
|
|
7070 |
mouseHandlers.clearstate();
|
|
|
7071 |
};
|
|
|
7072 |
const mouseDown = e => {
|
|
|
7073 |
if (isLeftMouse(e) && hasInternalTarget(e)) {
|
|
|
7074 |
mouseHandlers.mousedown(fromRawEvent(e));
|
|
|
7075 |
}
|
|
|
7076 |
};
|
|
|
7077 |
const mouseOver = e => {
|
|
|
7078 |
if (isLeftButtonPressed(e) && hasInternalTarget(e)) {
|
|
|
7079 |
mouseHandlers.mouseover(fromRawEvent(e));
|
|
|
7080 |
}
|
|
|
7081 |
};
|
|
|
7082 |
const mouseUp = e => {
|
|
|
7083 |
if (isLeftMouse(e) && hasInternalTarget(e)) {
|
|
|
7084 |
mouseHandlers.mouseup(fromRawEvent(e));
|
|
|
7085 |
}
|
|
|
7086 |
};
|
|
|
7087 |
const getDoubleTap = () => {
|
|
|
7088 |
const lastTarget = Cell(SugarElement.fromDom(body));
|
|
|
7089 |
const lastTimeStamp = Cell(0);
|
|
|
7090 |
const touchEnd = t => {
|
|
|
7091 |
const target = SugarElement.fromDom(t.target);
|
|
|
7092 |
if (isTag('td')(target) || isTag('th')(target)) {
|
|
|
7093 |
const lT = lastTarget.get();
|
|
|
7094 |
const lTS = lastTimeStamp.get();
|
|
|
7095 |
if (eq$1(lT, target) && t.timeStamp - lTS < 300) {
|
|
|
7096 |
t.preventDefault();
|
|
|
7097 |
external$1(target, target);
|
|
|
7098 |
}
|
|
|
7099 |
}
|
|
|
7100 |
lastTarget.set(target);
|
|
|
7101 |
lastTimeStamp.set(t.timeStamp);
|
|
|
7102 |
};
|
|
|
7103 |
return { touchEnd };
|
|
|
7104 |
};
|
|
|
7105 |
const doubleTap = getDoubleTap();
|
|
|
7106 |
editor.on('dragstart', dragStart);
|
|
|
7107 |
editor.on('mousedown', mouseDown);
|
|
|
7108 |
editor.on('mouseover', mouseOver);
|
|
|
7109 |
editor.on('mouseup', mouseUp);
|
|
|
7110 |
editor.on('touchend', doubleTap.touchEnd);
|
|
|
7111 |
editor.on('keyup', keyup);
|
|
|
7112 |
editor.on('keydown', keydown);
|
|
|
7113 |
editor.on('NodeChange', syncSelection);
|
|
|
7114 |
});
|
|
|
7115 |
editor.on('PreInit', () => {
|
|
|
7116 |
editor.serializer.addTempAttr(ephemera.firstSelected);
|
|
|
7117 |
editor.serializer.addTempAttr(ephemera.lastSelected);
|
|
|
7118 |
});
|
|
|
7119 |
const clearSelectedCells = container => annotations.clear(SugarElement.fromDom(container));
|
|
|
7120 |
const getSelectedCells = () => fold(cellSelection.get(), constant([]), cells => {
|
|
|
7121 |
return map$1(cells, cell => cell.dom);
|
|
|
7122 |
}, cell => [cell.dom]);
|
|
|
7123 |
return {
|
|
|
7124 |
getSelectedCells,
|
|
|
7125 |
clearSelectedCells
|
|
|
7126 |
};
|
|
|
7127 |
};
|
|
|
7128 |
|
|
|
7129 |
const Event = fields => {
|
|
|
7130 |
let handlers = [];
|
|
|
7131 |
const bind = handler => {
|
|
|
7132 |
if (handler === undefined) {
|
|
|
7133 |
throw new Error('Event bind error: undefined handler');
|
|
|
7134 |
}
|
|
|
7135 |
handlers.push(handler);
|
|
|
7136 |
};
|
|
|
7137 |
const unbind = handler => {
|
|
|
7138 |
handlers = filter$2(handlers, h => {
|
|
|
7139 |
return h !== handler;
|
|
|
7140 |
});
|
|
|
7141 |
};
|
|
|
7142 |
const trigger = (...args) => {
|
|
|
7143 |
const event = {};
|
|
|
7144 |
each$2(fields, (name, i) => {
|
|
|
7145 |
event[name] = args[i];
|
|
|
7146 |
});
|
|
|
7147 |
each$2(handlers, handler => {
|
|
|
7148 |
handler(event);
|
|
|
7149 |
});
|
|
|
7150 |
};
|
|
|
7151 |
return {
|
|
|
7152 |
bind,
|
|
|
7153 |
unbind,
|
|
|
7154 |
trigger
|
|
|
7155 |
};
|
|
|
7156 |
};
|
|
|
7157 |
|
|
|
7158 |
const create$1 = typeDefs => {
|
|
|
7159 |
const registry = map(typeDefs, event => {
|
|
|
7160 |
return {
|
|
|
7161 |
bind: event.bind,
|
|
|
7162 |
unbind: event.unbind
|
|
|
7163 |
};
|
|
|
7164 |
});
|
|
|
7165 |
const trigger = map(typeDefs, event => {
|
|
|
7166 |
return event.trigger;
|
|
|
7167 |
});
|
|
|
7168 |
return {
|
|
|
7169 |
registry,
|
|
|
7170 |
trigger
|
|
|
7171 |
};
|
|
|
7172 |
};
|
|
|
7173 |
|
|
|
7174 |
const last = (fn, rate) => {
|
|
|
7175 |
let timer = null;
|
|
|
7176 |
const cancel = () => {
|
|
|
7177 |
if (!isNull(timer)) {
|
|
|
7178 |
clearTimeout(timer);
|
|
|
7179 |
timer = null;
|
|
|
7180 |
}
|
|
|
7181 |
};
|
|
|
7182 |
const throttle = (...args) => {
|
|
|
7183 |
cancel();
|
|
|
7184 |
timer = setTimeout(() => {
|
|
|
7185 |
timer = null;
|
|
|
7186 |
fn.apply(null, args);
|
|
|
7187 |
}, rate);
|
|
|
7188 |
};
|
|
|
7189 |
return {
|
|
|
7190 |
cancel,
|
|
|
7191 |
throttle
|
|
|
7192 |
};
|
|
|
7193 |
};
|
|
|
7194 |
|
|
|
7195 |
const sort = arr => {
|
|
|
7196 |
return arr.slice(0).sort();
|
|
|
7197 |
};
|
|
|
7198 |
const reqMessage = (required, keys) => {
|
|
|
7199 |
throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.');
|
|
|
7200 |
};
|
|
|
7201 |
const unsuppMessage = unsupported => {
|
|
|
7202 |
throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', '));
|
|
|
7203 |
};
|
|
|
7204 |
const validateStrArr = (label, array) => {
|
|
|
7205 |
if (!isArray(array)) {
|
|
|
7206 |
throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.');
|
|
|
7207 |
}
|
|
|
7208 |
each$2(array, a => {
|
|
|
7209 |
if (!isString(a)) {
|
|
|
7210 |
throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.');
|
|
|
7211 |
}
|
|
|
7212 |
});
|
|
|
7213 |
};
|
|
|
7214 |
const invalidTypeMessage = (incorrect, type) => {
|
|
|
7215 |
throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.');
|
|
|
7216 |
};
|
|
|
7217 |
const checkDupes = everything => {
|
|
|
7218 |
const sorted = sort(everything);
|
|
|
7219 |
const dupe = find$1(sorted, (s, i) => {
|
|
|
7220 |
return i < sorted.length - 1 && s === sorted[i + 1];
|
|
|
7221 |
});
|
|
|
7222 |
dupe.each(d => {
|
|
|
7223 |
throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].');
|
|
|
7224 |
});
|
|
|
7225 |
};
|
|
|
7226 |
|
|
|
7227 |
const base = (handleUnsupported, required) => {
|
|
|
7228 |
return baseWith(handleUnsupported, required, {
|
|
|
7229 |
validate: isFunction,
|
|
|
7230 |
label: 'function'
|
|
|
7231 |
});
|
|
|
7232 |
};
|
|
|
7233 |
const baseWith = (handleUnsupported, required, pred) => {
|
|
|
7234 |
if (required.length === 0) {
|
|
|
7235 |
throw new Error('You must specify at least one required field.');
|
|
|
7236 |
}
|
|
|
7237 |
validateStrArr('required', required);
|
|
|
7238 |
checkDupes(required);
|
|
|
7239 |
return obj => {
|
|
|
7240 |
const keys$1 = keys(obj);
|
|
|
7241 |
const allReqd = forall(required, req => {
|
|
|
7242 |
return contains$2(keys$1, req);
|
|
|
7243 |
});
|
|
|
7244 |
if (!allReqd) {
|
|
|
7245 |
reqMessage(required, keys$1);
|
|
|
7246 |
}
|
|
|
7247 |
handleUnsupported(required, keys$1);
|
|
|
7248 |
const invalidKeys = filter$2(required, key => {
|
|
|
7249 |
return !pred.validate(obj[key], key);
|
|
|
7250 |
});
|
|
|
7251 |
if (invalidKeys.length > 0) {
|
|
|
7252 |
invalidTypeMessage(invalidKeys, pred.label);
|
|
|
7253 |
}
|
|
|
7254 |
return obj;
|
|
|
7255 |
};
|
|
|
7256 |
};
|
|
|
7257 |
const handleExact = (required, keys) => {
|
|
|
7258 |
const unsupported = filter$2(keys, key => {
|
|
|
7259 |
return !contains$2(required, key);
|
|
|
7260 |
});
|
|
|
7261 |
if (unsupported.length > 0) {
|
|
|
7262 |
unsuppMessage(unsupported);
|
|
|
7263 |
}
|
|
|
7264 |
};
|
|
|
7265 |
const exactly = required => base(handleExact, required);
|
|
|
7266 |
|
|
|
7267 |
const DragMode = exactly([
|
|
|
7268 |
'compare',
|
|
|
7269 |
'extract',
|
|
|
7270 |
'mutate',
|
|
|
7271 |
'sink'
|
|
|
7272 |
]);
|
|
|
7273 |
const DragSink = exactly([
|
|
|
7274 |
'element',
|
|
|
7275 |
'start',
|
|
|
7276 |
'stop',
|
|
|
7277 |
'destroy'
|
|
|
7278 |
]);
|
|
|
7279 |
const DragApi = exactly([
|
|
|
7280 |
'forceDrop',
|
|
|
7281 |
'drop',
|
|
|
7282 |
'move',
|
|
|
7283 |
'delayDrop'
|
|
|
7284 |
]);
|
|
|
7285 |
|
|
|
7286 |
const InDrag = () => {
|
|
|
7287 |
let previous = Optional.none();
|
|
|
7288 |
const reset = () => {
|
|
|
7289 |
previous = Optional.none();
|
|
|
7290 |
};
|
|
|
7291 |
const update = (mode, nu) => {
|
|
|
7292 |
const result = previous.map(old => {
|
|
|
7293 |
return mode.compare(old, nu);
|
|
|
7294 |
});
|
|
|
7295 |
previous = Optional.some(nu);
|
|
|
7296 |
return result;
|
|
|
7297 |
};
|
|
|
7298 |
const onEvent = (event, mode) => {
|
|
|
7299 |
const dataOption = mode.extract(event);
|
|
|
7300 |
dataOption.each(data => {
|
|
|
7301 |
const offset = update(mode, data);
|
|
|
7302 |
offset.each(d => {
|
|
|
7303 |
events.trigger.move(d);
|
|
|
7304 |
});
|
|
|
7305 |
});
|
|
|
7306 |
};
|
|
|
7307 |
const events = create$1({ move: Event(['info']) });
|
|
|
7308 |
return {
|
|
|
7309 |
onEvent,
|
|
|
7310 |
reset,
|
|
|
7311 |
events: events.registry
|
|
|
7312 |
};
|
|
|
7313 |
};
|
|
|
7314 |
|
|
|
7315 |
const NoDrag = () => {
|
|
|
7316 |
const events = create$1({ move: Event(['info']) });
|
|
|
7317 |
return {
|
|
|
7318 |
onEvent: noop,
|
|
|
7319 |
reset: noop,
|
|
|
7320 |
events: events.registry
|
|
|
7321 |
};
|
|
|
7322 |
};
|
|
|
7323 |
|
|
|
7324 |
const Movement = () => {
|
|
|
7325 |
const noDragState = NoDrag();
|
|
|
7326 |
const inDragState = InDrag();
|
|
|
7327 |
let dragState = noDragState;
|
|
|
7328 |
const on = () => {
|
|
|
7329 |
dragState.reset();
|
|
|
7330 |
dragState = inDragState;
|
|
|
7331 |
};
|
|
|
7332 |
const off = () => {
|
|
|
7333 |
dragState.reset();
|
|
|
7334 |
dragState = noDragState;
|
|
|
7335 |
};
|
|
|
7336 |
const onEvent = (event, mode) => {
|
|
|
7337 |
dragState.onEvent(event, mode);
|
|
|
7338 |
};
|
|
|
7339 |
const isOn = () => {
|
|
|
7340 |
return dragState === inDragState;
|
|
|
7341 |
};
|
|
|
7342 |
return {
|
|
|
7343 |
on,
|
|
|
7344 |
off,
|
|
|
7345 |
isOn,
|
|
|
7346 |
onEvent,
|
|
|
7347 |
events: inDragState.events
|
|
|
7348 |
};
|
|
|
7349 |
};
|
|
|
7350 |
|
|
|
7351 |
const setup = (mutation, mode, settings) => {
|
|
|
7352 |
let active = false;
|
|
|
7353 |
const events = create$1({
|
|
|
7354 |
start: Event([]),
|
|
|
7355 |
stop: Event([])
|
|
|
7356 |
});
|
|
|
7357 |
const movement = Movement();
|
|
|
7358 |
const drop = () => {
|
|
|
7359 |
sink.stop();
|
|
|
7360 |
if (movement.isOn()) {
|
|
|
7361 |
movement.off();
|
|
|
7362 |
events.trigger.stop();
|
|
|
7363 |
}
|
|
|
7364 |
};
|
|
|
7365 |
const throttledDrop = last(drop, 200);
|
|
|
7366 |
const go = parent => {
|
|
|
7367 |
sink.start(parent);
|
|
|
7368 |
movement.on();
|
|
|
7369 |
events.trigger.start();
|
|
|
7370 |
};
|
|
|
7371 |
const mousemove = event => {
|
|
|
7372 |
throttledDrop.cancel();
|
|
|
7373 |
movement.onEvent(event, mode);
|
|
|
7374 |
};
|
|
|
7375 |
movement.events.move.bind(event => {
|
|
|
7376 |
mode.mutate(mutation, event.info);
|
|
|
7377 |
});
|
|
|
7378 |
const on = () => {
|
|
|
7379 |
active = true;
|
|
|
7380 |
};
|
|
|
7381 |
const off = () => {
|
|
|
7382 |
active = false;
|
|
|
7383 |
};
|
|
|
7384 |
const isActive = () => active;
|
|
|
7385 |
const runIfActive = f => {
|
|
|
7386 |
return (...args) => {
|
|
|
7387 |
if (active) {
|
|
|
7388 |
f.apply(null, args);
|
|
|
7389 |
}
|
|
|
7390 |
};
|
|
|
7391 |
};
|
|
|
7392 |
const sink = mode.sink(DragApi({
|
|
|
7393 |
forceDrop: drop,
|
|
|
7394 |
drop: runIfActive(drop),
|
|
|
7395 |
move: runIfActive(mousemove),
|
|
|
7396 |
delayDrop: runIfActive(throttledDrop.throttle)
|
|
|
7397 |
}), settings);
|
|
|
7398 |
const destroy = () => {
|
|
|
7399 |
sink.destroy();
|
|
|
7400 |
};
|
|
|
7401 |
return {
|
|
|
7402 |
element: sink.element,
|
|
|
7403 |
go,
|
|
|
7404 |
on,
|
|
|
7405 |
off,
|
|
|
7406 |
isActive,
|
|
|
7407 |
destroy,
|
|
|
7408 |
events: events.registry
|
|
|
7409 |
};
|
|
|
7410 |
};
|
|
|
7411 |
|
|
|
7412 |
const css = namespace => {
|
|
|
7413 |
const dashNamespace = namespace.replace(/\./g, '-');
|
|
|
7414 |
const resolve = str => {
|
|
|
7415 |
return dashNamespace + '-' + str;
|
|
|
7416 |
};
|
|
|
7417 |
return { resolve };
|
|
|
7418 |
};
|
|
|
7419 |
|
|
|
7420 |
const styles$1 = css('ephox-dragster');
|
|
|
7421 |
const resolve$1 = styles$1.resolve;
|
|
|
7422 |
|
|
|
7423 |
const Blocker = options => {
|
|
|
7424 |
const settings = {
|
|
|
7425 |
layerClass: resolve$1('blocker'),
|
|
|
7426 |
...options
|
|
|
7427 |
};
|
|
|
7428 |
const div = SugarElement.fromTag('div');
|
|
|
7429 |
set$2(div, 'role', 'presentation');
|
|
|
7430 |
setAll(div, {
|
|
|
7431 |
position: 'fixed',
|
|
|
7432 |
left: '0px',
|
|
|
7433 |
top: '0px',
|
|
|
7434 |
width: '100%',
|
|
|
7435 |
height: '100%'
|
|
|
7436 |
});
|
|
|
7437 |
add(div, resolve$1('blocker'));
|
|
|
7438 |
add(div, settings.layerClass);
|
|
|
7439 |
const element = constant(div);
|
|
|
7440 |
const destroy = () => {
|
|
|
7441 |
remove$6(div);
|
|
|
7442 |
};
|
|
|
7443 |
return {
|
|
|
7444 |
element,
|
|
|
7445 |
destroy
|
|
|
7446 |
};
|
|
|
7447 |
};
|
|
|
7448 |
|
|
|
7449 |
const compare = (old, nu) => {
|
|
|
7450 |
return SugarPosition(nu.left - old.left, nu.top - old.top);
|
|
|
7451 |
};
|
|
|
7452 |
const extract = event => {
|
|
|
7453 |
return Optional.some(SugarPosition(event.x, event.y));
|
|
|
7454 |
};
|
|
|
7455 |
const mutate = (mutation, info) => {
|
|
|
7456 |
mutation.mutate(info.left, info.top);
|
|
|
7457 |
};
|
|
|
7458 |
const sink = (dragApi, settings) => {
|
|
|
7459 |
const blocker = Blocker(settings);
|
|
|
7460 |
const mdown = bind(blocker.element(), 'mousedown', dragApi.forceDrop);
|
|
|
7461 |
const mup = bind(blocker.element(), 'mouseup', dragApi.drop);
|
|
|
7462 |
const mmove = bind(blocker.element(), 'mousemove', dragApi.move);
|
|
|
7463 |
const mout = bind(blocker.element(), 'mouseout', dragApi.delayDrop);
|
|
|
7464 |
const destroy = () => {
|
|
|
7465 |
blocker.destroy();
|
|
|
7466 |
mup.unbind();
|
|
|
7467 |
mmove.unbind();
|
|
|
7468 |
mout.unbind();
|
|
|
7469 |
mdown.unbind();
|
|
|
7470 |
};
|
|
|
7471 |
const start = parent => {
|
|
|
7472 |
append$1(parent, blocker.element());
|
|
|
7473 |
};
|
|
|
7474 |
const stop = () => {
|
|
|
7475 |
remove$6(blocker.element());
|
|
|
7476 |
};
|
|
|
7477 |
return DragSink({
|
|
|
7478 |
element: blocker.element,
|
|
|
7479 |
start,
|
|
|
7480 |
stop,
|
|
|
7481 |
destroy
|
|
|
7482 |
});
|
|
|
7483 |
};
|
|
|
7484 |
var MouseDrag = DragMode({
|
|
|
7485 |
compare,
|
|
|
7486 |
extract,
|
|
|
7487 |
sink,
|
|
|
7488 |
mutate
|
|
|
7489 |
});
|
|
|
7490 |
|
|
|
7491 |
const transform = (mutation, settings = {}) => {
|
|
|
7492 |
var _a;
|
|
|
7493 |
const mode = (_a = settings.mode) !== null && _a !== void 0 ? _a : MouseDrag;
|
|
|
7494 |
return setup(mutation, mode, settings);
|
|
|
7495 |
};
|
|
|
7496 |
|
|
|
7497 |
const styles = css('ephox-snooker');
|
|
|
7498 |
const resolve = styles.resolve;
|
|
|
7499 |
|
|
|
7500 |
const Mutation = () => {
|
|
|
7501 |
const events = create$1({
|
|
|
7502 |
drag: Event([
|
|
|
7503 |
'xDelta',
|
|
|
7504 |
'yDelta'
|
|
|
7505 |
])
|
|
|
7506 |
});
|
|
|
7507 |
const mutate = (x, y) => {
|
|
|
7508 |
events.trigger.drag(x, y);
|
|
|
7509 |
};
|
|
|
7510 |
return {
|
|
|
7511 |
mutate,
|
|
|
7512 |
events: events.registry
|
|
|
7513 |
};
|
|
|
7514 |
};
|
|
|
7515 |
|
|
|
7516 |
const BarMutation = () => {
|
|
|
7517 |
const events = create$1({
|
|
|
7518 |
drag: Event([
|
|
|
7519 |
'xDelta',
|
|
|
7520 |
'yDelta',
|
|
|
7521 |
'target'
|
|
|
7522 |
])
|
|
|
7523 |
});
|
|
|
7524 |
let target = Optional.none();
|
|
|
7525 |
const delegate = Mutation();
|
|
|
7526 |
delegate.events.drag.bind(event => {
|
|
|
7527 |
target.each(t => {
|
|
|
7528 |
events.trigger.drag(event.xDelta, event.yDelta, t);
|
|
|
7529 |
});
|
|
|
7530 |
});
|
|
|
7531 |
const assign = t => {
|
|
|
7532 |
target = Optional.some(t);
|
|
|
7533 |
};
|
|
|
7534 |
const get = () => {
|
|
|
7535 |
return target;
|
|
|
7536 |
};
|
|
|
7537 |
return {
|
|
|
7538 |
assign,
|
|
|
7539 |
get,
|
|
|
7540 |
mutate: delegate.mutate,
|
|
|
7541 |
events: events.registry
|
|
|
7542 |
};
|
|
|
7543 |
};
|
|
|
7544 |
|
|
|
7545 |
const col = (column, x, y, w, h) => {
|
|
|
7546 |
const bar = SugarElement.fromTag('div');
|
|
|
7547 |
setAll(bar, {
|
|
|
7548 |
position: 'absolute',
|
|
|
7549 |
left: x - w / 2 + 'px',
|
|
|
7550 |
top: y + 'px',
|
|
|
7551 |
height: h + 'px',
|
|
|
7552 |
width: w + 'px'
|
|
|
7553 |
});
|
|
|
7554 |
setAll$1(bar, {
|
|
|
7555 |
'data-column': column,
|
|
|
7556 |
'role': 'presentation'
|
|
|
7557 |
});
|
|
|
7558 |
return bar;
|
|
|
7559 |
};
|
|
|
7560 |
const row = (r, x, y, w, h) => {
|
|
|
7561 |
const bar = SugarElement.fromTag('div');
|
|
|
7562 |
setAll(bar, {
|
|
|
7563 |
position: 'absolute',
|
|
|
7564 |
left: x + 'px',
|
|
|
7565 |
top: y - h / 2 + 'px',
|
|
|
7566 |
height: h + 'px',
|
|
|
7567 |
width: w + 'px'
|
|
|
7568 |
});
|
|
|
7569 |
setAll$1(bar, {
|
|
|
7570 |
'data-row': r,
|
|
|
7571 |
'role': 'presentation'
|
|
|
7572 |
});
|
|
|
7573 |
return bar;
|
|
|
7574 |
};
|
|
|
7575 |
|
|
|
7576 |
const resizeBar = resolve('resizer-bar');
|
|
|
7577 |
const resizeRowBar = resolve('resizer-rows');
|
|
|
7578 |
const resizeColBar = resolve('resizer-cols');
|
|
|
7579 |
const BAR_THICKNESS = 7;
|
|
|
7580 |
const resizableRows = (warehouse, isResizable) => bind$2(warehouse.all, (row, i) => isResizable(row.element) ? [i] : []);
|
|
|
7581 |
const resizableColumns = (warehouse, isResizable) => {
|
|
|
7582 |
const resizableCols = [];
|
|
|
7583 |
range$1(warehouse.grid.columns, index => {
|
|
|
7584 |
const colElmOpt = Warehouse.getColumnAt(warehouse, index).map(col => col.element);
|
|
|
7585 |
if (colElmOpt.forall(isResizable)) {
|
|
|
7586 |
resizableCols.push(index);
|
|
|
7587 |
}
|
|
|
7588 |
});
|
|
|
7589 |
return filter$2(resizableCols, colIndex => {
|
|
|
7590 |
const columnCells = Warehouse.filterItems(warehouse, cell => cell.column === colIndex);
|
|
|
7591 |
return forall(columnCells, cell => isResizable(cell.element));
|
|
|
7592 |
});
|
|
|
7593 |
};
|
|
|
7594 |
const destroy = wire => {
|
|
|
7595 |
const previous = descendants(wire.parent(), '.' + resizeBar);
|
|
|
7596 |
each$2(previous, remove$6);
|
|
|
7597 |
};
|
|
|
7598 |
const drawBar = (wire, positions, create) => {
|
|
|
7599 |
const origin = wire.origin();
|
|
|
7600 |
each$2(positions, cpOption => {
|
|
|
7601 |
cpOption.each(cp => {
|
|
|
7602 |
const bar = create(origin, cp);
|
|
|
7603 |
add(bar, resizeBar);
|
|
|
7604 |
append$1(wire.parent(), bar);
|
|
|
7605 |
});
|
|
|
7606 |
});
|
|
|
7607 |
};
|
|
|
7608 |
const refreshCol = (wire, colPositions, position, tableHeight) => {
|
|
|
7609 |
drawBar(wire, colPositions, (origin, cp) => {
|
|
|
7610 |
const colBar = col(cp.col, cp.x - origin.left, position.top - origin.top, BAR_THICKNESS, tableHeight);
|
|
|
7611 |
add(colBar, resizeColBar);
|
|
|
7612 |
return colBar;
|
|
|
7613 |
});
|
|
|
7614 |
};
|
|
|
7615 |
const refreshRow = (wire, rowPositions, position, tableWidth) => {
|
|
|
7616 |
drawBar(wire, rowPositions, (origin, cp) => {
|
|
|
7617 |
const rowBar = row(cp.row, position.left - origin.left, cp.y - origin.top, tableWidth, BAR_THICKNESS);
|
|
|
7618 |
add(rowBar, resizeRowBar);
|
|
|
7619 |
return rowBar;
|
|
|
7620 |
});
|
|
|
7621 |
};
|
|
|
7622 |
const refreshGrid = (warhouse, wire, table, rows, cols) => {
|
|
|
7623 |
const position = absolute(table);
|
|
|
7624 |
const isResizable = wire.isResizable;
|
|
|
7625 |
const rowPositions = rows.length > 0 ? height.positions(rows, table) : [];
|
|
|
7626 |
const resizableRowBars = rowPositions.length > 0 ? resizableRows(warhouse, isResizable) : [];
|
|
|
7627 |
const resizableRowPositions = filter$2(rowPositions, (_pos, i) => exists(resizableRowBars, barIndex => i === barIndex));
|
|
|
7628 |
refreshRow(wire, resizableRowPositions, position, getOuter$2(table));
|
|
|
7629 |
const colPositions = cols.length > 0 ? width.positions(cols, table) : [];
|
|
|
7630 |
const resizableColBars = colPositions.length > 0 ? resizableColumns(warhouse, isResizable) : [];
|
|
|
7631 |
const resizableColPositions = filter$2(colPositions, (_pos, i) => exists(resizableColBars, barIndex => i === barIndex));
|
|
|
7632 |
refreshCol(wire, resizableColPositions, position, getOuter$1(table));
|
|
|
7633 |
};
|
|
|
7634 |
const refresh = (wire, table) => {
|
|
|
7635 |
destroy(wire);
|
|
|
7636 |
if (wire.isResizable(table)) {
|
|
|
7637 |
const warehouse = Warehouse.fromTable(table);
|
|
|
7638 |
const rows$1 = rows(warehouse);
|
|
|
7639 |
const cols = columns(warehouse);
|
|
|
7640 |
refreshGrid(warehouse, wire, table, rows$1, cols);
|
|
|
7641 |
}
|
|
|
7642 |
};
|
|
|
7643 |
const each = (wire, f) => {
|
|
|
7644 |
const bars = descendants(wire.parent(), '.' + resizeBar);
|
|
|
7645 |
each$2(bars, f);
|
|
|
7646 |
};
|
|
|
7647 |
const hide = wire => {
|
|
|
7648 |
each(wire, bar => {
|
|
|
7649 |
set$1(bar, 'display', 'none');
|
|
|
7650 |
});
|
|
|
7651 |
};
|
|
|
7652 |
const show = wire => {
|
|
|
7653 |
each(wire, bar => {
|
|
|
7654 |
set$1(bar, 'display', 'block');
|
|
|
7655 |
});
|
|
|
7656 |
};
|
|
|
7657 |
const isRowBar = element => {
|
|
|
7658 |
return has(element, resizeRowBar);
|
|
|
7659 |
};
|
|
|
7660 |
const isColBar = element => {
|
|
|
7661 |
return has(element, resizeColBar);
|
|
|
7662 |
};
|
|
|
7663 |
|
|
|
7664 |
const resizeBarDragging = resolve('resizer-bar-dragging');
|
|
|
7665 |
const BarManager = wire => {
|
|
|
7666 |
const mutation = BarMutation();
|
|
|
7667 |
const resizing = transform(mutation, {});
|
|
|
7668 |
let hoverTable = Optional.none();
|
|
|
7669 |
const getResizer = (element, type) => {
|
|
|
7670 |
return Optional.from(get$b(element, type));
|
|
|
7671 |
};
|
|
|
7672 |
mutation.events.drag.bind(event => {
|
|
|
7673 |
getResizer(event.target, 'data-row').each(_dataRow => {
|
|
|
7674 |
const currentRow = getCssValue(event.target, 'top');
|
|
|
7675 |
set$1(event.target, 'top', currentRow + event.yDelta + 'px');
|
|
|
7676 |
});
|
|
|
7677 |
getResizer(event.target, 'data-column').each(_dataCol => {
|
|
|
7678 |
const currentCol = getCssValue(event.target, 'left');
|
|
|
7679 |
set$1(event.target, 'left', currentCol + event.xDelta + 'px');
|
|
|
7680 |
});
|
|
|
7681 |
});
|
|
|
7682 |
const getDelta = (target, dir) => {
|
|
|
7683 |
const newX = getCssValue(target, dir);
|
|
|
7684 |
const oldX = getAttrValue(target, 'data-initial-' + dir, 0);
|
|
|
7685 |
return newX - oldX;
|
|
|
7686 |
};
|
|
|
7687 |
resizing.events.stop.bind(() => {
|
|
|
7688 |
mutation.get().each(target => {
|
|
|
7689 |
hoverTable.each(table => {
|
|
|
7690 |
getResizer(target, 'data-row').each(row => {
|
|
|
7691 |
const delta = getDelta(target, 'top');
|
|
|
7692 |
remove$7(target, 'data-initial-top');
|
|
|
7693 |
events.trigger.adjustHeight(table, delta, parseInt(row, 10));
|
|
|
7694 |
});
|
|
|
7695 |
getResizer(target, 'data-column').each(column => {
|
|
|
7696 |
const delta = getDelta(target, 'left');
|
|
|
7697 |
remove$7(target, 'data-initial-left');
|
|
|
7698 |
events.trigger.adjustWidth(table, delta, parseInt(column, 10));
|
|
|
7699 |
});
|
|
|
7700 |
refresh(wire, table);
|
|
|
7701 |
});
|
|
|
7702 |
});
|
|
|
7703 |
});
|
|
|
7704 |
const handler = (target, dir) => {
|
|
|
7705 |
events.trigger.startAdjust();
|
|
|
7706 |
mutation.assign(target);
|
|
|
7707 |
set$2(target, 'data-initial-' + dir, getCssValue(target, dir));
|
|
|
7708 |
add(target, resizeBarDragging);
|
|
|
7709 |
set$1(target, 'opacity', '0.2');
|
|
|
7710 |
resizing.go(wire.parent());
|
|
|
7711 |
};
|
|
|
7712 |
const mousedown = bind(wire.parent(), 'mousedown', event => {
|
|
|
7713 |
if (isRowBar(event.target)) {
|
|
|
7714 |
handler(event.target, 'top');
|
|
|
7715 |
}
|
|
|
7716 |
if (isColBar(event.target)) {
|
|
|
7717 |
handler(event.target, 'left');
|
|
|
7718 |
}
|
|
|
7719 |
});
|
|
|
7720 |
const isRoot = e => {
|
|
|
7721 |
return eq$1(e, wire.view());
|
|
|
7722 |
};
|
|
|
7723 |
const findClosestEditableTable = target => closest$1(target, 'table', isRoot).filter(isEditable$1);
|
|
|
7724 |
const mouseover = bind(wire.view(), 'mouseover', event => {
|
|
|
7725 |
findClosestEditableTable(event.target).fold(() => {
|
|
|
7726 |
if (inBody(event.target)) {
|
|
|
7727 |
destroy(wire);
|
|
|
7728 |
}
|
|
|
7729 |
}, table => {
|
|
|
7730 |
if (resizing.isActive()) {
|
|
|
7731 |
hoverTable = Optional.some(table);
|
|
|
7732 |
refresh(wire, table);
|
|
|
7733 |
}
|
|
|
7734 |
});
|
|
|
7735 |
});
|
|
|
7736 |
const destroy$1 = () => {
|
|
|
7737 |
mousedown.unbind();
|
|
|
7738 |
mouseover.unbind();
|
|
|
7739 |
resizing.destroy();
|
|
|
7740 |
destroy(wire);
|
|
|
7741 |
};
|
|
|
7742 |
const refresh$1 = tbl => {
|
|
|
7743 |
refresh(wire, tbl);
|
|
|
7744 |
};
|
|
|
7745 |
const events = create$1({
|
|
|
7746 |
adjustHeight: Event([
|
|
|
7747 |
'table',
|
|
|
7748 |
'delta',
|
|
|
7749 |
'row'
|
|
|
7750 |
]),
|
|
|
7751 |
adjustWidth: Event([
|
|
|
7752 |
'table',
|
|
|
7753 |
'delta',
|
|
|
7754 |
'column'
|
|
|
7755 |
]),
|
|
|
7756 |
startAdjust: Event([])
|
|
|
7757 |
});
|
|
|
7758 |
return {
|
|
|
7759 |
destroy: destroy$1,
|
|
|
7760 |
refresh: refresh$1,
|
|
|
7761 |
on: resizing.on,
|
|
|
7762 |
off: resizing.off,
|
|
|
7763 |
hideBars: curry(hide, wire),
|
|
|
7764 |
showBars: curry(show, wire),
|
|
|
7765 |
events: events.registry
|
|
|
7766 |
};
|
|
|
7767 |
};
|
|
|
7768 |
|
|
|
7769 |
const create = (wire, resizing, lazySizing) => {
|
|
|
7770 |
const hdirection = height;
|
|
|
7771 |
const vdirection = width;
|
|
|
7772 |
const manager = BarManager(wire);
|
|
|
7773 |
const events = create$1({
|
|
|
7774 |
beforeResize: Event([
|
|
|
7775 |
'table',
|
|
|
7776 |
'type'
|
|
|
7777 |
]),
|
|
|
7778 |
afterResize: Event([
|
|
|
7779 |
'table',
|
|
|
7780 |
'type'
|
|
|
7781 |
]),
|
|
|
7782 |
startDrag: Event([])
|
|
|
7783 |
});
|
|
|
7784 |
manager.events.adjustHeight.bind(event => {
|
|
|
7785 |
const table = event.table;
|
|
|
7786 |
events.trigger.beforeResize(table, 'row');
|
|
|
7787 |
const delta = hdirection.delta(event.delta, table);
|
|
|
7788 |
adjustHeight(table, delta, event.row, hdirection);
|
|
|
7789 |
events.trigger.afterResize(table, 'row');
|
|
|
7790 |
});
|
|
|
7791 |
manager.events.startAdjust.bind(_event => {
|
|
|
7792 |
events.trigger.startDrag();
|
|
|
7793 |
});
|
|
|
7794 |
manager.events.adjustWidth.bind(event => {
|
|
|
7795 |
const table = event.table;
|
|
|
7796 |
events.trigger.beforeResize(table, 'col');
|
|
|
7797 |
const delta = vdirection.delta(event.delta, table);
|
|
|
7798 |
const tableSize = lazySizing(table);
|
|
|
7799 |
adjustWidth(table, delta, event.column, resizing, tableSize);
|
|
|
7800 |
events.trigger.afterResize(table, 'col');
|
|
|
7801 |
});
|
|
|
7802 |
return {
|
|
|
7803 |
on: manager.on,
|
|
|
7804 |
off: manager.off,
|
|
|
7805 |
refreshBars: manager.refresh,
|
|
|
7806 |
hideBars: manager.hideBars,
|
|
|
7807 |
showBars: manager.showBars,
|
|
|
7808 |
destroy: manager.destroy,
|
|
|
7809 |
events: events.registry
|
|
|
7810 |
};
|
|
|
7811 |
};
|
|
|
7812 |
const TableResize = { create };
|
|
|
7813 |
|
|
|
7814 |
const only = (element, isResizable) => {
|
|
|
7815 |
const parent = isDocument(element) ? documentElement(element) : element;
|
|
|
7816 |
return {
|
|
|
7817 |
parent: constant(parent),
|
|
|
7818 |
view: constant(element),
|
|
|
7819 |
origin: constant(SugarPosition(0, 0)),
|
|
|
7820 |
isResizable
|
|
|
7821 |
};
|
|
|
7822 |
};
|
|
|
7823 |
const detached = (editable, chrome, isResizable) => {
|
|
|
7824 |
const origin = () => absolute(chrome);
|
|
|
7825 |
return {
|
|
|
7826 |
parent: constant(chrome),
|
|
|
7827 |
view: constant(editable),
|
|
|
7828 |
origin,
|
|
|
7829 |
isResizable
|
|
|
7830 |
};
|
|
|
7831 |
};
|
|
|
7832 |
const body = (editable, chrome, isResizable) => {
|
|
|
7833 |
return {
|
|
|
7834 |
parent: constant(chrome),
|
|
|
7835 |
view: constant(editable),
|
|
|
7836 |
origin: constant(SugarPosition(0, 0)),
|
|
|
7837 |
isResizable
|
|
|
7838 |
};
|
|
|
7839 |
};
|
|
|
7840 |
const ResizeWire = {
|
|
|
7841 |
only,
|
|
|
7842 |
detached,
|
|
|
7843 |
body
|
|
|
7844 |
};
|
|
|
7845 |
|
|
|
7846 |
const createContainer = () => {
|
|
|
7847 |
const container = SugarElement.fromTag('div');
|
|
|
7848 |
setAll(container, {
|
|
|
7849 |
position: 'static',
|
|
|
7850 |
height: '0',
|
|
|
7851 |
width: '0',
|
|
|
7852 |
padding: '0',
|
|
|
7853 |
margin: '0',
|
|
|
7854 |
border: '0'
|
|
|
7855 |
});
|
|
|
7856 |
append$1(body$1(), container);
|
|
|
7857 |
return container;
|
|
|
7858 |
};
|
|
|
7859 |
const get = (editor, isResizable) => {
|
|
|
7860 |
return editor.inline ? ResizeWire.body(SugarElement.fromDom(editor.getBody()), createContainer(), isResizable) : ResizeWire.only(SugarElement.fromDom(editor.getDoc()), isResizable);
|
|
|
7861 |
};
|
|
|
7862 |
const remove = (editor, wire) => {
|
|
|
7863 |
if (editor.inline) {
|
|
|
7864 |
remove$6(wire.parent());
|
|
|
7865 |
}
|
|
|
7866 |
};
|
|
|
7867 |
|
|
|
7868 |
const isTable = node => isNonNullable(node) && node.nodeName === 'TABLE';
|
|
|
7869 |
const barResizerPrefix = 'bar-';
|
|
|
7870 |
const isResizable = elm => get$b(elm, 'data-mce-resize') !== 'false';
|
|
|
7871 |
const syncPixels = table => {
|
|
|
7872 |
const warehouse = Warehouse.fromTable(table);
|
|
|
7873 |
if (!Warehouse.hasColumns(warehouse)) {
|
|
|
7874 |
each$2(cells$1(table), cell => {
|
|
|
7875 |
const computedWidth = get$a(cell, 'width');
|
|
|
7876 |
set$1(cell, 'width', computedWidth);
|
|
|
7877 |
remove$7(cell, 'width');
|
|
|
7878 |
});
|
|
|
7879 |
}
|
|
|
7880 |
};
|
|
|
7881 |
const TableResizeHandler = editor => {
|
|
|
7882 |
const selectionRng = value();
|
|
|
7883 |
const tableResize = value();
|
|
|
7884 |
const resizeWire = value();
|
|
|
7885 |
let startW;
|
|
|
7886 |
let startRawW;
|
|
|
7887 |
const lazySizing = table => get$5(editor, table);
|
|
|
7888 |
const lazyResizingBehaviour = () => isPreserveTableColumnResizing(editor) ? preserveTable() : resizeTable();
|
|
|
7889 |
const getNumColumns = table => getGridSize(table).columns;
|
|
|
7890 |
const afterCornerResize = (table, origin, width) => {
|
|
|
7891 |
const isRightEdgeResize = endsWith(origin, 'e');
|
|
|
7892 |
if (startRawW === '') {
|
|
|
7893 |
convertToPercentSize(table);
|
|
|
7894 |
}
|
|
|
7895 |
if (width !== startW && startRawW !== '') {
|
|
|
7896 |
set$1(table, 'width', startRawW);
|
|
|
7897 |
const resizing = lazyResizingBehaviour();
|
|
|
7898 |
const tableSize = lazySizing(table);
|
|
|
7899 |
const col = isPreserveTableColumnResizing(editor) || isRightEdgeResize ? getNumColumns(table) - 1 : 0;
|
|
|
7900 |
adjustWidth(table, width - startW, col, resizing, tableSize);
|
|
|
7901 |
} else if (isPercentage$1(startRawW)) {
|
|
|
7902 |
const percentW = parseFloat(startRawW.replace('%', ''));
|
|
|
7903 |
const targetPercentW = width * percentW / startW;
|
|
|
7904 |
set$1(table, 'width', targetPercentW + '%');
|
|
|
7905 |
}
|
|
|
7906 |
if (isPixel(startRawW)) {
|
|
|
7907 |
syncPixels(table);
|
|
|
7908 |
}
|
|
|
7909 |
};
|
|
|
7910 |
const destroy = () => {
|
|
|
7911 |
tableResize.on(sz => {
|
|
|
7912 |
sz.destroy();
|
|
|
7913 |
});
|
|
|
7914 |
resizeWire.on(w => {
|
|
|
7915 |
remove(editor, w);
|
|
|
7916 |
});
|
|
|
7917 |
};
|
|
|
7918 |
editor.on('init', () => {
|
|
|
7919 |
const rawWire = get(editor, isResizable);
|
|
|
7920 |
resizeWire.set(rawWire);
|
|
|
7921 |
if (hasTableObjectResizing(editor) && hasTableResizeBars(editor)) {
|
|
|
7922 |
const resizing = lazyResizingBehaviour();
|
|
|
7923 |
const sz = TableResize.create(rawWire, resizing, lazySizing);
|
|
|
7924 |
sz.on();
|
|
|
7925 |
sz.events.startDrag.bind(_event => {
|
|
|
7926 |
selectionRng.set(editor.selection.getRng());
|
|
|
7927 |
});
|
|
|
7928 |
sz.events.beforeResize.bind(event => {
|
|
|
7929 |
const rawTable = event.table.dom;
|
|
|
7930 |
fireObjectResizeStart(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
|
|
|
7931 |
});
|
|
|
7932 |
sz.events.afterResize.bind(event => {
|
|
|
7933 |
const table = event.table;
|
|
|
7934 |
const rawTable = table.dom;
|
|
|
7935 |
removeDataStyle(table);
|
|
|
7936 |
selectionRng.on(rng => {
|
|
|
7937 |
editor.selection.setRng(rng);
|
|
|
7938 |
editor.focus();
|
|
|
7939 |
});
|
|
|
7940 |
fireObjectResized(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
|
|
|
7941 |
editor.undoManager.add();
|
|
|
7942 |
});
|
|
|
7943 |
tableResize.set(sz);
|
|
|
7944 |
}
|
|
|
7945 |
});
|
|
|
7946 |
editor.on('ObjectResizeStart', e => {
|
|
|
7947 |
const targetElm = e.target;
|
|
|
7948 |
if (isTable(targetElm)) {
|
|
|
7949 |
const table = SugarElement.fromDom(targetElm);
|
|
|
7950 |
each$2(editor.dom.select('.mce-clonedresizable'), clone => {
|
|
|
7951 |
editor.dom.addClass(clone, 'mce-' + getTableColumnResizingBehaviour(editor) + '-columns');
|
|
|
7952 |
});
|
|
|
7953 |
if (!isPixelSizing(table) && isTablePixelsForced(editor)) {
|
|
|
7954 |
convertToPixelSize(table);
|
|
|
7955 |
} else if (!isPercentSizing(table) && isTablePercentagesForced(editor)) {
|
|
|
7956 |
convertToPercentSize(table);
|
|
|
7957 |
}
|
|
|
7958 |
if (isNoneSizing(table) && startsWith(e.origin, barResizerPrefix)) {
|
|
|
7959 |
convertToPercentSize(table);
|
|
|
7960 |
}
|
|
|
7961 |
startW = e.width;
|
|
|
7962 |
startRawW = isTableResponsiveForced(editor) ? '' : getRawWidth(editor, targetElm).getOr('');
|
|
|
7963 |
}
|
|
|
7964 |
});
|
|
|
7965 |
editor.on('ObjectResized', e => {
|
|
|
7966 |
const targetElm = e.target;
|
|
|
7967 |
if (isTable(targetElm)) {
|
|
|
7968 |
const table = SugarElement.fromDom(targetElm);
|
|
|
7969 |
const origin = e.origin;
|
|
|
7970 |
if (startsWith(origin, 'corner-')) {
|
|
|
7971 |
afterCornerResize(table, origin, e.width);
|
|
|
7972 |
}
|
|
|
7973 |
removeDataStyle(table);
|
|
|
7974 |
fireTableModified(editor, table.dom, styleModified);
|
|
|
7975 |
}
|
|
|
7976 |
});
|
|
|
7977 |
editor.on('SwitchMode', () => {
|
|
|
7978 |
tableResize.on(resize => {
|
|
|
7979 |
if (editor.mode.isReadOnly()) {
|
|
|
7980 |
resize.hideBars();
|
|
|
7981 |
} else {
|
|
|
7982 |
resize.showBars();
|
|
|
7983 |
}
|
|
|
7984 |
});
|
|
|
7985 |
});
|
|
|
7986 |
editor.on('dragstart dragend', e => {
|
|
|
7987 |
tableResize.on(resize => {
|
|
|
7988 |
if (e.type === 'dragstart') {
|
|
|
7989 |
resize.hideBars();
|
|
|
7990 |
resize.off();
|
|
|
7991 |
} else {
|
|
|
7992 |
resize.on();
|
|
|
7993 |
resize.showBars();
|
|
|
7994 |
}
|
|
|
7995 |
});
|
|
|
7996 |
});
|
|
|
7997 |
editor.on('remove', () => {
|
|
|
7998 |
destroy();
|
|
|
7999 |
});
|
|
|
8000 |
const refresh = table => {
|
|
|
8001 |
tableResize.on(resize => resize.refreshBars(SugarElement.fromDom(table)));
|
|
|
8002 |
};
|
|
|
8003 |
const hide = () => {
|
|
|
8004 |
tableResize.on(resize => resize.hideBars());
|
|
|
8005 |
};
|
|
|
8006 |
const show = () => {
|
|
|
8007 |
tableResize.on(resize => resize.showBars());
|
|
|
8008 |
};
|
|
|
8009 |
return {
|
|
|
8010 |
refresh,
|
|
|
8011 |
hide,
|
|
|
8012 |
show
|
|
|
8013 |
};
|
|
|
8014 |
};
|
|
|
8015 |
|
|
|
8016 |
const setupTable = editor => {
|
|
|
8017 |
register(editor);
|
|
|
8018 |
const resizeHandler = TableResizeHandler(editor);
|
|
|
8019 |
const cellSelectionHandler = TableCellSelectionHandler(editor, resizeHandler);
|
|
|
8020 |
const actions = TableActions(editor, resizeHandler, cellSelectionHandler);
|
|
|
8021 |
registerCommands(editor, actions);
|
|
|
8022 |
registerQueryCommands(editor, actions);
|
|
|
8023 |
registerEvents(editor, actions);
|
|
|
8024 |
return {
|
|
|
8025 |
getSelectedCells: cellSelectionHandler.getSelectedCells,
|
|
|
8026 |
clearSelectedCells: cellSelectionHandler.clearSelectedCells
|
|
|
8027 |
};
|
|
|
8028 |
};
|
|
|
8029 |
|
|
|
8030 |
const DomModel = editor => {
|
|
|
8031 |
const table = setupTable(editor);
|
|
|
8032 |
return { table };
|
|
|
8033 |
};
|
|
|
8034 |
var Model = () => {
|
|
|
8035 |
global$1.add('dom', DomModel);
|
|
|
8036 |
};
|
|
|
8037 |
|
|
|
8038 |
Model();
|
|
|
8039 |
|
|
|
8040 |
})();
|