@gogocat/data-bind 1.12.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 +2756 -2530
- 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/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 +14 -14
- 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.js → applyBinding.ts} +27 -18
- package/src/{attrBinding.js → attrBinding.ts} +14 -13
- package/src/{binder.js → binder.ts} +289 -181
- package/src/changeBinding.ts +93 -0
- package/src/{commentWrapper.js → commentWrapper.ts} +33 -30
- package/src/config.ts +107 -0
- package/src/{createBindingOption.js → createBindingOption.ts} +39 -15
- 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.js → postProcess.ts} +6 -4
- package/src/{pubSub.js → pubSub.ts} +24 -21
- package/src/reactiveProxy.ts +285 -0
- package/src/{renderForOfBinding.js → renderForOfBinding.ts} +54 -32
- package/src/{renderIfBinding.js → renderIfBinding.ts} +41 -19
- package/src/{renderIteration.js → renderIteration.ts} +24 -8
- 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/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/applyBindingExport.js +0 -5
- package/src/changeBinding.js +0 -63
- package/src/config.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/renderTemplatesBinding.js +0 -44
- package/src/util.js +0 -648
- package/test/specs/blurBinding.spec.js +0 -57
- package/test/specs/formBinding.spec.js +0 -316
- 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
|
@@ -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;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {getViewModelValue} from './util';
|
|
2
|
+
import type {BindingCache, ViewModel, BindingAttrs} from './types';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* modelBinding
|
|
@@ -8,23 +9,23 @@ import {getViewModelValue} from './util';
|
|
|
8
9
|
* @param {object} bindingAttrs
|
|
9
10
|
* @param {boolean} forceRender
|
|
10
11
|
*/
|
|
11
|
-
const modelBinding = (cache, viewModel, bindingAttrs, forceRender) => {
|
|
12
|
+
const modelBinding = (cache: BindingCache, viewModel: ViewModel, bindingAttrs: BindingAttrs, forceRender: boolean): void => {
|
|
12
13
|
const dataKey = cache.dataKey;
|
|
13
|
-
let newValue = '';
|
|
14
|
-
const APP = viewModel.APP || viewModel.$root
|
|
14
|
+
let newValue: unknown = '';
|
|
15
|
+
const APP = viewModel.APP || viewModel.$root?.APP;
|
|
15
16
|
|
|
16
|
-
if (!dataKey || (!forceRender && !APP
|
|
17
|
+
if (!dataKey || (!forceRender && !(APP?.$rootElement as HTMLElement)?.contains(cache.el))) {
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
newValue = getViewModelValue(viewModel, dataKey);
|
|
21
22
|
|
|
22
23
|
if (typeof newValue !== 'undefined' && newValue !== null) {
|
|
23
|
-
const $element = cache.el;
|
|
24
|
+
const $element = cache.el as HTMLInputElement;
|
|
24
25
|
const isCheckbox = $element.type === 'checkbox';
|
|
25
26
|
const isRadio = $element.type === 'radio';
|
|
26
27
|
const inputName = $element.name;
|
|
27
|
-
const $radioGroup = isRadio ? APP
|
|
28
|
+
const $radioGroup = isRadio ? (APP?.$rootElement as HTMLElement).querySelectorAll(`input[name="${inputName}"]`) : [];
|
|
28
29
|
const oldValue = isCheckbox ? $element.checked : $element.value;
|
|
29
30
|
|
|
30
31
|
// update element value
|
|
@@ -36,13 +37,14 @@ const modelBinding = (cache, viewModel, bindingAttrs, forceRender) => {
|
|
|
36
37
|
const radioGroupLength = $radioGroup.length;
|
|
37
38
|
|
|
38
39
|
for (i = 0; i < radioGroupLength; i += 1) {
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
const radioInput = $radioGroup[i] as HTMLInputElement;
|
|
41
|
+
if (radioInput.value === newValue) {
|
|
42
|
+
radioInput.checked = true;
|
|
41
43
|
break;
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
} else {
|
|
45
|
-
$element.value = newValue;
|
|
47
|
+
$element.value = String(newValue);
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -3,18 +3,20 @@ import {
|
|
|
3
3
|
throwErrorMessage,
|
|
4
4
|
} from './util';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const postProcess = (tasks: Function[]): void => {
|
|
7
7
|
if (!tasks || !tasks.length) {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
each(tasks, (index, task) => {
|
|
11
|
+
each(tasks, (index: number, task: Function) => {
|
|
12
12
|
if (typeof task === 'function') {
|
|
13
13
|
try {
|
|
14
14
|
task();
|
|
15
15
|
} catch (err) {
|
|
16
|
-
throwErrorMessage(err,
|
|
16
|
+
throwErrorMessage(err, `Error postProcess: ${ String(task)}`);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
|
-
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default postProcess;
|
|
@@ -10,47 +10,58 @@ import * as util from './util';
|
|
|
10
10
|
};
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
interface Subscriber {
|
|
14
|
+
[compId: string]: Function | boolean | undefined;
|
|
15
|
+
isOnce?: boolean;
|
|
16
|
+
}
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
interface Events {
|
|
19
|
+
[eventName: string]: Subscriber[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const EVENTS: Events = {};
|
|
23
|
+
|
|
24
|
+
export const subscribeEvent = (instance: unknown = null, eventName: string = '', fn: Function, isOnce: boolean = false): void => {
|
|
25
|
+
if (!instance || typeof instance !== 'object' || !('compId' in instance) || !instance.compId || !eventName || typeof fn !== 'function') {
|
|
17
26
|
return;
|
|
18
27
|
}
|
|
19
28
|
|
|
20
|
-
let subscriber;
|
|
29
|
+
let subscriber: Subscriber;
|
|
21
30
|
let isSubscribed = false;
|
|
22
31
|
|
|
23
32
|
eventName = eventName.replace(util.REGEX.WHITE_SPACES, '');
|
|
24
33
|
EVENTS[eventName] = EVENTS[eventName] || [];
|
|
25
34
|
// check if already subscribed and update callback fn
|
|
35
|
+
const instanceWithViewModel = instance as { compId: string | number; viewModel: unknown };
|
|
26
36
|
isSubscribed = EVENTS[eventName].some((subscriber) => {
|
|
27
|
-
if (subscriber[
|
|
28
|
-
subscriber[
|
|
37
|
+
if (subscriber[instanceWithViewModel.compId]) {
|
|
38
|
+
subscriber[instanceWithViewModel.compId] = fn.bind(instanceWithViewModel.viewModel);
|
|
29
39
|
subscriber.isOnce = isOnce;
|
|
30
40
|
return true;
|
|
31
41
|
}
|
|
42
|
+
return false;
|
|
32
43
|
});
|
|
33
44
|
// push if not yet subscribe
|
|
34
45
|
if (!isSubscribed) {
|
|
35
46
|
subscriber = {};
|
|
36
|
-
subscriber[
|
|
47
|
+
subscriber[instanceWithViewModel.compId] = fn.bind(instanceWithViewModel.viewModel);
|
|
37
48
|
subscriber.isOnce = isOnce;
|
|
38
49
|
EVENTS[eventName].push(subscriber);
|
|
39
50
|
}
|
|
40
51
|
};
|
|
41
52
|
|
|
42
|
-
const subscribeEventOnce = (instance = null, eventName = '', fn) => {
|
|
53
|
+
export const subscribeEventOnce = (instance: unknown = null, eventName: string = '', fn: Function): void => {
|
|
43
54
|
subscribeEvent(instance, eventName, fn, true);
|
|
44
55
|
};
|
|
45
56
|
|
|
46
|
-
const unsubscribeEvent = (compId = '', eventName = '') => {
|
|
57
|
+
export const unsubscribeEvent = (compId: string | number = '', eventName: string = ''): void => {
|
|
47
58
|
if (!compId || !eventName) {
|
|
48
59
|
return;
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
let i = 0;
|
|
52
63
|
let subscribersLength = 0;
|
|
53
|
-
let subscriber;
|
|
64
|
+
let subscriber: Subscriber;
|
|
54
65
|
|
|
55
66
|
eventName = eventName.replace(util.REGEX.WHITE_SPACES, '');
|
|
56
67
|
|
|
@@ -65,7 +76,7 @@ const unsubscribeEvent = (compId = '', eventName = '') => {
|
|
|
65
76
|
}
|
|
66
77
|
}
|
|
67
78
|
// delete the event if no more subscriber
|
|
68
|
-
if (!EVENTS[eventName].length) {
|
|
79
|
+
if (EVENTS[eventName] && !EVENTS[eventName].length) {
|
|
69
80
|
delete EVENTS[eventName];
|
|
70
81
|
}
|
|
71
82
|
};
|
|
@@ -75,7 +86,7 @@ const unsubscribeEvent = (compId = '', eventName = '') => {
|
|
|
75
86
|
* @description unsubscribe all event by compId. eg when a component removed
|
|
76
87
|
* @param {string} compId
|
|
77
88
|
*/
|
|
78
|
-
const unsubscribeAllEvent = (compId = '') => {
|
|
89
|
+
export const unsubscribeAllEvent = (compId: string | number = ''): void => {
|
|
79
90
|
if (!compId) {
|
|
80
91
|
return;
|
|
81
92
|
}
|
|
@@ -84,7 +95,7 @@ const unsubscribeAllEvent = (compId = '') => {
|
|
|
84
95
|
});
|
|
85
96
|
};
|
|
86
97
|
|
|
87
|
-
const publishEvent = (eventName = '', ...args) => {
|
|
98
|
+
export const publishEvent = (eventName: string = '', ...args: unknown[]): void => {
|
|
88
99
|
if (!eventName || !EVENTS[eventName]) {
|
|
89
100
|
return;
|
|
90
101
|
}
|
|
@@ -103,11 +114,3 @@ const publishEvent = (eventName = '', ...args) => {
|
|
|
103
114
|
});
|
|
104
115
|
});
|
|
105
116
|
};
|
|
106
|
-
|
|
107
|
-
export {
|
|
108
|
-
subscribeEvent,
|
|
109
|
-
subscribeEventOnce,
|
|
110
|
-
unsubscribeEvent,
|
|
111
|
-
unsubscribeAllEvent,
|
|
112
|
-
publishEvent,
|
|
113
|
-
};
|