@html-next/vertical-collection 4.0.0-beta.1 → 4.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/addon/components/vertical-collection/component.js +244 -2
- package/index.js +3 -39
- package/package.json +1 -1
- package/addon/-debug/edge-visualization/debug-mixin.js +0 -93
- package/addon/-debug/edge-visualization/visualization.js +0 -134
- package/addon/-debug/index.js +0 -4
- package/addon/-debug/utils/validate-css.js +0 -12
- package/addon/-debug/utils/validate-rect.js +0 -13
- package/addon/-debug/utils/validate-style.js +0 -23
- package/app/initializers/debug.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { DEBUG } from '@glimmer/env';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
1
4
|
import { empty, readOnly } from '@ember/object/computed';
|
|
2
5
|
|
|
3
6
|
import Component from '@ember/component';
|
|
4
7
|
import { get, computed } from '@ember/object';
|
|
5
8
|
import { run } from '@ember/runloop';
|
|
6
9
|
import layout from './template';
|
|
10
|
+
import { ViewportContainer } from '../../-private';
|
|
7
11
|
|
|
8
12
|
import { scheduler, Token } from 'ember-raf-scheduler';
|
|
9
13
|
|
|
@@ -14,6 +18,166 @@ import {
|
|
|
14
18
|
objectAt
|
|
15
19
|
} from '../../-private';
|
|
16
20
|
|
|
21
|
+
/*
|
|
22
|
+
* BEGIN DEBUG HELPERS
|
|
23
|
+
*
|
|
24
|
+
* These methods and the Visualization class are used by DEBUG code paths.
|
|
25
|
+
*/
|
|
26
|
+
function isNonZero(value) {
|
|
27
|
+
let int = parseInt(value, 10);
|
|
28
|
+
let float = parseFloat(value);
|
|
29
|
+
|
|
30
|
+
return !isNaN(int) && (int !== 0 || float !== 0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function hasStyleValue(styles, key, value) {
|
|
34
|
+
return styles[key] === value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function hasStyleWithNonZeroValue(styles, key) {
|
|
38
|
+
return isNonZero(styles[key]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function styleIsOneOf(styles, key, values) {
|
|
42
|
+
return styles[key] && values.indexOf(styles[key]) !== -1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function applyVerticalStyles(element, geography) {
|
|
46
|
+
element.style.height = `${geography.height}px`;
|
|
47
|
+
element.style.top = `${geography.top}px`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class Visualization {
|
|
51
|
+
constructor(radar) {
|
|
52
|
+
this.radar = radar;
|
|
53
|
+
this.satellites = [];
|
|
54
|
+
this.cache = [];
|
|
55
|
+
|
|
56
|
+
this.wrapper = document.createElement('div');
|
|
57
|
+
this.wrapper.className = 'vertical-collection-visual-debugger';
|
|
58
|
+
|
|
59
|
+
this.container = document.createElement('div');
|
|
60
|
+
this.container.className = 'vc_visualization-container';
|
|
61
|
+
this.wrapper.appendChild(this.container);
|
|
62
|
+
|
|
63
|
+
this.itemContainer = document.createElement('div');
|
|
64
|
+
this.itemContainer.className = 'vc_visualization-item-container';
|
|
65
|
+
this.container.appendChild(this.itemContainer);
|
|
66
|
+
|
|
67
|
+
this.scrollContainer = document.createElement('div');
|
|
68
|
+
this.scrollContainer.className = 'vc_visualization-scroll-container';
|
|
69
|
+
this.container.appendChild(this.scrollContainer);
|
|
70
|
+
|
|
71
|
+
this.screen = document.createElement('div');
|
|
72
|
+
this.screen.className = 'vc_visualization-screen';
|
|
73
|
+
this.container.appendChild(this.screen);
|
|
74
|
+
|
|
75
|
+
document.body.appendChild(this.wrapper);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
render() {
|
|
79
|
+
this.styleViewport();
|
|
80
|
+
this.updateSatellites();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
styleViewport() {
|
|
84
|
+
const { _scrollContainer } = this.radar;
|
|
85
|
+
this.container.style.height = `${_scrollContainer.getBoundingClientRect().height}px`;
|
|
86
|
+
|
|
87
|
+
applyVerticalStyles(this.scrollContainer, _scrollContainer.getBoundingClientRect());
|
|
88
|
+
applyVerticalStyles(this.screen, ViewportContainer.getBoundingClientRect());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
makeSatellite() {
|
|
92
|
+
let satellite;
|
|
93
|
+
|
|
94
|
+
if (this.cache.length) {
|
|
95
|
+
satellite = this.cache.pop();
|
|
96
|
+
} else {
|
|
97
|
+
satellite = document.createElement('div');
|
|
98
|
+
satellite.className = 'vc_visualization-virtual-component';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.satellites.push(satellite);
|
|
102
|
+
this.itemContainer.append(satellite);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
updateSatellites() {
|
|
106
|
+
const { satellites: sats } = this;
|
|
107
|
+
let {
|
|
108
|
+
firstItemIndex,
|
|
109
|
+
lastItemIndex,
|
|
110
|
+
|
|
111
|
+
totalItems,
|
|
112
|
+
|
|
113
|
+
totalBefore,
|
|
114
|
+
totalAfter,
|
|
115
|
+
skipList,
|
|
116
|
+
_calculatedEstimateHeight
|
|
117
|
+
} = this.radar;
|
|
118
|
+
|
|
119
|
+
const isDynamic = !!skipList;
|
|
120
|
+
const itemHeights = isDynamic && skipList.values;
|
|
121
|
+
|
|
122
|
+
const firstVisualizedIndex = Math.max(firstItemIndex - 10, 0);
|
|
123
|
+
const lastVisualizedIndex = Math.min(lastItemIndex + 10, totalItems - 1);
|
|
124
|
+
|
|
125
|
+
const lengthWithBuffer = lastVisualizedIndex - firstVisualizedIndex + 1;
|
|
126
|
+
const isShrinking = sats.length > lengthWithBuffer;
|
|
127
|
+
|
|
128
|
+
while (sats.length !== lengthWithBuffer) {
|
|
129
|
+
if (isShrinking) {
|
|
130
|
+
const satellite = sats.pop();
|
|
131
|
+
|
|
132
|
+
satellite.parentNode.removeChild(satellite);
|
|
133
|
+
this.cache.push(satellite);
|
|
134
|
+
} else {
|
|
135
|
+
this.makeSatellite();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
for (let itemIndex = firstVisualizedIndex, i = 0; itemIndex <= lastVisualizedIndex; itemIndex++, i++) {
|
|
140
|
+
const element = sats[i];
|
|
141
|
+
|
|
142
|
+
const itemHeight = isDynamic ? itemHeights[itemIndex] : _calculatedEstimateHeight;
|
|
143
|
+
|
|
144
|
+
element.style.height = `${itemHeight}px`;
|
|
145
|
+
element.setAttribute('index', String(itemIndex));
|
|
146
|
+
element.innerText = String(itemIndex);
|
|
147
|
+
|
|
148
|
+
if (itemIndex < firstItemIndex) {
|
|
149
|
+
element.classList.add('culled');
|
|
150
|
+
totalBefore -= itemHeight;
|
|
151
|
+
} else if (itemIndex > lastItemIndex) {
|
|
152
|
+
element.classList.add('culled');
|
|
153
|
+
totalAfter -= itemHeight;
|
|
154
|
+
} else {
|
|
155
|
+
element.classList.remove('culled');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.itemContainer.style.paddingTop = `${totalBefore}px`;
|
|
160
|
+
this.itemContainer.style.paddingBottom = `${totalAfter}px`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
destroy() {
|
|
164
|
+
this.wrapper.parentNode.removeChild(this.wrapper);
|
|
165
|
+
this.wrapper = null;
|
|
166
|
+
this.radar = null;
|
|
167
|
+
this.component = null;
|
|
168
|
+
this.satellites.forEach((satellite) => {
|
|
169
|
+
if (satellite.parentNode) {
|
|
170
|
+
satellite.parentNode.removeChild(satellite);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
this.satellites = null;
|
|
174
|
+
this.cache = null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/*
|
|
178
|
+
* END DEBUG HELPERS
|
|
179
|
+
*/
|
|
180
|
+
|
|
17
181
|
const VerticalCollection = Component.extend({
|
|
18
182
|
layout,
|
|
19
183
|
|
|
@@ -200,7 +364,7 @@ const VerticalCollection = Component.extend({
|
|
|
200
364
|
}
|
|
201
365
|
},
|
|
202
366
|
|
|
203
|
-
/* Public API Methods
|
|
367
|
+
/* Public API Methods
|
|
204
368
|
@index => number
|
|
205
369
|
This will return offset height of the indexed item.
|
|
206
370
|
*/
|
|
@@ -233,6 +397,14 @@ const VerticalCollection = Component.extend({
|
|
|
233
397
|
registerAPI(null);
|
|
234
398
|
}
|
|
235
399
|
clearTimeout(this._nextSendActions);
|
|
400
|
+
|
|
401
|
+
if (DEBUG) {
|
|
402
|
+
if (this.__visualization) {
|
|
403
|
+
console.info('destroying visualization'); // eslint-disable-line no-console
|
|
404
|
+
this.__visualization.destroy();
|
|
405
|
+
this.__visualization = null;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
236
408
|
},
|
|
237
409
|
|
|
238
410
|
init() {
|
|
@@ -304,7 +476,7 @@ const VerticalCollection = Component.extend({
|
|
|
304
476
|
};
|
|
305
477
|
}
|
|
306
478
|
|
|
307
|
-
/* Public methods to Expose to parent
|
|
479
|
+
/* Public methods to Expose to parent
|
|
308
480
|
|
|
309
481
|
Usage:
|
|
310
482
|
|
|
@@ -340,6 +512,76 @@ const VerticalCollection = Component.extend({
|
|
|
340
512
|
};
|
|
341
513
|
registerAPI(publicAPI);
|
|
342
514
|
}
|
|
515
|
+
|
|
516
|
+
if (DEBUG) {
|
|
517
|
+
this.__visualization = null;
|
|
518
|
+
this._radar._debugDidUpdate = () => {
|
|
519
|
+
|
|
520
|
+
// Update visualization
|
|
521
|
+
//
|
|
522
|
+
// This debugging mode can be controlled via the argument
|
|
523
|
+
// `@debugVis={{true}}` at component invocation.
|
|
524
|
+
//
|
|
525
|
+
if (this.debugVis !== true) {
|
|
526
|
+
if (this.__visualization !== null) {
|
|
527
|
+
console.info('tearing down existing visualization'); // eslint-disable-line no-console
|
|
528
|
+
this.__visualization.destroy();
|
|
529
|
+
this.__visualization = null;
|
|
530
|
+
}
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
if (this.__visualization === null) {
|
|
535
|
+
this.__visualization = new Visualization(this._radar);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
this.__visualization.render();
|
|
539
|
+
|
|
540
|
+
// Detect issues with CSS
|
|
541
|
+
//
|
|
542
|
+
// This debugging mode can be controlled via the argument
|
|
543
|
+
// `@debugCSS={{true}}` at component invocation.
|
|
544
|
+
//
|
|
545
|
+
if (this.debugCSS !== true) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
let radar = this._radar;
|
|
550
|
+
let styles;
|
|
551
|
+
|
|
552
|
+
// check telescope
|
|
553
|
+
if (radar.scrollContainer !== ViewportContainer) {
|
|
554
|
+
styles = window.getComputedStyle(radar.scrollContainer);
|
|
555
|
+
} else {
|
|
556
|
+
styles = window.getComputedStyle(document.body);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
assert(`scrollContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
560
|
+
assert(`scrollContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
561
|
+
assert(`scrollContainer must define height or max-height`, hasStyleWithNonZeroValue(styles, 'height') || hasStyleWithNonZeroValue(styles, 'max-height'));
|
|
562
|
+
|
|
563
|
+
// conditional perf check for non-body scrolling
|
|
564
|
+
if (radar.scrollContainer !== ViewportContainer) {
|
|
565
|
+
assert(`scrollContainer must define overflow-y`, hasStyleValue(styles, 'overflow-y', 'scroll') || hasStyleValue(styles, 'overflow', 'scroll'));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// check itemContainer
|
|
569
|
+
styles = window.getComputedStyle(radar.itemContainer);
|
|
570
|
+
|
|
571
|
+
assert(`itemContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
572
|
+
assert(`itemContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
573
|
+
|
|
574
|
+
// check item defaults
|
|
575
|
+
assert(`You must supply at least one item to the collection to debug it's CSS.`, this.items.length);
|
|
576
|
+
|
|
577
|
+
let element = radar._itemContainer.firstElementChild;
|
|
578
|
+
|
|
579
|
+
styles = window.getComputedStyle(element);
|
|
580
|
+
|
|
581
|
+
assert(`Item cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
582
|
+
assert(`Item must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
583
|
+
};
|
|
584
|
+
}
|
|
343
585
|
}
|
|
344
586
|
});
|
|
345
587
|
|
package/index.js
CHANGED
|
@@ -6,13 +6,6 @@ const Rollup = require('broccoli-rollup');
|
|
|
6
6
|
const merge = require('broccoli-merge-trees');
|
|
7
7
|
const VersionChecker = require('ember-cli-version-checker');
|
|
8
8
|
|
|
9
|
-
function isProductionEnv() {
|
|
10
|
-
const isProd = /production/.test(process.env.EMBER_ENV);
|
|
11
|
-
const isTest = process.env.EMBER_CLI_TEST_COMMAND;
|
|
12
|
-
|
|
13
|
-
return isProd && !isTest;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
9
|
module.exports = {
|
|
17
10
|
name: require('./package').name,
|
|
18
11
|
|
|
@@ -43,10 +36,8 @@ module.exports = {
|
|
|
43
36
|
let withoutPrivate = new Funnel(tree, {
|
|
44
37
|
exclude: [
|
|
45
38
|
'**/**.hbs',
|
|
46
|
-
'-private'
|
|
47
|
-
|
|
48
|
-
].filter(Boolean),
|
|
49
|
-
|
|
39
|
+
'-private'
|
|
40
|
+
],
|
|
50
41
|
destDir: '@html-next/vertical-collection'
|
|
51
42
|
});
|
|
52
43
|
|
|
@@ -164,34 +155,7 @@ module.exports = {
|
|
|
164
155
|
this._setupBabelOptions(app.env);
|
|
165
156
|
|
|
166
157
|
if (!/production/.test(app.env) && !/test/.test(app.env)) {
|
|
167
|
-
|
|
158
|
+
this.import('vendor/debug.css');
|
|
168
159
|
}
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
treeForApp() {
|
|
172
|
-
const tree = this._super.treeForApp.apply(this, arguments);
|
|
173
|
-
|
|
174
|
-
const exclude = [];
|
|
175
|
-
|
|
176
|
-
if (isProductionEnv()) {
|
|
177
|
-
exclude.push('initializers/debug.js');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return new Funnel(tree, { exclude });
|
|
181
160
|
}
|
|
182
161
|
};
|
|
183
|
-
|
|
184
|
-
function findImporter(addon) {
|
|
185
|
-
if (typeof addon.import === 'function') {
|
|
186
|
-
// If addon.import() is present (CLI 2.7+) use that
|
|
187
|
-
return addon;
|
|
188
|
-
} else {
|
|
189
|
-
// Otherwise, reuse the _findHost implementation that would power addon.import()
|
|
190
|
-
let current = addon;
|
|
191
|
-
let app;
|
|
192
|
-
do {
|
|
193
|
-
app = current.app || app;
|
|
194
|
-
} while (current.parent.parent && (current = current.parent));
|
|
195
|
-
return app;
|
|
196
|
-
}
|
|
197
|
-
}
|
package/package.json
CHANGED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { assert } from '@ember/debug';
|
|
2
|
-
import Mixin from '@ember/object/mixin';
|
|
3
|
-
import Visualization from './visualization';
|
|
4
|
-
import { ViewportContainer } from '../../-private';
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
styleIsOneOf,
|
|
8
|
-
hasStyleValue,
|
|
9
|
-
hasStyleWithNonZeroValue
|
|
10
|
-
} from '../utils/validate-style';
|
|
11
|
-
|
|
12
|
-
export default Mixin.create({
|
|
13
|
-
debugVis: false,
|
|
14
|
-
debugCSS: false,
|
|
15
|
-
|
|
16
|
-
__visualization: null,
|
|
17
|
-
|
|
18
|
-
init() {
|
|
19
|
-
this._super(...arguments);
|
|
20
|
-
|
|
21
|
-
this._radar._debugDidUpdate = () => {
|
|
22
|
-
this.updateVisualization();
|
|
23
|
-
this.detectIssuesWithCSS();
|
|
24
|
-
};
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
detectIssuesWithCSS() {
|
|
28
|
-
if (this.debugCSS === false) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let radar = this._radar;
|
|
33
|
-
let styles;
|
|
34
|
-
|
|
35
|
-
// check telescope
|
|
36
|
-
if (radar.scrollContainer !== ViewportContainer) {
|
|
37
|
-
styles = window.getComputedStyle(radar.scrollContainer);
|
|
38
|
-
} else {
|
|
39
|
-
styles = window.getComputedStyle(document.body);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
assert(`scrollContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
43
|
-
assert(`scrollContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
44
|
-
assert(`scrollContainer must define height or max-height`, hasStyleWithNonZeroValue(styles, 'height') || hasStyleWithNonZeroValue(styles, 'max-height'));
|
|
45
|
-
|
|
46
|
-
// conditional perf check for non-body scrolling
|
|
47
|
-
if (radar.scrollContainer !== ViewportContainer) {
|
|
48
|
-
assert(`scrollContainer must define overflow-y`, hasStyleValue(styles, 'overflow-y', 'scroll') || hasStyleValue(styles, 'overflow', 'scroll'));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// check itemContainer
|
|
52
|
-
styles = window.getComputedStyle(radar.itemContainer);
|
|
53
|
-
|
|
54
|
-
assert(`itemContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
55
|
-
assert(`itemContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
56
|
-
|
|
57
|
-
// check item defaults
|
|
58
|
-
assert(`You must supply at least one item to the collection to debug it's CSS.`, this.items.length);
|
|
59
|
-
|
|
60
|
-
let element = radar._itemContainer.firstElementChild;
|
|
61
|
-
|
|
62
|
-
styles = window.getComputedStyle(element);
|
|
63
|
-
|
|
64
|
-
assert(`Item cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
65
|
-
assert(`Item must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
updateVisualization() {
|
|
69
|
-
if (this.debugVis === false) {
|
|
70
|
-
if (this.__visualization !== null) {
|
|
71
|
-
console.info('tearing down existing visualization'); // eslint-disable-line no-console
|
|
72
|
-
this.__visualization.destroy();
|
|
73
|
-
this.__visualization = null;
|
|
74
|
-
}
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (this.__visualization === null) {
|
|
79
|
-
this.__visualization = new Visualization(this._radar);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
this.__visualization.render();
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
willDestroy() {
|
|
86
|
-
this._super();
|
|
87
|
-
if (this.__visualization) {
|
|
88
|
-
console.info('destroying visualization'); // eslint-disable-line no-console
|
|
89
|
-
this.__visualization.destroy();
|
|
90
|
-
this.__visualization = null;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { ViewportContainer } from '../../-private';
|
|
2
|
-
|
|
3
|
-
function applyVerticalStyles(element, geography) {
|
|
4
|
-
element.style.height = `${geography.height}px`;
|
|
5
|
-
element.style.top = `${geography.top}px`;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export default class Visualization {
|
|
9
|
-
constructor(radar) {
|
|
10
|
-
this.radar = radar;
|
|
11
|
-
this.satellites = [];
|
|
12
|
-
this.cache = [];
|
|
13
|
-
|
|
14
|
-
this.wrapper = document.createElement('div');
|
|
15
|
-
this.wrapper.className = 'vertical-collection-visual-debugger';
|
|
16
|
-
|
|
17
|
-
this.container = document.createElement('div');
|
|
18
|
-
this.container.className = 'vc_visualization-container';
|
|
19
|
-
this.wrapper.appendChild(this.container);
|
|
20
|
-
|
|
21
|
-
this.itemContainer = document.createElement('div');
|
|
22
|
-
this.itemContainer.className = 'vc_visualization-item-container';
|
|
23
|
-
this.container.appendChild(this.itemContainer);
|
|
24
|
-
|
|
25
|
-
this.scrollContainer = document.createElement('div');
|
|
26
|
-
this.scrollContainer.className = 'vc_visualization-scroll-container';
|
|
27
|
-
this.container.appendChild(this.scrollContainer);
|
|
28
|
-
|
|
29
|
-
this.screen = document.createElement('div');
|
|
30
|
-
this.screen.className = 'vc_visualization-screen';
|
|
31
|
-
this.container.appendChild(this.screen);
|
|
32
|
-
|
|
33
|
-
document.body.appendChild(this.wrapper);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
render() {
|
|
37
|
-
this.styleViewport();
|
|
38
|
-
this.updateSatellites();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
styleViewport() {
|
|
42
|
-
const { _scrollContainer } = this.radar;
|
|
43
|
-
this.container.style.height = `${_scrollContainer.getBoundingClientRect().height}px`;
|
|
44
|
-
|
|
45
|
-
applyVerticalStyles(this.scrollContainer, _scrollContainer.getBoundingClientRect());
|
|
46
|
-
applyVerticalStyles(this.screen, ViewportContainer.getBoundingClientRect());
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
makeSatellite() {
|
|
50
|
-
let satellite;
|
|
51
|
-
|
|
52
|
-
if (this.cache.length) {
|
|
53
|
-
satellite = this.cache.pop();
|
|
54
|
-
} else {
|
|
55
|
-
satellite = document.createElement('div');
|
|
56
|
-
satellite.className = 'vc_visualization-virtual-component';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
this.satellites.push(satellite);
|
|
60
|
-
this.itemContainer.append(satellite);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
updateSatellites() {
|
|
64
|
-
const { satellites: sats } = this;
|
|
65
|
-
let {
|
|
66
|
-
firstItemIndex,
|
|
67
|
-
lastItemIndex,
|
|
68
|
-
|
|
69
|
-
totalItems,
|
|
70
|
-
|
|
71
|
-
totalBefore,
|
|
72
|
-
totalAfter,
|
|
73
|
-
skipList,
|
|
74
|
-
_calculatedEstimateHeight
|
|
75
|
-
} = this.radar;
|
|
76
|
-
|
|
77
|
-
const isDynamic = !!skipList;
|
|
78
|
-
const itemHeights = isDynamic && skipList.values;
|
|
79
|
-
|
|
80
|
-
const firstVisualizedIndex = Math.max(firstItemIndex - 10, 0);
|
|
81
|
-
const lastVisualizedIndex = Math.min(lastItemIndex + 10, totalItems - 1);
|
|
82
|
-
|
|
83
|
-
const lengthWithBuffer = lastVisualizedIndex - firstVisualizedIndex + 1;
|
|
84
|
-
const isShrinking = sats.length > lengthWithBuffer;
|
|
85
|
-
|
|
86
|
-
while (sats.length !== lengthWithBuffer) {
|
|
87
|
-
if (isShrinking) {
|
|
88
|
-
const satellite = sats.pop();
|
|
89
|
-
|
|
90
|
-
satellite.parentNode.removeChild(satellite);
|
|
91
|
-
this.cache.push(satellite);
|
|
92
|
-
} else {
|
|
93
|
-
this.makeSatellite();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
for (let itemIndex = firstVisualizedIndex, i = 0; itemIndex <= lastVisualizedIndex; itemIndex++, i++) {
|
|
98
|
-
const element = sats[i];
|
|
99
|
-
|
|
100
|
-
const itemHeight = isDynamic ? itemHeights[itemIndex] : _calculatedEstimateHeight;
|
|
101
|
-
|
|
102
|
-
element.style.height = `${itemHeight}px`;
|
|
103
|
-
element.setAttribute('index', String(itemIndex));
|
|
104
|
-
element.innerText = String(itemIndex);
|
|
105
|
-
|
|
106
|
-
if (itemIndex < firstItemIndex) {
|
|
107
|
-
element.classList.add('culled');
|
|
108
|
-
totalBefore -= itemHeight;
|
|
109
|
-
} else if (itemIndex > lastItemIndex) {
|
|
110
|
-
element.classList.add('culled');
|
|
111
|
-
totalAfter -= itemHeight;
|
|
112
|
-
} else {
|
|
113
|
-
element.classList.remove('culled');
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
this.itemContainer.style.paddingTop = `${totalBefore}px`;
|
|
118
|
-
this.itemContainer.style.paddingBottom = `${totalAfter}px`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
destroy() {
|
|
122
|
-
this.wrapper.parentNode.removeChild(this.wrapper);
|
|
123
|
-
this.wrapper = null;
|
|
124
|
-
this.radar = null;
|
|
125
|
-
this.component = null;
|
|
126
|
-
this.satellites.forEach((satellite) => {
|
|
127
|
-
if (satellite.parentNode) {
|
|
128
|
-
satellite.parentNode.removeChild(satellite);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
this.satellites = null;
|
|
132
|
-
this.cache = null;
|
|
133
|
-
}
|
|
134
|
-
}
|
package/addon/-debug/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export function hasCSSRule(rules, prop, value) {
|
|
2
|
-
let styleStr = `${prop}:\\s*${value}`;
|
|
3
|
-
let expr = new RegExp(styleStr, ['i']);
|
|
4
|
-
|
|
5
|
-
for (let i = 0; i < rules.length; i++) {
|
|
6
|
-
if (expr.test(rules[i].cssText)) {
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { isNonZero } from './validate-style';
|
|
2
|
-
|
|
3
|
-
export function hasDimension(rect, prop) {
|
|
4
|
-
return isNonZero(rect[prop]);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function hasDimensionAbove(rect, prop, amount) {
|
|
8
|
-
return hasDimension(rect, prop) && rect[prop] >= amount;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function hasDimensionEqual(rect, prop, amount) {
|
|
12
|
-
return hasDimension(rect, prop) && rect[prop] === amount;
|
|
13
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export function hasStyleValue(styles, key, value) {
|
|
3
|
-
return styles[key] === value;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function isNonZero(value) {
|
|
7
|
-
let int = parseInt(value, 10);
|
|
8
|
-
let float = parseFloat(value);
|
|
9
|
-
|
|
10
|
-
return !isNaN(int) && (int !== 0 || float !== 0);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function hasStyleWithNonZeroValue(styles, key) {
|
|
14
|
-
return isNonZero(styles[key]);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function styleIsOneOf(styles, key, values) {
|
|
18
|
-
return styles[key] && values.indexOf(styles[key]) !== -1;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function containsStyleValue(styles, key, value) {
|
|
22
|
-
return styles[key] && styles[key].indexOf(value) !== -1;
|
|
23
|
-
}
|