UNPKG

vscroll

Version:
1,603 lines (1,585 loc) 204 kB
/** * vscroll (https://github.com/dhilt/vscroll) FESM5 * Version: 1.8.0 (2025-11-28T14:24:41.992Z) * Author: Denis Hilt * License: MIT */ import { __values, __read, __assign, __extends, __spreadArray } from 'tslib'; var Reactive = /** @class */ (function () { function Reactive(value, options) { this.id = 0; if (value !== void 0) { this.value = value; this.initialValue = value; } this.options = options || {}; this.subscriptions = new Map(); } Reactive.prototype.set = function (value) { var e_1, _a; if (this.value === value && !this.options.emitEqual) { return; } this.value = value; try { for (var _b = __values(this.subscriptions), _c = _b.next(); !_c.done; _c = _b.next()) { var _d = __read(_c.value, 2), sub = _d[1]; sub.emit(value); if (this.value !== value) { break; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } }; Reactive.prototype.get = function () { return this.value; }; Reactive.prototype.on = function (func) { var _this = this; var id = this.id++; var subscription = { emit: func, off: function () { subscription.emit = function () { return null; }; _this.subscriptions.delete(id); } }; this.subscriptions.set(id, subscription); if (this.options.emitOnSubscribe) { subscription.emit(this.value); } return function () { return subscription.off(); }; }; Reactive.prototype.once = function (func) { var off = this.on(function (v) { off(); func(v); }); return off; }; Reactive.prototype.reset = function () { this.set(this.initialValue); }; Reactive.prototype.dispose = function () { this.subscriptions.forEach(function (sub) { return sub.off(); }); }; return Reactive; }()); var AdapterPropName; (function (AdapterPropName) { AdapterPropName["id"] = "id"; AdapterPropName["mock"] = "mock"; AdapterPropName["augmented"] = "augmented"; AdapterPropName["version"] = "version"; AdapterPropName["init"] = "init"; AdapterPropName["init$"] = "init$"; AdapterPropName["packageInfo"] = "packageInfo"; AdapterPropName["itemsCount"] = "itemsCount"; AdapterPropName["bufferInfo"] = "bufferInfo"; AdapterPropName["isLoading"] = "isLoading"; AdapterPropName["isLoading$"] = "isLoading$"; AdapterPropName["loopPending"] = "loopPending"; AdapterPropName["loopPending$"] = "loopPending$"; AdapterPropName["firstVisible"] = "firstVisible"; AdapterPropName["firstVisible$"] = "firstVisible$"; AdapterPropName["lastVisible"] = "lastVisible"; AdapterPropName["lastVisible$"] = "lastVisible$"; AdapterPropName["bof"] = "bof"; AdapterPropName["bof$"] = "bof$"; AdapterPropName["eof"] = "eof"; AdapterPropName["eof$"] = "eof$"; AdapterPropName["paused"] = "paused"; AdapterPropName["paused$"] = "paused$"; AdapterPropName["reset"] = "reset"; AdapterPropName["reload"] = "reload"; AdapterPropName["append"] = "append"; AdapterPropName["prepend"] = "prepend"; AdapterPropName["check"] = "check"; AdapterPropName["remove"] = "remove"; AdapterPropName["clip"] = "clip"; AdapterPropName["insert"] = "insert"; AdapterPropName["replace"] = "replace"; AdapterPropName["update"] = "update"; AdapterPropName["pause"] = "pause"; AdapterPropName["resume"] = "resume"; AdapterPropName["fix"] = "fix"; AdapterPropName["relax"] = "relax"; AdapterPropName["showLog"] = "showLog"; })(AdapterPropName || (AdapterPropName = {})); var AdapterPropType; (function (AdapterPropType) { AdapterPropType[AdapterPropType["Scalar"] = 0] = "Scalar"; AdapterPropType[AdapterPropType["Reactive"] = 1] = "Reactive"; AdapterPropType[AdapterPropType["WorkflowRunner"] = 2] = "WorkflowRunner"; AdapterPropType[AdapterPropType["Function"] = 3] = "Function"; })(AdapterPropType || (AdapterPropType = {})); var Name = AdapterPropName; var Type = AdapterPropType; var noop = function () { return null; }; var methodPreResult = { immediate: true, success: true, details: 'Adapter is not initialized' }; var methodPausedResult = { immediate: true, success: true, details: 'Scroller is paused' }; var noopWF = function () { return Promise.resolve(methodPreResult); }; var emptyPackageInfo = { core: { name: '', version: '' }, consumer: { name: '', version: '' } }; var bufferInfoDefault = { firstIndex: NaN, lastIndex: NaN, minIndex: NaN, maxIndex: NaN, absMinIndex: -Infinity, absMaxIndex: +Infinity, defaultSize: NaN }; var EMPTY_ITEM = { data: {}, element: {} }; var getDefaultAdapterProps = function () { return [ { type: Type.Scalar, name: Name.id, value: 0, permanent: true }, { type: Type.Scalar, name: Name.mock, value: true, permanent: true }, { type: Type.Scalar, name: Name.augmented, value: false, permanent: true }, { type: Type.Scalar, name: Name.version, value: '', permanent: true }, { type: Type.Scalar, name: Name.init, value: false, reactive: Name.init$ }, { type: Type.Scalar, name: Name.packageInfo, value: emptyPackageInfo, onDemand: true }, { type: Type.Scalar, name: Name.itemsCount, value: 0, onDemand: true }, { type: Type.Scalar, name: Name.bufferInfo, value: bufferInfoDefault, onDemand: true }, { type: Type.Scalar, name: Name.isLoading, value: false, reactive: Name.isLoading$ }, { type: Type.Scalar, name: Name.loopPending, value: false, reactive: Name.loopPending$ }, { type: Type.Scalar, name: Name.firstVisible, value: EMPTY_ITEM, reactive: Name.firstVisible$, wanted: true }, { type: Type.Scalar, name: Name.lastVisible, value: EMPTY_ITEM, reactive: Name.lastVisible$, wanted: true }, { type: Type.Scalar, name: Name.bof, value: false, reactive: Name.bof$ }, { type: Type.Scalar, name: Name.eof, value: false, reactive: Name.eof$ }, { type: Type.Scalar, name: Name.paused, value: false, reactive: Name.paused$ }, { type: Type.WorkflowRunner, name: Name.reset, value: noopWF, allowedWhenPaused: true }, { type: Type.WorkflowRunner, name: Name.reload, value: noopWF }, { type: Type.WorkflowRunner, name: Name.append, value: noopWF }, { type: Type.WorkflowRunner, name: Name.prepend, value: noopWF }, { type: Type.WorkflowRunner, name: Name.check, value: noopWF }, { type: Type.WorkflowRunner, name: Name.remove, value: noopWF }, { type: Type.WorkflowRunner, name: Name.clip, value: noopWF }, { type: Type.WorkflowRunner, name: Name.insert, value: noopWF }, { type: Type.WorkflowRunner, name: Name.replace, value: noopWF }, { type: Type.WorkflowRunner, name: Name.update, value: noopWF }, { type: Type.WorkflowRunner, name: Name.pause, value: noopWF }, { type: Type.WorkflowRunner, name: Name.resume, value: noopWF, allowedWhenPaused: true }, { type: Type.WorkflowRunner, name: Name.fix, value: noopWF }, { type: Type.Function, name: Name.relax, value: noop }, { type: Type.Function, name: Name.showLog, value: noop }, { type: Type.Reactive, name: Name.init$, value: new Reactive() }, { type: Type.Reactive, name: Name.isLoading$, value: new Reactive() }, { type: Type.Reactive, name: Name.loopPending$, value: new Reactive() }, { type: Type.Reactive, name: Name.firstVisible$, value: new Reactive(EMPTY_ITEM, { emitOnSubscribe: true }), wanted: true }, { type: Type.Reactive, name: Name.lastVisible$, value: new Reactive(EMPTY_ITEM, { emitOnSubscribe: true }), wanted: true }, { type: Type.Reactive, name: Name.bof$, value: new Reactive() }, { type: Type.Reactive, name: Name.eof$, value: new Reactive() }, { type: Type.Reactive, name: Name.paused$, value: new Reactive() } ]; }; var reactiveConfigStorage = new Map(); var core = { name: 'vscroll', version: '1.8.0' }; var getBox = function (id) { var _a; return (_a = wantedStorage.get(id || -1)) === null || _a === void 0 ? void 0 : _a.box; }; var setBox = function (_a, id) { var name = _a.name, wanted = _a.wanted; var Wanted = wantedStorage.get(id || -1); if (wanted && Wanted && !Wanted.box[name] && !Wanted.block) { var a = AdapterPropName.firstVisible, a$ = AdapterPropName.firstVisible$; var b = AdapterPropName.lastVisible, b$ = AdapterPropName.lastVisible$; Wanted.box[a] = Wanted.box[a$] = [a, a$].some(function (n) { return n === name; }) || Wanted.box[a]; Wanted.box[b] = Wanted.box[b$] = [b, b$].some(function (n) { return n === name; }) || Wanted.box[b]; return true; } return false; }; var setBlock = function (value, id) { var Wanted = wantedStorage.get(id || -1); if (Wanted) { Wanted.block = value; } }; var wantedUtils = { getBox: getBox, setBox: setBox, setBlock: setBlock }; var wantedStorage = new Map(); var instanceCount$1 = 0; var AdapterContext = /** @class */ (function () { function AdapterContext(config) { var _this = this; var mock = config.mock, reactive = config.reactive; var id = ++instanceCount$1; var conf = { configurable: true }; var reactivePropsStore = {}; wantedStorage.set(id, { box: {}, block: false }); // set up permanent props Object.defineProperty(this, AdapterPropName.id, __assign({ get: function () { return id; } }, conf)); Object.defineProperty(this, AdapterPropName.mock, __assign({ get: function () { return mock; } }, conf)); Object.defineProperty(this, AdapterPropName.augmented, __assign({ get: function () { return false; } }, conf)); Object.defineProperty(this, AdapterPropName.version, __assign({ get: function () { return core.version; } }, conf)); // set up default props, they will be reassigned during the Adapter instantiation getDefaultAdapterProps() .filter(function (_a) { var permanent = _a.permanent; return !permanent; }) .forEach(function (prop) { var value = prop.value; // reactive props might be reconfigured by the vscroll consumer if (reactive && prop.type === AdapterPropType.Reactive) { var react = reactive[prop.name]; if (react) { // here we have a configured reactive property that came from the outer config // this prop must be exposed via Adapter, but at the same time we need to // persist the original default value as it will be used by the Adapter internally reactivePropsStore[prop.name] = __assign(__assign({}, react), { default: value // persisting the default native Reactive prop }); value = react.source; // exposing the configured prop instead of the default one } } Object.defineProperty(_this, prop.name, __assign({ get: function () { wantedUtils.setBox(prop, id); return value; } }, conf)); }); if (reactive) { // save both configured and default reactive props in the store reactiveConfigStorage.set(id, reactivePropsStore); } } return AdapterContext; }()); var getDefaultAdapterConfig = function () { var reactive = getDefaultAdapterProps() .filter(function (_a) { var type = _a.type; return type === AdapterPropType.Reactive; }) .reduce(function (acc, _a) { var name = _a.name, value = _a.value; acc[name] = { source: value, emit: function (source, val) { return source.set(val); } }; return acc; }, {}); return { mock: false, reactive: reactive }; }; var DatasourceGeneric = /** @class */ (function () { function DatasourceGeneric(datasource, config) { this.get = datasource.get; this.settings = datasource.settings; this.devSettings = datasource.devSettings; var adapterContext = new AdapterContext(config || { mock: false }); this.adapter = adapterContext; } // todo: should it be published? DatasourceGeneric.prototype.dispose = function () { reactiveConfigStorage.delete(this.adapter.id); wantedStorage.delete(this.adapter.id); }; return DatasourceGeneric; }()); var makeDatasource = function (getAdapterConfig) { return /** @class */ (function (_super) { __extends(class_1, _super); function class_1(datasource) { var config = typeof getAdapterConfig === 'function' ? getAdapterConfig() : getDefaultAdapterConfig(); return _super.call(this, datasource, config) || this; } return class_1; }(DatasourceGeneric)); }; var Datasource = makeDatasource(); var Direction; (function (Direction) { Direction["forward"] = "forward"; Direction["backward"] = "backward"; })(Direction || (Direction = {})); var SizeStrategy; (function (SizeStrategy) { SizeStrategy["Average"] = "average"; SizeStrategy["Constant"] = "constant"; SizeStrategy["Frequent"] = "frequent"; })(SizeStrategy || (SizeStrategy = {})); var ValidatorType; (function (ValidatorType) { ValidatorType["number"] = "must be a number"; ValidatorType["integer"] = "must be an integer"; ValidatorType["integerUnlimited"] = "must be an integer or infinity"; ValidatorType["moreOrEqual"] = "must be a number greater than (or equal to) {arg1}"; ValidatorType["itemList"] = "must be an array of items {arg1}"; ValidatorType["boolean"] = "must be a boolean"; ValidatorType["object"] = "must be an object"; ValidatorType["element"] = "must be an html element"; ValidatorType["function"] = "must be a function"; ValidatorType["funcOfxArguments"] = "must have {arg1} argument(s)"; ValidatorType["funcOfxAndMoreArguments"] = "must have at least {arg1} argument(s)"; ValidatorType["funcOfXToYArguments"] = "must have {arg1} to {arg2} arguments"; ValidatorType["oneOfCan"] = "can be present as only one item of {arg1} list"; ValidatorType["oneOfMust"] = "must be present as only one item of {arg1} list"; ValidatorType["or"] = "must satisfy at least 1 validator from {arg1} list"; ValidatorType["enum"] = "must belong to {arg1} list"; })(ValidatorType || (ValidatorType = {})); var getError = function (msg, args) { return (args || ['']).reduce(function (acc, arg, index) { return acc.replace("{arg".concat(index + 1, "}"), arg); }, msg); }; var getNumber = function (value) { return typeof value === 'number' || (typeof value === 'string' && value !== '') ? Number(value) : NaN; }; var onNumber = function (value) { var parsedValue = getNumber(value); var errors = []; if (Number.isNaN(parsedValue)) { errors.push(ValidatorType.number); } return { value: parsedValue, isSet: true, isValid: !errors.length, errors: errors }; }; var onInteger = function (value) { var errors = []; value = getNumber(value); var parsedValue = parseInt(String(value), 10); if (value !== parsedValue) { errors.push(ValidatorType.integer); } return { value: parsedValue, isSet: true, isValid: !errors.length, errors: errors }; }; var onIntegerUnlimited = function (value) { var parsedValue = value; var errors = []; value = getNumber(value); if (!Number.isFinite(value)) { parsedValue = value; } else { parsedValue = parseInt(String(value), 10); } if (value !== parsedValue) { errors.push(ValidatorType.integerUnlimited); } return { value: parsedValue, isSet: true, isValid: !errors.length, errors: errors }; }; var onMoreOrEqual = function (limit, fallback) { return function (value) { var result = onNumber(value); if (!result.isValid) { return result; } var parsedValue = result.value; var errors = []; if (parsedValue < limit) { if (!fallback) { errors.push(getError(ValidatorType.moreOrEqual, [String(limit)])); } else { parsedValue = limit; } } return { value: parsedValue, isSet: true, isValid: !errors.length, errors: errors }; }; }; var onBoolean = function (value) { var errors = []; var parsedValue = value; if (value === 'true') { parsedValue = true; } else if (value === 'false') { parsedValue = false; } if (typeof parsedValue !== 'boolean') { errors.push(ValidatorType.boolean); } return { value: parsedValue, isSet: true, isValid: !errors.length, errors: errors }; }; var onObject = function (value) { var errors = []; if (!value || Object.prototype.toString.call(value) !== '[object Object]') { errors.push(ValidatorType.object); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; var onHtmlElement = function (value) { var errors = []; if (!(value instanceof Element) && !(value instanceof Document)) { errors.push(ValidatorType.element); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; var onItemList = function (value) { var parsedValue = value; var errors = []; if (!Array.isArray(value)) { errors.push(ValidatorType.itemList); parsedValue = []; } else if (!value.length) { errors.push(getError(ValidatorType.itemList, ['with at least 1 item'])); } else if (value.length > 1) { var type = typeof value[0]; for (var i = value.length - 1; i >= 0; i--) { if (typeof value[i] !== type) { errors.push(getError(ValidatorType.itemList, ['of items of the same type'])); break; } } } return { value: parsedValue, isSet: true, isValid: !errors.length, errors: errors }; }; var onFunction = function (value) { var errors = []; if (typeof value !== 'function') { errors.push(ValidatorType.function); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; var onFunctionWithXArguments = function (argsCount) { return function (value) { var result = onFunction(value); if (!result.isValid) { return result; } value = result.value; var errors = []; if (value.length !== argsCount) { errors.push(getError(ValidatorType.funcOfxArguments, [String(argsCount)])); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; }; var onFunctionWithXAndMoreArguments = function (argsCount) { return function (value) { var result = onFunction(value); if (!result.isValid) { return result; } value = result.value; var errors = []; if (value.length < argsCount) { errors.push(getError(ValidatorType.funcOfxArguments, [String(argsCount)])); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; }; var onFunctionWithXToYArguments = function (from, to) { return function (value) { var result = onFunction(value); if (!result.isValid) { return result; } value = result.value; var errors = []; if (value.length < from || value.length > to) { errors.push(getError(ValidatorType.funcOfXToYArguments, [String(from), String(to)])); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; }; var onOneOf = function (tokens, must) { return function (value, context) { var errors = []; var isSet = value !== void 0; var noOneIsPresent = !isSet; var err = must ? ValidatorType.oneOfMust : ValidatorType.oneOfCan; if (!Array.isArray(tokens) || !tokens.length) { errors.push(getError(err, ['undefined'])); } else { for (var i = tokens.length - 1; i >= 0; i--) { var token = tokens[i]; if (typeof token !== 'string') { errors.push(getError(err, [tokens.join('", "')]) + ' (non-string token)'); break; } var isAnotherPresent = context && Object.prototype.hasOwnProperty.call(context, token); if (isSet && isAnotherPresent) { errors.push(getError(err, [tokens.join('", "')]) + " (".concat(token, " is present)")); break; } if (noOneIsPresent && isAnotherPresent) { noOneIsPresent = false; } } if (must && noOneIsPresent) { errors.push(getError(err, [tokens.join('", "')])); } } return { value: value, isSet: isSet, isValid: !errors.length, errors: errors }; }; }; var onOr = function (validators) { return function (value) { var errors = []; if (validators.every(function (validator) { return !validator.method(value).isValid; })) { errors.push(validators.map(function (v) { return v.type; }).join(' OR ')); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; }; var onEnum = function (list) { return function (value) { var errors = []; var values = Object.keys(list) .filter(function (k) { return isNaN(Number(k)); }) .map(function (k) { return list[k]; }); if (!values.some(function (item) { return item === value; })) { errors.push(getError(ValidatorType.enum, ['[' + values.join(',') + ']'])); } return { value: value, isSet: true, isValid: !errors.length, errors: errors }; }; }; var VALIDATORS = { NUMBER: { type: ValidatorType.number, method: onNumber }, INTEGER: { type: ValidatorType.integer, method: onInteger }, INTEGER_UNLIMITED: { type: ValidatorType.integerUnlimited, method: onIntegerUnlimited }, MORE_OR_EQUAL: function (limit, fallback) { return ({ type: ValidatorType.moreOrEqual, method: onMoreOrEqual(limit, fallback) }); }, BOOLEAN: { type: ValidatorType.boolean, method: onBoolean }, OBJECT: { type: ValidatorType.object, method: onObject }, ITEM_LIST: { type: ValidatorType.itemList, method: onItemList }, ELEMENT: { type: ValidatorType.element, method: onHtmlElement }, FUNC: { type: ValidatorType.function, method: onFunction }, FUNC_WITH_X_ARGUMENTS: function (count) { return ({ type: ValidatorType.funcOfxArguments, method: onFunctionWithXArguments(count) }); }, FUNC_WITH_X_AND_MORE_ARGUMENTS: function (count) { return ({ type: ValidatorType.funcOfxAndMoreArguments, method: onFunctionWithXAndMoreArguments(count) }); }, FUNC_WITH_X_TO_Y_ARGUMENTS: function (from, to) { return ({ type: ValidatorType.funcOfXToYArguments, method: onFunctionWithXToYArguments(from, to) }); }, ONE_OF_CAN: function (list) { return ({ type: ValidatorType.oneOfCan, method: onOneOf(list, false) }); }, ONE_OF_MUST: function (list) { return ({ type: ValidatorType.oneOfMust, method: onOneOf(list, true) }); }, OR: function (list) { return ({ type: ValidatorType.or, method: onOr(list) }); }, ENUM: function (list) { return ({ type: ValidatorType.enum, method: onEnum(list) }); } }; var ValidatedData = /** @class */ (function () { function ValidatedData(context) { this.params = {}; this.contextErrors = []; this.errors = []; this.isValid = true; this.setContext(context); } ValidatedData.prototype.setContext = function (context) { if (!context || Object.prototype.toString.call(context) !== '[object Object]') { this.setCommonError('context is not an object'); this.isValidContext = false; } else { this.isValidContext = true; } this.context = context; }; ValidatedData.prototype.setValidity = function () { var _this = this; this.errors = Object.keys(this.params).reduce(function (acc, key) { return __spreadArray(__spreadArray([], __read(acc), false), __read(_this.params[key].errors), false); }, []); this.isValid = !this.errors.length; }; ValidatedData.prototype.setCommonError = function (error) { this.contextErrors.push(error); this.errors.push(error); this.isValid = false; }; ValidatedData.prototype.setParam = function (token, value) { if (!value.isValid) { value.errors = !value.isSet ? ["\"".concat(token, "\" must be set")] : value.errors.map(function (err) { return "\"".concat(token, "\" ").concat(err); }); } this.params[token] = value; this.setValidity(); }; ValidatedData.prototype.showErrors = function () { return this.errors.length ? 'validation failed: ' + this.errors.join(', ') : ''; }; return ValidatedData; }()); var runValidator = function (current, validator, context) { var value = current.value, errors = current.errors; var result = validator.method(value, context); var _errors = __spreadArray(__spreadArray([], __read(errors), false), __read(result.errors), false); return { value: result.value, isSet: result.isSet, isValid: !_errors.length, errors: _errors }; }; var getDefault = function (value, prop) { var empty = value === void 0; var auto = !prop.mandatory && prop.defaultValue !== void 0; return { value: !empty ? value : auto ? prop.defaultValue : void 0, isSet: !empty || auto, isValid: !empty || !prop.mandatory, errors: [] }; }; var validateOne = function (context, name, prop) { var e_1, _a; var result = getDefault(context[name], prop); if (!result.isSet) { var oneOfMust = prop.validators.find(function (v) { return v.type === ValidatorType.oneOfMust; }); if (oneOfMust) { return runValidator(result, oneOfMust, context); } } else { try { for (var _b = __values(Object.values(prop.validators)), _c = _b.next(); !_c.done; _c = _b.next()) { var validator = _c.value; var current = runValidator(result, validator, context); if (!current.isValid && prop.defaultValue !== void 0) { return { value: prop.defaultValue, isSet: true, isValid: true, errors: [] }; } Object.assign(result, current); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } } return result; }; var validate = function (context, params) { var data = new ValidatedData(context); Object.entries(params).forEach(function (_a) { var _b = __read(_a, 2), key = _b[0], prop = _b[1]; return data.setParam(key, data.isValidContext ? validateOne(data.context, key, prop) : getDefault(void 0, prop)); }); return data; }; var _a$4; var OBJECT$2 = VALIDATORS.OBJECT, FUNC_WITH_X_AND_MORE_ARGUMENTS$1 = VALIDATORS.FUNC_WITH_X_AND_MORE_ARGUMENTS; var DatasourceProps; (function (DatasourceProps) { DatasourceProps["get"] = "get"; DatasourceProps["settings"] = "settings"; DatasourceProps["devSettings"] = "devSettings"; })(DatasourceProps || (DatasourceProps = {})); var DATASOURCE = (_a$4 = {}, _a$4[DatasourceProps.get] = { validators: [FUNC_WITH_X_AND_MORE_ARGUMENTS$1(2)], mandatory: true }, _a$4[DatasourceProps.settings] = { validators: [OBJECT$2] }, _a$4[DatasourceProps.devSettings] = { validators: [OBJECT$2] }, _a$4); var _a$3, _b$2, _c$1; var NUMBER = VALIDATORS.NUMBER, INTEGER$1 = VALIDATORS.INTEGER, INTEGER_UNLIMITED$1 = VALIDATORS.INTEGER_UNLIMITED, MORE_OR_EQUAL = VALIDATORS.MORE_OR_EQUAL, BOOLEAN$1 = VALIDATORS.BOOLEAN, ELEMENT$1 = VALIDATORS.ELEMENT, FUNC$1 = VALIDATORS.FUNC, OR$1 = VALIDATORS.OR, ENUM = VALIDATORS.ENUM; var Settings$1; (function (Settings) { Settings["adapter"] = "adapter"; Settings["startIndex"] = "startIndex"; Settings["minIndex"] = "minIndex"; Settings["maxIndex"] = "maxIndex"; Settings["itemSize"] = "itemSize"; Settings["bufferSize"] = "bufferSize"; Settings["padding"] = "padding"; Settings["infinite"] = "infinite"; Settings["horizontal"] = "horizontal"; Settings["windowViewport"] = "windowViewport"; Settings["viewportElement"] = "viewportElement"; Settings["inverse"] = "inverse"; Settings["onBeforeClip"] = "onBeforeClip"; Settings["sizeStrategy"] = "sizeStrategy"; })(Settings$1 || (Settings$1 = {})); var DevSettings; (function (DevSettings) { DevSettings["debug"] = "debug"; DevSettings["immediateLog"] = "immediateLog"; DevSettings["logProcessRun"] = "logProcessRun"; DevSettings["logTime"] = "logTime"; DevSettings["logColor"] = "logColor"; DevSettings["throttle"] = "throttle"; DevSettings["initDelay"] = "initDelay"; DevSettings["initWindowDelay"] = "initWindowDelay"; DevSettings["cacheData"] = "cacheData"; DevSettings["cacheOnReload"] = "cacheOnReload"; DevSettings["dismissOverflowAnchor"] = "dismissOverflowAnchor"; DevSettings["directionPriority"] = "directionPriority"; })(DevSettings || (DevSettings = {})); var MIN = (_a$3 = {}, _a$3[Settings$1.itemSize] = 1, _a$3[Settings$1.bufferSize] = 1, _a$3[Settings$1.padding] = 0.01, _a$3[DevSettings.throttle] = 0, _a$3[DevSettings.initDelay] = 0, _a$3[DevSettings.initWindowDelay] = 0, _a$3); var SETTINGS = (_b$2 = {}, _b$2[Settings$1.adapter] = { validators: [BOOLEAN$1], defaultValue: false }, _b$2[Settings$1.startIndex] = { validators: [INTEGER$1], defaultValue: 1 }, _b$2[Settings$1.minIndex] = { validators: [INTEGER_UNLIMITED$1], defaultValue: -Infinity }, _b$2[Settings$1.maxIndex] = { validators: [INTEGER_UNLIMITED$1], defaultValue: Infinity }, _b$2[Settings$1.itemSize] = { validators: [INTEGER$1, MORE_OR_EQUAL(MIN[Settings$1.itemSize], true)], defaultValue: NaN }, _b$2[Settings$1.bufferSize] = { validators: [INTEGER$1, MORE_OR_EQUAL(MIN[Settings$1.bufferSize], true)], defaultValue: 5 }, _b$2[Settings$1.padding] = { validators: [NUMBER, MORE_OR_EQUAL(MIN[Settings$1.padding], true)], defaultValue: 0.5 }, _b$2[Settings$1.infinite] = { validators: [BOOLEAN$1], defaultValue: false }, _b$2[Settings$1.horizontal] = { validators: [BOOLEAN$1], defaultValue: false }, _b$2[Settings$1.windowViewport] = { validators: [BOOLEAN$1], defaultValue: false }, _b$2[Settings$1.viewportElement] = { validators: [OR$1([ELEMENT$1, FUNC$1])], defaultValue: null }, _b$2[Settings$1.inverse] = { validators: [BOOLEAN$1], defaultValue: false }, _b$2[Settings$1.onBeforeClip] = { validators: [FUNC$1], defaultValue: null }, _b$2[Settings$1.sizeStrategy] = { validators: [ENUM(SizeStrategy)], defaultValue: SizeStrategy.Average }, _b$2); var DEV_SETTINGS = (_c$1 = {}, _c$1[DevSettings.debug] = { validators: [BOOLEAN$1], defaultValue: false }, _c$1[DevSettings.immediateLog] = { validators: [BOOLEAN$1], defaultValue: true }, _c$1[DevSettings.logProcessRun] = { validators: [BOOLEAN$1], defaultValue: false }, _c$1[DevSettings.logTime] = { validators: [BOOLEAN$1], defaultValue: false }, _c$1[DevSettings.logColor] = { validators: [BOOLEAN$1], defaultValue: true }, _c$1[DevSettings.throttle] = { validators: [INTEGER$1, MORE_OR_EQUAL(MIN[DevSettings.throttle], true)], defaultValue: 40 }, _c$1[DevSettings.initDelay] = { validators: [INTEGER$1, MORE_OR_EQUAL(MIN[DevSettings.initDelay], true)], defaultValue: 1 }, _c$1[DevSettings.initWindowDelay] = { validators: [INTEGER$1, MORE_OR_EQUAL(MIN[DevSettings.initWindowDelay], true)], defaultValue: 40 }, _c$1[DevSettings.cacheData] = { validators: [BOOLEAN$1], defaultValue: false }, _c$1[DevSettings.cacheOnReload] = { validators: [BOOLEAN$1], defaultValue: false }, _c$1[DevSettings.dismissOverflowAnchor] = { validators: [BOOLEAN$1], defaultValue: true }, _c$1[DevSettings.directionPriority] = { validators: [ENUM(Direction)], defaultValue: Direction.backward }, _c$1); var CommonProcess; (function (CommonProcess) { CommonProcess["init"] = "init"; CommonProcess["scroll"] = "scroll"; CommonProcess["start"] = "start"; CommonProcess["preFetch"] = "preFetch"; CommonProcess["fetch"] = "fetch"; CommonProcess["postFetch"] = "postFetch"; CommonProcess["render"] = "render"; CommonProcess["preClip"] = "preClip"; CommonProcess["clip"] = "clip"; CommonProcess["adjust"] = "adjust"; CommonProcess["end"] = "end"; })(CommonProcess || (CommonProcess = {})); var AdapterProcess; (function (AdapterProcess) { AdapterProcess["reset"] = "adapter.reset"; AdapterProcess["reload"] = "adapter.reload"; AdapterProcess["append"] = "adapter.append"; AdapterProcess["prepend"] = "adapter.prepend"; AdapterProcess["check"] = "adapter.check"; AdapterProcess["remove"] = "adapter.remove"; AdapterProcess["replace"] = "adapter.replace"; AdapterProcess["update"] = "adapter.update"; AdapterProcess["clip"] = "adapter.clip"; AdapterProcess["insert"] = "adapter.insert"; AdapterProcess["pause"] = "adapter.pause"; AdapterProcess["fix"] = "adapter.fix"; })(AdapterProcess || (AdapterProcess = {})); var ProcessStatus; (function (ProcessStatus) { ProcessStatus["start"] = "start"; ProcessStatus["next"] = "next"; ProcessStatus["done"] = "done"; ProcessStatus["error"] = "error"; })(ProcessStatus || (ProcessStatus = {})); var _a$2, _b$1, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; var INTEGER = VALIDATORS.INTEGER, INTEGER_UNLIMITED = VALIDATORS.INTEGER_UNLIMITED, BOOLEAN = VALIDATORS.BOOLEAN, OBJECT$1 = VALIDATORS.OBJECT, ITEM_LIST = VALIDATORS.ITEM_LIST, FUNC_WITH_X_ARGUMENTS$1 = VALIDATORS.FUNC_WITH_X_ARGUMENTS, FUNC_WITH_X_AND_MORE_ARGUMENTS = VALIDATORS.FUNC_WITH_X_AND_MORE_ARGUMENTS, FUNC_WITH_X_TO_Y_ARGUMENTS = VALIDATORS.FUNC_WITH_X_TO_Y_ARGUMENTS, ONE_OF_MUST = VALIDATORS.ONE_OF_MUST, ONE_OF_CAN = VALIDATORS.ONE_OF_CAN, OR = VALIDATORS.OR; var AdapterNoParams; (function (AdapterNoParams) { })(AdapterNoParams || (AdapterNoParams = {})); var NO_METHOD_PARAMS = {}; var RESET_METHOD_PARAMS = (_a$2 = {}, _a$2[DatasourceProps.get] = { validators: [FUNC_WITH_X_AND_MORE_ARGUMENTS(2)] }, _a$2[DatasourceProps.settings] = { validators: [OBJECT$1] }, _a$2[DatasourceProps.devSettings] = { validators: [OBJECT$1] }, _a$2); var AdapterReloadParams; (function (AdapterReloadParams) { AdapterReloadParams["reloadIndex"] = "reloadIndex"; })(AdapterReloadParams || (AdapterReloadParams = {})); var RELOAD_METHOD_PARAMS = (_b$1 = {}, _b$1[AdapterReloadParams.reloadIndex] = { validators: [INTEGER] }, _b$1); var AdapterPrependParams; (function (AdapterPrependParams) { AdapterPrependParams["items"] = "items"; AdapterPrependParams["bof"] = "bof"; AdapterPrependParams["increase"] = "increase"; AdapterPrependParams["virtualize"] = "virtualize"; })(AdapterPrependParams || (AdapterPrependParams = {})); var PREPEND_METHOD_PARAMS = (_c = {}, _c[AdapterPrependParams.items] = { validators: [ITEM_LIST], mandatory: true }, _c[AdapterPrependParams.bof] = { validators: [BOOLEAN, ONE_OF_CAN([AdapterPrependParams.virtualize])], defaultValue: false }, _c[AdapterPrependParams.increase] = { validators: [BOOLEAN], defaultValue: false }, _c[AdapterPrependParams.virtualize] = { validators: [BOOLEAN, ONE_OF_CAN([AdapterPrependParams.bof])], defaultValue: false }, _c); var AdapterAppendParams; (function (AdapterAppendParams) { AdapterAppendParams["items"] = "items"; AdapterAppendParams["eof"] = "eof"; AdapterAppendParams["decrease"] = "decrease"; AdapterAppendParams["virtualize"] = "virtualize"; })(AdapterAppendParams || (AdapterAppendParams = {})); var APPEND_METHOD_PARAMS = (_d = {}, _d[AdapterAppendParams.items] = { validators: [ITEM_LIST], mandatory: true }, _d[AdapterAppendParams.eof] = { validators: [BOOLEAN, ONE_OF_CAN([AdapterAppendParams.virtualize])], defaultValue: false }, _d[AdapterAppendParams.decrease] = { validators: [BOOLEAN], defaultValue: false }, _d[AdapterPrependParams.virtualize] = { validators: [BOOLEAN, ONE_OF_CAN([AdapterAppendParams.eof])], defaultValue: false }, _d); var AdapterRemoveParams; (function (AdapterRemoveParams) { AdapterRemoveParams["predicate"] = "predicate"; AdapterRemoveParams["indexes"] = "indexes"; AdapterRemoveParams["increase"] = "increase"; })(AdapterRemoveParams || (AdapterRemoveParams = {})); var REMOVE_METHOD_PARAMS = (_e = {}, _e[AdapterRemoveParams.predicate] = { validators: [FUNC_WITH_X_ARGUMENTS$1(1), ONE_OF_MUST([AdapterRemoveParams.indexes])] }, _e[AdapterRemoveParams.indexes] = { validators: [ITEM_LIST, ONE_OF_MUST([AdapterRemoveParams.predicate])] }, _e[AdapterRemoveParams.increase] = { validators: [BOOLEAN], defaultValue: false }, _e); var AdapterClipParams; (function (AdapterClipParams) { AdapterClipParams["backwardOnly"] = "backwardOnly"; AdapterClipParams["forwardOnly"] = "forwardOnly"; })(AdapterClipParams || (AdapterClipParams = {})); var CLIP_METHOD_PARAMS = (_f = {}, _f[AdapterClipParams.backwardOnly] = { validators: [BOOLEAN, ONE_OF_CAN([AdapterClipParams.forwardOnly])], defaultValue: false }, _f[AdapterClipParams.forwardOnly] = { validators: [BOOLEAN, ONE_OF_CAN([AdapterClipParams.backwardOnly])], defaultValue: false }, _f); var AdapterInsertParams; (function (AdapterInsertParams) { AdapterInsertParams["items"] = "items"; AdapterInsertParams["before"] = "before"; AdapterInsertParams["after"] = "after"; AdapterInsertParams["beforeIndex"] = "beforeIndex"; AdapterInsertParams["afterIndex"] = "afterIndex"; AdapterInsertParams["decrease"] = "decrease"; })(AdapterInsertParams || (AdapterInsertParams = {})); var INSERT_METHOD_PARAMS = (_g = {}, _g[AdapterInsertParams.items] = { validators: [ITEM_LIST], mandatory: true }, _g[AdapterInsertParams.before] = { validators: [ FUNC_WITH_X_ARGUMENTS$1(1), ONE_OF_MUST([ AdapterInsertParams.after, AdapterInsertParams.beforeIndex, AdapterInsertParams.afterIndex ]) ] }, _g[AdapterInsertParams.after] = { validators: [ FUNC_WITH_X_ARGUMENTS$1(1), ONE_OF_MUST([ AdapterInsertParams.before, AdapterInsertParams.beforeIndex, AdapterInsertParams.afterIndex ]) ] }, _g[AdapterInsertParams.beforeIndex] = { validators: [ INTEGER, ONE_OF_MUST([ AdapterInsertParams.before, AdapterInsertParams.after, AdapterInsertParams.afterIndex ]) ] }, _g[AdapterInsertParams.afterIndex] = { validators: [ INTEGER, ONE_OF_MUST([ AdapterInsertParams.before, AdapterInsertParams.after, AdapterInsertParams.beforeIndex ]) ] }, _g[AdapterInsertParams.decrease] = { validators: [BOOLEAN], defaultValue: false }, _g); var AdapterReplaceParams; (function (AdapterReplaceParams) { AdapterReplaceParams["items"] = "items"; AdapterReplaceParams["predicate"] = "predicate"; AdapterReplaceParams["fixRight"] = "fixRight"; })(AdapterReplaceParams || (AdapterReplaceParams = {})); var REPLACE_METHOD_PARAMS = (_h = {}, _h[AdapterInsertParams.items] = { validators: [ITEM_LIST], mandatory: true }, _h[AdapterReplaceParams.predicate] = { validators: [FUNC_WITH_X_ARGUMENTS$1(1)], mandatory: true }, _h[AdapterReplaceParams.fixRight] = { validators: [BOOLEAN], defaultValue: false }, _h); var AdapterUpdateParams; (function (AdapterUpdateParams) { AdapterUpdateParams["predicate"] = "predicate"; AdapterUpdateParams["fixRight"] = "fixRight"; })(AdapterUpdateParams || (AdapterUpdateParams = {})); var UPDATE_METHOD_PARAMS = (_j = {}, _j[AdapterUpdateParams.predicate] = { validators: [FUNC_WITH_X_ARGUMENTS$1(1)], mandatory: true }, _j[AdapterUpdateParams.fixRight] = { validators: [BOOLEAN], defaultValue: false }, _j); var AdapterFixParams; (function (AdapterFixParams) { AdapterFixParams["scrollPosition"] = "scrollPosition"; AdapterFixParams["minIndex"] = "minIndex"; AdapterFixParams["maxIndex"] = "maxIndex"; AdapterFixParams["updater"] = "updater"; AdapterFixParams["scrollToItem"] = "scrollToItem"; AdapterFixParams["scrollToItemOpt"] = "scrollToItemOpt"; })(AdapterFixParams || (AdapterFixParams = {})); var FIX_METHOD_PARAMS = (_k = {}, _k[AdapterFixParams.scrollPosition] = { validators: [INTEGER_UNLIMITED] }, _k[AdapterFixParams.minIndex] = { validators: [INTEGER_UNLIMITED] }, _k[AdapterFixParams.maxIndex] = { validators: [INTEGER_UNLIMITED] }, _k[AdapterFixParams.updater] = { validators: [FUNC_WITH_X_TO_Y_ARGUMENTS(1, 2)] }, _k[AdapterFixParams.scrollToItem] = { validators: [FUNC_WITH_X_ARGUMENTS$1(1)] }, _k[AdapterFixParams.scrollToItemOpt] = { validators: [OR([BOOLEAN, OBJECT$1])] }, _k); var AdapterMethods = (_l = {}, _l[AdapterProcess.reset] = DatasourceProps, _l[AdapterProcess.reload] = AdapterReloadParams, _l[AdapterProcess.prepend] = AdapterPrependParams, _l[AdapterProcess.append] = AdapterAppendParams, _l[AdapterProcess.check] = AdapterNoParams, _l[AdapterProcess.remove] = AdapterRemoveParams, _l[AdapterProcess.clip] = AdapterClipParams, _l[AdapterProcess.insert] = AdapterInsertParams, _l[AdapterProcess.replace] = AdapterReplaceParams, _l[AdapterProcess.update] = AdapterUpdateParams, _l[AdapterProcess.pause] = AdapterNoParams, _l[AdapterProcess.fix] = AdapterFixParams, _l); var ADAPTER_METHODS = (_m = {}, _m[AdapterProcess.reset] = RESET_METHOD_PARAMS, _m[AdapterProcess.reload] = RELOAD_METHOD_PARAMS, _m[AdapterProcess.prepend] = PREPEND_METHOD_PARAMS, _m[AdapterProcess.append] = APPEND_METHOD_PARAMS, _m[AdapterProcess.check] = NO_METHOD_PARAMS, _m[AdapterProcess.remove] = REMOVE_METHOD_PARAMS, _m[AdapterProcess.clip] = CLIP_METHOD_PARAMS, _m[AdapterProcess.insert] = INSERT_METHOD_PARAMS, _m[AdapterProcess.replace] = REPLACE_METHOD_PARAMS, _m[AdapterProcess.update] = UPDATE_METHOD_PARAMS, _m[AdapterProcess.pause] = NO_METHOD_PARAMS, _m[AdapterProcess.fix] = FIX_METHOD_PARAMS, _m); var _a$1; var ELEMENT = VALIDATORS.ELEMENT, OBJECT = VALIDATORS.OBJECT, FUNC = VALIDATORS.FUNC, FUNC_WITH_X_ARGUMENTS = VALIDATORS.FUNC_WITH_X_ARGUMENTS; var WorkflowProps; (function (WorkflowProps) { WorkflowProps["consumer"] = "consumer"; WorkflowProps["element"] = "element"; WorkflowProps["datasource"] = "datasource"; WorkflowProps["run"] = "run"; WorkflowProps["Routines"] = "Routines"; })(WorkflowProps || (WorkflowProps = {})); var WORKFLOW = (_a$1 = {}, _a$1[WorkflowProps.consumer] = { validators: [OBJECT] }, _a$1[WorkflowProps.element] = { validators: [ELEMENT], mandatory: true }, _a$1[WorkflowProps.datasource] = { validators: [OBJECT], mandatory: true }, _a$1[WorkflowProps.run] = { validators: [FUNC_WITH_X_ARGUMENTS(1)], mandatory: true }, _a$1[WorkflowProps.Routines] = { validators: [FUNC] }, _a$1); var Settings = /** @class */ (function () { function Settings(settings, devSettings, instanceIndex) { this.parseInput(settings, SETTINGS); this.parseInput(devSettings, DEV_SETTINGS); this.instanceIndex = instanceIndex; this.initializeDelay = this.getInitializeDelay(); this.viewport = this.getViewport(); // todo: min/max indexes must be ignored if infinite mode is enabled ?? } Settings.prototype.parseInput = function (input, props) { var _this = this; var result = validate(input, props); if (!result.isValid) { throw new Error('Invalid settings'); } Object.entries(result.params).forEach(function (_a) { var _b; var _c = __read(_a, 2), key = _c[0], par = _c[1]; return Object.assign(_this, (_b = {}, _b[key] = par.value, _b)); }); }; Settings.prototype.getInitializeDelay = function () { var result = 0; if (this.windowViewport && this.initWindowDelay && !('scrollRestoration' in history)) { result = this.initWindowDelay; } if (this.initDelay > 0) { result = Math.max(result, this.initDelay); } return result; }; Settings.prototype.getViewport = function () { if (typeof this.viewportElement !== 'function') { return this.viewportElement; } var value = this.viewportElement(); var result = validateOne({ value: value }, 'value', { validators: [VALIDATORS.ELEMENT] }); if (!result.isValid) { return null; // fallback to default (null) if Function didn't return HTML element synchronously } return result.value; }; return Settings; }()); var BaseProcessFactory = function (process) { var _a; return _a = /** @class */ (function () { function BaseProcess() { } return BaseProcess; }()), _a.process = process, _a; }; var BaseAdapterProcessFactory = function (process) { var _a; return _a = /** @class */ (function (_super) { __extends(BaseAdapterProcess, _super); function BaseAdapterProcess() { return _super !== null && _super.apply(this, arguments) || this; } BaseAdapterProcess.parseInput = function (scroller, options, ignoreErrors, _process) { if (ignoreErrors === void 0) { ignoreErrors = false; } var result = { data: validate(options, ADAPTER_METHODS[_process || process]) }; if (result.data.isValid) { result.params = Object.entries(result.data.params).reduce(function (acc, _b) { var _c; var _d = __read(_b, 2), key = _d[0], value = _d[1].value; return (__assign(__assign({}, acc), (_c = {}, _c[key] = value, _c))); }, {}); } else { scroller.logger.log(function () { return result.data.showErrors(); }); if (!ignoreErrors) { scroller.workflow.call({ process: process, status: ProcessStatus.error, payload: { error: "Wrong argument of the \"".concat(process, "\" method call") } }); } } return result; }; return BaseAdapterProcess; }(BaseProcessFactory(process))), _a.process = process, _a; }; var initProcesses = [CommonProcess.init, AdapterProcess.reset, AdapterProcess.reload]; var Init = /** @class */ (function (_super) { __extends(Init, _super); function Init() { return _super !== null && _super.apply(this, arguments) || this; } Init.run = function (scroller, process) { var state = scroller.state, workflow = scroller.workflow; var isInitial = initProcesses.includes(process); scroller.logger.logCycle(true); state.startWorkflowCycle(isInitial, process); workflow.call({ process: Init.process, status: ProcessStatus.next }); }; return Init; }(BaseProcessFactory(CommonProcess.init))); var Scroll = /** @class */ (function (_super) { __extends(Scroll, _super); function Scroll() { return _super !== null && _super.apply(this, arguments) || this; } Scroll.run = function (scroller, _payload) { var workflow = scroller.workflow, viewport = scroller.viewport; var position = viewport.scrollPosition; if (Scroll.onSynthetic(scroller, position)) { return; } Scroll.onThrottle(scroller, position, function () { return Scroll.onScroll(scroller, workflow); }); }; Scroll.onSynthetic = function (scroller, position) { var scroll = scroller.state.scroll; var synthPos = scroll.syntheticPosition; if (synthPos !== null) { if (scroll.syntheticFulfill) { scroll.syntheticPosition = null; } if (!scroll.syntheticFulfill || synthPos === position) { scroller.logger.log(function () { return [ 'skipping scroll', position, "[".concat(scroll.syntheticFulfill ? '' : 'pre-', "synthetic]") ]; }); return true; } scroller.logger.log(function () { return [ 'synthetic scroll has been fulfilled:', position, position < synthPos ? '<' : '>', synthPos ]; }); } return false; }; Scroll.onThrottle = function (scroller, position, done) { var state = scroller.state, settings = scroller.settings, logger = scroller.logger; var scroll = state.scroll; scroll.current = Scroll.getScrollEvent(position, scroll.previous); var _a = scroll.current, direction = _a.direction, time = _a.time; var timeDiff = scroll.previous ? time - scroll.previous.time : Infinity; var delta = settings.throttle - timeDiff; var shouldDelay = isFinite(delta) && delta > 0; var alreadyDelayed = !!scroll.scrollTimer; logger.log(function () { return [ direction === Direction.backward ? '\u2934' : '\u2935', position, shouldDelay ? timeDiff + 'ms' : '0ms', shouldDelay ? (alreadyDelayed ? 'delayed' : "/ ".concat(delta, "ms delay")) : '' ]; }); if (!shouldDelay) { if (scroll.scrollTimer) { clearTimeout(scroll.scrollTimer); scroll.scrollTimer = null; } done(); return; } if (!alreadyDelayed) { scroll.scrollTimer = setTimeout(function () { logger.log(function () { var curr = Scroll.getScrollEvent(scroller.viewport.scrollPosition, scroll.current); return [ curr.direction === Direction.backward ? '\u2934' : '\u2935', curr.position, curr.time - time + 'ms', 'triggered by timer set on', position ]; }); scroll.scrollTimer = null; done(); }, delta); } }; Scroll.getScrollEvent = function (position, previous) { var time = Number(new Date()); var direction = Direction.forward; if (previous) { if (position === previous.position) { direction = previous.direction; } else if (position < previous.position) { direction = Direction.backwar