@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
@@ -1,26 +1,24 @@
1
- const viewModel = {
2
- databases: ENV.generateData().toArray(),
3
- };
4
- let oldDbLength = viewModel.databases.length;
5
- let newDbLength = 0;
6
-
7
- function refreshApp() {
8
- let shouldUpdateTemplate = true;
9
-
10
- viewModel.databases = ENV.generateData().toArray();
11
- newDbLength = viewModel.databases.length;
12
- shouldUpdateTemplate = oldDbLength !== newDbLength;
13
- // only re-render template binding if database size different
14
- dbMonApp.render({templateBinding: shouldUpdateTemplate});
15
- oldDbLength = newDbLength;
16
-
17
- Monitoring.renderRate.ping();
18
- setTimeout(refreshApp, ENV.timeout);
19
- }
20
-
21
-
22
- const dbMonApp = dataBind.init(document.getElementById('app'), viewModel);
23
- dbMonApp.render().then(function() {
24
- console.log('dbMonApp inited');
25
- refreshApp();
26
- });
1
+ const performanceEnv = window.ENV;
2
+ const performanceMonitoring = window.Monitoring;
3
+
4
+ const viewModel = {
5
+ databases: performanceEnv.generateData().toArray(),
6
+ };
7
+
8
+ // Manual mode for performance benchmark
9
+ const dbMonApp = dataBind.init(document.getElementById('app'), viewModel, {reactive: false});
10
+
11
+ function refreshApp() {
12
+ viewModel.databases = performanceEnv.generateData().toArray();
13
+ dbMonApp.render();
14
+
15
+ performanceMonitoring.renderRate.ping();
16
+ setTimeout(refreshApp, performanceEnv.timeout);
17
+ }
18
+
19
+ // render().then() works with both reactive and manual modes
20
+ // The callback runs after the initial render completes
21
+ dbMonApp.render().then(() => {
22
+ console.log('dbMonApp (Manual) inited');
23
+ refreshApp();
24
+ });
@@ -0,0 +1,79 @@
1
+ const { useState, useEffect, useRef } = React;
2
+
3
+ // Query component
4
+ function Query({ query }) {
5
+ return (
6
+ <td className={query.elapsedClassName}>
7
+ <span>{query.formatElapsed}</span>
8
+ <div className="popover left">
9
+ <div className="popover-content">{query.query}</div>
10
+ <div className="arrow"></div>
11
+ </div>
12
+ </td>
13
+ );
14
+ }
15
+
16
+ // Database row component
17
+ function Database({ database }) {
18
+ return (
19
+ <tr>
20
+ <td className="dbname">{database.dbname}</td>
21
+ <td className="query-count">
22
+ <span className={database.lastSample.countClassName}>
23
+ {database.lastSample.nbQueries}
24
+ </span>
25
+ </td>
26
+ {database.lastSample.topFiveQueries.map((query, index) => (
27
+ <Query key={index} query={query} />
28
+ ))}
29
+ </tr>
30
+ );
31
+ }
32
+
33
+ // Main app component
34
+ function App() {
35
+ const [databases, setDatabases] = useState([]);
36
+ const performanceEnv = useRef(window.ENV);
37
+ const performanceMonitoring = useRef(window.Monitoring);
38
+ const timeoutId = useRef(null);
39
+
40
+ const refreshApp = () => {
41
+ const newData = performanceEnv.current.generateData().toArray();
42
+ setDatabases(newData);
43
+
44
+ performanceMonitoring.current.renderRate.ping();
45
+ timeoutId.current = setTimeout(refreshApp, performanceEnv.current.timeout);
46
+ };
47
+
48
+ useEffect(() => {
49
+ // Initial render
50
+ const initialData = performanceEnv.current.generateData().toArray();
51
+ setDatabases(initialData);
52
+
53
+ console.log('dbMonApp (React) initialized');
54
+
55
+ // Start the refresh loop
56
+ timeoutId.current = setTimeout(refreshApp, performanceEnv.current.timeout);
57
+
58
+ // Cleanup on unmount
59
+ return () => {
60
+ if (timeoutId.current) {
61
+ clearTimeout(timeoutId.current);
62
+ }
63
+ };
64
+ }, []);
65
+
66
+ return (
67
+ <table className="table table-striped latest-data">
68
+ <tbody>
69
+ {databases.map((database, index) => (
70
+ <Database key={index} database={database} />
71
+ ))}
72
+ </tbody>
73
+ </table>
74
+ );
75
+ }
76
+
77
+ // Render the app
78
+ const root = ReactDOM.createRoot(document.getElementById('app'));
79
+ root.render(<App />);
@@ -0,0 +1,28 @@
1
+ const performanceEnv = window.ENV;
2
+ const performanceMonitoring = window.Monitoring;
3
+
4
+ const viewModel = {
5
+ databases: performanceEnv.generateData().toArray(),
6
+ };
7
+
8
+ // Reactive mode is enabled by default (no need to specify {reactive: true})
9
+ // This demo uses automatic reactive rendering for all updates
10
+ const dbMonApp = dataBind.init(document.getElementById('app'), viewModel);
11
+
12
+ function refreshApp() {
13
+ // Update via component.viewModel to trigger reactive updates
14
+ dbMonApp.viewModel.databases = performanceEnv.generateData().toArray();
15
+
16
+ // In reactive mode, render is triggered automatically
17
+ // No need to call render() manually!
18
+
19
+ performanceMonitoring.renderRate.ping();
20
+ setTimeout(refreshApp, performanceEnv.timeout);
21
+ }
22
+
23
+ // render().then() works with both reactive and manual modes
24
+ // The callback runs after the initial render completes
25
+ dbMonApp.render().then(() => {
26
+ console.log('dbMonApp (Reactive) inited');
27
+ refreshApp();
28
+ });
@@ -5,11 +5,11 @@ const fiberViewModel = {
5
5
  dots: [],
6
6
  dotCss: 'dot',
7
7
  onHoverDot: {
8
- in: function(e, $el, index) {
8
+ in(e, $el, index) {
9
9
  $el.style.background = '#ff0';
10
10
  this.dots[index].isMouseOver = true;
11
11
  },
12
- out: function(e, $el, index) {
12
+ out(e, $el, index) {
13
13
  $el.style.background = '#61dafb';
14
14
  this.dots[index].isMouseOver = false;
15
15
  },
@@ -53,7 +53,7 @@ function createDot(x, y) {
53
53
 
54
54
  function recursiveUpdateDotsData(viewModel) {
55
55
  const remainder = getElapsedSecond() % 10;
56
- const text = Math.floor(remainder) + '';
56
+ const text = `${Math.floor(remainder) }`;
57
57
  const scaleXFactor = (1 + (5 - Math.abs(5 - remainder)) / 10) / 2.1;
58
58
 
59
59
  // update viewModel data
@@ -79,7 +79,7 @@ fiberViewModel.dots = createDotList();
79
79
  // start binding on DOM ready
80
80
  // formComponentC - test for-of binding
81
81
  const fiberComponent = dataBind.init(document.querySelector('[data-bind-comp="fiberDemoComponent"]'), fiberViewModel);
82
- fiberComponent.render().then(function() {
82
+ fiberComponent.render().then(() => {
83
83
  // for debug
84
84
  console.log(fiberComponent);
85
85
  window.fiberComponent = fiberComponent;
@@ -1,4 +1,4 @@
1
- /* eslint-disable max-len */
1
+
2
2
  (() => {
3
3
  const filterComponentViewModel = {
4
4
  renderIntro: true,
@@ -12,7 +12,7 @@
12
12
  description:
13
13
  '"Hansel and Gretel" (also known as Hansel and Grettel, Hansel and Grethel, or Little Brother and Little Sister) is a well-known fairy tale of German origin, recorded by the Brothers Grimm and published in 1812. Hansel and Gretel are a young brother and sister kidnapped by a cannibalistic witch living deep in the forest in a house constructed of cake and confectionery. The two children escape with their lives by outwitting her. The tale has been adapted to various media, most notably the opera Hänsel und Gretel (1893) by Engelbert Humperdinck. Under the Aarne–Thompson classification system, "Hansel and Gretel" is classified under Class 327.',
14
14
  },
15
- setStoryImgAttr: function() {
15
+ setStoryImgAttr() {
16
16
  const picPath = this.story.pic || '';
17
17
  const ret = {
18
18
  alt: this.story.title,
@@ -25,20 +25,20 @@
25
25
  }
26
26
  return ret;
27
27
  },
28
- addPic: function(e, $el) {
28
+ addPic(e) {
29
29
  e.preventDefault();
30
30
  this.story.pic = storyPic;
31
31
  this.updateView();
32
32
  },
33
- removePic: function(e, $el) {
33
+ removePic(e) {
34
34
  e.preventDefault();
35
35
  this.story.pic = '';
36
36
  this.updateView();
37
37
  },
38
- toUpper: function(strg) {
38
+ toUpper(strg) {
39
39
  return strg.toUpperCase();
40
40
  },
41
- toDateFormat: function(dateString) {
41
+ toDateFormat(dateString) {
42
42
  const date = new Date(dateString);
43
43
  const monthNames = [
44
44
  'January',
@@ -71,8 +71,8 @@
71
71
  // start binding on DOM ready
72
72
 
73
73
  // main
74
- filterComponent = dataBind.init(document.querySelector('[data-bind-comp="filterComponent"]'), filterComponentViewModel);
75
- filterComponent.render().then(function() {
74
+ const filterComponent = dataBind.init(document.querySelector('[data-bind-comp="filterComponent"]'), filterComponentViewModel);
75
+ filterComponent.render().then(() => {
76
76
  // for debug
77
77
  console.log(filterComponent);
78
78
  window.filterComponent = filterComponent;
@@ -1,4 +1,4 @@
1
- (function() {
1
+ (function () {
2
2
  // viewModel as Class for create multiple instance
3
3
  class FormComponentVewModel {
4
4
  constructor() {
@@ -51,7 +51,7 @@
51
51
  onInputChange(e, $el, newValue, oldValue, index) {
52
52
  console.log('onInputChange: ', this);
53
53
  this.personalDetails[index].show = false;
54
- this.updateView();
54
+ // Reactive mode - automatic render!
55
55
  }
56
56
 
57
57
  addRows(e) {
@@ -72,29 +72,27 @@
72
72
  updatedCss: 'updated',
73
73
  },
74
74
  );
75
- this.updateView();
75
+ // Reactive mode - automatic render!
76
76
  }
77
77
  removeRows(e) {
78
78
  e.preventDefault();
79
79
  this.personalDetails.splice(this.personalDetails.length - 2, 2);
80
- this.updateView();
80
+ // Reactive mode - automatic render!
81
81
  }
82
82
  afterTemplateRender() {
83
83
  console.log('template rendered');
84
84
  }
85
- updateView(opt) {
86
- this.APP.render(opt);
87
- }
88
85
  }
89
86
 
90
87
  // formComponentC viewModel
91
- forOfComponentViewModel = new FormComponentVewModel();
88
+ const forOfComponentViewModel = new FormComponentVewModel();
92
89
 
93
90
  // start binding on DOM ready
94
91
 
95
92
  // formComponentC - test for-of binding
93
+ // Reactive mode is now the default!
96
94
  const forOfComponent = dataBind.init(document.querySelector('[data-bind-comp="forOfComponent"]'), forOfComponentViewModel);
97
- forOfComponent.render().then(function() {
95
+ forOfComponent.render().then(() => {
98
96
  // for debug
99
97
  window.forOfComponent = forOfComponent;
100
98
  });
@@ -1,4 +1,4 @@
1
- /* eslint-disable max-len */
1
+
2
2
  // search-results-component
3
3
  (() => {
4
4
  const viewModel = {
@@ -81,7 +81,7 @@
81
81
  options: [{text: '1', value: '1'}, {text: '2', value: '2'}, {text: '3', value: '3'}],
82
82
  },
83
83
  ],
84
- getResultItemAttr: function(index, oldAttrObj, $el) {
84
+ getResultItemAttr(index, oldAttrObj, $el) {
85
85
  const self = this;
86
86
  if (self.searchResults[index].image) {
87
87
  return {
@@ -90,7 +90,7 @@
90
90
  };
91
91
  }
92
92
  },
93
- setResultOptionAttr: function($data, oldAttrObj, $el) {
93
+ setResultOptionAttr($data, oldAttrObj, $el) {
94
94
  if ($data && $data.value) {
95
95
  // todo: the index here is the outter loop index
96
96
  return {
@@ -98,21 +98,24 @@
98
98
  };
99
99
  }
100
100
  },
101
- onAdMessageCheck: function(e, $el, newValue, oldValue, index) {
101
+ onAdMessageCheck(e, $el, newValue, oldValue, index) {
102
102
  console.log('onAdMessageCheck: ', $el, newValue, oldValue, index);
103
103
  },
104
- onAdBookmarkClick: function(e, $el, index) {
104
+ onAdBookmarkClick(e, $el, index) {
105
105
  e.preventDefault();
106
106
  console.log('onAdBookmarkClick: ', $el, index);
107
107
  },
108
108
  };
109
109
 
110
+ // Default mutations count, controlled by slider
111
+ let mutationsCount = 50;
112
+
110
113
  const generateRamdomData = () => {
111
114
  const data = [];
112
115
  const getRandomNumber = (x, y) => {
113
116
  return Math.floor(Math.random() * (y - x + 1) + x);
114
117
  };
115
- const randomSeed = getRandomNumber(1, 30);
118
+ const randomSeed = mutationsCount;
116
119
  const images = [
117
120
  'bootstrap/images/pic-home.jpg',
118
121
  'bootstrap/images/pic-carpenter.jpg',
@@ -132,7 +135,7 @@
132
135
  for (let i = 0; i < randomSeed; i += 1) {
133
136
  data.push({
134
137
  id: i,
135
- title: 'Sample gardening service' + i,
138
+ title: `Sample gardening service${ i}`,
136
139
  description: descriptions[getRandomNumber(0, descriptions.length - 1)],
137
140
  image: images[getRandomNumber(0, images.length - 1)],
138
141
  bookmarked: false,
@@ -145,34 +148,58 @@
145
148
  };
146
149
 
147
150
  const updateResults = () => {
148
- window.updateInterval = setInterval(function() {
149
- viewModel.searchResults = generateRamdomData();
150
- searchResultsComponent.render();
151
+ window.updateInterval = setInterval(() => {
152
+ // Important: Use searchResultsComponent.viewModel (proxied version) for reactive updates
153
+ searchResultsComponent.viewModel.searchResults = generateRamdomData();
154
+ // Automatic render happens via reactive proxy!
155
+
156
+ // Note: In reactive mode, render is called automatically.
157
+ // For monitoring, we manually trigger render().then() to get the promise callback
158
+ // This is safe because render() is debounced - it won't cause double rendering
159
+ if (typeof Monitoring !== 'undefined') {
160
+ searchResultsComponent.render().then(() => {
161
+ Monitoring.renderRate.ping();
162
+ });
163
+ }
151
164
  });
152
165
  };
153
166
 
154
167
  // start binding on DOM ready
155
168
 
156
- // debug
157
- const searchResultsComponent = dataBind.init(document.querySelector('[data-bind-comp="search-results-component"]'), viewModel);
169
+ // debug - Reactive mode is now the default!
170
+ const searchResultsComponent = dataBind.init(
171
+ document.querySelector('[data-bind-comp="search-results-component"]'),
172
+ viewModel
173
+ );
158
174
 
159
- searchResultsComponent.render().then(function() {
175
+ searchResultsComponent.render().then(() => {
160
176
  // for debug
161
177
  console.log(searchResultsComponent);
162
178
  window.searchResultsComponent = searchResultsComponent;
163
179
 
164
- btnRandomRender = document.getElementById('btnRandomRender');
165
- btnStopRandomRender = document.getElementById('btnStopRandomRender');
180
+ const btnRandomRender = document.getElementById('btnRandomRender');
181
+ const btnStopRandomRender = document.getElementById('btnStopRandomRender');
166
182
 
167
- btnRandomRender.addEventListener('click', function(e) {
183
+ btnRandomRender.addEventListener('click', (e) => {
168
184
  e.preventDefault();
169
185
  clearInterval(window.updateInterval);
170
186
  updateResults();
171
187
  }, false);
172
188
 
173
- btnStopRandomRender.addEventListener('click', function(e) {
189
+ btnStopRandomRender.addEventListener('click', (e) => {
174
190
  e.preventDefault();
175
191
  clearInterval(window.updateInterval);
176
192
  }, false);
193
+
194
+ // Connect mutations slider to control item count
195
+ const mutationsSlider = document.getElementById('mutations');
196
+ const mutationsValueSpan = document.getElementById('mutationsValue');
197
+
198
+ if (mutationsSlider && mutationsValueSpan) {
199
+ mutationsSlider.addEventListener('input', (e) => {
200
+ mutationsCount = parseInt(e.target.value, 10);
201
+ mutationsValueSpan.textContent = mutationsCount;
202
+ });
203
+ }
177
204
  });
178
205
  })();
@@ -1,4 +1,4 @@
1
- (() =>{
1
+ (() => {
2
2
  const formAppViewModel = {
3
3
  intro: {
4
4
  title: 'Form generator demo',
@@ -10,11 +10,7 @@
10
10
  And finally a quick test of attribute binding 😎`,
11
11
  btnText: 'Fake button »',
12
12
  },
13
- attrTest: {
14
- class: 'show',
15
- name: 'abc',
16
- },
17
- onBtnClick: function(e, $el) {
13
+ onBtnClick(e, $el) {
18
14
  e.preventDefault();
19
15
  console.log('onBtnClick: ', $el);
20
16
  },
@@ -43,13 +39,13 @@
43
39
  onInputChange(e, $el, newValue, oldValue) {
44
40
  console.log('onInputChange: ', this);
45
41
  this.personalDetails[0].show = false;
46
- this.updateView();
42
+ // Reactive mode - automatic render!
47
43
  }
48
44
  afterTemplateRender() {
49
45
  console.log('template rendered');
50
46
  }
51
- updateView(opt) {
52
- this.APP.render(opt);
47
+ updateView(opt) { // Note: render is automatic in reactive mode
48
+ // Reactive mode - automatic render!
53
49
  }
54
50
  getInputAttr(index) {
55
51
  const personalDetail = this.personalDetails[index];
@@ -62,6 +58,7 @@
62
58
 
63
59
  // use new instance of FormComponentVewModel and overwrite personalDetails
64
60
  const formComponentBViewModel = new FormComponentVewModel();
61
+
65
62
  formComponentBViewModel.personalDetails = [
66
63
  {
67
64
  show: true,
@@ -79,11 +76,37 @@
79
76
  },
80
77
  ];
81
78
 
79
+
80
+ // componentRangeInput
81
+ const componentRangeInputViewModel = {
82
+ range: {
83
+ value: 50,
84
+ },
85
+ getRangeAttr() {
86
+ return {
87
+ type: 'range',
88
+ name: 'test-range',
89
+ id: 'test-range',
90
+ min: 0,
91
+ max: 100,
92
+ step: 1,
93
+ };
94
+ },
95
+ onInputChange(e, $el, newValue, oldValue) {
96
+ e.preventDefault();
97
+ this.range.value = newValue;
98
+ // Reactive mode - automatic render!
99
+ },
100
+ updateView(opt) { // Note: render is automatic in reactive mode
101
+ // Reactive mode - automatic render!
102
+ },
103
+ };
104
+
82
105
  // start binding on DOM ready
83
106
 
84
107
  // main formApp
85
108
  const formApp = dataBind.init(document.querySelector('[data-bind-comp="formApp"]'), formAppViewModel);
86
- formApp.render().then(function() {
109
+ formApp.render().then(() => {
87
110
  // for debug
88
111
  console.log(formApp);
89
112
  window.formApp = formApp;
@@ -92,7 +115,7 @@
92
115
  // formComponentA
93
116
  const formComponentA = dataBind.init(document.querySelector('[data-bind-comp="formComponentA"]'), new FormComponentVewModel());
94
117
 
95
- formComponentA.render().then(function() {
118
+ formComponentA.render().then(() => {
96
119
  // for debug
97
120
  console.log(formComponentA);
98
121
  window.formComponentA = formComponentA;
@@ -101,9 +124,18 @@
101
124
  // formComponentB
102
125
  const formComponentB = dataBind.init(document.querySelector('[data-bind-comp="formComponentB"]'), formComponentBViewModel);
103
126
 
104
- formComponentB.render().then(function() {
127
+ formComponentB.render().then(() => {
105
128
  // for debug
106
129
  console.log(formComponentB);
107
130
  window.formComponentB = formComponentB;
108
131
  });
132
+
133
+ // componentRangeInput
134
+ const componentRangeInput = dataBind.init(document.querySelector('[data-bind-comp="componentRangeInput"]'), componentRangeInputViewModel);
135
+
136
+ componentRangeInput.render().then(() => {
137
+ // for debug
138
+ console.log(componentRangeInput);
139
+ window.componentRangeInput = componentRangeInput;
140
+ });
109
141
  })();
@@ -0,0 +1,117 @@
1
+ (function () {
2
+ console.log('=== Global Configuration Demo ===');
3
+
4
+ // Example 1: Default configuration (reactive: true is built-in default)
5
+ console.log('\n1. Creating component with default config (reactive: true)');
6
+ const defaultExample = dataBind.init(
7
+ document.querySelector('[data-bind-comp="default-example"]'),
8
+ {
9
+ counter: 0,
10
+ increment() {
11
+ this.counter++;
12
+ // Reactive mode - automatic render!
13
+ },
14
+ reset() {
15
+ this.counter = 0;
16
+ // Reactive mode - automatic render!
17
+ },
18
+ },
19
+ );
20
+
21
+ defaultExample.render().then(() => {
22
+ console.log('Example 1 initialized - Mode:', defaultExample.isReactive ? 'REACTIVE' : 'MANUAL');
23
+ document.getElementById('mode1').textContent = defaultExample.isReactive ? 'REACTIVE ✅' : 'MANUAL';
24
+ });
25
+
26
+ // Change global configuration to manual mode
27
+ console.log('\n2. Calling dataBind.use({ reactive: false })');
28
+ dataBind.use({
29
+ reactive: false,
30
+ });
31
+ console.log('Global default is now: reactive = false');
32
+
33
+ // Example 2: Component created after use() call - uses manual mode
34
+ console.log('\n3. Creating component after use() call (should use manual mode)');
35
+ const globalManualExample = dataBind.init(
36
+ document.querySelector('[data-bind-comp="global-manual"]'),
37
+ {
38
+ counter: 0,
39
+ increment() {
40
+ this.counter++;
41
+ // Manual mode - need to call render()
42
+ globalManualExample.render();
43
+ },
44
+ reset() {
45
+ this.counter = 0;
46
+ // Manual mode - need to call render()
47
+ globalManualExample.render();
48
+ },
49
+ },
50
+ );
51
+
52
+ globalManualExample.render().then(() => {
53
+ console.log('Example 2 initialized - Mode:', globalManualExample.isReactive ? 'REACTIVE' : 'MANUAL');
54
+ document.getElementById('mode2').textContent = globalManualExample.isReactive ? 'REACTIVE' : 'MANUAL ✅';
55
+ });
56
+
57
+ // Example 3: Chainable API
58
+ console.log('\n4. Creating component with chainable API: dataBind.use({reactive: false}).init(...)');
59
+ const chainableExample = dataBind.use({reactive: false}).init(
60
+ document.querySelector('[data-bind-comp="chainable"]'),
61
+ {
62
+ counter: 0,
63
+ increment() {
64
+ this.counter++;
65
+ // Manual mode - need to call render()
66
+ chainableExample.render();
67
+ },
68
+ reset() {
69
+ this.counter = 0;
70
+ // Manual mode - need to call render()
71
+ chainableExample.render();
72
+ },
73
+ },
74
+ );
75
+
76
+ chainableExample.render().then(() => {
77
+ console.log('Example 3 initialized - Mode:', chainableExample.isReactive ? 'REACTIVE' : 'MANUAL');
78
+ document.getElementById('mode3').textContent = chainableExample.isReactive ? 'REACTIVE' : 'MANUAL ✅ (chained)';
79
+ });
80
+
81
+ // Example 4: Override global setting with instance option
82
+ console.log('\n5. Creating component with instance override { reactive: true }');
83
+ const instanceOverride = dataBind.init(
84
+ document.querySelector('[data-bind-comp="instance-override"]'),
85
+ {
86
+ counter: 0,
87
+ increment() {
88
+ this.counter++;
89
+ // Reactive mode - automatic render! (overridden)
90
+ },
91
+ reset() {
92
+ this.counter = 0;
93
+ // Reactive mode - automatic render! (overridden)
94
+ },
95
+ },
96
+ {reactive: true}, // Instance override
97
+ );
98
+
99
+ instanceOverride.render().then(() => {
100
+ console.log('Example 4 initialized - Mode:', instanceOverride.isReactive ? 'REACTIVE' : 'MANUAL');
101
+ document.getElementById('mode4').textContent = instanceOverride.isReactive ? 'REACTIVE ✅ (overridden)' : 'MANUAL';
102
+ });
103
+
104
+ console.log('\n=== Summary ===');
105
+ console.log('Example 1: Created before use() call → REACTIVE (built-in default)');
106
+ console.log('Example 2: Created after use({reactive: false}) → MANUAL (global default)');
107
+ console.log('Example 3: Created with chainable API → MANUAL (chained use)');
108
+ console.log('Example 4: Created with {reactive: true} → REACTIVE (instance override)');
109
+
110
+ // Debug access
111
+ window.configExamples = {
112
+ default: defaultExample,
113
+ globalManual: globalManualExample,
114
+ chainable: chainableExample,
115
+ instanceOverride: instanceOverride,
116
+ };
117
+ })();