@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.
Files changed (274) hide show
  1. package/.editorconfig +14 -14
  2. package/.vscode/launch.json +12 -12
  3. package/CONFIGURATION.md +294 -0
  4. package/REACTIVE_MODE.md +553 -0
  5. package/README.md +266 -829
  6. package/babel.config.json +30 -0
  7. package/dist/js/_escape.d.ts +14 -0
  8. package/dist/js/_escape.d.ts.map +1 -0
  9. package/dist/js/applyBinding.d.ts +11 -0
  10. package/dist/js/applyBinding.d.ts.map +1 -0
  11. package/dist/js/attrBinding.d.ts +12 -0
  12. package/dist/js/attrBinding.d.ts.map +1 -0
  13. package/dist/js/binder.d.ts +67 -0
  14. package/dist/js/binder.d.ts.map +1 -0
  15. package/dist/js/changeBinding.d.ts +19 -0
  16. package/dist/js/changeBinding.d.ts.map +1 -0
  17. package/dist/js/commentWrapper.d.ts +39 -0
  18. package/dist/js/commentWrapper.d.ts.map +1 -0
  19. package/dist/js/config.d.ts +55 -0
  20. package/dist/js/config.d.ts.map +1 -0
  21. package/dist/js/createBindingOption.d.ts +32 -0
  22. package/dist/js/createBindingOption.d.ts.map +1 -0
  23. package/dist/js/createEventBinding.d.ts +10 -0
  24. package/dist/js/createEventBinding.d.ts.map +1 -0
  25. package/dist/js/cssBinding.d.ts +15 -0
  26. package/dist/js/cssBinding.d.ts.map +1 -0
  27. package/dist/js/dataBind.js +2772 -2519
  28. package/dist/js/dataBind.min.js +8 -1
  29. package/dist/js/dataBind.min.js.map +1 -1
  30. package/dist/js/domWalker.d.ts +9 -0
  31. package/dist/js/domWalker.d.ts.map +1 -0
  32. package/dist/js/forOfBinding.d.ts +12 -0
  33. package/dist/js/forOfBinding.d.ts.map +1 -0
  34. package/dist/js/hoverBinding.d.ts +13 -0
  35. package/dist/js/hoverBinding.d.ts.map +1 -0
  36. package/dist/js/ifBinding.d.ts +12 -0
  37. package/dist/js/ifBinding.d.ts.map +1 -0
  38. package/dist/js/index.d.ts +10 -0
  39. package/dist/js/index.d.ts.map +1 -0
  40. package/dist/js/modelBinding.d.ts +12 -0
  41. package/dist/js/modelBinding.d.ts.map +1 -0
  42. package/dist/js/postProcess.d.ts +3 -0
  43. package/dist/js/postProcess.d.ts.map +1 -0
  44. package/dist/js/pubSub.d.ts +11 -0
  45. package/dist/js/pubSub.d.ts.map +1 -0
  46. package/dist/js/reactiveProxy.d.ts +28 -0
  47. package/dist/js/reactiveProxy.d.ts.map +1 -0
  48. package/dist/js/renderForOfBinding.d.ts +8 -0
  49. package/dist/js/renderForOfBinding.d.ts.map +1 -0
  50. package/dist/js/renderIfBinding.d.ts +22 -0
  51. package/dist/js/renderIfBinding.d.ts.map +1 -0
  52. package/dist/js/renderIteration.d.ts +16 -0
  53. package/dist/js/renderIteration.d.ts.map +1 -0
  54. package/dist/js/renderTemplate.d.ts +14 -0
  55. package/dist/js/renderTemplate.d.ts.map +1 -0
  56. package/dist/js/renderTemplatesBinding.d.ts +19 -0
  57. package/dist/js/renderTemplatesBinding.d.ts.map +1 -0
  58. package/dist/js/showBinding.d.ts +13 -0
  59. package/dist/js/showBinding.d.ts.map +1 -0
  60. package/dist/js/switchBinding.d.ts +13 -0
  61. package/dist/js/switchBinding.d.ts.map +1 -0
  62. package/dist/js/textBinding.d.ts +13 -0
  63. package/dist/js/textBinding.d.ts.map +1 -0
  64. package/dist/js/types/_escape.d.ts +14 -0
  65. package/dist/js/types/_escape.d.ts.map +1 -0
  66. package/dist/js/types/applyBinding.d.ts +11 -0
  67. package/dist/js/types/applyBinding.d.ts.map +1 -0
  68. package/dist/js/types/attrBinding.d.ts +12 -0
  69. package/dist/js/types/attrBinding.d.ts.map +1 -0
  70. package/dist/js/types/binder.d.ts +67 -0
  71. package/dist/js/types/binder.d.ts.map +1 -0
  72. package/dist/js/types/changeBinding.d.ts +19 -0
  73. package/dist/js/types/changeBinding.d.ts.map +1 -0
  74. package/dist/js/types/commentWrapper.d.ts +39 -0
  75. package/dist/js/types/commentWrapper.d.ts.map +1 -0
  76. package/dist/js/types/config.d.ts +55 -0
  77. package/dist/js/types/config.d.ts.map +1 -0
  78. package/dist/js/types/createBindingOption.d.ts +32 -0
  79. package/dist/js/types/createBindingOption.d.ts.map +1 -0
  80. package/dist/js/types/createEventBinding.d.ts +10 -0
  81. package/dist/js/types/createEventBinding.d.ts.map +1 -0
  82. package/dist/js/types/cssBinding.d.ts +15 -0
  83. package/dist/js/types/cssBinding.d.ts.map +1 -0
  84. package/dist/js/types/domWalker.d.ts +9 -0
  85. package/dist/js/types/domWalker.d.ts.map +1 -0
  86. package/dist/js/types/forOfBinding.d.ts +12 -0
  87. package/dist/js/types/forOfBinding.d.ts.map +1 -0
  88. package/dist/js/types/hoverBinding.d.ts +13 -0
  89. package/dist/js/types/hoverBinding.d.ts.map +1 -0
  90. package/dist/js/types/ifBinding.d.ts +12 -0
  91. package/dist/js/types/ifBinding.d.ts.map +1 -0
  92. package/dist/js/types/index.d.ts +10 -0
  93. package/dist/js/types/index.d.ts.map +1 -0
  94. package/dist/js/types/modelBinding.d.ts +12 -0
  95. package/dist/js/types/modelBinding.d.ts.map +1 -0
  96. package/dist/js/types/postProcess.d.ts +3 -0
  97. package/dist/js/types/postProcess.d.ts.map +1 -0
  98. package/dist/js/types/pubSub.d.ts +11 -0
  99. package/dist/js/types/pubSub.d.ts.map +1 -0
  100. package/dist/js/types/reactiveProxy.d.ts +28 -0
  101. package/dist/js/types/reactiveProxy.d.ts.map +1 -0
  102. package/dist/js/types/renderForOfBinding.d.ts +8 -0
  103. package/dist/js/types/renderForOfBinding.d.ts.map +1 -0
  104. package/dist/js/types/renderIfBinding.d.ts +22 -0
  105. package/dist/js/types/renderIfBinding.d.ts.map +1 -0
  106. package/dist/js/types/renderIteration.d.ts +16 -0
  107. package/dist/js/types/renderIteration.d.ts.map +1 -0
  108. package/dist/js/types/renderTemplate.d.ts +14 -0
  109. package/dist/js/types/renderTemplate.d.ts.map +1 -0
  110. package/dist/js/types/renderTemplatesBinding.d.ts +19 -0
  111. package/dist/js/types/renderTemplatesBinding.d.ts.map +1 -0
  112. package/dist/js/types/showBinding.d.ts +13 -0
  113. package/dist/js/types/showBinding.d.ts.map +1 -0
  114. package/dist/js/types/switchBinding.d.ts +13 -0
  115. package/dist/js/types/switchBinding.d.ts.map +1 -0
  116. package/dist/js/types/textBinding.d.ts +13 -0
  117. package/dist/js/types/textBinding.d.ts.map +1 -0
  118. package/dist/js/types/types.d.ts +111 -0
  119. package/dist/js/types/types.d.ts.map +1 -0
  120. package/dist/js/types/util.d.ts +119 -0
  121. package/dist/js/types/util.d.ts.map +1 -0
  122. package/dist/js/types.d.ts +111 -0
  123. package/dist/js/types.d.ts.map +1 -0
  124. package/dist/js/util.d.ts +119 -0
  125. package/dist/js/util.d.ts.map +1 -0
  126. package/eslint.config.js +124 -0
  127. package/examples/DBMONSTER_COMPARISON.md +123 -0
  128. package/examples/afterRenderDemo.html +119 -0
  129. package/examples/bootstrap/css/animate.css +1579 -1579
  130. package/examples/bootstrap/css/bootstrap.min.css +6 -6
  131. package/examples/bootstrap/css/homeservices.css +378 -390
  132. package/examples/bootstrap/css/open-iconic.css +511 -511
  133. package/examples/bootstrap/fonts/open-iconic.svg +543 -543
  134. package/examples/bootstrap/js/compMessageDialog.js +20 -19
  135. package/examples/bootstrap/js/compSearchBar.js +12 -19
  136. package/examples/bootstrap/js/compSearchResults.js +50 -46
  137. package/examples/bootstrap/js/featureAdsResult.json +65 -65
  138. package/examples/bootstrap/js/searchResult.json +57 -57
  139. package/examples/bootstrap.html +343 -332
  140. package/examples/css/baseTodo.css +141 -141
  141. package/examples/css/dbMonsterStyles.css +27 -27
  142. package/examples/css/indexTodo.css +374 -374
  143. package/examples/dbmonsterForOfReactive.html +40 -0
  144. package/examples/dbmonsterReact.html +19 -0
  145. package/examples/forOfBindingSimpleDebug.html +45 -0
  146. package/examples/form.html +20 -4
  147. package/examples/globalConfig.html +131 -0
  148. package/examples/js/afterRenderDemo.js +190 -0
  149. package/examples/js/appTodo.js +46 -46
  150. package/examples/js/attrBindingDemo.js +2 -2
  151. package/examples/js/dbMonApp.js +24 -26
  152. package/examples/js/dbMonAppReact.jsx +79 -0
  153. package/examples/js/dbMonAppReactive.js +28 -0
  154. package/examples/js/fiberDemo.js +4 -4
  155. package/examples/js/filtersDemo.js +8 -8
  156. package/examples/js/forOfDemo.js +7 -9
  157. package/examples/js/forOfDemoComplex.js +44 -17
  158. package/examples/js/form.js +44 -12
  159. package/examples/js/globalConfig.js +117 -0
  160. package/examples/js/ifBindingDemo.js +16 -16
  161. package/examples/js/reactiveDemo.js +119 -0
  162. package/examples/js/switchBindingDemo.js +8 -8
  163. package/examples/react-dbmonster/dist/bundle.js +43 -0
  164. package/examples/react-dbmonster/package-lock.json +537 -0
  165. package/examples/react-dbmonster/package.json +16 -0
  166. package/examples/react-dbmonster/src/index.jsx +80 -0
  167. package/examples/reactiveDemo.html +127 -0
  168. package/examples/refreshRateTest.html +75 -75
  169. package/index.html +841 -0
  170. package/package.json +31 -34
  171. package/rollup.config.js +79 -36
  172. package/src/{_escape.js → _escape.ts} +19 -17
  173. package/src/applyBinding.ts +179 -0
  174. package/src/{attrBinding.js → attrBinding.ts} +14 -13
  175. package/src/binder.ts +289 -0
  176. package/src/changeBinding.ts +93 -0
  177. package/src/{commentWrapper.js → commentWrapper.ts} +33 -30
  178. package/src/config.ts +107 -0
  179. package/src/createBindingOption.ts +91 -0
  180. package/src/createEventBinding.ts +88 -0
  181. package/src/{cssBinding.js → cssBinding.ts} +13 -11
  182. package/src/{domWalker.js → domWalker.ts} +44 -30
  183. package/src/{forOfBinding.js → forOfBinding.ts} +4 -3
  184. package/src/hoverBinding.ts +84 -0
  185. package/src/{ifBinding.js → ifBinding.ts} +14 -12
  186. package/src/index.ts +53 -0
  187. package/src/{modelBinding.js → modelBinding.ts} +11 -9
  188. package/src/postProcess.ts +22 -0
  189. package/src/{pubSub.js → pubSub.ts} +24 -15
  190. package/src/reactiveProxy.ts +285 -0
  191. package/src/{renderForOfBinding.js → renderForOfBinding.ts} +55 -33
  192. package/src/{renderIfBinding.js → renderIfBinding.ts} +45 -20
  193. package/src/renderIteration.ts +53 -0
  194. package/src/renderTemplate.ts +165 -0
  195. package/src/renderTemplatesBinding.ts +73 -0
  196. package/src/{showBinding.js → showBinding.ts} +4 -3
  197. package/src/{switchBinding.js → switchBinding.ts} +18 -15
  198. package/src/{textBinding.js → textBinding.ts} +5 -4
  199. package/src/types.ts +124 -0
  200. package/src/util.ts +810 -0
  201. package/test/css/reporter.css +9 -9
  202. package/test/fixtures/dataBindBootstrap.html +2 -2
  203. package/test/fixtures/formBindings.html +9 -1
  204. package/test/globals.d.ts +19 -0
  205. package/test/helpers/testHelper.js +46 -11
  206. package/test/mocks/featureAdsResult.json +65 -65
  207. package/test/mocks/searchResult.json +57 -57
  208. package/test/specs/{attrBinding.spec.js → attrBinding.spec.ts} +103 -106
  209. package/test/specs/{binder.spec.js → binder.spec.ts} +29 -27
  210. package/test/specs/blurBinding.spec.ts +60 -0
  211. package/test/specs/chainableUse.spec.ts +125 -0
  212. package/test/specs/clickBinding.spec.ts +194 -0
  213. package/test/specs/{cssBinding.spec.js → cssBinding.spec.ts} +72 -79
  214. package/test/specs/{dataBindBootstrap.spec.js → dataBindBootstrap.spec.ts} +332 -313
  215. package/test/specs/{filter.spec.js → filter.spec.ts} +75 -76
  216. package/test/specs/{forOfBinding.spec.js → forOfBinding.spec.ts} +208 -219
  217. package/test/specs/formBinding.spec.ts +272 -0
  218. package/test/specs/ifBinding.spec.ts +165 -0
  219. package/test/specs/{nestedComponent.spec.js → nestedComponent.spec.ts} +88 -88
  220. package/test/specs/reactiveProxy.spec.ts +465 -0
  221. package/test/specs/{showBinding.spec.js → showBinding.spec.ts} +148 -149
  222. package/test/specs/{switchBinding.spec.js → switchBinding.spec.ts} +172 -173
  223. package/test/specs/templateBinding.spec.ts +273 -0
  224. package/test/specs/{textBinding.spec.js → textBinding.spec.ts} +47 -48
  225. package/test/tsconfig.json +31 -0
  226. package/test-output.txt +200 -0
  227. package/test-reactive.html +224 -0
  228. package/tsconfig.json +28 -0
  229. package/vendors/lodash.custom.js +4577 -4577
  230. package/vendors/lodash.custom.min.js +45 -45
  231. package/vitest.config.js +27 -0
  232. package/.eslintrc.js +0 -1
  233. package/.grunt/grunt-contrib-jasmine/boot.js +0 -161
  234. package/.grunt/grunt-contrib-jasmine/dist/js/dataBind.js +0 -9
  235. package/.grunt/grunt-contrib-jasmine/grunt-template-jasmine-istanbul/reporter.js +0 -23
  236. package/.grunt/grunt-contrib-jasmine/jasmine-html.js +0 -853
  237. package/.grunt/grunt-contrib-jasmine/jasmine.css +0 -271
  238. package/.grunt/grunt-contrib-jasmine/jasmine.js +0 -9761
  239. package/.grunt/grunt-contrib-jasmine/jasmine_favicon.png +0 -0
  240. package/.grunt/grunt-contrib-jasmine/json2.js +0 -489
  241. package/.grunt/grunt-contrib-jasmine/reporter.js +0 -107
  242. package/coverage/coverage.json +0 -1
  243. package/coverage/lcov/lcov-report/base.css +0 -213
  244. package/coverage/lcov/lcov-report/index.html +0 -93
  245. package/coverage/lcov/lcov-report/js/dataBind.js.html +0 -6596
  246. package/coverage/lcov/lcov-report/js/index.html +0 -93
  247. package/coverage/lcov/lcov-report/prettify.css +0 -1
  248. package/coverage/lcov/lcov-report/prettify.js +0 -1
  249. package/coverage/lcov/lcov-report/sort-arrow-sprite.png +0 -0
  250. package/coverage/lcov/lcov-report/sorter.js +0 -158
  251. package/coverage/lcov/lcov.info +0 -1991
  252. package/eslintrc.json +0 -40
  253. package/examples/bootstrap/js/bootstrap.min.js +0 -6
  254. package/examples/bootstrap/js/popper.min.js +0 -5
  255. package/examples/bootstrap/js/searchSuggestion.js +0 -58
  256. package/examples/bootstrap/js/typeahead.jquery.js +0 -1538
  257. package/gruntfile.js +0 -92
  258. package/gulpfile.js +0 -32
  259. package/src/binder.js +0 -422
  260. package/src/changeBinding.js +0 -57
  261. package/src/config.js +0 -65
  262. package/src/createBindingOption.js +0 -66
  263. package/src/createEventBinding.js +0 -46
  264. package/src/eventSystem.js +0 -46
  265. package/src/hoverBinding.js +0 -57
  266. package/src/index.js +0 -26
  267. package/src/renderTemplate.js +0 -128
  268. package/src/util.js +0 -648
  269. package/test/specs/blurBinding.spec.js +0 -57
  270. package/test/specs/formBinding.spec.js +0 -292
  271. package/test/specs/ifBinding.spec.js +0 -169
  272. package/test/specs/templateBinding.spec.js +0 -117
  273. package/vendors/jasmine-jquery.js +0 -841
  274. package/vendors/jquery-3.2.1.min.js +0 -4
