@fullcalendar/scrollgrid
Advanced tools
Comparing version 5.0.0-beta.1 to 5.0.0-beta.2
245
main.js
/*! | ||
FullCalendar ScrollGrid Plugin v5.0.0-beta.1 | ||
FullCalendar ScrollGrid Plugin v5.0.0-beta.2 | ||
Docs & License: https://fullcalendar.io/scheduler | ||
@@ -7,3 +7,3 @@ (c) 2019 Adam Shaw | ||
import { EmitterMixin, DelayedRunner, preventDefault, htmlToElement, removeElement, computeEdges, findElements, translateRect, computeInnerRect, applyStyle, createRef, getScrollbarWidths, setRef, getIsRtlScrollbarOnLeft, h, Scroller, isPropsEqual, BaseComponent, memoizeArraylike, renderMicroColGroup, RefMap, memoizeHashlike, getScrollGridClassNames, Fragment, getSectionClassNames, getAllowYScrolling, getSectionHasLiquidHeight, renderChunkContent, computeShrinkWidth, CLIENT_HEIGHT_WIGGLE, collectFromHash, mapHash, render, isArraysEqual, sanitizeShrinkWidth, hasShrinkWidth, compareObjs, isColPropsEqual, createPlugin } from '@fullcalendar/core'; | ||
import { EmitterMixin, DelayedRunner, htmlToElement, removeElement, computeEdges, findElements, translateRect, computeInnerRect, applyStyle, createRef, getScrollbarWidths, setRef, getIsRtlScrollbarOnLeft, h, Scroller, isPropsEqual, BaseComponent, memoizeArraylike, renderMicroColGroup, RefMap, memoizeHashlike, getScrollGridClassNames, Fragment, getSectionClassNames, getAllowYScrolling, getSectionHasLiquidHeight, renderChunkContent, computeShrinkWidth, collectFromHash, mapHash, render, isArraysEqual, sanitizeShrinkWidth, hasShrinkWidth, compareObjs, isColPropsEqual, createPlugin } from '@fullcalendar/core'; | ||
import { __extends, __assign } from 'tslib'; | ||
@@ -22,51 +22,37 @@ | ||
this.isTouching = false; // user currently has finger down? | ||
this.isMoving = false; // whether a scroll event has happened recently | ||
this.isTouchScrollEnabled = false; | ||
this.moveEndReporter = new DelayedRunner(this._reportMovingEnd.bind(this)); | ||
// Scroll Events | ||
this.isRecentlyWheeled = false; | ||
this.isRecentlyScrolled = false; | ||
this.wheelWaiter = new DelayedRunner(this._handleWheelWaited.bind(this)); | ||
this.scrollWaiter = new DelayedRunner(this._handleScrollWaited.bind(this)); | ||
// Handlers | ||
// ---------------------------------------------------------------------------------------------- | ||
this.reportScroll = function () { | ||
if (!_this.isScrolling) { | ||
_this.reportScrollStart(); | ||
} | ||
_this.emitter.trigger('scroll'); | ||
_this.isMoving = true; | ||
_this.moveEndReporter.request(500); | ||
this.handleScroll = function () { | ||
_this.startScroll(); | ||
_this.emitter.trigger('scroll', _this.isRecentlyWheeled, _this.isTouching); | ||
_this.isRecentlyScrolled = true; | ||
_this.scrollWaiter.request(500); | ||
}; | ||
this.reportScrollStart = function () { | ||
if (!_this.isScrolling) { | ||
_this.isScrolling = true; | ||
_this.emitter.trigger('scrollStart', _this.isTouching); // created in constructor | ||
} | ||
// will fire *before* the scroll event is fired (might not cause a scroll) | ||
this.handleWheel = function () { | ||
_this.isRecentlyWheeled = true; | ||
_this.wheelWaiter.request(500); | ||
}; | ||
this.reportWheel = function (ev) { | ||
_this.emitter.trigger('wheel'); | ||
}; | ||
// Touch Events | ||
// ---------------------------------------------------------------------------------------------- | ||
// will fire *before* the scroll event is fired | ||
this.reportTouchStart = function () { | ||
// will fire *before* the scroll event is fired (might not cause a scroll) | ||
this.handleTouchStart = function () { | ||
_this.isTouching = true; | ||
}; | ||
this.reportTouchEnd = function () { | ||
if (_this.isTouching) { | ||
_this.isTouching = false; | ||
// if touch scrolling was re-enabled during a recent touch scroll | ||
// then unbind the handlers that are preventing it from happening. | ||
if (_this.isTouchScrollEnabled) { | ||
_this.unbindPreventTouchScroll(); // won't do anything if not bound | ||
} | ||
// if the user ended their touch, and the scroll area wasn't moving, | ||
// we consider this to be the end of the scroll. | ||
if (!_this.isMoving) { | ||
_this.reportScrollEnd(); // won't fire if already ended | ||
} | ||
this.handleTouchEnd = function () { | ||
_this.isTouching = false; | ||
// if the user ended their touch, and the scroll area wasn't moving, | ||
// we consider this to be the end of the scroll. | ||
if (!_this.isRecentlyScrolled) { | ||
_this.endScroll(); // won't fire if already ended | ||
} | ||
}; | ||
el.addEventListener('scroll', this.reportScroll); | ||
el.addEventListener('touchstart', this.reportTouchStart, { passive: true }); | ||
el.addEventListener('touchend', this.reportTouchEnd); | ||
el.addEventListener('scroll', this.handleScroll); | ||
el.addEventListener('touchstart', this.handleTouchStart, { passive: true }); | ||
el.addEventListener('touchend', this.handleTouchEnd); | ||
for (var _i = 0, WHEEL_EVENT_NAMES_1 = WHEEL_EVENT_NAMES; _i < WHEEL_EVENT_NAMES_1.length; _i++) { | ||
var eventName = WHEEL_EVENT_NAMES_1[_i]; | ||
el.addEventListener(eventName, this.reportWheel); | ||
el.addEventListener(eventName, this.handleWheel); | ||
} | ||
@@ -76,48 +62,38 @@ } | ||
var el = this.el; | ||
el.removeEventListener('scroll', this.reportScroll); | ||
el.removeEventListener('touchstart', this.reportTouchStart, { passive: true }); | ||
el.removeEventListener('touchend', this.reportTouchEnd); | ||
el.removeEventListener('scroll', this.handleScroll); | ||
el.removeEventListener('touchstart', this.handleTouchStart, { passive: true }); | ||
el.removeEventListener('touchend', this.handleTouchEnd); | ||
for (var _i = 0, WHEEL_EVENT_NAMES_2 = WHEEL_EVENT_NAMES; _i < WHEEL_EVENT_NAMES_2.length; _i++) { | ||
var eventName = WHEEL_EVENT_NAMES_2[_i]; | ||
el.removeEventListener(eventName, this.reportWheel); | ||
el.removeEventListener(eventName, this.handleWheel); | ||
} | ||
}; | ||
// Touch scroll prevention | ||
// Start / Stop | ||
// ---------------------------------------------------------------------------------------------- | ||
ScrollListener.prototype.disableTouchScroll = function () { | ||
this.isTouchScrollEnabled = false; | ||
this.bindPreventTouchScroll(); // will be unbound in enableTouchScroll or reportTouchEnd | ||
}; | ||
ScrollListener.prototype.enableTouchScroll = function () { | ||
this.isTouchScrollEnabled = true; | ||
// only immediately unbind if a touch event is NOT in progress. | ||
// otherwise, it will be handled by reportTouchEnd. | ||
if (!this.isTouching) { | ||
this.unbindPreventTouchScroll(); | ||
ScrollListener.prototype.startScroll = function () { | ||
if (!this.isScrolling) { | ||
this.isScrolling = true; | ||
this.emitter.trigger('scrollStart', this.isRecentlyWheeled, this.isTouching); | ||
} | ||
}; | ||
ScrollListener.prototype.bindPreventTouchScroll = function () { | ||
if (!this.preventTouchScrollHandler) { | ||
this.el.addEventListener('touchmove', (this.preventTouchScrollHandler = preventDefault)); | ||
ScrollListener.prototype.endScroll = function () { | ||
if (this.isScrolling) { | ||
this.emitter.trigger('scrollEnd'); | ||
this.isScrolling = false; | ||
this.isRecentlyScrolled = true; | ||
this.isRecentlyWheeled = false; | ||
this.scrollWaiter.clear(); | ||
this.wheelWaiter.clear(); | ||
} | ||
}; | ||
ScrollListener.prototype.unbindPreventTouchScroll = function () { | ||
if (this.preventTouchScrollHandler) { | ||
this.el.removeEventListener('touchmove', this.preventTouchScrollHandler); | ||
this.preventTouchScrollHandler = null; | ||
} | ||
}; | ||
ScrollListener.prototype._reportMovingEnd = function () { | ||
this.isMoving = false; | ||
ScrollListener.prototype._handleScrollWaited = function () { | ||
this.isRecentlyScrolled = false; | ||
// only end the scroll if not currently touching. | ||
// if touching, the scrolling will end later, on touchend. | ||
if (!this.isTouching) { | ||
this.reportScrollEnd(); | ||
this.endScroll(); // won't fire if already ended | ||
} | ||
}; | ||
ScrollListener.prototype.reportScrollEnd = function () { | ||
if (this.isScrolling) { | ||
this.emitter.trigger('scrollEnd'); | ||
this.isScrolling = false; | ||
} | ||
ScrollListener.prototype._handleWheelWaited = function () { | ||
this.isRecentlyWheeled = false; | ||
}; | ||
@@ -204,2 +180,4 @@ return ScrollListener; | ||
This is because we attach the coords with JS, and the VDOM might take away the fc-sticky class but doesn't know kill the positioning. | ||
TODO: don't query text-align:center. isn't compatible with flexbox centering. instead, check natural X coord within parent container | ||
*/ | ||
@@ -217,5 +195,6 @@ var StickyScroller = /** @class */ (function () { | ||
var viewportWidth = scrollEl.clientWidth; | ||
var viewportHeight = scrollEl.clientHeight; | ||
if (_this.usingRelative) { | ||
var elDestinations = _this.computeElDestinations(elGeoms, viewportWidth); // read before prepPositioning | ||
assignRelativePositions(els, elGeoms, elDestinations); | ||
assignRelativePositions(els, elGeoms, elDestinations, viewportWidth, viewportHeight); | ||
} | ||
@@ -271,2 +250,3 @@ else { | ||
}; | ||
// only for IE | ||
StickyScroller.prototype.computeElDestinations = function (elGeoms, viewportWidth) { | ||
@@ -302,7 +282,18 @@ var scrollEl = this.scrollEl; | ||
}()); | ||
function assignRelativePositions(els, elGeoms, elDestinations) { | ||
function assignRelativePositions(els, elGeoms, elDestinations, viewportWidth, viewportHeight) { | ||
els.forEach(function (el, i) { | ||
var naturalBound = elGeoms[i].naturalBound; | ||
var left = elDestinations[i].left - naturalBound.left; | ||
var top = elDestinations[i].top - naturalBound.top; | ||
var _a = elGeoms[i], naturalBound = _a.naturalBound, parentBound = _a.parentBound; | ||
var parentWidth = parentBound.right - parentBound.left; | ||
var parentHeight = parentBound.bottom - parentBound.bottom; | ||
var left; | ||
var top; | ||
if (parentWidth > viewportWidth || | ||
parentHeight > viewportHeight) { | ||
left = elDestinations[i].left - naturalBound.left; | ||
top = elDestinations[i].top - naturalBound.top; | ||
} | ||
else { // if parent container can be completely in view, we don't need stickiness | ||
left = ''; | ||
top = ''; | ||
} | ||
applyStyle(el, { | ||
@@ -318,9 +309,15 @@ position: 'relative', | ||
els.forEach(function (el, i) { | ||
var stickyLeft = 0; | ||
if (elGeoms[i].textAlign === 'center') { | ||
stickyLeft = (viewportWidth - elGeoms[i].elWidth) / 2; | ||
var _a = elGeoms[i], textAlign = _a.textAlign, elWidth = _a.elWidth, parentBound = _a.parentBound; | ||
var parentWidth = parentBound.right - parentBound.left; | ||
var left; | ||
if (textAlign === 'center' && | ||
parentWidth > viewportWidth) { | ||
left = (viewportWidth - elWidth) / 2; | ||
} | ||
else { // if parent container can be completely in view, we don't need stickiness | ||
left = ''; | ||
} | ||
applyStyle(el, { | ||
left: stickyLeft, | ||
right: stickyLeft, | ||
left: left, | ||
right: left, | ||
top: 0 | ||
@@ -427,18 +424,18 @@ }); | ||
var scrollListener = new ScrollListener(el); | ||
var onScrollStart = function () { | ||
if (!_this.isPaused && !_this.masterEl) { | ||
_this.assignMaster(el); | ||
} | ||
}; | ||
var onScroll = function () { | ||
if (!_this.isPaused && el === _this.masterEl) { | ||
for (var _i = 0, scrollEls_1 = scrollEls; _i < scrollEls_1.length; _i++) { | ||
var otherEl = scrollEls_1[_i]; | ||
if (otherEl !== el) { | ||
if (isVertical) { | ||
otherEl.scrollTop = el.scrollTop; | ||
var onScroll = function (isWheel, isTouch) { | ||
if (!_this.isPaused) { | ||
if (!_this.masterEl || (_this.masterEl !== el && (isWheel || isTouch))) { | ||
_this.assignMaster(el); | ||
} | ||
if (_this.masterEl === el) { // dealing with current | ||
for (var _i = 0, scrollEls_1 = scrollEls; _i < scrollEls_1.length; _i++) { | ||
var otherEl = scrollEls_1[_i]; | ||
if (otherEl !== el) { | ||
if (isVertical) { | ||
otherEl.scrollTop = el.scrollTop; | ||
} | ||
else { | ||
otherEl.scrollLeft = el.scrollLeft; | ||
} | ||
} | ||
else { | ||
otherEl.scrollLeft = el.scrollLeft; | ||
} | ||
} | ||
@@ -449,22 +446,12 @@ } | ||
var onScrollEnd = function () { | ||
if (!_this.isPaused && el === _this.masterEl) { | ||
_this.unassignMaster(); | ||
if (_this.masterEl === el) { | ||
_this.masterEl = null; | ||
} | ||
}; | ||
// // when the user scrolls via mousewheel, we know for sure the target | ||
// // scroller should be the master. capture the various x-browser events that fire. | ||
// const onWheel = () => { | ||
// if (!this.isPaused) { | ||
// this.assignMaster(el) | ||
// } | ||
// } | ||
scrollListener.emitter | ||
.on('scrollStart', onScrollStart) | ||
.on('scroll', onScroll) | ||
.on('scrollEnd', onScrollEnd); | ||
// .on('wheel', onWheel) // TODO: revive? | ||
return scrollListener; | ||
}; | ||
ScrollSyncer.prototype.assignMaster = function (el) { | ||
this.unassignMaster(); | ||
this.masterEl = el; | ||
@@ -474,15 +461,6 @@ for (var _i = 0, _a = this.scrollListeners; _i < _a.length; _i++) { | ||
if (scrollListener.el !== el) { | ||
scrollListener.disableTouchScroll(); | ||
scrollListener.endScroll(); // to prevent residual scrolls from reclaiming master | ||
} | ||
} | ||
}; | ||
ScrollSyncer.prototype.unassignMaster = function () { | ||
if (this.masterEl) { | ||
for (var _i = 0, _a = this.scrollListeners; _i < _a.length; _i++) { | ||
var scrollListener = _a[_i]; | ||
scrollListener.enableTouchScroll(); | ||
} | ||
this.masterEl = null; | ||
} | ||
}; | ||
/* | ||
@@ -589,3 +567,3 @@ will normalize the scrollLeft value | ||
h("colgroup", null, colGroupStats.map(function (colGroupStat, i) { return renderMacroCol(colGroupStat, shrinkWidths[i]); })), | ||
props.sections.map(function (sectionConfig, i) { return _this.renderSection(sectionConfig, i, colGroupStats, microColGroupNodes, state.sectionRowMaxHeights); })), | ||
h("tbody", null, props.sections.map(function (sectionConfig, i) { return _this.renderSection(sectionConfig, i, colGroupStats, microColGroupNodes, state.sectionRowMaxHeights); }))), | ||
props.forPrint && | ||
@@ -771,3 +749,3 @@ h("div", { ref: this.printContainerRef }))); | ||
var currentScrollers = this.clippedScrollerRefs.currentMap; | ||
var currentScrollerEls = this.scrollerElRefs.currentMap; | ||
var scrollerEls = this.scrollerElRefs.currentMap; | ||
var forceYScrollbars = false; | ||
@@ -778,3 +756,4 @@ var forceXScrollbars = false; | ||
for (var sectionI = 0; sectionI < sectionCnt; sectionI++) { // along edge | ||
var scroller = currentScrollers[sectionI * chunksPerSection + sideScrollI]; | ||
var index = sectionI * chunksPerSection + sideScrollI; | ||
var scroller = currentScrollers[index]; | ||
if (scroller && scroller.needsYScrolling()) { | ||
@@ -786,3 +765,4 @@ forceYScrollbars = true; | ||
for (var chunkI = 0; chunkI < chunksPerSection; chunkI++) { // along last row | ||
var scroller = currentScrollers[lastSectionI * chunksPerSection + chunkI]; | ||
var index = lastSectionI * chunksPerSection + chunkI; | ||
var scroller = currentScrollers[index]; | ||
if (scroller && scroller.needsXScrolling()) { | ||
@@ -796,10 +776,11 @@ forceXScrollbars = true; | ||
var index = sectionI * chunksPerSection + chunkI; | ||
var scrollerEl = currentScrollerEls[index]; | ||
var scrollerEl = scrollerEls[index]; | ||
if (scrollerEl) { | ||
scrollerClientWidths[index] = (chunkI === sideScrollI && forceYScrollbars) // TODO: problem with border/padding maybe? | ||
? scrollerEl.offsetWidth - scrollbarWidth.y | ||
: scrollerEl.clientWidth; // will be doing hidden-scroll | ||
scrollerClientHeights[index] = (sectionI === lastSectionI && forceXScrollbars) | ||
? scrollerEl.offsetHeight - scrollbarWidth.x | ||
: scrollerEl.clientHeight - CLIENT_HEIGHT_WIGGLE; // will be doing hidden-scroll | ||
var harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders | ||
scrollerClientWidths[index] = Math.floor(harnessEl.getBoundingClientRect().width - ((chunkI === sideScrollI && forceYScrollbars) | ||
? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future | ||
: 0)); | ||
scrollerClientHeights[index] = Math.floor(harnessEl.getBoundingClientRect().height - ((sectionI === lastSectionI && forceXScrollbars) | ||
? scrollbarWidth.x // use global because scroller might not have scrollbars yet but will need them in future | ||
: 0)); | ||
} | ||
@@ -806,0 +787,0 @@ } |
{ | ||
"name": "@fullcalendar/scrollgrid", | ||
"version": "5.0.0-beta.1", | ||
"version": "5.0.0-beta.2", | ||
"title": "FullCalendar ScrollGrid Plugin", | ||
@@ -30,3 +30,3 @@ "description": "internal package", | ||
"peerDependencies": { | ||
"@fullcalendar/core": "5.0.0-beta.1" | ||
"@fullcalendar/core": "5.0.0-beta.2" | ||
}, | ||
@@ -33,0 +33,0 @@ "main": "main.js", |
51341
1047