@gogocat/data-bind 1.11.0 → 2.0.0
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/.editorconfig +14 -14
- package/.vscode/launch.json +12 -12
- package/CONFIGURATION.md +294 -0
- package/REACTIVE_MODE.md +553 -0
- package/README.md +266 -829
- package/babel.config.json +30 -0
- package/dist/js/_escape.d.ts +14 -0
- package/dist/js/_escape.d.ts.map +1 -0
- package/dist/js/applyBinding.d.ts +11 -0
- package/dist/js/applyBinding.d.ts.map +1 -0
- package/dist/js/attrBinding.d.ts +12 -0
- package/dist/js/attrBinding.d.ts.map +1 -0
- package/dist/js/binder.d.ts +67 -0
- package/dist/js/binder.d.ts.map +1 -0
- package/dist/js/changeBinding.d.ts +19 -0
- package/dist/js/changeBinding.d.ts.map +1 -0
- package/dist/js/commentWrapper.d.ts +39 -0
- package/dist/js/commentWrapper.d.ts.map +1 -0
- package/dist/js/config.d.ts +55 -0
- package/dist/js/config.d.ts.map +1 -0
- package/dist/js/createBindingOption.d.ts +32 -0
- package/dist/js/createBindingOption.d.ts.map +1 -0
- package/dist/js/createEventBinding.d.ts +10 -0
- package/dist/js/createEventBinding.d.ts.map +1 -0
- package/dist/js/cssBinding.d.ts +15 -0
- package/dist/js/cssBinding.d.ts.map +1 -0
- package/dist/js/dataBind.js +2772 -2519
- package/dist/js/dataBind.min.js +8 -1
- package/dist/js/dataBind.min.js.map +1 -1
- package/dist/js/domWalker.d.ts +9 -0
- package/dist/js/domWalker.d.ts.map +1 -0
- package/dist/js/forOfBinding.d.ts +12 -0
- package/dist/js/forOfBinding.d.ts.map +1 -0
- package/dist/js/hoverBinding.d.ts +13 -0
- package/dist/js/hoverBinding.d.ts.map +1 -0
- package/dist/js/ifBinding.d.ts +12 -0
- package/dist/js/ifBinding.d.ts.map +1 -0
- package/dist/js/index.d.ts +10 -0
- package/dist/js/index.d.ts.map +1 -0
- package/dist/js/modelBinding.d.ts +12 -0
- package/dist/js/modelBinding.d.ts.map +1 -0
- package/dist/js/postProcess.d.ts +3 -0
- package/dist/js/postProcess.d.ts.map +1 -0
- package/dist/js/pubSub.d.ts +11 -0
- package/dist/js/pubSub.d.ts.map +1 -0
- package/dist/js/reactiveProxy.d.ts +28 -0
- package/dist/js/reactiveProxy.d.ts.map +1 -0
- package/dist/js/renderForOfBinding.d.ts +8 -0
- package/dist/js/renderForOfBinding.d.ts.map +1 -0
- package/dist/js/renderIfBinding.d.ts +22 -0
- package/dist/js/renderIfBinding.d.ts.map +1 -0
- package/dist/js/renderIteration.d.ts +16 -0
- package/dist/js/renderIteration.d.ts.map +1 -0
- package/dist/js/renderTemplate.d.ts +14 -0
- package/dist/js/renderTemplate.d.ts.map +1 -0
- package/dist/js/renderTemplatesBinding.d.ts +19 -0
- package/dist/js/renderTemplatesBinding.d.ts.map +1 -0
- package/dist/js/showBinding.d.ts +13 -0
- package/dist/js/showBinding.d.ts.map +1 -0
- package/dist/js/switchBinding.d.ts +13 -0
- package/dist/js/switchBinding.d.ts.map +1 -0
- package/dist/js/textBinding.d.ts +13 -0
- package/dist/js/textBinding.d.ts.map +1 -0
- package/dist/js/types/_escape.d.ts +14 -0
- package/dist/js/types/_escape.d.ts.map +1 -0
- package/dist/js/types/applyBinding.d.ts +11 -0
- package/dist/js/types/applyBinding.d.ts.map +1 -0
- package/dist/js/types/attrBinding.d.ts +12 -0
- package/dist/js/types/attrBinding.d.ts.map +1 -0
- package/dist/js/types/binder.d.ts +67 -0
- package/dist/js/types/binder.d.ts.map +1 -0
- package/dist/js/types/changeBinding.d.ts +19 -0
- package/dist/js/types/changeBinding.d.ts.map +1 -0
- package/dist/js/types/commentWrapper.d.ts +39 -0
- package/dist/js/types/commentWrapper.d.ts.map +1 -0
- package/dist/js/types/config.d.ts +55 -0
- package/dist/js/types/config.d.ts.map +1 -0
- package/dist/js/types/createBindingOption.d.ts +32 -0
- package/dist/js/types/createBindingOption.d.ts.map +1 -0
- package/dist/js/types/createEventBinding.d.ts +10 -0
- package/dist/js/types/createEventBinding.d.ts.map +1 -0
- package/dist/js/types/cssBinding.d.ts +15 -0
- package/dist/js/types/cssBinding.d.ts.map +1 -0
- package/dist/js/types/domWalker.d.ts +9 -0
- package/dist/js/types/domWalker.d.ts.map +1 -0
- package/dist/js/types/forOfBinding.d.ts +12 -0
- package/dist/js/types/forOfBinding.d.ts.map +1 -0
- package/dist/js/types/hoverBinding.d.ts +13 -0
- package/dist/js/types/hoverBinding.d.ts.map +1 -0
- package/dist/js/types/ifBinding.d.ts +12 -0
- package/dist/js/types/ifBinding.d.ts.map +1 -0
- package/dist/js/types/index.d.ts +10 -0
- package/dist/js/types/index.d.ts.map +1 -0
- package/dist/js/types/modelBinding.d.ts +12 -0
- package/dist/js/types/modelBinding.d.ts.map +1 -0
- package/dist/js/types/postProcess.d.ts +3 -0
- package/dist/js/types/postProcess.d.ts.map +1 -0
- package/dist/js/types/pubSub.d.ts +11 -0
- package/dist/js/types/pubSub.d.ts.map +1 -0
- package/dist/js/types/reactiveProxy.d.ts +28 -0
- package/dist/js/types/reactiveProxy.d.ts.map +1 -0
- package/dist/js/types/renderForOfBinding.d.ts +8 -0
- package/dist/js/types/renderForOfBinding.d.ts.map +1 -0
- package/dist/js/types/renderIfBinding.d.ts +22 -0
- package/dist/js/types/renderIfBinding.d.ts.map +1 -0
- package/dist/js/types/renderIteration.d.ts +16 -0
- package/dist/js/types/renderIteration.d.ts.map +1 -0
- package/dist/js/types/renderTemplate.d.ts +14 -0
- package/dist/js/types/renderTemplate.d.ts.map +1 -0
- package/dist/js/types/renderTemplatesBinding.d.ts +19 -0
- package/dist/js/types/renderTemplatesBinding.d.ts.map +1 -0
- package/dist/js/types/showBinding.d.ts +13 -0
- package/dist/js/types/showBinding.d.ts.map +1 -0
- package/dist/js/types/switchBinding.d.ts +13 -0
- package/dist/js/types/switchBinding.d.ts.map +1 -0
- package/dist/js/types/textBinding.d.ts +13 -0
- package/dist/js/types/textBinding.d.ts.map +1 -0
- package/dist/js/types/types.d.ts +111 -0
- package/dist/js/types/types.d.ts.map +1 -0
- package/dist/js/types/util.d.ts +119 -0
- package/dist/js/types/util.d.ts.map +1 -0
- package/dist/js/types.d.ts +111 -0
- package/dist/js/types.d.ts.map +1 -0
- package/dist/js/util.d.ts +119 -0
- package/dist/js/util.d.ts.map +1 -0
- package/eslint.config.js +124 -0
- package/examples/DBMONSTER_COMPARISON.md +123 -0
- package/examples/afterRenderDemo.html +119 -0
- package/examples/bootstrap/css/animate.css +1579 -1579
- package/examples/bootstrap/css/bootstrap.min.css +6 -6
- package/examples/bootstrap/css/homeservices.css +378 -390
- package/examples/bootstrap/css/open-iconic.css +511 -511
- package/examples/bootstrap/fonts/open-iconic.svg +543 -543
- package/examples/bootstrap/js/compMessageDialog.js +20 -19
- package/examples/bootstrap/js/compSearchBar.js +12 -19
- package/examples/bootstrap/js/compSearchResults.js +50 -46
- package/examples/bootstrap/js/featureAdsResult.json +65 -65
- package/examples/bootstrap/js/searchResult.json +57 -57
- package/examples/bootstrap.html +343 -332
- package/examples/css/baseTodo.css +141 -141
- package/examples/css/dbMonsterStyles.css +27 -27
- package/examples/css/indexTodo.css +374 -374
- package/examples/dbmonsterForOfReactive.html +40 -0
- package/examples/dbmonsterReact.html +19 -0
- package/examples/forOfBindingSimpleDebug.html +45 -0
- package/examples/form.html +20 -4
- package/examples/globalConfig.html +131 -0
- package/examples/js/afterRenderDemo.js +190 -0
- package/examples/js/appTodo.js +46 -46
- package/examples/js/attrBindingDemo.js +2 -2
- package/examples/js/dbMonApp.js +24 -26
- package/examples/js/dbMonAppReact.jsx +79 -0
- package/examples/js/dbMonAppReactive.js +28 -0
- package/examples/js/fiberDemo.js +4 -4
- package/examples/js/filtersDemo.js +8 -8
- package/examples/js/forOfDemo.js +7 -9
- package/examples/js/forOfDemoComplex.js +44 -17
- package/examples/js/form.js +44 -12
- package/examples/js/globalConfig.js +117 -0
- package/examples/js/ifBindingDemo.js +16 -16
- package/examples/js/reactiveDemo.js +119 -0
- package/examples/js/switchBindingDemo.js +8 -8
- package/examples/react-dbmonster/dist/bundle.js +43 -0
- package/examples/react-dbmonster/package-lock.json +537 -0
- package/examples/react-dbmonster/package.json +16 -0
- package/examples/react-dbmonster/src/index.jsx +80 -0
- package/examples/reactiveDemo.html +127 -0
- package/examples/refreshRateTest.html +75 -75
- package/index.html +841 -0
- package/package.json +31 -34
- package/rollup.config.js +79 -36
- package/src/{_escape.js → _escape.ts} +19 -17
- package/src/applyBinding.ts +179 -0
- package/src/{attrBinding.js → attrBinding.ts} +14 -13
- package/src/binder.ts +289 -0
- package/src/changeBinding.ts +93 -0
- package/src/{commentWrapper.js → commentWrapper.ts} +33 -30
- package/src/config.ts +107 -0
- package/src/createBindingOption.ts +91 -0
- package/src/createEventBinding.ts +88 -0
- package/src/{cssBinding.js → cssBinding.ts} +13 -11
- package/src/{domWalker.js → domWalker.ts} +44 -30
- package/src/{forOfBinding.js → forOfBinding.ts} +4 -3
- package/src/hoverBinding.ts +84 -0
- package/src/{ifBinding.js → ifBinding.ts} +14 -12
- package/src/index.ts +53 -0
- package/src/{modelBinding.js → modelBinding.ts} +11 -9
- package/src/postProcess.ts +22 -0
- package/src/{pubSub.js → pubSub.ts} +24 -15
- package/src/reactiveProxy.ts +285 -0
- package/src/{renderForOfBinding.js → renderForOfBinding.ts} +55 -33
- package/src/{renderIfBinding.js → renderIfBinding.ts} +45 -20
- package/src/renderIteration.ts +53 -0
- package/src/renderTemplate.ts +165 -0
- package/src/renderTemplatesBinding.ts +73 -0
- package/src/{showBinding.js → showBinding.ts} +4 -3
- package/src/{switchBinding.js → switchBinding.ts} +18 -15
- package/src/{textBinding.js → textBinding.ts} +5 -4
- package/src/types.ts +124 -0
- package/src/util.ts +810 -0
- package/test/css/reporter.css +9 -9
- package/test/fixtures/dataBindBootstrap.html +2 -2
- package/test/fixtures/formBindings.html +9 -1
- package/test/globals.d.ts +19 -0
- package/test/helpers/testHelper.js +46 -11
- package/test/mocks/featureAdsResult.json +65 -65
- package/test/mocks/searchResult.json +57 -57
- package/test/specs/{attrBinding.spec.js → attrBinding.spec.ts} +103 -106
- package/test/specs/{binder.spec.js → binder.spec.ts} +29 -27
- package/test/specs/blurBinding.spec.ts +60 -0
- package/test/specs/chainableUse.spec.ts +125 -0
- package/test/specs/clickBinding.spec.ts +194 -0
- package/test/specs/{cssBinding.spec.js → cssBinding.spec.ts} +72 -79
- package/test/specs/{dataBindBootstrap.spec.js → dataBindBootstrap.spec.ts} +332 -313
- package/test/specs/{filter.spec.js → filter.spec.ts} +75 -76
- package/test/specs/{forOfBinding.spec.js → forOfBinding.spec.ts} +208 -219
- package/test/specs/formBinding.spec.ts +272 -0
- package/test/specs/ifBinding.spec.ts +165 -0
- package/test/specs/{nestedComponent.spec.js → nestedComponent.spec.ts} +88 -88
- package/test/specs/reactiveProxy.spec.ts +465 -0
- package/test/specs/{showBinding.spec.js → showBinding.spec.ts} +148 -149
- package/test/specs/{switchBinding.spec.js → switchBinding.spec.ts} +172 -173
- package/test/specs/templateBinding.spec.ts +273 -0
- package/test/specs/{textBinding.spec.js → textBinding.spec.ts} +47 -48
- package/test/tsconfig.json +31 -0
- package/test-output.txt +200 -0
- package/test-reactive.html +224 -0
- package/tsconfig.json +28 -0
- package/vendors/lodash.custom.js +4577 -4577
- package/vendors/lodash.custom.min.js +45 -45
- package/vitest.config.js +27 -0
- package/.eslintrc.js +0 -1
- package/.grunt/grunt-contrib-jasmine/boot.js +0 -161
- package/.grunt/grunt-contrib-jasmine/dist/js/dataBind.js +0 -9
- package/.grunt/grunt-contrib-jasmine/grunt-template-jasmine-istanbul/reporter.js +0 -23
- package/.grunt/grunt-contrib-jasmine/jasmine-html.js +0 -853
- package/.grunt/grunt-contrib-jasmine/jasmine.css +0 -271
- package/.grunt/grunt-contrib-jasmine/jasmine.js +0 -9761
- package/.grunt/grunt-contrib-jasmine/jasmine_favicon.png +0 -0
- package/.grunt/grunt-contrib-jasmine/json2.js +0 -489
- package/.grunt/grunt-contrib-jasmine/reporter.js +0 -107
- package/coverage/coverage.json +0 -1
- package/coverage/lcov/lcov-report/base.css +0 -213
- package/coverage/lcov/lcov-report/index.html +0 -93
- package/coverage/lcov/lcov-report/js/dataBind.js.html +0 -6596
- package/coverage/lcov/lcov-report/js/index.html +0 -93
- package/coverage/lcov/lcov-report/prettify.css +0 -1
- package/coverage/lcov/lcov-report/prettify.js +0 -1
- package/coverage/lcov/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov/lcov-report/sorter.js +0 -158
- package/coverage/lcov/lcov.info +0 -1991
- package/eslintrc.json +0 -40
- package/examples/bootstrap/js/bootstrap.min.js +0 -6
- package/examples/bootstrap/js/popper.min.js +0 -5
- package/examples/bootstrap/js/searchSuggestion.js +0 -58
- package/examples/bootstrap/js/typeahead.jquery.js +0 -1538
- package/gruntfile.js +0 -92
- package/gulpfile.js +0 -32
- package/src/binder.js +0 -422
- package/src/changeBinding.js +0 -57
- package/src/config.js +0 -65
- package/src/createBindingOption.js +0 -66
- package/src/createEventBinding.js +0 -46
- package/src/eventSystem.js +0 -46
- package/src/hoverBinding.js +0 -57
- package/src/index.js +0 -26
- package/src/renderTemplate.js +0 -128
- package/src/util.js +0 -648
- package/test/specs/blurBinding.spec.js +0 -57
- package/test/specs/formBinding.spec.js +0 -292
- package/test/specs/ifBinding.spec.js +0 -169
- package/test/specs/templateBinding.spec.js +0 -117
- package/vendors/jasmine-jquery.js +0 -841
- package/vendors/jquery-3.2.1.min.js +0 -4
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bindingUpdateConditions,
|
|
3
|
+
} from './config';
|
|
4
|
+
import {extend} from './util';
|
|
5
|
+
|
|
6
|
+
export interface BindingOption {
|
|
7
|
+
templateBinding?: boolean;
|
|
8
|
+
textBinding?: boolean;
|
|
9
|
+
cssBinding?: boolean;
|
|
10
|
+
ifBinding?: boolean;
|
|
11
|
+
showBinding?: boolean;
|
|
12
|
+
modelBinding?: boolean;
|
|
13
|
+
attrBinding?: boolean;
|
|
14
|
+
forOfBinding?: boolean;
|
|
15
|
+
switchBinding?: boolean;
|
|
16
|
+
changeBinding?: boolean;
|
|
17
|
+
clickBinding?: boolean;
|
|
18
|
+
dblclickBinding?: boolean;
|
|
19
|
+
blurBinding?: boolean;
|
|
20
|
+
focusBinding?: boolean;
|
|
21
|
+
hoverBinding?: boolean;
|
|
22
|
+
inputBinding?: boolean;
|
|
23
|
+
submitBinding?: boolean;
|
|
24
|
+
forceRender?: boolean;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* createBindingOption
|
|
30
|
+
* @param {string} condition
|
|
31
|
+
* @param {object} opt
|
|
32
|
+
* @description
|
|
33
|
+
* generate binding update option object by condition
|
|
34
|
+
* @return {object} updateOption
|
|
35
|
+
*/
|
|
36
|
+
const createBindingOption = (condition: string = '', opt: BindingOption = {}): BindingOption => {
|
|
37
|
+
const visualBindingOptions: BindingOption = {
|
|
38
|
+
templateBinding: false,
|
|
39
|
+
textBinding: true,
|
|
40
|
+
cssBinding: true,
|
|
41
|
+
ifBinding: true,
|
|
42
|
+
showBinding: true,
|
|
43
|
+
modelBinding: true,
|
|
44
|
+
attrBinding: true,
|
|
45
|
+
forOfBinding: true,
|
|
46
|
+
switchBinding: true,
|
|
47
|
+
};
|
|
48
|
+
const eventsBindingOptions: BindingOption = {
|
|
49
|
+
changeBinding: true,
|
|
50
|
+
clickBinding: true,
|
|
51
|
+
dblclickBinding: true,
|
|
52
|
+
blurBinding: true,
|
|
53
|
+
focusBinding: true,
|
|
54
|
+
hoverBinding: true,
|
|
55
|
+
inputBinding: true,
|
|
56
|
+
submitBinding: true,
|
|
57
|
+
};
|
|
58
|
+
// this is visualBindingOptions but everything false
|
|
59
|
+
// concrete declear for performance purpose
|
|
60
|
+
const serverRenderedOptions: BindingOption = {
|
|
61
|
+
templateBinding: false,
|
|
62
|
+
textBinding: false,
|
|
63
|
+
cssBinding: false,
|
|
64
|
+
ifBinding: false,
|
|
65
|
+
showBinding: false,
|
|
66
|
+
modelBinding: false,
|
|
67
|
+
attrBinding: false,
|
|
68
|
+
forOfBinding: false,
|
|
69
|
+
switchBinding: false,
|
|
70
|
+
};
|
|
71
|
+
let updateOption: BindingOption = {};
|
|
72
|
+
|
|
73
|
+
switch (condition) {
|
|
74
|
+
case bindingUpdateConditions.serverRendered:
|
|
75
|
+
updateOption = extend(false, {}, eventsBindingOptions, serverRenderedOptions, opt);
|
|
76
|
+
break;
|
|
77
|
+
case bindingUpdateConditions.init:
|
|
78
|
+
// flag templateBinding to true to render tempalte(s)
|
|
79
|
+
opt.templateBinding = true;
|
|
80
|
+
opt.forceRender = true;
|
|
81
|
+
updateOption = extend(false, {}, visualBindingOptions, eventsBindingOptions, opt);
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
// when called again only update visualBinding options
|
|
85
|
+
updateOption = extend(false, {}, visualBindingOptions, opt);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return updateOption;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default createBindingOption;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getFormData,
|
|
3
|
+
getViewModelValue,
|
|
4
|
+
resolveViewModelContext,
|
|
5
|
+
resolveParamList,
|
|
6
|
+
} from './util';
|
|
7
|
+
import type {BindingCache, ViewModel} from './types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Create event handler wrapper
|
|
11
|
+
*/
|
|
12
|
+
const createEventHandlerWrapper = (
|
|
13
|
+
type: string,
|
|
14
|
+
paramList: unknown[],
|
|
15
|
+
handlerFn: Function,
|
|
16
|
+
viewModelContext: ViewModel,
|
|
17
|
+
): EventListener => {
|
|
18
|
+
return function handlerWrap(e: Event): void {
|
|
19
|
+
let formData: Record<string, unknown>;
|
|
20
|
+
let args: unknown[] = [];
|
|
21
|
+
if (type === 'submit') {
|
|
22
|
+
formData = getFormData(e.currentTarget as HTMLFormElement);
|
|
23
|
+
args = [e, e.currentTarget, formData, ...paramList];
|
|
24
|
+
} else {
|
|
25
|
+
args = [e, e.currentTarget, ...paramList];
|
|
26
|
+
}
|
|
27
|
+
handlerFn.apply(viewModelContext, args);
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
interface CreateEventBindingParams {
|
|
32
|
+
cache?: BindingCache;
|
|
33
|
+
forceRender?: boolean;
|
|
34
|
+
type?: string;
|
|
35
|
+
viewModel?: ViewModel;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const createEventBinding = ({
|
|
39
|
+
cache = {} as BindingCache,
|
|
40
|
+
forceRender = false,
|
|
41
|
+
type = '',
|
|
42
|
+
viewModel = {} as ViewModel,
|
|
43
|
+
}: CreateEventBindingParams): void => {
|
|
44
|
+
const handlerName = cache.dataKey;
|
|
45
|
+
let paramList = cache.parameters;
|
|
46
|
+
let viewModelContext: ViewModel;
|
|
47
|
+
const APP = viewModel.APP || viewModel.$root?.APP;
|
|
48
|
+
const rootElement = APP?.$rootElement as HTMLElement | undefined;
|
|
49
|
+
|
|
50
|
+
if (!type || !handlerName || (!forceRender && rootElement && !rootElement.contains(cache.el))) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const handlerFn = getViewModelValue(viewModel, handlerName);
|
|
55
|
+
|
|
56
|
+
if (typeof handlerFn === 'function') {
|
|
57
|
+
viewModelContext = resolveViewModelContext(viewModel, handlerName);
|
|
58
|
+
paramList = paramList ? resolveParamList(viewModel, paramList) : [];
|
|
59
|
+
|
|
60
|
+
// Store handler key for this event type on the DOM element itself
|
|
61
|
+
// This prevents duplicate handlers even if multiple cache objects exist for same element
|
|
62
|
+
const handlerKey = `_db_${type}Handler`;
|
|
63
|
+
const el = cache.el as HTMLElement & Record<string, unknown>;
|
|
64
|
+
|
|
65
|
+
// Check if handler already exists and skip if it's the same
|
|
66
|
+
// This prevents adding duplicate handlers when the same element is processed multiple times
|
|
67
|
+
if (el[handlerKey]) {
|
|
68
|
+
// Handler already exists, remove it before adding new one
|
|
69
|
+
el.removeEventListener(type, el[handlerKey] as EventListener, false);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Create new handler wrapper
|
|
73
|
+
const handlerWrap = createEventHandlerWrapper(
|
|
74
|
+
type,
|
|
75
|
+
paramList,
|
|
76
|
+
handlerFn,
|
|
77
|
+
viewModelContext,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// Store the handler on the DOM element so we can remove it later
|
|
81
|
+
el[handlerKey] = handlerWrap;
|
|
82
|
+
|
|
83
|
+
// Add the new event listener
|
|
84
|
+
el.addEventListener(type, handlerWrap, false);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default createEventBinding;
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
arrayRemoveMatch,
|
|
5
5
|
each,
|
|
6
6
|
} from './util';
|
|
7
|
+
import type {BindingCache, ViewModel, BindingAttrs, PlainObject} from './types';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* cssBinding
|
|
@@ -16,11 +17,11 @@ import {
|
|
|
16
17
|
* @param {object} bindingAttrs
|
|
17
18
|
* @param {boolean} forceRender
|
|
18
19
|
*/
|
|
19
|
-
const cssBinding = (cache, viewModel, bindingAttrs, forceRender) => {
|
|
20
|
+
const cssBinding = (cache: BindingCache, viewModel: ViewModel, bindingAttrs: BindingAttrs, forceRender: boolean): void => {
|
|
20
21
|
const dataKey = cache.dataKey;
|
|
21
|
-
const APP = viewModel.APP || viewModel.$root
|
|
22
|
+
const APP = viewModel.APP || viewModel.$root?.APP;
|
|
22
23
|
|
|
23
|
-
if (!dataKey || (!forceRender && !APP
|
|
24
|
+
if (!dataKey || (!forceRender && !(APP?.$rootElement as HTMLElement)?.contains(cache.el))) {
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -30,10 +31,10 @@ const cssBinding = (cache, viewModel, bindingAttrs, forceRender) => {
|
|
|
30
31
|
const oldCssList = cache.elementData.viewModelPropValue;
|
|
31
32
|
let newCssList = '';
|
|
32
33
|
const vmCssListObj = getViewModelPropValue(viewModel, cache);
|
|
33
|
-
let vmCssListArray = [];
|
|
34
|
+
let vmCssListArray: string[] = [];
|
|
34
35
|
let isViewDataObject = false;
|
|
35
36
|
let isViewDataString = false;
|
|
36
|
-
let cssList = [];
|
|
37
|
+
let cssList: string[] = [];
|
|
37
38
|
|
|
38
39
|
if (typeof vmCssListObj === 'string') {
|
|
39
40
|
isViewDataString = true;
|
|
@@ -47,7 +48,7 @@ const cssBinding = (cache, viewModel, bindingAttrs, forceRender) => {
|
|
|
47
48
|
if (isViewDataObject) {
|
|
48
49
|
newCssList = JSON.stringify(vmCssListObj);
|
|
49
50
|
} else {
|
|
50
|
-
newCssList = vmCssListObj.replace(/\s\s+/g, ' ').trim();
|
|
51
|
+
newCssList = (vmCssListObj as string).replace(/\s\s+/g, ' ').trim();
|
|
51
52
|
vmCssListArray = newCssList.split(' ');
|
|
52
53
|
}
|
|
53
54
|
// reject if nothing changed
|
|
@@ -64,7 +65,7 @@ const cssBinding = (cache, viewModel, bindingAttrs, forceRender) => {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
if (isViewDataObject) {
|
|
67
|
-
each(vmCssListObj,
|
|
68
|
+
each(vmCssListObj as PlainObject, (k: string, v: unknown) => {
|
|
68
69
|
const i = cssList.indexOf(k);
|
|
69
70
|
if (v === true) {
|
|
70
71
|
cssList.push(k);
|
|
@@ -74,20 +75,21 @@ const cssBinding = (cache, viewModel, bindingAttrs, forceRender) => {
|
|
|
74
75
|
});
|
|
75
76
|
} else if (isViewDataString) {
|
|
76
77
|
// remove oldCssList items from cssList
|
|
77
|
-
|
|
78
|
+
const oldCssArray = typeof oldCssList === 'string' && oldCssList ? oldCssList.split(' ') : [];
|
|
79
|
+
cssList = arrayRemoveMatch(cssList, oldCssArray) as string[];
|
|
78
80
|
cssList = cssList.concat(vmCssListArray);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
// unique cssList array
|
|
82
|
-
cssList = cssList.filter((v, i, a) => {
|
|
84
|
+
cssList = cssList.filter((v: string, i: number, a: string[]) => {
|
|
83
85
|
return a.indexOf(v) === i;
|
|
84
86
|
});
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
const cssListString = cssList.join(' ');
|
|
87
89
|
// update element data
|
|
88
90
|
cache.elementData.viewModelPropValue = newCssList;
|
|
89
91
|
// replace all css classes
|
|
90
|
-
cache.el.setAttribute('class',
|
|
92
|
+
cache.el.setAttribute('class', cssListString);
|
|
91
93
|
};
|
|
92
94
|
|
|
93
95
|
export default cssBinding;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {invertObj, extractFilterList, getFunctionParameterList, REGEX} from './util';
|
|
2
2
|
import {constants} from './config';
|
|
3
|
+
import type {PlainObject, BindingAttrs, ElementCache, BindingCache} from './types';
|
|
3
4
|
|
|
4
|
-
let bindingAttrsMap;
|
|
5
|
+
let bindingAttrsMap: PlainObject | undefined;
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* walkDOM
|
|
@@ -10,47 +11,52 @@ let bindingAttrsMap;
|
|
|
10
11
|
* @param {object} node
|
|
11
12
|
* @param {function} func
|
|
12
13
|
*/
|
|
13
|
-
const walkDOM = (node, func) => {
|
|
14
|
+
const walkDOM = (node: HTMLElement, func: (node: HTMLElement) => boolean): void => {
|
|
14
15
|
let parseChildNode = true;
|
|
15
|
-
|
|
16
|
-
while (
|
|
17
|
-
parseChildNode = func(
|
|
16
|
+
let currentNode = node.firstElementChild as HTMLElement | null;
|
|
17
|
+
while (currentNode) {
|
|
18
|
+
parseChildNode = func(currentNode);
|
|
18
19
|
if (parseChildNode) {
|
|
19
|
-
walkDOM(
|
|
20
|
+
walkDOM(currentNode, func);
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
+
currentNode = currentNode.nextElementSibling as HTMLElement | null;
|
|
22
23
|
}
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
const getAttributesObject = (node) => {
|
|
26
|
-
const ret = {};
|
|
27
|
-
Array.prototype.slice.call(node.attributes).forEach((item) => {
|
|
26
|
+
const getAttributesObject = (node: HTMLElement): PlainObject => {
|
|
27
|
+
const ret: PlainObject = {};
|
|
28
|
+
Array.prototype.slice.call(node.attributes).forEach((item: Attr) => {
|
|
28
29
|
ret[item.name] = item.value;
|
|
29
30
|
});
|
|
30
31
|
return ret;
|
|
31
32
|
};
|
|
32
33
|
|
|
33
|
-
const checkSkipChildParseBindings = (attrObj = {}, bindingAttrs) => {
|
|
34
|
-
return [bindingAttrs.forOf, bindingAttrs.if, bindingAttrs.case, bindingAttrs.default].filter((type) => {
|
|
34
|
+
const checkSkipChildParseBindings = (attrObj: PlainObject = {}, bindingAttrs: BindingAttrs): string[] => {
|
|
35
|
+
return [bindingAttrs.forOf, bindingAttrs.if, bindingAttrs.case, bindingAttrs.default].filter((type: string) => {
|
|
35
36
|
return typeof attrObj[type] !== 'undefined';
|
|
36
37
|
});
|
|
37
38
|
};
|
|
38
39
|
|
|
39
|
-
const rootSkipCheck = (node) => {
|
|
40
|
+
const rootSkipCheck = (node: HTMLElement): boolean => {
|
|
40
41
|
return node.tagName === 'SVG';
|
|
41
42
|
};
|
|
42
43
|
|
|
43
|
-
const defaultSkipCheck = (node, bindingAttrs) => {
|
|
44
|
+
const defaultSkipCheck = (node: HTMLElement, bindingAttrs: BindingAttrs): boolean => {
|
|
44
45
|
return node.tagName === 'SVG' || node.hasAttribute(bindingAttrs.comp);
|
|
45
46
|
};
|
|
46
47
|
|
|
47
|
-
const populateBindingCache = ({node, attrObj, bindingCache, type}
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const populateBindingCache = ({node, attrObj, bindingCache, type}: {
|
|
49
|
+
node: HTMLElement;
|
|
50
|
+
attrObj: PlainObject;
|
|
51
|
+
bindingCache: ElementCache;
|
|
52
|
+
type: string;
|
|
53
|
+
}): ElementCache => {
|
|
54
|
+
let attrValue: string;
|
|
55
|
+
let cacheData: Partial<BindingCache>;
|
|
50
56
|
|
|
51
57
|
if (bindingAttrsMap && bindingAttrsMap[type] && typeof attrObj[type] !== 'undefined') {
|
|
52
58
|
bindingCache[type] = bindingCache[type] || [];
|
|
53
|
-
attrValue = attrObj[type] || '';
|
|
59
|
+
attrValue = (attrObj[type] as string) || '';
|
|
54
60
|
|
|
55
61
|
if (attrValue) {
|
|
56
62
|
attrValue = attrValue.replace(REGEX.LINE_BREAKS_TABS, '').replace(REGEX.WHITE_SPACES, ' ').trim();
|
|
@@ -67,28 +73,36 @@ const populateBindingCache = ({node, attrObj, bindingCache, type}) => {
|
|
|
67
73
|
// populate cacheData.parameters
|
|
68
74
|
// for store function call parameters eg. '$index', '$root'
|
|
69
75
|
// useful with DOM for-loop template as reference to binding data
|
|
70
|
-
const paramList = getFunctionParameterList(cacheData.dataKey);
|
|
76
|
+
const paramList = getFunctionParameterList(cacheData.dataKey || '');
|
|
71
77
|
if (paramList) {
|
|
72
78
|
cacheData.parameters = paramList;
|
|
73
|
-
cacheData.dataKey = cacheData.dataKey.replace(REGEX.FUNCTION_PARAM, '').trim();
|
|
79
|
+
cacheData.dataKey = (cacheData.dataKey || '').replace(REGEX.FUNCTION_PARAM, '').trim();
|
|
74
80
|
}
|
|
75
81
|
// store parent array reference to cacheData
|
|
76
82
|
cacheData[constants.PARENT_REF] = bindingCache[type];
|
|
77
|
-
bindingCache[type].push(cacheData);
|
|
83
|
+
bindingCache[type].push(cacheData as BindingCache);
|
|
78
84
|
}
|
|
79
85
|
return bindingCache;
|
|
80
86
|
};
|
|
81
87
|
|
|
82
|
-
const createBindingCache = ({rootNode = null, bindingAttrs = {}, skipCheck, isRenderedTemplate = false}
|
|
83
|
-
|
|
88
|
+
const createBindingCache = ({rootNode = null, bindingAttrs = {} as BindingAttrs, skipCheck, isRenderedTemplate = false}: {
|
|
89
|
+
rootNode?: HTMLElement | null;
|
|
90
|
+
bindingAttrs?: BindingAttrs;
|
|
91
|
+
skipCheck?: (node: HTMLElement) => boolean;
|
|
92
|
+
isRenderedTemplate?: boolean;
|
|
93
|
+
}): ElementCache => {
|
|
94
|
+
let bindingCache: ElementCache = {};
|
|
84
95
|
|
|
85
|
-
if (!rootNode instanceof window.Node) {
|
|
96
|
+
if (!(rootNode instanceof window.Node)) {
|
|
86
97
|
throw new TypeError('walkDOM: Expected a DOM node');
|
|
87
98
|
}
|
|
88
99
|
|
|
89
100
|
bindingAttrsMap = bindingAttrsMap || invertObj(bindingAttrs);
|
|
90
101
|
|
|
91
|
-
const parseNode = (
|
|
102
|
+
const parseNode = (
|
|
103
|
+
node: HTMLElement,
|
|
104
|
+
skipNodeCheckFn: (node: HTMLElement, bindingAttrs: BindingAttrs) => boolean = defaultSkipCheck,
|
|
105
|
+
): boolean => {
|
|
92
106
|
let isSkipForOfChild = false;
|
|
93
107
|
|
|
94
108
|
if (node.nodeType !== 1 || !node.hasAttributes()) {
|
|
@@ -102,7 +116,7 @@ const createBindingCache = ({rootNode = null, bindingAttrs = {}, skipCheck, isRe
|
|
|
102
116
|
// skip same element that has forOf binding the forOf is alredy parsed
|
|
103
117
|
const attrObj = getAttributesObject(node);
|
|
104
118
|
const hasSkipChildParseBindings = checkSkipChildParseBindings(attrObj, bindingAttrs);
|
|
105
|
-
let iterateList = [];
|
|
119
|
+
let iterateList: string[] = [];
|
|
106
120
|
|
|
107
121
|
if (hasSkipChildParseBindings.length) {
|
|
108
122
|
isSkipForOfChild = true;
|
|
@@ -114,13 +128,13 @@ const createBindingCache = ({rootNode = null, bindingAttrs = {}, skipCheck, isRe
|
|
|
114
128
|
iterateList = Object.keys(attrObj);
|
|
115
129
|
}
|
|
116
130
|
|
|
117
|
-
iterateList.forEach((key) => {
|
|
131
|
+
iterateList.forEach((key: string) => {
|
|
118
132
|
// skip for switch case and default bining
|
|
119
133
|
if (key !== bindingAttrs.case && key !== bindingAttrs.default) {
|
|
120
134
|
bindingCache = populateBindingCache({
|
|
121
|
-
node
|
|
122
|
-
attrObj
|
|
123
|
-
bindingCache
|
|
135
|
+
node,
|
|
136
|
+
attrObj,
|
|
137
|
+
bindingCache,
|
|
124
138
|
type: key,
|
|
125
139
|
});
|
|
126
140
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {maxDatakeyLength} from './config';
|
|
2
2
|
import {REGEX} from './util';
|
|
3
3
|
import renderForOfBinding from './renderForOfBinding';
|
|
4
|
+
import type {BindingCache, ViewModel, BindingAttrs} from './types';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* forOfBinding
|
|
@@ -10,7 +11,7 @@ import renderForOfBinding from './renderForOfBinding';
|
|
|
10
11
|
* @param {object} viewModel
|
|
11
12
|
* @param {object} bindingAttrs
|
|
12
13
|
*/
|
|
13
|
-
const forOfBinding = (cache, viewModel, bindingAttrs) => {
|
|
14
|
+
const forOfBinding = (cache: BindingCache, viewModel: ViewModel, bindingAttrs: BindingAttrs, _forceRender?: boolean): void => {
|
|
14
15
|
const dataKey = cache.dataKey;
|
|
15
16
|
|
|
16
17
|
if (!dataKey || dataKey.length > maxDatakeyLength) {
|
|
@@ -42,8 +43,8 @@ const forOfBinding = (cache, viewModel, bindingAttrs) => {
|
|
|
42
43
|
|
|
43
44
|
renderForOfBinding({
|
|
44
45
|
bindingData: cache,
|
|
45
|
-
viewModel
|
|
46
|
-
bindingAttrs
|
|
46
|
+
viewModel,
|
|
47
|
+
bindingAttrs,
|
|
47
48
|
});
|
|
48
49
|
};
|
|
49
50
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
import {bindingDataReference} from './config';
|
|
3
|
+
import {
|
|
4
|
+
getViewModelValue,
|
|
5
|
+
resolveViewModelContext,
|
|
6
|
+
resolveParamList,
|
|
7
|
+
} from './util';
|
|
8
|
+
import type {BindingCache, ViewModel, BindingAttrs, PlainObject} from './types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create mouse enter handler
|
|
12
|
+
*/
|
|
13
|
+
const createMouseEnterHandler = (
|
|
14
|
+
cache: BindingCache,
|
|
15
|
+
handlers: PlainObject,
|
|
16
|
+
inHandlerName: string,
|
|
17
|
+
viewModelContext: ViewModel,
|
|
18
|
+
paramList: unknown[],
|
|
19
|
+
): (e: MouseEvent) => void => {
|
|
20
|
+
return function onMouseEnterHandler(e: MouseEvent) {
|
|
21
|
+
const args = [e, cache.el, ...paramList];
|
|
22
|
+
(handlers[inHandlerName] as Function).apply(viewModelContext, args);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create mouse leave handler
|
|
28
|
+
*/
|
|
29
|
+
const createMouseLeaveHandler = (
|
|
30
|
+
cache: BindingCache,
|
|
31
|
+
handlers: PlainObject,
|
|
32
|
+
outHandlerName: string,
|
|
33
|
+
viewModelContext: ViewModel,
|
|
34
|
+
paramList: unknown[],
|
|
35
|
+
): (e: MouseEvent) => void => {
|
|
36
|
+
return function onMouseLeaveHandler(e: MouseEvent) {
|
|
37
|
+
const args = [e, cache.el, ...paramList];
|
|
38
|
+
(handlers[outHandlerName] as Function).apply(viewModelContext, args);
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* hoverBinding
|
|
44
|
+
* DOM decleartive on hover event binding
|
|
45
|
+
* event handler bind to viewModel method according to the DOM attribute
|
|
46
|
+
* @param {object} cache
|
|
47
|
+
* @param {object} viewModel
|
|
48
|
+
* @param {object} bindingAttrs
|
|
49
|
+
* @param {boolean} forceRender
|
|
50
|
+
*/
|
|
51
|
+
const hoverBinding = (cache: BindingCache, viewModel: ViewModel, bindingAttrs: BindingAttrs, forceRender: boolean): void => {
|
|
52
|
+
const handlerName = cache.dataKey;
|
|
53
|
+
let paramList = cache.parameters;
|
|
54
|
+
const inHandlerName = bindingDataReference.mouseEnterHandlerName;
|
|
55
|
+
const outHandlerName = bindingDataReference.mouseLeaveHandlerName;
|
|
56
|
+
let viewModelContext: ViewModel;
|
|
57
|
+
const APP = viewModel.APP || viewModel.$root?.APP;
|
|
58
|
+
|
|
59
|
+
cache.elementData = cache.elementData || {};
|
|
60
|
+
|
|
61
|
+
// TODO: check what is APP.$rootElement.contains(cache.el)
|
|
62
|
+
const rootElement = APP?.$rootElement as HTMLElement | undefined;
|
|
63
|
+
if (!handlerName || (!forceRender && rootElement && !rootElement.contains(cache.el))) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const handlers = getViewModelValue(viewModel, handlerName) as PlainObject;
|
|
68
|
+
|
|
69
|
+
if (handlers && typeof handlers[inHandlerName] === 'function' && typeof handlers[outHandlerName] === 'function') {
|
|
70
|
+
viewModelContext = resolveViewModelContext(viewModel, handlerName);
|
|
71
|
+
paramList = paramList ? resolveParamList(viewModel, paramList) : [];
|
|
72
|
+
|
|
73
|
+
const onMouseEnterHandler = createMouseEnterHandler(cache, handlers as PlainObject, inHandlerName, viewModelContext, paramList);
|
|
74
|
+
const onMouseLeaveHandler = createMouseLeaveHandler(cache, handlers as PlainObject, outHandlerName, viewModelContext, paramList);
|
|
75
|
+
|
|
76
|
+
cache.el.removeEventListener('mouseenter', onMouseEnterHandler, false);
|
|
77
|
+
cache.el.removeEventListener('mouseleave', onMouseLeaveHandler, false);
|
|
78
|
+
|
|
79
|
+
cache.el.addEventListener('mouseenter', onMouseEnterHandler, false);
|
|
80
|
+
cache.el.addEventListener('mouseleave', onMouseLeaveHandler, false);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default hoverBinding;
|
|
@@ -2,6 +2,7 @@ import {bindingAttrs as configBindingAttrs, constants} from './config';
|
|
|
2
2
|
import {getViewModelPropValue, removeElement} from './util';
|
|
3
3
|
import {createClonedElementCache, wrapCommentAround} from './commentWrapper';
|
|
4
4
|
import {renderIfBinding, removeIfBinding} from './renderIfBinding';
|
|
5
|
+
import type {BindingCache, ViewModel, BindingAttrs} from './types';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* if-Binding
|
|
@@ -11,7 +12,7 @@ import {renderIfBinding, removeIfBinding} from './renderIfBinding';
|
|
|
11
12
|
* @param {object} viewModel
|
|
12
13
|
* @param {object} bindingAttrs
|
|
13
14
|
*/
|
|
14
|
-
const ifBinding = (cache, viewModel, bindingAttrs) => {
|
|
15
|
+
const ifBinding = (cache: BindingCache, viewModel: ViewModel, bindingAttrs: BindingAttrs, _forceRender?: boolean): void => {
|
|
15
16
|
const dataKey = cache.dataKey;
|
|
16
17
|
|
|
17
18
|
// isOnce only return if there is no child bindings
|
|
@@ -38,8 +39,8 @@ const ifBinding = (cache, viewModel, bindingAttrs) => {
|
|
|
38
39
|
removeElement(cache.el);
|
|
39
40
|
// delete cache.fragment;
|
|
40
41
|
removeBindingInQueue({
|
|
41
|
-
viewModel
|
|
42
|
-
cache
|
|
42
|
+
viewModel,
|
|
43
|
+
cache,
|
|
43
44
|
});
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
@@ -63,8 +64,8 @@ const ifBinding = (cache, viewModel, bindingAttrs) => {
|
|
|
63
64
|
// render element
|
|
64
65
|
renderIfBinding({
|
|
65
66
|
bindingData: cache,
|
|
66
|
-
viewModel
|
|
67
|
-
bindingAttrs
|
|
67
|
+
viewModel,
|
|
68
|
+
bindingAttrs,
|
|
68
69
|
});
|
|
69
70
|
|
|
70
71
|
// if render once
|
|
@@ -72,20 +73,21 @@ const ifBinding = (cache, viewModel, bindingAttrs) => {
|
|
|
72
73
|
if (cache.isOnce && !cache.hasIterationBindingCache) {
|
|
73
74
|
// delete cache.fragment;
|
|
74
75
|
removeBindingInQueue({
|
|
75
|
-
viewModel
|
|
76
|
-
cache
|
|
76
|
+
viewModel,
|
|
77
|
+
cache,
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
};
|
|
81
82
|
|
|
82
|
-
const removeBindingInQueue = ({viewModel, cache}) => {
|
|
83
|
+
const removeBindingInQueue = ({viewModel, cache}: {viewModel: ViewModel; cache: BindingCache}): boolean => {
|
|
83
84
|
let ret = false;
|
|
84
|
-
if (viewModel.APP
|
|
85
|
+
if (viewModel.APP?.postProcessQueue) {
|
|
86
|
+
const parentRef = cache[constants.PARENT_REF] as BindingCache[];
|
|
85
87
|
viewModel.APP.postProcessQueue.push(
|
|
86
|
-
((cache, index) => () => {
|
|
87
|
-
|
|
88
|
-
})(cache,
|
|
88
|
+
((cache: BindingCache, index: number) => () => {
|
|
89
|
+
parentRef.splice(index, 1);
|
|
90
|
+
})(cache, parentRef.indexOf(cache)),
|
|
89
91
|
);
|
|
90
92
|
ret = true;
|
|
91
93
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as config from './config';
|
|
2
|
+
import {extend} from './util';
|
|
3
|
+
import Binder from './binder';
|
|
4
|
+
import type {PlainObject, ViewModel, BindingAttrs, BinderOptions} from './types';
|
|
5
|
+
|
|
6
|
+
const isSupportPromise = typeof window['Promise'] === 'function';
|
|
7
|
+
|
|
8
|
+
let bindingAttrs = config.bindingAttrs;
|
|
9
|
+
|
|
10
|
+
// Global default options for all Binder instances
|
|
11
|
+
const defaultOptions: BinderOptions = {
|
|
12
|
+
reactive: true, // Enable reactive mode by default
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
interface DataBindAPI {
|
|
16
|
+
use: (settings: PlainObject) => DataBindAPI;
|
|
17
|
+
init: ($rootElement: HTMLElement, viewModel: ViewModel | null, options?: BinderOptions) => Binder | void;
|
|
18
|
+
version: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const use = (settings: PlainObject = {}): DataBindAPI => {
|
|
22
|
+
if (settings.bindingAttrs) {
|
|
23
|
+
bindingAttrs = extend(false, {}, settings.bindingAttrs as PlainObject) as unknown as typeof config.bindingAttrs;
|
|
24
|
+
}
|
|
25
|
+
// Allow setting global reactive option
|
|
26
|
+
if (typeof settings.reactive === 'boolean') {
|
|
27
|
+
defaultOptions.reactive = settings.reactive;
|
|
28
|
+
}
|
|
29
|
+
// Allow setting global trackChanges option
|
|
30
|
+
if (typeof settings.trackChanges === 'boolean') {
|
|
31
|
+
defaultOptions.trackChanges = settings.trackChanges;
|
|
32
|
+
}
|
|
33
|
+
// Return API for chaining
|
|
34
|
+
return api;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const init = ($rootElement: HTMLElement, viewModel: ViewModel | null = null, options?: BinderOptions): Binder | void => {
|
|
38
|
+
if (!isSupportPromise) {
|
|
39
|
+
return console.warn('Browser not support Promise');
|
|
40
|
+
}
|
|
41
|
+
// Merge global defaults with instance-specific options
|
|
42
|
+
// Instance options take precedence over global defaults
|
|
43
|
+
const mergedOptions = {...defaultOptions, ...options};
|
|
44
|
+
return new Binder($rootElement, viewModel, bindingAttrs as unknown as BindingAttrs, mergedOptions);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const api: DataBindAPI = {
|
|
48
|
+
use,
|
|
49
|
+
init,
|
|
50
|
+
version: '@version@',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default api;
|