@lenne.tech/ng-base 0.2.1 → 0.2.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/bundles/lenne.tech-ng-base-src-lib-base.umd.js +251 -15
- package/bundles/lenne.tech-ng-base-src-lib-base.umd.js.map +1 -1
- package/bundles/lenne.tech-ng-base.umd.js +251 -15
- package/bundles/lenne.tech-ng-base.umd.js.map +1 -1
- package/esm2015/lib/base/interfaces/base-module-config.interface.js +1 -1
- package/esm2015/lib/base/services/scroll.service.js +201 -16
- package/esm2015/src/lib/base/interfaces/base-module-config.interface.js +1 -1
- package/esm2015/src/lib/base/services/scroll.service.js +201 -16
- package/fesm2015/lenne.tech-ng-base-src-lib-base.js +200 -15
- package/fesm2015/lenne.tech-ng-base-src-lib-base.js.map +1 -1
- package/fesm2015/lenne.tech-ng-base.js +200 -15
- package/fesm2015/lenne.tech-ng-base.js.map +1 -1
- package/lib/base/interfaces/base-module-config.interface.d.ts +5 -0
- package/lib/base/services/scroll.service.d.ts +66 -3
- package/package.json +1 -1
- package/src/lib/base/interfaces/base-module-config.interface.d.ts +5 -0
- package/src/lib/base/lenne.tech-ng-base-src-lib-base.metadata.json +1 -1
- package/src/lib/base/services/scroll.service.d.ts +66 -3
|
@@ -14,6 +14,7 @@ import * as i1$1 from '@angular/router';
|
|
|
14
14
|
import { Router } from '@angular/router';
|
|
15
15
|
import { buildClientSchema, getIntrospectionQuery } from 'graphql';
|
|
16
16
|
import { map } from 'rxjs/operators';
|
|
17
|
+
import { __awaiter } from 'tslib';
|
|
17
18
|
|
|
18
19
|
const BASE_MODULE_CONFIG = new InjectionToken('BASE_MODULE_CONFIG');
|
|
19
20
|
|
|
@@ -2004,31 +2005,73 @@ class ScrollService {
|
|
|
2004
2005
|
this.router = router;
|
|
2005
2006
|
this.moduleConfig = moduleConfig;
|
|
2006
2007
|
/**
|
|
2007
|
-
*
|
|
2008
|
+
* Is a scroll listener set
|
|
2009
|
+
*
|
|
2010
|
+
* @protected
|
|
2008
2011
|
*/
|
|
2009
|
-
this.
|
|
2012
|
+
this.scrollListener = false;
|
|
2010
2013
|
/**
|
|
2011
|
-
*
|
|
2012
|
-
*
|
|
2014
|
+
* Current scroll timer;
|
|
2015
|
+
*
|
|
2016
|
+
* @protected
|
|
2013
2017
|
*/
|
|
2014
|
-
this.
|
|
2015
|
-
const config = Object.assign({ scrollDetectionOffset: 200, scrollOffset: 100 }, moduleConfig);
|
|
2018
|
+
this.scrollTimer = -1;
|
|
2019
|
+
const config = Object.assign({ scrollDetectionOffset: 200, scrollOffset: 100, scrollSamplingRate: 100 }, moduleConfig);
|
|
2016
2020
|
this.detectionOffset = config.scrollDetectionOffset;
|
|
2017
2021
|
this.scrollOffset = config.scrollOffset;
|
|
2022
|
+
this.scrollSamplingRate = config.scrollSamplingRate;
|
|
2018
2023
|
}
|
|
2019
2024
|
/**
|
|
2020
2025
|
* Scroll to structureElement with specific ID
|
|
2021
2026
|
*/
|
|
2022
2027
|
scrollTo(id, options = {}) {
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2028
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2029
|
+
// Prepare config
|
|
2030
|
+
const config = Object.assign({ checkUrl: true, loadImagesBefore: true, resetStyles: false, setOverflow: true, stopPropagation: true }, options);
|
|
2031
|
+
// Check current URL
|
|
2032
|
+
if (config.checkUrl && this.router.url !== '/' && !this.router.url.startsWith('/#')) {
|
|
2033
|
+
yield this.router.navigate(['/'], { fragment: id });
|
|
2034
|
+
return !config.stopPropagation;
|
|
2035
|
+
}
|
|
2036
|
+
// Check if target element exits
|
|
2037
|
+
const el = document.getElementById(id);
|
|
2038
|
+
if (!el) {
|
|
2039
|
+
console.error('Missing scroll element with ID:', id);
|
|
2040
|
+
return !config.stopPropagation;
|
|
2041
|
+
}
|
|
2042
|
+
// Check if body overflow is visible
|
|
2043
|
+
// This is necessary for scroll handling
|
|
2044
|
+
const body = document.querySelector('body');
|
|
2045
|
+
let undoOverflowChanges = false;
|
|
2046
|
+
const scrollBodyStyles = JSON.parse(JSON.stringify(window.getComputedStyle(body)));
|
|
2047
|
+
if (config.setOverflow && (scrollBodyStyles.overflowX !== 'visible' || scrollBodyStyles.overflowY !== 'visible')) {
|
|
2048
|
+
// Set body overflow to visible
|
|
2049
|
+
console.warn('Style of body element for overflowX and overflowY will be set to "visible" for scrolling!');
|
|
2050
|
+
body.style.overflowX = 'visible';
|
|
2051
|
+
body.style.overflowY = 'visible';
|
|
2052
|
+
undoOverflowChanges = true;
|
|
2053
|
+
}
|
|
2054
|
+
// Load images before scrolling (once)
|
|
2055
|
+
if (config.loadImagesBefore) {
|
|
2056
|
+
yield this.preLoadImages();
|
|
2057
|
+
}
|
|
2058
|
+
// Get get bounding rect of target element
|
|
2059
|
+
const cords = el.getBoundingClientRect();
|
|
2060
|
+
// Scroll to element
|
|
2061
|
+
window.scrollBy({ top: cords.top - this.scrollOffset, behavior: 'smooth' });
|
|
2062
|
+
yield this.scrollDone({
|
|
2063
|
+
doneFunction: () => {
|
|
2064
|
+
// Undo changes
|
|
2065
|
+
if (undoOverflowChanges && config.resetStyles) {
|
|
2066
|
+
body.style.overflowX = scrollBodyStyles.overflowX;
|
|
2067
|
+
body.style.overflowY = scrollBodyStyles.overflowY;
|
|
2068
|
+
console.warn('Original style of body element for overflowX and overflowY is set.');
|
|
2069
|
+
}
|
|
2070
|
+
},
|
|
2071
|
+
});
|
|
2072
|
+
// Return stop propagation configuration
|
|
2073
|
+
return !config.stopPropagation;
|
|
2074
|
+
});
|
|
2032
2075
|
}
|
|
2033
2076
|
/**
|
|
2034
2077
|
* Get last active structureElement
|
|
@@ -2058,6 +2101,148 @@ class ScrollService {
|
|
|
2058
2101
|
const lastActiveElement = this.getLastActiveElement(list);
|
|
2059
2102
|
return id === lastActiveElement || (lastActiveElement === null && isFirst);
|
|
2060
2103
|
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Scroll done promise
|
|
2106
|
+
*/
|
|
2107
|
+
scrollDone(options = {}) {
|
|
2108
|
+
// Init configuration
|
|
2109
|
+
const config = Object.assign({ doneFunction: undefined, timeout: undefined }, options);
|
|
2110
|
+
// Return promise for scroll done
|
|
2111
|
+
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
2112
|
+
// Init variables
|
|
2113
|
+
let rejected = false;
|
|
2114
|
+
let timeoutId;
|
|
2115
|
+
// Set timeout handling if necessary
|
|
2116
|
+
if (config.timeout) {
|
|
2117
|
+
timeoutId = window.setTimeout(() => {
|
|
2118
|
+
rejected = true;
|
|
2119
|
+
reject(new Error('Timeout for scrollDone after:' + config.timeout));
|
|
2120
|
+
}, config.timeout);
|
|
2121
|
+
}
|
|
2122
|
+
// Wait for scroll done
|
|
2123
|
+
yield this.scrollDoneDetection();
|
|
2124
|
+
// Resolve promise if not already rejected
|
|
2125
|
+
if (!rejected) {
|
|
2126
|
+
// Stop timeout if set
|
|
2127
|
+
if (timeoutId) {
|
|
2128
|
+
window.clearTimeout(timeoutId);
|
|
2129
|
+
}
|
|
2130
|
+
// Get result (if doneFunction is set)
|
|
2131
|
+
let result;
|
|
2132
|
+
if (config.doneFunction) {
|
|
2133
|
+
result = yield config.doneFunction();
|
|
2134
|
+
}
|
|
2135
|
+
// Scroll done
|
|
2136
|
+
resolve(result);
|
|
2137
|
+
}
|
|
2138
|
+
}));
|
|
2139
|
+
}
|
|
2140
|
+
/**
|
|
2141
|
+
* Scroll done detecton
|
|
2142
|
+
*
|
|
2143
|
+
* @protected
|
|
2144
|
+
*/
|
|
2145
|
+
scrollDoneDetection() {
|
|
2146
|
+
// Return current scroll promise (Singelton)
|
|
2147
|
+
if (this.scrollPromise) {
|
|
2148
|
+
return this.scrollPromise;
|
|
2149
|
+
}
|
|
2150
|
+
// Create current scroll promise
|
|
2151
|
+
this.scrollPromise = new Promise((resolve) => {
|
|
2152
|
+
this.scrollPromiseResolve = resolve;
|
|
2153
|
+
if (this.scrollTimer !== -1) {
|
|
2154
|
+
window.clearTimeout(this.scrollTimer);
|
|
2155
|
+
}
|
|
2156
|
+
this.scrollTimer = window.setTimeout(() => {
|
|
2157
|
+
window.removeEventListener('scroll', this.scrollDoneDetection.bind(this));
|
|
2158
|
+
this.scrollPromise = undefined;
|
|
2159
|
+
resolve();
|
|
2160
|
+
}, this.scrollSamplingRate);
|
|
2161
|
+
});
|
|
2162
|
+
// Lisitening to scroll event;
|
|
2163
|
+
window.addEventListener('scroll', this.scrollDoneDetection.bind(this));
|
|
2164
|
+
// Return promise
|
|
2165
|
+
return this.scrollPromise;
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Preaload images (for lazy handling)
|
|
2169
|
+
*
|
|
2170
|
+
* @param options
|
|
2171
|
+
* @protected
|
|
2172
|
+
*/
|
|
2173
|
+
preLoadImages(options) {
|
|
2174
|
+
// Init configuration
|
|
2175
|
+
const config = Object.assign({ doneFunnction: undefined, timeout: undefined }, options);
|
|
2176
|
+
return new Promise((resolve) => {
|
|
2177
|
+
// Init variables
|
|
2178
|
+
let resolved = false;
|
|
2179
|
+
let timeoutId;
|
|
2180
|
+
// Init loading
|
|
2181
|
+
const images = Array.from(document.getElementsByTagName('img'));
|
|
2182
|
+
const promises = [];
|
|
2183
|
+
// Prepare images
|
|
2184
|
+
for (const image of images) {
|
|
2185
|
+
const src = image.getAttribute('src');
|
|
2186
|
+
// Check if changes are necessary and possible
|
|
2187
|
+
if ((image.complete && image.naturalHeight !== 0) || image.getAttribute('loading') !== 'lazy' || !src) {
|
|
2188
|
+
continue;
|
|
2189
|
+
}
|
|
2190
|
+
const newImage = document.createElement('img');
|
|
2191
|
+
Array.from(image.attributes).forEach((attr) => {
|
|
2192
|
+
if (attr.name !== 'loading' && attr.name !== 'src') {
|
|
2193
|
+
newImage.setAttribute(attr.name, attr.value);
|
|
2194
|
+
}
|
|
2195
|
+
});
|
|
2196
|
+
image.replaceWith(newImage);
|
|
2197
|
+
promises.push(this.loadImage(newImage, src));
|
|
2198
|
+
}
|
|
2199
|
+
if (config.timeout) {
|
|
2200
|
+
timeoutId = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
2201
|
+
resolved = true;
|
|
2202
|
+
if (config.doneFunnction) {
|
|
2203
|
+
yield config.doneFunction();
|
|
2204
|
+
}
|
|
2205
|
+
resolve(undefined);
|
|
2206
|
+
}));
|
|
2207
|
+
}
|
|
2208
|
+
// Wait until all images loaded
|
|
2209
|
+
Promise.all(promises)
|
|
2210
|
+
.catch((e) => console.error('Error during image loading', e))
|
|
2211
|
+
.finally(() => __awaiter(this, void 0, void 0, function* () {
|
|
2212
|
+
// Check if already resolved
|
|
2213
|
+
if (resolved) {
|
|
2214
|
+
return;
|
|
2215
|
+
}
|
|
2216
|
+
// Stop timeout
|
|
2217
|
+
if (timeoutId) {
|
|
2218
|
+
clearTimeout(timeoutId);
|
|
2219
|
+
}
|
|
2220
|
+
// Return result
|
|
2221
|
+
let result;
|
|
2222
|
+
if (config.doneFunnction) {
|
|
2223
|
+
result = yield config.doneFunction();
|
|
2224
|
+
}
|
|
2225
|
+
resolve(result);
|
|
2226
|
+
}));
|
|
2227
|
+
});
|
|
2228
|
+
}
|
|
2229
|
+
/**
|
|
2230
|
+
* Load image for image element
|
|
2231
|
+
*
|
|
2232
|
+
* @param imageElement
|
|
2233
|
+
* @param src
|
|
2234
|
+
* @protected
|
|
2235
|
+
*/
|
|
2236
|
+
loadImage(imageElement, src) {
|
|
2237
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2238
|
+
src = src || imageElement.src;
|
|
2239
|
+
return new Promise((resolve, reject) => {
|
|
2240
|
+
imageElement.onload = () => resolve(imageElement);
|
|
2241
|
+
imageElement.onerror = reject;
|
|
2242
|
+
imageElement.src = src;
|
|
2243
|
+
});
|
|
2244
|
+
});
|
|
2245
|
+
}
|
|
2061
2246
|
}
|
|
2062
2247
|
ScrollService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ScrollService_Factory() { return new ScrollService(i0.ɵɵinject(i1$1.Router), i0.ɵɵinject(BASE_MODULE_CONFIG)); }, token: ScrollService, providedIn: "root" });
|
|
2063
2248
|
ScrollService.decorators = [
|