@fullcalendar/scrollgrid 7.0.0-beta.0 → 7.0.0-beta.1
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/index.cjs +1 -1
- package/index.global.js +51 -133
- package/index.global.min.js +2 -2
- package/index.js +1 -1
- package/internal.cjs +49 -131
- package/internal.d.ts +10 -29
- package/internal.js +50 -132
- package/package.json +3 -3
package/index.cjs
CHANGED
|
@@ -13,7 +13,7 @@ var premiumCommonPlugin__default = /*#__PURE__*/_interopDefaultLegacy(premiumCom
|
|
|
13
13
|
|
|
14
14
|
var index = index_cjs.createPlugin({
|
|
15
15
|
name: '@fullcalendar/scrollgrid',
|
|
16
|
-
premiumReleaseDate: '2024-10-
|
|
16
|
+
premiumReleaseDate: '2024-10-09',
|
|
17
17
|
deps: [premiumCommonPlugin__default["default"]],
|
|
18
18
|
scrollerSyncerClass: internalCommon.ScrollerSyncer
|
|
19
19
|
});
|
package/index.global.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
FullCalendar ScrollGrid Plugin v7.0.0-beta.
|
|
2
|
+
FullCalendar ScrollGrid Plugin v7.0.0-beta.1
|
|
3
3
|
Docs & License: https://fullcalendar.io/docs/premium
|
|
4
4
|
(c) 2024 Adam Shaw
|
|
5
5
|
*/
|
|
@@ -10,160 +10,74 @@ FullCalendar.ScrollGrid = (function (exports, core, premiumCommonPlugin, interna
|
|
|
10
10
|
|
|
11
11
|
var premiumCommonPlugin__default = /*#__PURE__*/_interopDefault(premiumCommonPlugin);
|
|
12
12
|
|
|
13
|
-
const WHEEL_EVENT_NAMES = 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ');
|
|
14
13
|
/*
|
|
15
|
-
|
|
14
|
+
Fires:
|
|
15
|
+
- scrollEnd: (x, y) => void
|
|
16
16
|
*/
|
|
17
|
-
class ScrollListener {
|
|
18
|
-
constructor(el) {
|
|
19
|
-
this.el = el;
|
|
20
|
-
this.emitter = new internal$1.Emitter();
|
|
21
|
-
this.isScrolling = false;
|
|
22
|
-
this.isTouching = false; // user currently has finger down?
|
|
23
|
-
this.isRecentlyWheeled = false;
|
|
24
|
-
this.isRecentlyScrolled = false;
|
|
25
|
-
this.wheelWaiter = new internal$1.DelayedRunner(this._handleWheelWaited.bind(this));
|
|
26
|
-
this.scrollWaiter = new internal$1.DelayedRunner(this._handleScrollWaited.bind(this));
|
|
27
|
-
// Handlers
|
|
28
|
-
// ----------------------------------------------------------------------------------------------
|
|
29
|
-
this.handleScroll = () => {
|
|
30
|
-
this.startScroll();
|
|
31
|
-
this.emitter.trigger('scroll', this.isRecentlyWheeled, this.isTouching);
|
|
32
|
-
this.isRecentlyScrolled = true;
|
|
33
|
-
this.scrollWaiter.request(500);
|
|
34
|
-
};
|
|
35
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
36
|
-
this.handleWheel = () => {
|
|
37
|
-
this.isRecentlyWheeled = true;
|
|
38
|
-
this.wheelWaiter.request(500);
|
|
39
|
-
};
|
|
40
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
41
|
-
this.handleTouchStart = () => {
|
|
42
|
-
this.isTouching = true;
|
|
43
|
-
};
|
|
44
|
-
this.handleTouchEnd = () => {
|
|
45
|
-
this.isTouching = false;
|
|
46
|
-
// if the user ended their touch, and the scroll area wasn't moving,
|
|
47
|
-
// we consider this to be the end of the scroll.
|
|
48
|
-
if (!this.isRecentlyScrolled) {
|
|
49
|
-
this.endScroll(); // won't fire if already ended
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
el.addEventListener('scroll', this.handleScroll);
|
|
53
|
-
el.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
54
|
-
el.addEventListener('touchend', this.handleTouchEnd);
|
|
55
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
56
|
-
el.addEventListener(eventName, this.handleWheel, { passive: true });
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
destroy() {
|
|
60
|
-
let { el } = this;
|
|
61
|
-
el.removeEventListener('scroll', this.handleScroll);
|
|
62
|
-
el.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
63
|
-
el.removeEventListener('touchend', this.handleTouchEnd);
|
|
64
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
65
|
-
el.removeEventListener(eventName, this.handleWheel, { passive: true });
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// Start / Stop
|
|
69
|
-
// ----------------------------------------------------------------------------------------------
|
|
70
|
-
startScroll() {
|
|
71
|
-
if (!this.isScrolling) {
|
|
72
|
-
this.isScrolling = true;
|
|
73
|
-
this.emitter.trigger('scrollStart', this.isRecentlyWheeled, this.isTouching);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
endScroll() {
|
|
77
|
-
if (this.isScrolling) {
|
|
78
|
-
this.emitter.trigger('scrollEnd');
|
|
79
|
-
this.isScrolling = false;
|
|
80
|
-
this.isRecentlyScrolled = true;
|
|
81
|
-
this.isRecentlyWheeled = false;
|
|
82
|
-
this.scrollWaiter.clear();
|
|
83
|
-
this.wheelWaiter.clear();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
_handleScrollWaited() {
|
|
87
|
-
this.isRecentlyScrolled = false;
|
|
88
|
-
// only end the scroll if not currently touching.
|
|
89
|
-
// if touching, the scrolling will end later, on touchend.
|
|
90
|
-
if (!this.isTouching) {
|
|
91
|
-
this.endScroll(); // won't fire if already ended
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
_handleWheelWaited() {
|
|
95
|
-
this.isRecentlyWheeled = false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
17
|
class ScrollerSyncer {
|
|
100
18
|
constructor(isHorizontal = false) {
|
|
101
19
|
this.isHorizontal = isHorizontal;
|
|
102
|
-
this.
|
|
103
|
-
this.
|
|
20
|
+
this.emitter = new internal$1.Emitter();
|
|
21
|
+
this.scrollers = [];
|
|
22
|
+
this.destroyFuncs = [];
|
|
104
23
|
this.isPaused = false;
|
|
105
24
|
}
|
|
106
|
-
handleChildren(scrollers
|
|
25
|
+
handleChildren(scrollers) {
|
|
107
26
|
if (!internal$1.isArraysEqual(this.scrollers, scrollers)) {
|
|
108
27
|
this.destroy();
|
|
109
|
-
this.scrollers = scrollers;
|
|
110
|
-
const scrollListeners = [];
|
|
111
28
|
for (const scroller of scrollers) {
|
|
112
29
|
if (scroller) { // could be null
|
|
113
|
-
|
|
30
|
+
this.destroyFuncs.push(this.bindScroller(scroller));
|
|
31
|
+
this.scrollers.push(scroller);
|
|
114
32
|
}
|
|
115
33
|
}
|
|
116
|
-
this.scrollListeners = scrollListeners;
|
|
117
34
|
}
|
|
118
|
-
this.isRtl = isRtl;
|
|
119
35
|
}
|
|
120
36
|
destroy() {
|
|
121
|
-
for (let
|
|
122
|
-
|
|
37
|
+
for (let destroyFunc of this.destroyFuncs) {
|
|
38
|
+
destroyFunc();
|
|
123
39
|
}
|
|
40
|
+
this.destroyFuncs = [];
|
|
41
|
+
this.scrollers = [];
|
|
124
42
|
}
|
|
125
43
|
get x() {
|
|
126
|
-
const {
|
|
127
|
-
|
|
128
|
-
return internal$1.getNormalizedScrollX(el, isRtl);
|
|
44
|
+
const { scrollers, masterScroller } = this;
|
|
45
|
+
return (masterScroller || scrollers[0]).x;
|
|
129
46
|
}
|
|
130
47
|
get y() {
|
|
131
|
-
const {
|
|
132
|
-
|
|
133
|
-
return el.scrollTop;
|
|
48
|
+
const { scrollers, masterScroller } = this;
|
|
49
|
+
return (masterScroller || scrollers[0]).y;
|
|
134
50
|
}
|
|
135
|
-
scrollTo(
|
|
51
|
+
scrollTo(scrollArg) {
|
|
136
52
|
this.isPaused = true;
|
|
137
|
-
const {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
scrollListener.el.scrollTop = y;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (x != null) {
|
|
144
|
-
for (let scrollListener of scrollListeners) {
|
|
145
|
-
internal$1.setNormalizedScrollX(scrollListener.el, isRtl, x);
|
|
146
|
-
}
|
|
53
|
+
const { scrollers } = this;
|
|
54
|
+
for (let scroller of scrollers) {
|
|
55
|
+
scroller.scrollTo(scrollArg);
|
|
147
56
|
}
|
|
148
57
|
this.isPaused = false;
|
|
149
58
|
}
|
|
150
|
-
|
|
59
|
+
addScrollEndListener(handler) {
|
|
60
|
+
this.emitter.on('scrollEnd', handler);
|
|
61
|
+
}
|
|
62
|
+
removeScrollEndListener(handler) {
|
|
63
|
+
this.emitter.off('scrollEnd', handler);
|
|
64
|
+
}
|
|
65
|
+
bindScroller(scroller) {
|
|
151
66
|
let { isHorizontal } = this;
|
|
152
|
-
let scrollListener = new ScrollListener(el);
|
|
153
67
|
const onScroll = (isWheel, isTouch) => {
|
|
154
68
|
if (!this.isPaused) {
|
|
155
|
-
if (!this.
|
|
156
|
-
this.assignMaster(
|
|
69
|
+
if (!this.masterScroller || (this.masterScroller !== scroller && (isWheel || isTouch))) {
|
|
70
|
+
this.assignMaster(scroller);
|
|
157
71
|
}
|
|
158
|
-
if (this.
|
|
159
|
-
for (let
|
|
160
|
-
|
|
161
|
-
if (otherEl !== el) {
|
|
72
|
+
if (this.masterScroller === scroller) { // dealing with current
|
|
73
|
+
for (let otherScroller of this.scrollers) {
|
|
74
|
+
if (otherScroller !== scroller) {
|
|
162
75
|
if (isHorizontal) {
|
|
163
|
-
|
|
76
|
+
// TODO: user raw scrollLeft for better performance. No normalization necessary
|
|
77
|
+
otherScroller.scrollTo({ x: scroller.x });
|
|
164
78
|
}
|
|
165
79
|
else {
|
|
166
|
-
|
|
80
|
+
otherScroller.scrollTo({ y: scroller.y });
|
|
167
81
|
}
|
|
168
82
|
}
|
|
169
83
|
}
|
|
@@ -171,19 +85,23 @@ FullCalendar.ScrollGrid = (function (exports, core, premiumCommonPlugin, interna
|
|
|
171
85
|
}
|
|
172
86
|
};
|
|
173
87
|
const onScrollEnd = () => {
|
|
174
|
-
if (this.
|
|
175
|
-
this.
|
|
88
|
+
if (this.masterScroller === scroller) {
|
|
89
|
+
this.masterScroller = null;
|
|
90
|
+
this.emitter.trigger('scrollEnd', this.x, this.y);
|
|
176
91
|
}
|
|
177
92
|
};
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return
|
|
93
|
+
scroller.listener.emitter.on('scroll', onScroll);
|
|
94
|
+
scroller.listener.emitter.on('scrollEnd', onScrollEnd);
|
|
95
|
+
return () => {
|
|
96
|
+
scroller.listener.emitter.off('scroll', onScroll);
|
|
97
|
+
scroller.listener.emitter.off('scrollEnd', onScrollEnd);
|
|
98
|
+
};
|
|
181
99
|
}
|
|
182
|
-
assignMaster(
|
|
183
|
-
this.
|
|
184
|
-
for (let
|
|
185
|
-
if (
|
|
186
|
-
|
|
100
|
+
assignMaster(masterScroller) {
|
|
101
|
+
this.masterScroller = masterScroller;
|
|
102
|
+
for (let scroller of this.scrollers) {
|
|
103
|
+
if (scroller !== masterScroller) {
|
|
104
|
+
scroller.endScroll(); // to prevent residual scrolls from reclaiming master
|
|
187
105
|
}
|
|
188
106
|
}
|
|
189
107
|
}
|
|
@@ -191,7 +109,7 @@ FullCalendar.ScrollGrid = (function (exports, core, premiumCommonPlugin, interna
|
|
|
191
109
|
|
|
192
110
|
var plugin = core.createPlugin({
|
|
193
111
|
name: '@fullcalendar/scrollgrid',
|
|
194
|
-
premiumReleaseDate: '2024-10-
|
|
112
|
+
premiumReleaseDate: '2024-10-09',
|
|
195
113
|
deps: [premiumCommonPlugin__default["default"]],
|
|
196
114
|
scrollerSyncerClass: ScrollerSyncer
|
|
197
115
|
});
|
package/index.global.min.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
FullCalendar ScrollGrid Plugin v7.0.0-beta.
|
|
2
|
+
FullCalendar ScrollGrid Plugin v7.0.0-beta.1
|
|
3
3
|
Docs & License: https://fullcalendar.io/docs/premium
|
|
4
4
|
(c) 2024 Adam Shaw
|
|
5
5
|
*/
|
|
6
|
-
FullCalendar.ScrollGrid=function(
|
|
6
|
+
FullCalendar.ScrollGrid=function(r,s,l,e){"use strict";function t(r){return r&&r.__esModule?r:{default:r}}var o=t(l);class i{constructor(r=!1){this.isHorizontal=r,this.emitter=new e.Emitter,this.scrollers=[],this.destroyFuncs=[],this.isPaused=!1}handleChildren(r){if(!e.isArraysEqual(this.scrollers,r)){this.destroy();for(const s of r)s&&(this.destroyFuncs.push(this.bindScroller(s)),this.scrollers.push(s))}}destroy(){for(let r of this.destroyFuncs)r();this.destroyFuncs=[],this.scrollers=[]}get x(){const{scrollers:r,masterScroller:s}=this;return(s||r[0]).x}get y(){const{scrollers:r,masterScroller:s}=this;return(s||r[0]).y}scrollTo(r){this.isPaused=!0;const{scrollers:s}=this;for(let l of s)l.scrollTo(r);this.isPaused=!1}addScrollEndListener(r){this.emitter.on("scrollEnd",r)}removeScrollEndListener(r){this.emitter.off("scrollEnd",r)}bindScroller(r){let{isHorizontal:s}=this;const l=(l,e)=>{if(!this.isPaused&&((!this.masterScroller||this.masterScroller!==r&&(l||e))&&this.assignMaster(r),this.masterScroller===r))for(let l of this.scrollers)l!==r&&(s?l.scrollTo({x:r.x}):l.scrollTo({y:r.y}))},e=()=>{this.masterScroller===r&&(this.masterScroller=null,this.emitter.trigger("scrollEnd",this.x,this.y))};return r.listener.emitter.on("scroll",l),r.listener.emitter.on("scrollEnd",e),()=>{r.listener.emitter.off("scroll",l),r.listener.emitter.off("scrollEnd",e)}}assignMaster(r){this.masterScroller=r;for(let s of this.scrollers)s!==r&&s.endScroll()}}var n=s.createPlugin({name:"@fullcalendar/scrollgrid",premiumReleaseDate:"2024-10-09",deps:[o.default],scrollerSyncerClass:i}),c={__proto__:null,ScrollerSyncer:i};return s.globalPlugins.push(n),r.Internal=c,r.default=n,Object.defineProperty(r,"__esModule",{value:!0}),r}({},FullCalendar,FullCalendar.PremiumCommon,FullCalendar.Internal);
|
package/index.js
CHANGED
package/internal.cjs
CHANGED
|
@@ -4,160 +4,74 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var internal_cjs = require('@fullcalendar/core/internal.cjs');
|
|
6
6
|
|
|
7
|
-
const WHEEL_EVENT_NAMES = 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ');
|
|
8
7
|
/*
|
|
9
|
-
|
|
8
|
+
Fires:
|
|
9
|
+
- scrollEnd: (x, y) => void
|
|
10
10
|
*/
|
|
11
|
-
class ScrollListener {
|
|
12
|
-
constructor(el) {
|
|
13
|
-
this.el = el;
|
|
14
|
-
this.emitter = new internal_cjs.Emitter();
|
|
15
|
-
this.isScrolling = false;
|
|
16
|
-
this.isTouching = false; // user currently has finger down?
|
|
17
|
-
this.isRecentlyWheeled = false;
|
|
18
|
-
this.isRecentlyScrolled = false;
|
|
19
|
-
this.wheelWaiter = new internal_cjs.DelayedRunner(this._handleWheelWaited.bind(this));
|
|
20
|
-
this.scrollWaiter = new internal_cjs.DelayedRunner(this._handleScrollWaited.bind(this));
|
|
21
|
-
// Handlers
|
|
22
|
-
// ----------------------------------------------------------------------------------------------
|
|
23
|
-
this.handleScroll = () => {
|
|
24
|
-
this.startScroll();
|
|
25
|
-
this.emitter.trigger('scroll', this.isRecentlyWheeled, this.isTouching);
|
|
26
|
-
this.isRecentlyScrolled = true;
|
|
27
|
-
this.scrollWaiter.request(500);
|
|
28
|
-
};
|
|
29
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
30
|
-
this.handleWheel = () => {
|
|
31
|
-
this.isRecentlyWheeled = true;
|
|
32
|
-
this.wheelWaiter.request(500);
|
|
33
|
-
};
|
|
34
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
35
|
-
this.handleTouchStart = () => {
|
|
36
|
-
this.isTouching = true;
|
|
37
|
-
};
|
|
38
|
-
this.handleTouchEnd = () => {
|
|
39
|
-
this.isTouching = false;
|
|
40
|
-
// if the user ended their touch, and the scroll area wasn't moving,
|
|
41
|
-
// we consider this to be the end of the scroll.
|
|
42
|
-
if (!this.isRecentlyScrolled) {
|
|
43
|
-
this.endScroll(); // won't fire if already ended
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
el.addEventListener('scroll', this.handleScroll);
|
|
47
|
-
el.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
48
|
-
el.addEventListener('touchend', this.handleTouchEnd);
|
|
49
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
50
|
-
el.addEventListener(eventName, this.handleWheel, { passive: true });
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
destroy() {
|
|
54
|
-
let { el } = this;
|
|
55
|
-
el.removeEventListener('scroll', this.handleScroll);
|
|
56
|
-
el.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
57
|
-
el.removeEventListener('touchend', this.handleTouchEnd);
|
|
58
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
59
|
-
el.removeEventListener(eventName, this.handleWheel, { passive: true });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// Start / Stop
|
|
63
|
-
// ----------------------------------------------------------------------------------------------
|
|
64
|
-
startScroll() {
|
|
65
|
-
if (!this.isScrolling) {
|
|
66
|
-
this.isScrolling = true;
|
|
67
|
-
this.emitter.trigger('scrollStart', this.isRecentlyWheeled, this.isTouching);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
endScroll() {
|
|
71
|
-
if (this.isScrolling) {
|
|
72
|
-
this.emitter.trigger('scrollEnd');
|
|
73
|
-
this.isScrolling = false;
|
|
74
|
-
this.isRecentlyScrolled = true;
|
|
75
|
-
this.isRecentlyWheeled = false;
|
|
76
|
-
this.scrollWaiter.clear();
|
|
77
|
-
this.wheelWaiter.clear();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
_handleScrollWaited() {
|
|
81
|
-
this.isRecentlyScrolled = false;
|
|
82
|
-
// only end the scroll if not currently touching.
|
|
83
|
-
// if touching, the scrolling will end later, on touchend.
|
|
84
|
-
if (!this.isTouching) {
|
|
85
|
-
this.endScroll(); // won't fire if already ended
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
_handleWheelWaited() {
|
|
89
|
-
this.isRecentlyWheeled = false;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
11
|
class ScrollerSyncer {
|
|
94
12
|
constructor(isHorizontal = false) {
|
|
95
13
|
this.isHorizontal = isHorizontal;
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
14
|
+
this.emitter = new internal_cjs.Emitter();
|
|
15
|
+
this.scrollers = [];
|
|
16
|
+
this.destroyFuncs = [];
|
|
98
17
|
this.isPaused = false;
|
|
99
18
|
}
|
|
100
|
-
handleChildren(scrollers
|
|
19
|
+
handleChildren(scrollers) {
|
|
101
20
|
if (!internal_cjs.isArraysEqual(this.scrollers, scrollers)) {
|
|
102
21
|
this.destroy();
|
|
103
|
-
this.scrollers = scrollers;
|
|
104
|
-
const scrollListeners = [];
|
|
105
22
|
for (const scroller of scrollers) {
|
|
106
23
|
if (scroller) { // could be null
|
|
107
|
-
|
|
24
|
+
this.destroyFuncs.push(this.bindScroller(scroller));
|
|
25
|
+
this.scrollers.push(scroller);
|
|
108
26
|
}
|
|
109
27
|
}
|
|
110
|
-
this.scrollListeners = scrollListeners;
|
|
111
28
|
}
|
|
112
|
-
this.isRtl = isRtl;
|
|
113
29
|
}
|
|
114
30
|
destroy() {
|
|
115
|
-
for (let
|
|
116
|
-
|
|
31
|
+
for (let destroyFunc of this.destroyFuncs) {
|
|
32
|
+
destroyFunc();
|
|
117
33
|
}
|
|
34
|
+
this.destroyFuncs = [];
|
|
35
|
+
this.scrollers = [];
|
|
118
36
|
}
|
|
119
37
|
get x() {
|
|
120
|
-
const {
|
|
121
|
-
|
|
122
|
-
return internal_cjs.getNormalizedScrollX(el, isRtl);
|
|
38
|
+
const { scrollers, masterScroller } = this;
|
|
39
|
+
return (masterScroller || scrollers[0]).x;
|
|
123
40
|
}
|
|
124
41
|
get y() {
|
|
125
|
-
const {
|
|
126
|
-
|
|
127
|
-
return el.scrollTop;
|
|
42
|
+
const { scrollers, masterScroller } = this;
|
|
43
|
+
return (masterScroller || scrollers[0]).y;
|
|
128
44
|
}
|
|
129
|
-
scrollTo(
|
|
45
|
+
scrollTo(scrollArg) {
|
|
130
46
|
this.isPaused = true;
|
|
131
|
-
const {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
scrollListener.el.scrollTop = y;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (x != null) {
|
|
138
|
-
for (let scrollListener of scrollListeners) {
|
|
139
|
-
internal_cjs.setNormalizedScrollX(scrollListener.el, isRtl, x);
|
|
140
|
-
}
|
|
47
|
+
const { scrollers } = this;
|
|
48
|
+
for (let scroller of scrollers) {
|
|
49
|
+
scroller.scrollTo(scrollArg);
|
|
141
50
|
}
|
|
142
51
|
this.isPaused = false;
|
|
143
52
|
}
|
|
144
|
-
|
|
53
|
+
addScrollEndListener(handler) {
|
|
54
|
+
this.emitter.on('scrollEnd', handler);
|
|
55
|
+
}
|
|
56
|
+
removeScrollEndListener(handler) {
|
|
57
|
+
this.emitter.off('scrollEnd', handler);
|
|
58
|
+
}
|
|
59
|
+
bindScroller(scroller) {
|
|
145
60
|
let { isHorizontal } = this;
|
|
146
|
-
let scrollListener = new ScrollListener(el);
|
|
147
61
|
const onScroll = (isWheel, isTouch) => {
|
|
148
62
|
if (!this.isPaused) {
|
|
149
|
-
if (!this.
|
|
150
|
-
this.assignMaster(
|
|
63
|
+
if (!this.masterScroller || (this.masterScroller !== scroller && (isWheel || isTouch))) {
|
|
64
|
+
this.assignMaster(scroller);
|
|
151
65
|
}
|
|
152
|
-
if (this.
|
|
153
|
-
for (let
|
|
154
|
-
|
|
155
|
-
if (otherEl !== el) {
|
|
66
|
+
if (this.masterScroller === scroller) { // dealing with current
|
|
67
|
+
for (let otherScroller of this.scrollers) {
|
|
68
|
+
if (otherScroller !== scroller) {
|
|
156
69
|
if (isHorizontal) {
|
|
157
|
-
|
|
70
|
+
// TODO: user raw scrollLeft for better performance. No normalization necessary
|
|
71
|
+
otherScroller.scrollTo({ x: scroller.x });
|
|
158
72
|
}
|
|
159
73
|
else {
|
|
160
|
-
|
|
74
|
+
otherScroller.scrollTo({ y: scroller.y });
|
|
161
75
|
}
|
|
162
76
|
}
|
|
163
77
|
}
|
|
@@ -165,19 +79,23 @@ class ScrollerSyncer {
|
|
|
165
79
|
}
|
|
166
80
|
};
|
|
167
81
|
const onScrollEnd = () => {
|
|
168
|
-
if (this.
|
|
169
|
-
this.
|
|
82
|
+
if (this.masterScroller === scroller) {
|
|
83
|
+
this.masterScroller = null;
|
|
84
|
+
this.emitter.trigger('scrollEnd', this.x, this.y);
|
|
170
85
|
}
|
|
171
86
|
};
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return
|
|
87
|
+
scroller.listener.emitter.on('scroll', onScroll);
|
|
88
|
+
scroller.listener.emitter.on('scrollEnd', onScrollEnd);
|
|
89
|
+
return () => {
|
|
90
|
+
scroller.listener.emitter.off('scroll', onScroll);
|
|
91
|
+
scroller.listener.emitter.off('scrollEnd', onScrollEnd);
|
|
92
|
+
};
|
|
175
93
|
}
|
|
176
|
-
assignMaster(
|
|
177
|
-
this.
|
|
178
|
-
for (let
|
|
179
|
-
if (
|
|
180
|
-
|
|
94
|
+
assignMaster(masterScroller) {
|
|
95
|
+
this.masterScroller = masterScroller;
|
|
96
|
+
for (let scroller of this.scrollers) {
|
|
97
|
+
if (scroller !== masterScroller) {
|
|
98
|
+
scroller.endScroll(); // to prevent residual scrolls from reclaiming master
|
|
181
99
|
}
|
|
182
100
|
}
|
|
183
101
|
}
|
package/internal.d.ts
CHANGED
|
@@ -1,44 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
declare class ScrollListener {
|
|
4
|
-
el: HTMLElement;
|
|
5
|
-
emitter: Emitter<any>;
|
|
6
|
-
private isScrolling;
|
|
7
|
-
private isTouching;
|
|
8
|
-
private isRecentlyWheeled;
|
|
9
|
-
private isRecentlyScrolled;
|
|
10
|
-
private wheelWaiter;
|
|
11
|
-
private scrollWaiter;
|
|
12
|
-
constructor(el: HTMLElement);
|
|
13
|
-
destroy(): void;
|
|
14
|
-
private startScroll;
|
|
15
|
-
endScroll(): void;
|
|
16
|
-
handleScroll: () => void;
|
|
17
|
-
_handleScrollWaited(): void;
|
|
18
|
-
handleWheel: () => void;
|
|
19
|
-
_handleWheelWaited(): void;
|
|
20
|
-
handleTouchStart: () => void;
|
|
21
|
-
handleTouchEnd: () => void;
|
|
22
|
-
}
|
|
1
|
+
import { ScrollerSyncerInterface, Scroller } from '@fullcalendar/core/internal';
|
|
23
2
|
|
|
24
3
|
declare class ScrollerSyncer implements ScrollerSyncerInterface {
|
|
25
4
|
private isHorizontal;
|
|
5
|
+
private emitter;
|
|
26
6
|
private scrollers;
|
|
27
|
-
private
|
|
28
|
-
private
|
|
7
|
+
private destroyFuncs;
|
|
8
|
+
private masterScroller;
|
|
29
9
|
private isPaused;
|
|
30
|
-
private isRtl;
|
|
31
10
|
constructor(isHorizontal?: boolean);
|
|
32
|
-
handleChildren(scrollers: Scroller[]
|
|
11
|
+
handleChildren(scrollers: Scroller[]): void;
|
|
33
12
|
destroy(): void;
|
|
34
13
|
get x(): number;
|
|
35
14
|
get y(): number;
|
|
36
|
-
scrollTo(
|
|
15
|
+
scrollTo(scrollArg: {
|
|
37
16
|
x?: number;
|
|
38
17
|
y?: number;
|
|
39
18
|
}): void;
|
|
40
|
-
|
|
41
|
-
|
|
19
|
+
addScrollEndListener(handler: (x: number, y: number) => void): void;
|
|
20
|
+
removeScrollEndListener(handler: (x: number, y: number) => void): void;
|
|
21
|
+
bindScroller(scroller: Scroller): () => void;
|
|
22
|
+
assignMaster(masterScroller: Scroller): void;
|
|
42
23
|
}
|
|
43
24
|
|
|
44
25
|
export { ScrollerSyncer };
|
package/internal.js
CHANGED
|
@@ -1,159 +1,73 @@
|
|
|
1
|
-
import { Emitter,
|
|
1
|
+
import { Emitter, isArraysEqual } from '@fullcalendar/core/internal.js';
|
|
2
2
|
|
|
3
|
-
const WHEEL_EVENT_NAMES = 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ');
|
|
4
3
|
/*
|
|
5
|
-
|
|
4
|
+
Fires:
|
|
5
|
+
- scrollEnd: (x, y) => void
|
|
6
6
|
*/
|
|
7
|
-
class ScrollListener {
|
|
8
|
-
constructor(el) {
|
|
9
|
-
this.el = el;
|
|
10
|
-
this.emitter = new Emitter();
|
|
11
|
-
this.isScrolling = false;
|
|
12
|
-
this.isTouching = false; // user currently has finger down?
|
|
13
|
-
this.isRecentlyWheeled = false;
|
|
14
|
-
this.isRecentlyScrolled = false;
|
|
15
|
-
this.wheelWaiter = new DelayedRunner(this._handleWheelWaited.bind(this));
|
|
16
|
-
this.scrollWaiter = new DelayedRunner(this._handleScrollWaited.bind(this));
|
|
17
|
-
// Handlers
|
|
18
|
-
// ----------------------------------------------------------------------------------------------
|
|
19
|
-
this.handleScroll = () => {
|
|
20
|
-
this.startScroll();
|
|
21
|
-
this.emitter.trigger('scroll', this.isRecentlyWheeled, this.isTouching);
|
|
22
|
-
this.isRecentlyScrolled = true;
|
|
23
|
-
this.scrollWaiter.request(500);
|
|
24
|
-
};
|
|
25
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
26
|
-
this.handleWheel = () => {
|
|
27
|
-
this.isRecentlyWheeled = true;
|
|
28
|
-
this.wheelWaiter.request(500);
|
|
29
|
-
};
|
|
30
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
31
|
-
this.handleTouchStart = () => {
|
|
32
|
-
this.isTouching = true;
|
|
33
|
-
};
|
|
34
|
-
this.handleTouchEnd = () => {
|
|
35
|
-
this.isTouching = false;
|
|
36
|
-
// if the user ended their touch, and the scroll area wasn't moving,
|
|
37
|
-
// we consider this to be the end of the scroll.
|
|
38
|
-
if (!this.isRecentlyScrolled) {
|
|
39
|
-
this.endScroll(); // won't fire if already ended
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
el.addEventListener('scroll', this.handleScroll);
|
|
43
|
-
el.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
44
|
-
el.addEventListener('touchend', this.handleTouchEnd);
|
|
45
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
46
|
-
el.addEventListener(eventName, this.handleWheel, { passive: true });
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
destroy() {
|
|
50
|
-
let { el } = this;
|
|
51
|
-
el.removeEventListener('scroll', this.handleScroll);
|
|
52
|
-
el.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
53
|
-
el.removeEventListener('touchend', this.handleTouchEnd);
|
|
54
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
55
|
-
el.removeEventListener(eventName, this.handleWheel, { passive: true });
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// Start / Stop
|
|
59
|
-
// ----------------------------------------------------------------------------------------------
|
|
60
|
-
startScroll() {
|
|
61
|
-
if (!this.isScrolling) {
|
|
62
|
-
this.isScrolling = true;
|
|
63
|
-
this.emitter.trigger('scrollStart', this.isRecentlyWheeled, this.isTouching);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
endScroll() {
|
|
67
|
-
if (this.isScrolling) {
|
|
68
|
-
this.emitter.trigger('scrollEnd');
|
|
69
|
-
this.isScrolling = false;
|
|
70
|
-
this.isRecentlyScrolled = true;
|
|
71
|
-
this.isRecentlyWheeled = false;
|
|
72
|
-
this.scrollWaiter.clear();
|
|
73
|
-
this.wheelWaiter.clear();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
_handleScrollWaited() {
|
|
77
|
-
this.isRecentlyScrolled = false;
|
|
78
|
-
// only end the scroll if not currently touching.
|
|
79
|
-
// if touching, the scrolling will end later, on touchend.
|
|
80
|
-
if (!this.isTouching) {
|
|
81
|
-
this.endScroll(); // won't fire if already ended
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
_handleWheelWaited() {
|
|
85
|
-
this.isRecentlyWheeled = false;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
7
|
class ScrollerSyncer {
|
|
90
8
|
constructor(isHorizontal = false) {
|
|
91
9
|
this.isHorizontal = isHorizontal;
|
|
92
|
-
this.
|
|
93
|
-
this.
|
|
10
|
+
this.emitter = new Emitter();
|
|
11
|
+
this.scrollers = [];
|
|
12
|
+
this.destroyFuncs = [];
|
|
94
13
|
this.isPaused = false;
|
|
95
14
|
}
|
|
96
|
-
handleChildren(scrollers
|
|
15
|
+
handleChildren(scrollers) {
|
|
97
16
|
if (!isArraysEqual(this.scrollers, scrollers)) {
|
|
98
17
|
this.destroy();
|
|
99
|
-
this.scrollers = scrollers;
|
|
100
|
-
const scrollListeners = [];
|
|
101
18
|
for (const scroller of scrollers) {
|
|
102
19
|
if (scroller) { // could be null
|
|
103
|
-
|
|
20
|
+
this.destroyFuncs.push(this.bindScroller(scroller));
|
|
21
|
+
this.scrollers.push(scroller);
|
|
104
22
|
}
|
|
105
23
|
}
|
|
106
|
-
this.scrollListeners = scrollListeners;
|
|
107
24
|
}
|
|
108
|
-
this.isRtl = isRtl;
|
|
109
25
|
}
|
|
110
26
|
destroy() {
|
|
111
|
-
for (let
|
|
112
|
-
|
|
27
|
+
for (let destroyFunc of this.destroyFuncs) {
|
|
28
|
+
destroyFunc();
|
|
113
29
|
}
|
|
30
|
+
this.destroyFuncs = [];
|
|
31
|
+
this.scrollers = [];
|
|
114
32
|
}
|
|
115
33
|
get x() {
|
|
116
|
-
const {
|
|
117
|
-
|
|
118
|
-
return getNormalizedScrollX(el, isRtl);
|
|
34
|
+
const { scrollers, masterScroller } = this;
|
|
35
|
+
return (masterScroller || scrollers[0]).x;
|
|
119
36
|
}
|
|
120
37
|
get y() {
|
|
121
|
-
const {
|
|
122
|
-
|
|
123
|
-
return el.scrollTop;
|
|
38
|
+
const { scrollers, masterScroller } = this;
|
|
39
|
+
return (masterScroller || scrollers[0]).y;
|
|
124
40
|
}
|
|
125
|
-
scrollTo(
|
|
41
|
+
scrollTo(scrollArg) {
|
|
126
42
|
this.isPaused = true;
|
|
127
|
-
const {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
scrollListener.el.scrollTop = y;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (x != null) {
|
|
134
|
-
for (let scrollListener of scrollListeners) {
|
|
135
|
-
setNormalizedScrollX(scrollListener.el, isRtl, x);
|
|
136
|
-
}
|
|
43
|
+
const { scrollers } = this;
|
|
44
|
+
for (let scroller of scrollers) {
|
|
45
|
+
scroller.scrollTo(scrollArg);
|
|
137
46
|
}
|
|
138
47
|
this.isPaused = false;
|
|
139
48
|
}
|
|
140
|
-
|
|
49
|
+
addScrollEndListener(handler) {
|
|
50
|
+
this.emitter.on('scrollEnd', handler);
|
|
51
|
+
}
|
|
52
|
+
removeScrollEndListener(handler) {
|
|
53
|
+
this.emitter.off('scrollEnd', handler);
|
|
54
|
+
}
|
|
55
|
+
bindScroller(scroller) {
|
|
141
56
|
let { isHorizontal } = this;
|
|
142
|
-
let scrollListener = new ScrollListener(el);
|
|
143
57
|
const onScroll = (isWheel, isTouch) => {
|
|
144
58
|
if (!this.isPaused) {
|
|
145
|
-
if (!this.
|
|
146
|
-
this.assignMaster(
|
|
59
|
+
if (!this.masterScroller || (this.masterScroller !== scroller && (isWheel || isTouch))) {
|
|
60
|
+
this.assignMaster(scroller);
|
|
147
61
|
}
|
|
148
|
-
if (this.
|
|
149
|
-
for (let
|
|
150
|
-
|
|
151
|
-
if (otherEl !== el) {
|
|
62
|
+
if (this.masterScroller === scroller) { // dealing with current
|
|
63
|
+
for (let otherScroller of this.scrollers) {
|
|
64
|
+
if (otherScroller !== scroller) {
|
|
152
65
|
if (isHorizontal) {
|
|
153
|
-
|
|
66
|
+
// TODO: user raw scrollLeft for better performance. No normalization necessary
|
|
67
|
+
otherScroller.scrollTo({ x: scroller.x });
|
|
154
68
|
}
|
|
155
69
|
else {
|
|
156
|
-
|
|
70
|
+
otherScroller.scrollTo({ y: scroller.y });
|
|
157
71
|
}
|
|
158
72
|
}
|
|
159
73
|
}
|
|
@@ -161,19 +75,23 @@ class ScrollerSyncer {
|
|
|
161
75
|
}
|
|
162
76
|
};
|
|
163
77
|
const onScrollEnd = () => {
|
|
164
|
-
if (this.
|
|
165
|
-
this.
|
|
78
|
+
if (this.masterScroller === scroller) {
|
|
79
|
+
this.masterScroller = null;
|
|
80
|
+
this.emitter.trigger('scrollEnd', this.x, this.y);
|
|
166
81
|
}
|
|
167
82
|
};
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
return
|
|
83
|
+
scroller.listener.emitter.on('scroll', onScroll);
|
|
84
|
+
scroller.listener.emitter.on('scrollEnd', onScrollEnd);
|
|
85
|
+
return () => {
|
|
86
|
+
scroller.listener.emitter.off('scroll', onScroll);
|
|
87
|
+
scroller.listener.emitter.off('scrollEnd', onScrollEnd);
|
|
88
|
+
};
|
|
171
89
|
}
|
|
172
|
-
assignMaster(
|
|
173
|
-
this.
|
|
174
|
-
for (let
|
|
175
|
-
if (
|
|
176
|
-
|
|
90
|
+
assignMaster(masterScroller) {
|
|
91
|
+
this.masterScroller = masterScroller;
|
|
92
|
+
for (let scroller of this.scrollers) {
|
|
93
|
+
if (scroller !== masterScroller) {
|
|
94
|
+
scroller.endScroll(); // to prevent residual scrolls from reclaiming master
|
|
177
95
|
}
|
|
178
96
|
}
|
|
179
97
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fullcalendar/scrollgrid",
|
|
3
|
-
"version": "7.0.0-beta.
|
|
3
|
+
"version": "7.0.0-beta.1",
|
|
4
4
|
"title": "FullCalendar ScrollGrid Plugin",
|
|
5
5
|
"description": "Tabular data chunked into scrollable panes",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@fullcalendar/premium-common": "7.0.0-beta.
|
|
7
|
+
"@fullcalendar/premium-common": "7.0.0-beta.1"
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
|
-
"@fullcalendar/core": "7.0.0-beta.
|
|
10
|
+
"@fullcalendar/core": "7.0.0-beta.1"
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
|
13
13
|
"keywords": [
|