tencent.jquery.pix.component 1.0.68 → 1.0.70
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.
|
@@ -15,6 +15,7 @@ import './videocss.scss'
|
|
|
15
15
|
* @param {string} options.vid 腾讯视频id
|
|
16
16
|
* @param {string} [options.videoUrl] 视频地址,非腾讯视频时使用,比如上传到cos的视频
|
|
17
17
|
* @param {string} [options.previewUrl] 视频预览图
|
|
18
|
+
* @param {string} [options.timeUnit] 视频的时间单位 默认是s秒 ,如果是ms,则传1000
|
|
18
19
|
* @param {0|1} [options.videoType=1] 视频类型选项,0: 标清,1: 高清
|
|
19
20
|
* @param {number} [options.autoHideControlsDelayMs=5000] 自动隐藏控制条延迟时间,单位ms
|
|
20
21
|
* @param {boolean} [options.showProgressBar=true] 是否显示进度条
|
|
@@ -24,18 +25,20 @@ import './videocss.scss'
|
|
|
24
25
|
export function VideoPlayer(options) {
|
|
25
26
|
this.options = options
|
|
26
27
|
if (typeof this.options.stateChanged !== 'function') {
|
|
27
|
-
this.options.stateChanged = () => {};
|
|
28
|
+
this.options.stateChanged = () => { };
|
|
28
29
|
}
|
|
29
30
|
this.init()
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
VideoPlayer.prototype.init = async function() {
|
|
33
|
-
if (
|
|
34
|
-
|
|
33
|
+
VideoPlayer.prototype.init = async function () {
|
|
34
|
+
if ('timeUnit' in this.options) {
|
|
35
|
+
// 浏览器,单位s ; PixUI,单位ms
|
|
36
|
+
this.timeUnit = Number(this.options.timeUnit) || 1;
|
|
35
37
|
} else {
|
|
36
|
-
this.
|
|
38
|
+
this.timeUnit = 1;
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
|
|
39
42
|
const $container = $(this.options.container);
|
|
40
43
|
this.$container = $container;
|
|
41
44
|
$container.html(VideoHTML);
|
|
@@ -81,7 +84,7 @@ VideoPlayer.prototype.init = async function() {
|
|
|
81
84
|
this.bindEvent();
|
|
82
85
|
}
|
|
83
86
|
|
|
84
|
-
VideoPlayer.prototype.bindEvent = function() {
|
|
87
|
+
VideoPlayer.prototype.bindEvent = function () {
|
|
85
88
|
const container = this.$container;
|
|
86
89
|
container.off()
|
|
87
90
|
.on('click', '.myplayer-video-cover', () => {
|
|
@@ -157,7 +160,7 @@ VideoPlayer.prototype.bindEvent = function() {
|
|
|
157
160
|
}
|
|
158
161
|
}
|
|
159
162
|
|
|
160
|
-
VideoPlayer.prototype.play = function() {
|
|
163
|
+
VideoPlayer.prototype.play = function () {
|
|
161
164
|
if (this.state.firstPlay) {
|
|
162
165
|
this.state.firstPlay = false;
|
|
163
166
|
this.$container.find('.myplayer-video-cover,.myplayer-video-preview').hide();
|
|
@@ -175,7 +178,7 @@ VideoPlayer.prototype.play = function() {
|
|
|
175
178
|
this.options.stateChanged.call(this, 'play');
|
|
176
179
|
}
|
|
177
180
|
|
|
178
|
-
VideoPlayer.prototype.pause = function() {
|
|
181
|
+
VideoPlayer.prototype.pause = function () {
|
|
179
182
|
this.showControls();
|
|
180
183
|
const video = this.$container.find('video')[0];
|
|
181
184
|
video.pause();
|
|
@@ -188,8 +191,8 @@ VideoPlayer.prototype.pause = function() {
|
|
|
188
191
|
this.options.stateChanged.call(this, 'pause');
|
|
189
192
|
}
|
|
190
193
|
|
|
191
|
-
VideoPlayer.prototype.stop = function() {
|
|
192
|
-
|
|
194
|
+
VideoPlayer.prototype.stop = function () {
|
|
195
|
+
|
|
193
196
|
const video = this.$container.find('video')[0];
|
|
194
197
|
video.pause();
|
|
195
198
|
video.currentTime = 0;
|
|
@@ -204,8 +207,8 @@ VideoPlayer.prototype.stop = function() {
|
|
|
204
207
|
this.options.stateChanged.call(this, 'stop');
|
|
205
208
|
}
|
|
206
209
|
|
|
207
|
-
VideoPlayer.prototype.maskClicked = function() {
|
|
208
|
-
|
|
210
|
+
VideoPlayer.prototype.maskClicked = function () {
|
|
211
|
+
|
|
209
212
|
if (this.state.controlsVisible === true) {
|
|
210
213
|
if (this.state.playing === true) {
|
|
211
214
|
this.pause();
|
|
@@ -223,7 +226,7 @@ VideoPlayer.prototype.maskClicked = function() {
|
|
|
223
226
|
}
|
|
224
227
|
}
|
|
225
228
|
|
|
226
|
-
VideoPlayer.prototype.showControls = function() {
|
|
229
|
+
VideoPlayer.prototype.showControls = function () {
|
|
227
230
|
const container = this.$container;
|
|
228
231
|
container.find('.myplayer-video-mask').removeClass('myplayer-transparent');
|
|
229
232
|
container.find('.myplayer-top').removeClass('myplayer-transparent');
|
|
@@ -236,7 +239,7 @@ VideoPlayer.prototype.showControls = function() {
|
|
|
236
239
|
this.hideControlsWithDelay();
|
|
237
240
|
}
|
|
238
241
|
|
|
239
|
-
VideoPlayer.prototype.hideControls = function() {
|
|
242
|
+
VideoPlayer.prototype.hideControls = function () {
|
|
240
243
|
const container = this.$container;
|
|
241
244
|
container.find('.myplayer-video-mask').addClass('myplayer-transparent');
|
|
242
245
|
container.find('.myplayer-top').addClass('myplayer-transparent');
|
|
@@ -245,7 +248,7 @@ VideoPlayer.prototype.hideControls = function() {
|
|
|
245
248
|
this.state.updatingProgress = false;
|
|
246
249
|
}
|
|
247
250
|
|
|
248
|
-
VideoPlayer.prototype.hideControlsWithDelay = function() {
|
|
251
|
+
VideoPlayer.prototype.hideControlsWithDelay = function () {
|
|
249
252
|
this.state.controlsDelayStart = Date.now();
|
|
250
253
|
setTimeout(() => {
|
|
251
254
|
const nowTime = Date.now();
|
|
@@ -258,7 +261,7 @@ VideoPlayer.prototype.hideControlsWithDelay = function() {
|
|
|
258
261
|
}, this.options.autoHideControlsDelayMs);
|
|
259
262
|
}
|
|
260
263
|
|
|
261
|
-
VideoPlayer.prototype.startUpdatingProgress = function() {
|
|
264
|
+
VideoPlayer.prototype.startUpdatingProgress = function () {
|
|
262
265
|
this.updateProgress();
|
|
263
266
|
|
|
264
267
|
if (this.state.updatingProgress) {
|
|
@@ -266,13 +269,13 @@ VideoPlayer.prototype.startUpdatingProgress = function() {
|
|
|
266
269
|
}
|
|
267
270
|
}
|
|
268
271
|
|
|
269
|
-
VideoPlayer.prototype.updateProgress = function() {
|
|
272
|
+
VideoPlayer.prototype.updateProgress = function () {
|
|
270
273
|
const video = this.$container.find('video')[0];
|
|
271
274
|
if (!video) return;
|
|
272
|
-
|
|
275
|
+
|
|
273
276
|
const currentTime = video.currentTime || 0;
|
|
274
277
|
const duration = video.duration || 0;
|
|
275
|
-
|
|
278
|
+
|
|
276
279
|
// 防止duration为NaN或0时计算出错
|
|
277
280
|
if (duration && !isNaN(duration) && duration > 0) {
|
|
278
281
|
const progress = currentTime / duration;
|
|
@@ -286,23 +289,22 @@ VideoPlayer.prototype.updateProgress = function() {
|
|
|
286
289
|
}
|
|
287
290
|
|
|
288
291
|
// 格式化当前播放时间(currentTime单位为秒)
|
|
289
|
-
this.$container.find('.myplayer-playtime').html(formatTime(currentTime));
|
|
292
|
+
this.$container.find('.myplayer-playtime').html(this.formatTime(currentTime));
|
|
290
293
|
}
|
|
291
294
|
|
|
292
|
-
VideoPlayer.prototype.updateTotalTime = function() {
|
|
295
|
+
VideoPlayer.prototype.updateTotalTime = function () {
|
|
293
296
|
const video = this.$container.find('video')[0];
|
|
294
297
|
if (!video) return;
|
|
295
|
-
|
|
296
298
|
const duration = video.duration;
|
|
297
|
-
|
|
299
|
+
|
|
298
300
|
// 只有当duration有效时才更新显示
|
|
299
301
|
if (duration && !isNaN(duration) && isFinite(duration) && duration > 0) {
|
|
300
302
|
// duration单位为秒
|
|
301
|
-
this.$container.find('.myplayer-totaltime').html(formatTime(duration));
|
|
303
|
+
this.$container.find('.myplayer-totaltime').html(this.formatTime(duration));
|
|
302
304
|
}
|
|
303
305
|
}
|
|
304
306
|
|
|
305
|
-
VideoPlayer.prototype.toggleFullScreen = function() {
|
|
307
|
+
VideoPlayer.prototype.toggleFullScreen = function () {
|
|
306
308
|
const $container = this.$container;
|
|
307
309
|
const fullScreenBtn = $container.find('.myplayer-btn-full-screen');
|
|
308
310
|
const exitFullScreenBtn = $container.find('.myplayer-btn-exit-full-screen');
|
|
@@ -366,15 +368,15 @@ VideoPlayer.prototype.setFullScreen = function (target = true) {
|
|
|
366
368
|
* 将容器移动到body(进入全屏时调用)
|
|
367
369
|
* @private
|
|
368
370
|
*/
|
|
369
|
-
VideoPlayer.prototype._moveToBody = function() {
|
|
371
|
+
VideoPlayer.prototype._moveToBody = function () {
|
|
370
372
|
const containerEl = this.$container[0];
|
|
371
|
-
|
|
373
|
+
|
|
372
374
|
// 保存原始位置信息(仅在第一次移动时保存)
|
|
373
375
|
if (!this.state.originalParent) {
|
|
374
376
|
this.state.originalParent = containerEl.parentNode;
|
|
375
377
|
this.state.originalNextSibling = containerEl.nextSibling;
|
|
376
378
|
}
|
|
377
|
-
|
|
379
|
+
|
|
378
380
|
// 从原容器解绑
|
|
379
381
|
this.$container.off();
|
|
380
382
|
// 从body解绑所有相关事件
|
|
@@ -383,10 +385,10 @@ VideoPlayer.prototype._moveToBody = function() {
|
|
|
383
385
|
$(document.body).off('dragstart.myplayer');
|
|
384
386
|
$(document.body).off('drag.myplayer');
|
|
385
387
|
$(document.body).off('dragend.myplayer');
|
|
386
|
-
|
|
388
|
+
|
|
387
389
|
// 移动到body
|
|
388
390
|
document.body.appendChild(containerEl);
|
|
389
|
-
|
|
391
|
+
|
|
390
392
|
// 重新绑定事件
|
|
391
393
|
this.bindEvent();
|
|
392
394
|
}
|
|
@@ -395,24 +397,24 @@ VideoPlayer.prototype._moveToBody = function() {
|
|
|
395
397
|
* 将容器移回原位置(退出全屏时调用)
|
|
396
398
|
* @private
|
|
397
399
|
*/
|
|
398
|
-
VideoPlayer.prototype._moveBackToOriginal = function() {
|
|
400
|
+
VideoPlayer.prototype._moveBackToOriginal = function () {
|
|
399
401
|
const containerEl = this.$container[0];
|
|
400
|
-
|
|
402
|
+
|
|
401
403
|
// 如果没有保存原始位置,说明还没移动过,直接返回
|
|
402
404
|
if (!this.state.originalParent) {
|
|
403
405
|
return;
|
|
404
406
|
}
|
|
405
|
-
|
|
407
|
+
|
|
406
408
|
// 解绑事件
|
|
407
409
|
this.$container.off();
|
|
408
|
-
|
|
410
|
+
|
|
409
411
|
// 移回原位置
|
|
410
412
|
if (this.state.originalNextSibling) {
|
|
411
413
|
this.state.originalParent.insertBefore(containerEl, this.state.originalNextSibling);
|
|
412
414
|
} else {
|
|
413
415
|
this.state.originalParent.appendChild(containerEl);
|
|
414
416
|
}
|
|
415
|
-
|
|
417
|
+
|
|
416
418
|
// 重新绑定事件
|
|
417
419
|
this.bindEvent();
|
|
418
420
|
}
|
|
@@ -421,11 +423,11 @@ VideoPlayer.prototype._moveBackToOriginal = function() {
|
|
|
421
423
|
* 进度条拖动开始
|
|
422
424
|
* @param {MouseEvent} e
|
|
423
425
|
*/
|
|
424
|
-
VideoPlayer.prototype.progressDragStart = function(e) {
|
|
426
|
+
VideoPlayer.prototype.progressDragStart = function (e) {
|
|
425
427
|
if (!this.options.showProgressBar) {
|
|
426
428
|
return;
|
|
427
429
|
}
|
|
428
|
-
|
|
430
|
+
|
|
429
431
|
this.state.updatingProgress = false;
|
|
430
432
|
if (this.state.playing === true) {
|
|
431
433
|
this.pause();
|
|
@@ -436,11 +438,11 @@ VideoPlayer.prototype.progressDragStart = function(e) {
|
|
|
436
438
|
* 进度条拖动
|
|
437
439
|
* @param {MouseEvent} e
|
|
438
440
|
*/
|
|
439
|
-
VideoPlayer.prototype.progressDrag = function(e) {
|
|
441
|
+
VideoPlayer.prototype.progressDrag = function (e) {
|
|
440
442
|
if (!this.options.showProgressBar) {
|
|
441
443
|
return;
|
|
442
444
|
}
|
|
443
|
-
|
|
445
|
+
|
|
444
446
|
const $container = this.$container;
|
|
445
447
|
const progress = $container.find('.myplayer-progress');
|
|
446
448
|
const subprogress = $container.find('.myplayer-subprogress');
|
|
@@ -451,63 +453,86 @@ VideoPlayer.prototype.progressDrag = function(e) {
|
|
|
451
453
|
const rect = progress[0].getBoundingClientRect();
|
|
452
454
|
const clientX = e.clientX !== undefined ? e.clientX : (e.touches ? e.touches[0].clientX : 0);
|
|
453
455
|
const curOffset = Math.max(Math.min(clientX - rect.left, parentWidth), 0);
|
|
454
|
-
|
|
456
|
+
|
|
455
457
|
subprogress.width(`${curOffset}px`);
|
|
456
458
|
const adjustedPlayTime = curOffset / parentWidth * video.duration;
|
|
457
|
-
$container.find('.myplayer-playtime').html(formatTime(adjustedPlayTime));
|
|
459
|
+
$container.find('.myplayer-playtime').html(this.formatTime(adjustedPlayTime));
|
|
458
460
|
}
|
|
459
461
|
|
|
460
462
|
/**
|
|
461
463
|
* 进度条拖动结束
|
|
462
464
|
* @param {MouseEvent} e
|
|
463
465
|
*/
|
|
464
|
-
VideoPlayer.prototype.progressDragEnd = function(e) {
|
|
466
|
+
VideoPlayer.prototype.progressDragEnd = function (e) {
|
|
465
467
|
if (!this.options.showProgressBar) {
|
|
466
468
|
return;
|
|
467
469
|
}
|
|
468
|
-
|
|
470
|
+
|
|
469
471
|
const $container = this.$container;
|
|
470
472
|
const video = $container.find('video')[0];
|
|
471
473
|
const progress = $container.find('.myplayer-progress');
|
|
472
474
|
const parentWidth = progress.width();
|
|
473
|
-
|
|
475
|
+
|
|
474
476
|
// 使用getBoundingClientRect计算准确的点击位置
|
|
475
477
|
const rect = progress[0].getBoundingClientRect();
|
|
476
478
|
const clientX = e.clientX !== undefined ? e.clientX : (e.touches ? e.touches[0].clientX : 0);
|
|
477
479
|
const curOffset = Math.max(Math.min(clientX - rect.left, parentWidth), 0);
|
|
478
|
-
|
|
480
|
+
|
|
481
|
+
const duration = video.duration;//this.getCurrentDuration();
|
|
479
482
|
// 计算目标播放时间(单位:秒)
|
|
480
|
-
const targetTime = (curOffset / parentWidth) *
|
|
481
|
-
|
|
483
|
+
const targetTime = (curOffset / parentWidth) * duration;
|
|
484
|
+
|
|
482
485
|
// 确保duration有效再设置currentTime
|
|
483
|
-
if (
|
|
484
|
-
|
|
486
|
+
if (duration && !isNaN(duration) && duration > 0) {
|
|
487
|
+
|
|
488
|
+
// 这里的currentTime单位为秒
|
|
489
|
+
video.currentTime = this.getCurrentDuration(targetTime);
|
|
485
490
|
}
|
|
486
491
|
|
|
487
492
|
this.play();
|
|
488
|
-
|
|
493
|
+
|
|
489
494
|
this.state.updatingProgress = true;
|
|
490
495
|
this.startUpdatingProgress();
|
|
491
496
|
}
|
|
492
497
|
|
|
498
|
+
// 格式化时间
|
|
499
|
+
VideoPlayer.prototype.formatTime = function (duration) {
|
|
500
|
+
let secs = duration;
|
|
501
|
+
if (this.timeUnit !== 1) {
|
|
502
|
+
secs = secs / this.timeUnit;
|
|
503
|
+
}
|
|
504
|
+
const minutes = Math.floor(secs / 60);
|
|
505
|
+
const seconds = Math.floor(secs % 60);
|
|
506
|
+
return `${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// 获取当前的视频时间
|
|
510
|
+
VideoPlayer.prototype.getCurrentDuration = function (duration) {
|
|
511
|
+
let secs = duration;
|
|
512
|
+
if (this.timeUnit !== 1) {
|
|
513
|
+
secs = secs / this.timeUnit;
|
|
514
|
+
}
|
|
515
|
+
return secs;
|
|
516
|
+
}
|
|
517
|
+
|
|
493
518
|
/**
|
|
494
519
|
* 获取视频真实地址
|
|
495
520
|
* @param {string} vid 腾讯视频vid
|
|
496
521
|
* @param {0|1} [type] 类型,0: 标清,1: 高清
|
|
497
522
|
* @returns {Promise<string>} 真实视频地址
|
|
498
523
|
*/
|
|
499
|
-
const getVideoURL = async function(vid, type = 1) {
|
|
524
|
+
const getVideoURL = async function (vid, type = 1) {
|
|
500
525
|
const sApiUrl = `https://vv.video.qq.com/getinfo?vid=${vid}&platform=101001&charge=0&otype=json&t=${Date.now()}`;
|
|
501
526
|
|
|
502
527
|
try {
|
|
503
|
-
|
|
528
|
+
|
|
504
529
|
const res = await fetchData(sApiUrl);
|
|
505
|
-
|
|
530
|
+
|
|
506
531
|
const processedStr = res.replace('QZOutputJson=', '');
|
|
507
532
|
const jsonStr = processedStr.substring(0, processedStr.length - 1);
|
|
508
533
|
const resObj = JSON.parse(jsonStr);
|
|
509
534
|
const sRealUrl = `${resObj.vl.vi[0].ul.ui[type].url}${resObj.vl.vi[0].fn}?vkey=${resObj.vl.vi[0].fvkey}`;
|
|
510
|
-
|
|
535
|
+
|
|
511
536
|
return sRealUrl;
|
|
512
537
|
} catch (err) {
|
|
513
538
|
console.error(err)
|
|
@@ -520,7 +545,7 @@ const getVideoURL = async function(vid, type = 1) {
|
|
|
520
545
|
* @param {string} url
|
|
521
546
|
* @returns {Promise<string>}
|
|
522
547
|
*/
|
|
523
|
-
const fetchData = function(url) {
|
|
548
|
+
const fetchData = function (url) {
|
|
524
549
|
const xhr = new XMLHttpRequest();
|
|
525
550
|
xhr.open('GET', url);
|
|
526
551
|
xhr.send();
|
|
@@ -538,8 +563,3 @@ const fetchData = function(url) {
|
|
|
538
563
|
});
|
|
539
564
|
}
|
|
540
565
|
|
|
541
|
-
const formatTime = function(secs) {
|
|
542
|
-
const minutes = Math.floor(secs / 60);
|
|
543
|
-
const seconds = Math.floor(secs % 60);
|
|
544
|
-
return `${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
|
545
|
-
}
|
|
@@ -31,9 +31,24 @@ const DEFAULTS = {
|
|
|
31
31
|
export function Waterfall(optionsInput = {}) {
|
|
32
32
|
$ = getEnv().$;
|
|
33
33
|
|
|
34
|
-
this.
|
|
34
|
+
this.optionsInput = optionsInput
|
|
35
|
+
|
|
36
|
+
this.init();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
Waterfall.prototype.init = function (optionsMain = null) {
|
|
41
|
+
if (optionsMain) {
|
|
42
|
+
this.options = Object.assign({}, DEFAULTS, optionsMain);
|
|
43
|
+
} else {
|
|
44
|
+
this.options = Object.assign({}, DEFAULTS, this.optionsInput);
|
|
45
|
+
}
|
|
46
|
+
const self = this;
|
|
35
47
|
const options = this.options;
|
|
36
48
|
const $container = $(options.container);
|
|
49
|
+
const $scrollDom = options.scrollDom ? $(options.scrollDom) : $container;
|
|
50
|
+
|
|
51
|
+
|
|
37
52
|
// 标记是否有更新元素用的回调函数
|
|
38
53
|
this.hasUpdateItem = options.updateItem && (options.updateItem.constructor === Function) ? true : false;
|
|
39
54
|
|
|
@@ -109,9 +124,14 @@ export function Waterfall(optionsInput = {}) {
|
|
|
109
124
|
this.columnItems.push(this.createColumn(i));
|
|
110
125
|
}
|
|
111
126
|
|
|
112
|
-
this
|
|
113
|
-
|
|
127
|
+
this.$scrollDom = $scrollDom;
|
|
128
|
+
|
|
114
129
|
this.nodePool = []; // DOM 节点池
|
|
130
|
+
this.activeNodes = new Map(); // 当前活跃节点(索引 -> DOM)
|
|
131
|
+
this.allReadyNodes = new Map(); // 所有节点(索引 -> DOM)
|
|
132
|
+
this.renderIndex = 0; // 渲染索引(保留兼容性)
|
|
133
|
+
|
|
134
|
+
|
|
115
135
|
|
|
116
136
|
// 新方案:初始化数据ID映射
|
|
117
137
|
this.dataIdMap = new Map(); // 数据ID -> 布局信息映射
|
|
@@ -128,23 +148,6 @@ export function Waterfall(optionsInput = {}) {
|
|
|
128
148
|
});
|
|
129
149
|
});
|
|
130
150
|
|
|
131
|
-
this.init();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
Waterfall.prototype.init = function () {
|
|
136
|
-
const self = this;
|
|
137
|
-
const options = this.options;
|
|
138
|
-
const $container = $(options.container);
|
|
139
|
-
const $scrollDom = options.scrollDom ? $(options.scrollDom) : $container;
|
|
140
|
-
|
|
141
|
-
this.$scrollDom = $scrollDom;
|
|
142
|
-
|
|
143
|
-
this.nodePool = []; // DOM 节点池
|
|
144
|
-
this.activeNodes = new Map(); // 当前活跃节点(索引 -> DOM)
|
|
145
|
-
this.allReadyNodes = new Map(); // 所有节点(索引 -> DOM)
|
|
146
|
-
this.renderIndex = 0; // 渲染索引(保留兼容性)
|
|
147
|
-
|
|
148
151
|
$container.html(`
|
|
149
152
|
<div class="waterfall-list-scroll" style="">
|
|
150
153
|
<div class="waterfall-list-viewport"></div>
|