@@ -0,0 +1,111 @@
1
+ export type UnknownValue = unknown;
2
+ export interface PlainObject {
3
+ [key: string]: unknown;
4
+ }
5
+ export interface ViewModel {
6
+ [key: string]: unknown;
7
+ APP?: {
8
+ render?: (opt?: UpdateOption) => void | Promise<void>;
9
+ postProcessQueue?: Array<() => void>;
10
+ [key: string]: unknown;
11
+ };
12
+ $root?: ViewModel;
13
+ $data?: unknown;
14
+ $index?: number;
15
+ }
16
+ export interface ElementData {
17
+ viewModelPropValue?: unknown;
18
+ displayStyle?: string | null;
19
+ computedStyle?: string | null;
20
+ [key: string]: unknown;
21
+ }
22
+ export interface BindingCache {
23
+ el: HTMLElement;
24
+ dataKey?: string;
25
+ parameters?: unknown[];
26
+ filters?: string[];
27
+ isOnce?: boolean;
28
+ elementData?: ElementData;
29
+ bindingCache?: unknown;
30
+ type?: string;
31
+ fragment?: DocumentFragment;
32
+ hasIterationBindingCache?: boolean;
33
+ iterationBindingCache?: unknown;
34
+ parentElement?: HTMLElement | null;
35
+ previousNonTemplateElement?: Node | null;
36
+ nextNonTemplateElement?: Node | null;
37
+ iterator?: {
38
+ alias?: string;
39
+ dataKey?: string;
40
+ };
41
+ cases?: CaseData[];
42
+ [key: string]: unknown;
43
+ }
44
+ export interface CaseData {
45
+ el: HTMLElement;
46
+ dataKey?: string;
47
+ type: string;
48
+ isDefault?: boolean;
49
+ fragment?: DocumentFragment;
50
+ hasIterationBindingCache?: boolean;
51
+ iterationBindingCache?: unknown;
52
+ [key: string]: unknown;
53
+ }
54
+ export interface ElementCache {
55
+ [key: string]: BindingCache[];
56
+ }
57
+ export interface UpdateOption {
58
+ forceRender?: boolean;
59
+ attrBinding?: boolean;
60
+ cssBinding?: boolean;
61
+ textBinding?: boolean;
62
+ modelBinding?: boolean;
63
+ showBinding?: boolean;
64
+ ifBinding?: boolean;
65
+ switchBinding?: boolean;
66
+ forOfBinding?: boolean;
67
+ changeBinding?: boolean;
68
+ submitBinding?: boolean;
69
+ clickBinding?: boolean;
70
+ dblclickBinding?: boolean;
71
+ blurBinding?: boolean;
72
+ focusBinding?: boolean;
73
+ hoverBinding?: boolean;
74
+ inputBinding?: boolean;
75
+ [key: string]: unknown;
76
+ }
77
+ export interface DeferredObj<T = unknown> {
78
+ promise: Promise<T>;
79
+ resolve: (value?: T) => void;
80
+ reject: (reason?: unknown) => void;
81
+ }
82
+ export interface WrapMap {
83
+ [key: string]: [string, string, string];
84
+ }
85
+ export interface BindingAttrs {
86
+ [key: string]: string;
87
+ attr: string;
88
+ css: string;
89
+ text: string;
90
+ model: string;
91
+ show: string;
92
+ if: string;
93
+ switch: string;
94
+ case: string;
95
+ default: string;
96
+ forOf: string;
97
+ change: string;
98
+ submit: string;
99
+ click: string;
100
+ dblclick: string;
101
+ blur: string;
102
+ focus: string;
103
+ hover: string;
104
+ input: string;
105
+ tmp: string;
106
+ }
107
+ export interface BinderOptions {
108
+ reactive?: boolean;
109
+ trackChanges?: boolean;
110
+ }
111
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import type { ViewModel, BindingCache, ElementCache, DeferredObj, PlainObject } from './types';
2
+ export declare const REGEX: {
3
+ BAD_TAGS: RegExp;
4
+ FOR_OF: RegExp;
5
+ FUNCTION_PARAM: RegExp;
6
+ HTML_TAG: RegExp;
7
+ OBJECT_LITERAL: RegExp;
8
+ PIPE: RegExp;
9
+ WHITE_SPACES: RegExp;
10
+ LINE_BREAKS_TABS: RegExp;
11
+ };
12
+ export declare const isArray: (obj: unknown) => obj is unknown[];
13
+ export declare const isJsObject: (obj: unknown) => obj is object;
14
+ export declare const isPlainObject: (obj: unknown) => obj is PlainObject;
15
+ export declare const isObjectLiteralString: (str?: string) => boolean;
16
+ export declare const isEmptyObject: (obj: unknown) => boolean;
17
+ export declare const createHtmlFragment: (htmlString: unknown) => DocumentFragment | null;
18
+ export declare const generateElementCache: (bindingAttrs: PlainObject | unknown[]) => ElementCache;
19
+ /**
20
+ * getViewModelValue
21
+ * @description walk a object by provided string path. eg 'a.b.c'
22
+ * @param {object} viewModel
23
+ * @param {string} prop
24
+ * @return {object}
25
+ */
26
+ export declare const getViewModelValue: (viewModel: ViewModel, prop: string) => unknown;
27
+ /**
28
+ * setViewModelValue
29
+ * @description populate viewModel object by path string
30
+ * @param {object} obj
31
+ * @param {string} prop
32
+ * @param {string} value
33
+ * @return {call} underscore set
34
+ */
35
+ export declare const setViewModelValue: (obj: PlainObject, prop: string, value: unknown) => PlainObject;
36
+ export declare const getViewModelPropValue: (viewModel: ViewModel, bindingCache: BindingCache) => unknown;
37
+ export declare const parseStringToJson: (str: string) => PlainObject;
38
+ /**
39
+ * arrayRemoveMatch
40
+ * @description remove match items in fromArray out of toArray
41
+ * @param {array} toArray
42
+ * @param {array} frommArray
43
+ * @return {boolean}
44
+ */
45
+ export declare const arrayRemoveMatch: (toArray: unknown[], frommArray: unknown[]) => unknown[];
46
+ export declare const getFormData: ($form: HTMLFormElement) => PlainObject;
47
+ /**
48
+ * getFunctionParameterList
49
+ * @description convert parameter string to arrary
50
+ * eg. '("a","b","c")' > ["a","b","c"]
51
+ * @param {string} str
52
+ * @return {array} paramlist
53
+ */
54
+ export declare const getFunctionParameterList: (str: string) => string[] | undefined;
55
+ export declare const extractFilterList: (cacheData: Partial<BindingCache>) => Partial<BindingCache>;
56
+ export declare const invertObj: (sourceObj: PlainObject) => PlainObject;
57
+ export declare const createDeferredObj: () => DeferredObj;
58
+ /**
59
+ * debounce
60
+ * @description decorate a function to be debounce using requestAnimationFrame
61
+ * @param {function} fn
62
+ * @param {context} ctx
63
+ * @return {function}
64
+ */
65
+ export declare const debounceRaf: (fn: Function, ctx?: unknown) => Function;
66
+ /**
67
+ * getNodeAttrObj
68
+ * @description convert Node attributes object to a json object
69
+ * @param {object} node
70
+ * @param {array} skipList
71
+ * @return {object}
72
+ */
73
+ export declare const getNodeAttrObj: (node: HTMLElement, skipList?: string | string[]) => Record<string, string> | undefined;
74
+ /**
75
+ * extend
76
+ * @param {boolean} isDeepMerge
77
+ * @param {object} target
78
+ * @param {object} sources
79
+ * @return {object} merged object
80
+ */
81
+ export declare const extend: (isDeepMerge?: boolean, target?: PlainObject, ...sources: PlainObject[]) => PlainObject;
82
+ export declare const each: (obj: unknown[] | PlainObject, fn: Function) => void;
83
+ /**
84
+ * cloneDomNode
85
+ * @param {object} element
86
+ * @return {object} cloned element
87
+ * @description helper function to clone node
88
+ */
89
+ export declare const cloneDomNode: (element: HTMLElement) => HTMLElement;
90
+ /**
91
+ * insertAfter
92
+ * @param {object} parentNode
93
+ * @param {object} newNode
94
+ * @param {object} referenceNode
95
+ * @return {object} node
96
+ * @description helper function to insert new node before the reference node
97
+ */
98
+ export declare const insertAfter: (parentNode: Node, newNode: Node, referenceNode: Node | null) => Node;
99
+ export declare const resolveViewModelContext: (viewModel: ViewModel, datakey: string) => ViewModel;
100
+ export declare const resolveParamList: (viewModel: ViewModel, paramList: unknown[]) => unknown[] | undefined;
101
+ export declare const removeElement: (el: HTMLElement) => void;
102
+ export declare const emptyElement: (node: HTMLElement) => HTMLElement;
103
+ /**
104
+ * updateDomWithMinimalChanges
105
+ * @description Updates DOM by comparing existing nodes with new fragment
106
+ * Only modifies what changed - performs minimal DOM manipulation
107
+ * @param {HTMLElement} targetElement - The existing DOM element to update
108
+ * @param {DocumentFragment} newFragment - The new content to apply
109
+ */
110
+ export declare const updateDomWithMinimalChanges: (targetElement: HTMLElement, newFragment: DocumentFragment) => void;
111
+ export declare const throwErrorMessage: (err?: unknown, errorMessage?: string) => void;
112
+ /**
113
+ * parseBindingObjectString
114
+ * @description parse bining object string to object with value always stringify
115
+ * @param {string} str - eg '{ id: $data.id, name: $data.name }'
116
+ * @return {object} - eg { id: '$data.id', name: '$data.name'}
117
+ */
118
+ export declare const parseBindingObjectString: (str?: string) => Record<string, string> | null;
119
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import js from '@eslint/js';
2
+ import globals from 'globals';
3
+ import tseslint from 'typescript-eslint';
4
+
5
+ export default [
6
+ // Base recommended configs
7
+ js.configs.recommended,
8
+ ...tseslint.configs.recommended,
9
+
10
+ // JavaScript and TypeScript files - general rules
11
+ {
12
+ files: ['**/*.{js,mjs,cjs,ts}'],
13
+ languageOptions: {
14
+ ecmaVersion: 2022,
15
+ sourceType: 'module',
16
+ globals: {
17
+ ...globals.browser,
18
+ ...globals.node,
19
+ ...globals.es2021,
20
+ // Test globals
21
+ dataBind: 'readonly',
22
+ loadFixture: 'readonly',
23
+ simulateInput: 'readonly',
24
+ simulateClick: 'readonly',
25
+ simulateBlur: 'readonly',
26
+ },
27
+ },
28
+ rules: {
29
+ // Code Style
30
+ 'indent': ['error', 4, {SwitchCase: 1}],
31
+ 'linebreak-style': 'off',
32
+ 'quotes': ['error', 'single', {avoidEscape: true, allowTemplateLiterals: true}],
33
+ 'semi': ['error', 'always'],
34
+ 'comma-dangle': ['error', 'always-multiline'],
35
+ 'comma-spacing': ['error', {before: false, after: true}],
36
+ 'key-spacing': ['error', {beforeColon: false, afterColon: true}],
37
+ 'object-curly-spacing': ['error', 'never'],
38
+ 'array-bracket-spacing': ['error', 'never'],
39
+ 'space-before-function-paren': ['error', {
40
+ anonymous: 'always',
41
+ named: 'never',
42
+ asyncArrow: 'always',
43
+ }],
44
+ 'space-in-parens': ['error', 'never'],
45
+ 'space-before-blocks': ['error', 'always'],
46
+ 'keyword-spacing': ['error', {before: true, after: true}],
47
+ 'arrow-spacing': ['error', {before: true, after: true}],
48
+ 'no-multiple-empty-lines': ['error', {max: 2, maxEOF: 1}],
49
+ 'no-trailing-spaces': 'error',
50
+ 'eol-last': ['error', 'always'],
51
+
52
+ // Max Length
53
+ 'max-len': ['error', {
54
+ code: 150,
55
+ tabWidth: 4,
56
+ ignoreUrls: true,
57
+ ignoreStrings: true,
58
+ ignoreTemplateLiterals: true,
59
+ ignoreRegExpLiterals: true,
60
+ ignorePattern: 'data:image/|\\s*require\\s*\\(|^\\s*loader\\.lazy|-\\*-|^import\\s',
61
+ }],
62
+
63
+ // Best Practices
64
+ 'no-var': 'error',
65
+ 'prefer-const': 'error',
66
+ 'prefer-arrow-callback': 'warn',
67
+ 'prefer-template': 'warn',
68
+ 'object-shorthand': ['warn', 'always'],
69
+ 'no-useless-escape': 'off',
70
+ 'no-prototype-builtins': 'off',
71
+ 'prefer-rest-params': 'off',
72
+
73
+ // Variables
74
+ 'no-unused-vars': 'off', // Use TypeScript version instead
75
+
76
+ // TypeScript Rules
77
+ '@typescript-eslint/no-unused-vars': ['error', {
78
+ argsIgnorePattern: '^_',
79
+ varsIgnorePattern: '^_',
80
+ caughtErrorsIgnorePattern: '^_',
81
+ }],
82
+ '@typescript-eslint/no-explicit-any': 'warn',
83
+ '@typescript-eslint/no-this-alias': 'off',
84
+ '@typescript-eslint/no-unsafe-function-type': 'off',
85
+ '@typescript-eslint/explicit-function-return-type': 'off',
86
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
87
+ '@typescript-eslint/no-non-null-assertion': 'warn',
88
+
89
+ // Security
90
+ 'no-eval': 'error',
91
+ 'no-implied-eval': 'error',
92
+ 'no-new-func': 'error',
93
+ 'no-script-url': 'error',
94
+ },
95
+ },
96
+
97
+ // Test files - more relaxed rules
98
+ {
99
+ files: ['test/**/*.{js,ts}', '**/*.spec.{js,ts}', '**/*.test.{js,ts}'],
100
+ rules: {
101
+ '@typescript-eslint/no-explicit-any': 'off',
102
+ '@typescript-eslint/no-unused-vars': 'off',
103
+ '@typescript-eslint/no-non-null-assertion': 'off',
104
+ 'max-len': ['error', {
105
+ code: 200, // Allow longer lines in tests
106
+ ignoreStrings: true,
107
+ ignoreTemplateLiterals: true,
108
+ }],
109
+ },
110
+ },
111
+
112
+ // Ignore patterns
113
+ {
114
+ ignores: [
115
+ 'node_modules',
116
+ 'dist',
117
+ 'coverage',
118
+ 'vendors',
119
+ '.grunt',
120
+ '*.min.js',
121
+ '*.bundle.js',
122
+ ],
123
+ },
124
+ ];
@@ -0,0 +1,123 @@
1
+ # DBMonster Performance Comparison
2
+
3
+ This directory contains two versions of the dbmonster benchmark to compare performance between manual and reactive rendering modes.
4
+
5
+ ## Files
6
+
7
+ ### Manual Mode
8
+ - **HTML**: `dbmonsterForOf.html`
9
+ - **JS**: `js/dbMonApp.js`
10
+ - **Mode**: `{reactive: false}` (manual mode)
11
+
12
+ ### Reactive Mode
13
+ - **HTML**: `dbmonsterForOfReactive.html`
14
+ - **JS**: `js/dbMonAppReactive.js`
15
+ - **Mode**: Default (reactive mode enabled)
16
+
17
+ ## Key Differences
18
+
19
+ ### Manual Mode (`dbMonApp.js`)
20
+
21
+ ```javascript
22
+ // Manual mode - explicit control
23
+ const dbMonApp = dataBind.init(document.getElementById('app'), viewModel, {reactive: false});
24
+
25
+ function refreshApp() {
26
+ // Update original viewModel
27
+ viewModel.databases = performanceEnv.generateData().toArray();
28
+
29
+ // Manual render with selective template binding
30
+ dbMonApp.render({templateBinding: shouldUpdateTemplate});
31
+
32
+ // Manual tracking of template binding updates
33
+ oldDbLength = newDbLength;
34
+ }
35
+ ```
36
+
37
+ **Characteristics:**
38
+ - ✅ Full control over when renders happen
39
+ - ✅ Can selectively update template bindings (only when database count changes)
40
+ - ✅ Lower overhead (no Proxy wrapper)
41
+ - ❌ More code to write and maintain
42
+
43
+ ### Reactive Mode (`dbMonAppReactive.js`)
44
+
45
+ ```javascript
46
+ // Reactive mode - automatic updates
47
+ const dbMonApp = dataBind.init(document.getElementById('app'), viewModel);
48
+
49
+ function refreshApp() {
50
+ // Update via component.viewModel to trigger automatic render
51
+ dbMonApp.viewModel.databases = performanceEnv.generateData().toArray();
52
+
53
+ // No render() call needed - automatic!
54
+ // Template bindings always update
55
+ }
56
+ ```
57
+
58
+ **Characteristics:**
59
+ - ✅ Less code - automatic rendering
60
+ - ✅ Modern reactive pattern (like Vue 3, MobX)
61
+ - ✅ No manual render() calls needed
62
+ - ⚠️ Slight Proxy overhead
63
+ - ⚠️ Always updates template bindings (can't selectively skip)
64
+
65
+ ## Performance Testing
66
+
67
+ ### How to Test
68
+
69
+ 1. Open both HTML files in separate browser tabs
70
+ 2. Watch the performance metrics displayed by the monitoring scripts
71
+ 3. Compare:
72
+ - **Render Rate** (renders/second)
73
+ - **Memory Usage**
74
+ - **Paint Time**
75
+
76
+ ### Expected Results
77
+
78
+ **Manual Mode:**
79
+ - May have slightly better raw performance due to no Proxy overhead
80
+ - Can optimize by skipping template binding updates when database count unchanged
81
+ - More predictable render timing
82
+
83
+ **Reactive Mode:**
84
+ - Slightly more overhead from Proxy wrapper (~1-5%)
85
+ - Always updates template bindings (may be slower if database count doesn't change)
86
+ - Automatic batching via RAF debouncing
87
+
88
+ ### When to Use Each Mode
89
+
90
+ **Use Manual Mode When:**
91
+ - Maximum performance is critical (high-frequency updates)
92
+ - You need fine-grained control over rendering
93
+ - Working with very large objects (>10000 properties)
94
+ - Building performance benchmarks
95
+
96
+ **Use Reactive Mode When:**
97
+ - Building typical web applications
98
+ - Developer experience and code maintainability are priorities
99
+ - Moderate update frequencies
100
+ - You want automatic, predictable rendering
101
+
102
+ ## Technical Details
103
+
104
+ ### RAF Debouncing
105
+
106
+ Both modes use `requestAnimationFrame` debouncing:
107
+ - Multiple changes within a single frame are batched into one render
108
+ - This ensures optimal performance in both modes
109
+
110
+ ### Proxy Overhead
111
+
112
+ Reactive mode uses JavaScript Proxy to intercept property changes:
113
+ - Modern browsers have highly optimized Proxy implementations
114
+ - Overhead is typically negligible for most applications
115
+ - Only noticeable with extremely high-frequency updates (like dbmonster)
116
+
117
+ ## Conclusion
118
+
119
+ The dbmonster benchmark is an extreme stress test with continuous high-frequency updates. In real-world applications, the performance difference between manual and reactive modes is typically negligible, while reactive mode provides significantly better developer experience.
120
+
121
+ Choose based on your use case:
122
+ - **Performance benchmarks / extreme cases**: Manual mode
123
+ - **Real-world applications**: Reactive mode
@@ -0,0 +1,119 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>afterRender() Demo | dataBind.js</title>
7
+ <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" />
8
+ <style>
9
+ body { padding: 20px; }
10
+ .demo-section { margin: 20px 0; padding: 20px; border: 1px solid #ddd; border-radius: 5px; }
11
+ .log {
12
+ background: #f8f9fa;
13
+ padding: 10px;
14
+ margin-top: 10px;
15
+ max-height: 200px;
16
+ overflow-y: auto;
17
+ font-family: monospace;
18
+ font-size: 12px;
19
+ }
20
+ .log-entry { margin: 2px 0; }
21
+ .highlight { background-color: #fff3cd; }
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <div class="container">
26
+ <h1>afterRender() Demo</h1>
27
+ <p class="lead">
28
+ The <code>afterRender(callback)</code> method registers callbacks that run after each render completes.
29
+ Perfect for reactive mode!
30
+ </p>
31
+
32
+ <!-- Example 1: Basic Usage -->
33
+ <div class="demo-section">
34
+ <h3>Example 1: Basic Usage</h3>
35
+ <p>afterRender callback fires after every reactive update</p>
36
+
37
+ <div data-bind-comp="basic-demo">
38
+ <p>Counter: <span data-bind-text="counter"></span></p>
39
+ <button class="btn btn-primary" data-bind-click="increment">Increment</button>
40
+ <button class="btn btn-secondary" data-bind-click="reset">Reset</button>
41
+ </div>
42
+
43
+ <div class="log" id="basic-log"></div>
44
+ </div>
45
+
46
+ <!-- Example 2: Performance Monitoring -->
47
+ <div class="demo-section">
48
+ <h3>Example 2: Performance Monitoring</h3>
49
+ <p>Use afterRender to track render performance</p>
50
+
51
+ <div data-bind-comp="perf-demo">
52
+ <p>Items: <span data-bind-text="items.length"></span></p>
53
+ <button class="btn btn-primary" data-bind-click="addItems">Add 10 Items</button>
54
+ <button class="btn btn-danger" data-bind-click="clearItems">Clear All</button>
55
+
56
+ <ul>
57
+ <li data-bind-for="item of items" data-bind-text="item.text"></li>
58
+ </ul>
59
+ </div>
60
+
61
+ <div class="log" id="perf-log"></div>
62
+ </div>
63
+
64
+ <!-- Example 3: DOM Manipulation -->
65
+ <div class="demo-section">
66
+ <h3>Example 3: Post-Render DOM Manipulation</h3>
67
+ <p>Use afterRender to manipulate DOM after updates</p>
68
+
69
+ <div data-bind-comp="dom-demo">
70
+ <div>
71
+ <p>Active: <span data-bind-text="activeCount"></span> / <span data-bind-text="items.length"></span></p>
72
+ <button class="btn btn-success" data-bind-click="addItem">Add Item</button>
73
+ <button class="btn btn-warning" data-bind-click="toggleFirst">Toggle First</button>
74
+ </div>
75
+
76
+ <ul id="dom-list">
77
+ <li data-bind-for="item of items" data-bind-css="item.active ? 'highlight' : ''">
78
+ <span data-bind-text="item.text"></span>
79
+ <span data-bind-if="item.active"> (Active)</span>
80
+ </li>
81
+ </ul>
82
+ </div>
83
+
84
+ <div class="log" id="dom-log"></div>
85
+ </div>
86
+
87
+ <!-- Example 4: Remove Callback -->
88
+ <div class="demo-section">
89
+ <h3>Example 4: Add/Remove Callbacks</h3>
90
+ <p>Dynamically add and remove afterRender callbacks</p>
91
+
92
+ <div data-bind-comp="toggle-demo">
93
+ <p>Value: <span data-bind-text="value"></span></p>
94
+ <button class="btn btn-primary" data-bind-click="increment">Change Value</button>
95
+ <button class="btn btn-success" id="addCallback">Add Logger</button>
96
+ <button class="btn btn-danger" id="removeCallback">Remove Logger</button>
97
+ <button class="btn btn-warning" id="clearCallbacks">Clear All</button>
98
+ </div>
99
+
100
+ <div class="log" id="toggle-log"></div>
101
+ </div>
102
+
103
+ <div class="alert alert-info mt-4">
104
+ <h5>Key Features:</h5>
105
+ <ul>
106
+ <li>✅ <code>component.afterRender(callback)</code> - Register callback</li>
107
+ <li>✅ <code>component.removeAfterRender(callback)</code> - Remove specific callback</li>
108
+ <li>✅ <code>component.clearAfterRender()</code> - Remove all callbacks</li>
109
+ <li>✅ Callbacks fire after every render (automatic with reactive mode)</li>
110
+ <li>✅ Multiple callbacks supported</li>
111
+ <li>✅ Chainable API</li>
112
+ </ul>
113
+ </div>
114
+ </div>
115
+
116
+ <script src="../dist/js/dataBind.min.js"></script>
117
+ <script src="js/afterRenderDemo.js"></script>
118
+ </body>
119
+ </html>