@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.
Files changed (271) 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 +2756 -2530
  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/globalConfig.html +131 -0
  147. package/examples/js/afterRenderDemo.js +190 -0
  148. package/examples/js/appTodo.js +46 -46
  149. package/examples/js/attrBindingDemo.js +2 -2
  150. package/examples/js/dbMonApp.js +24 -26
  151. package/examples/js/dbMonAppReact.jsx +79 -0
  152. package/examples/js/dbMonAppReactive.js +28 -0
  153. package/examples/js/fiberDemo.js +4 -4
  154. package/examples/js/filtersDemo.js +8 -8
  155. package/examples/js/forOfDemo.js +7 -9
  156. package/examples/js/forOfDemoComplex.js +44 -17
  157. package/examples/js/form.js +14 -14
  158. package/examples/js/globalConfig.js +117 -0
  159. package/examples/js/ifBindingDemo.js +16 -16
  160. package/examples/js/reactiveDemo.js +119 -0
  161. package/examples/js/switchBindingDemo.js +8 -8
  162. package/examples/react-dbmonster/dist/bundle.js +43 -0
  163. package/examples/react-dbmonster/package-lock.json +537 -0
  164. package/examples/react-dbmonster/package.json +16 -0
  165. package/examples/react-dbmonster/src/index.jsx +80 -0
  166. package/examples/reactiveDemo.html +127 -0
  167. package/examples/refreshRateTest.html +75 -75
  168. package/index.html +841 -0
  169. package/package.json +31 -34
  170. package/rollup.config.js +79 -36
  171. package/src/{_escape.js → _escape.ts} +19 -17
  172. package/src/{applyBinding.js → applyBinding.ts} +27 -18
  173. package/src/{attrBinding.js → attrBinding.ts} +14 -13
  174. package/src/{binder.js → binder.ts} +289 -181
  175. package/src/changeBinding.ts +93 -0
  176. package/src/{commentWrapper.js → commentWrapper.ts} +33 -30
  177. package/src/config.ts +107 -0
  178. package/src/{createBindingOption.js → createBindingOption.ts} +39 -15
  179. package/src/createEventBinding.ts +88 -0
  180. package/src/{cssBinding.js → cssBinding.ts} +13 -11
  181. package/src/{domWalker.js → domWalker.ts} +44 -30
  182. package/src/{forOfBinding.js → forOfBinding.ts} +4 -3
  183. package/src/hoverBinding.ts +84 -0
  184. package/src/{ifBinding.js → ifBinding.ts} +14 -12
  185. package/src/index.ts +53 -0
  186. package/src/{modelBinding.js → modelBinding.ts} +11 -9
  187. package/src/{postProcess.js → postProcess.ts} +6 -4
  188. package/src/{pubSub.js → pubSub.ts} +24 -21
  189. package/src/reactiveProxy.ts +285 -0
  190. package/src/{renderForOfBinding.js → renderForOfBinding.ts} +54 -32
  191. package/src/{renderIfBinding.js → renderIfBinding.ts} +41 -19
  192. package/src/{renderIteration.js → renderIteration.ts} +24 -8
  193. package/src/renderTemplate.ts +165 -0
  194. package/src/renderTemplatesBinding.ts +73 -0
  195. package/src/{showBinding.js → showBinding.ts} +4 -3
  196. package/src/{switchBinding.js → switchBinding.ts} +18 -15
  197. package/src/{textBinding.js → textBinding.ts} +5 -4
  198. package/src/types.ts +124 -0
  199. package/src/util.ts +810 -0
  200. package/test/css/reporter.css +9 -9
  201. package/test/globals.d.ts +19 -0
  202. package/test/helpers/testHelper.js +46 -11
  203. package/test/mocks/featureAdsResult.json +65 -65
  204. package/test/mocks/searchResult.json +57 -57
  205. package/test/specs/{attrBinding.spec.js → attrBinding.spec.ts} +103 -106
  206. package/test/specs/{binder.spec.js → binder.spec.ts} +29 -27
  207. package/test/specs/blurBinding.spec.ts +60 -0
  208. package/test/specs/chainableUse.spec.ts +125 -0
  209. package/test/specs/clickBinding.spec.ts +194 -0
  210. package/test/specs/{cssBinding.spec.js → cssBinding.spec.ts} +72 -79
  211. package/test/specs/{dataBindBootstrap.spec.js → dataBindBootstrap.spec.ts} +332 -313
  212. package/test/specs/{filter.spec.js → filter.spec.ts} +75 -76
  213. package/test/specs/{forOfBinding.spec.js → forOfBinding.spec.ts} +208 -219
  214. package/test/specs/formBinding.spec.ts +272 -0
  215. package/test/specs/ifBinding.spec.ts +165 -0
  216. package/test/specs/{nestedComponent.spec.js → nestedComponent.spec.ts} +88 -88
  217. package/test/specs/reactiveProxy.spec.ts +465 -0
  218. package/test/specs/{showBinding.spec.js → showBinding.spec.ts} +148 -149
  219. package/test/specs/{switchBinding.spec.js → switchBinding.spec.ts} +172 -173
  220. package/test/specs/templateBinding.spec.ts +273 -0
  221. package/test/specs/{textBinding.spec.js → textBinding.spec.ts} +47 -48
  222. package/test/tsconfig.json +31 -0
  223. package/test-output.txt +200 -0
  224. package/test-reactive.html +224 -0
  225. package/tsconfig.json +28 -0
  226. package/vendors/lodash.custom.js +4577 -4577
  227. package/vendors/lodash.custom.min.js +45 -45
  228. package/vitest.config.js +27 -0
  229. package/.eslintrc.js +0 -1
  230. package/.grunt/grunt-contrib-jasmine/boot.js +0 -161
  231. package/.grunt/grunt-contrib-jasmine/dist/js/dataBind.js +0 -9
  232. package/.grunt/grunt-contrib-jasmine/grunt-template-jasmine-istanbul/reporter.js +0 -23
  233. package/.grunt/grunt-contrib-jasmine/jasmine-html.js +0 -853
  234. package/.grunt/grunt-contrib-jasmine/jasmine.css +0 -271
  235. package/.grunt/grunt-contrib-jasmine/jasmine.js +0 -9761
  236. package/.grunt/grunt-contrib-jasmine/jasmine_favicon.png +0 -0
  237. package/.grunt/grunt-contrib-jasmine/json2.js +0 -489
  238. package/.grunt/grunt-contrib-jasmine/reporter.js +0 -107
  239. package/coverage/coverage.json +0 -1
  240. package/coverage/lcov/lcov-report/base.css +0 -213
  241. package/coverage/lcov/lcov-report/index.html +0 -93
  242. package/coverage/lcov/lcov-report/js/dataBind.js.html +0 -6596
  243. package/coverage/lcov/lcov-report/js/index.html +0 -93
  244. package/coverage/lcov/lcov-report/prettify.css +0 -1
  245. package/coverage/lcov/lcov-report/prettify.js +0 -1
  246. package/coverage/lcov/lcov-report/sort-arrow-sprite.png +0 -0
  247. package/coverage/lcov/lcov-report/sorter.js +0 -158
  248. package/coverage/lcov/lcov.info +0 -1991
  249. package/eslintrc.json +0 -40
  250. package/examples/bootstrap/js/bootstrap.min.js +0 -6
  251. package/examples/bootstrap/js/popper.min.js +0 -5
  252. package/examples/bootstrap/js/searchSuggestion.js +0 -58
  253. package/examples/bootstrap/js/typeahead.jquery.js +0 -1538
  254. package/gruntfile.js +0 -92
  255. package/gulpfile.js +0 -32
  256. package/src/applyBindingExport.js +0 -5
  257. package/src/changeBinding.js +0 -63
  258. package/src/config.js +0 -66
  259. package/src/createEventBinding.js +0 -46
  260. package/src/eventSystem.js +0 -46
  261. package/src/hoverBinding.js +0 -57
  262. package/src/index.js +0 -26
  263. package/src/renderTemplate.js +0 -128
  264. package/src/renderTemplatesBinding.js +0 -44
  265. package/src/util.js +0 -648
  266. package/test/specs/blurBinding.spec.js +0 -57
  267. package/test/specs/formBinding.spec.js +0 -316
  268. package/test/specs/ifBinding.spec.js +0 -169
  269. package/test/specs/templateBinding.spec.js +0 -117
  270. package/vendors/jasmine-jquery.js +0 -841
  271. package/vendors/jquery-3.2.1.min.js +0 -4
@@ -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,7 +10,7 @@
10
10
  And finally a quick test of attribute binding 😎`,
11
11
  btnText: 'Fake button »',
12
12
  },
13
- onBtnClick: function(e, $el) {
13
+ onBtnClick(e, $el) {
14
14
  e.preventDefault();
15
15
  console.log('onBtnClick: ', $el);
16
16
  },
@@ -39,13 +39,13 @@
39
39
  onInputChange(e, $el, newValue, oldValue) {
40
40
  console.log('onInputChange: ', this);
41
41
  this.personalDetails[0].show = false;
42
- this.updateView();
42
+ // Reactive mode - automatic render!
43
43
  }
44
44
  afterTemplateRender() {
45
45
  console.log('template rendered');
46
46
  }
47
- updateView(opt) {
48
- this.APP.render(opt);
47
+ updateView(opt) { // Note: render is automatic in reactive mode
48
+ // Reactive mode - automatic render!
49
49
  }
50
50
  getInputAttr(index) {
51
51
  const personalDetail = this.personalDetails[index];
@@ -82,7 +82,7 @@
82
82
  range: {
83
83
  value: 50,
84
84
  },
85
- getRangeAttr: function() {
85
+ getRangeAttr() {
86
86
  return {
87
87
  type: 'range',
88
88
  name: 'test-range',
@@ -92,13 +92,13 @@
92
92
  step: 1,
93
93
  };
94
94
  },
95
- onInputChange: function(e, $el, newValue, oldValue) {
95
+ onInputChange(e, $el, newValue, oldValue) {
96
96
  e.preventDefault();
97
97
  this.range.value = newValue;
98
- this.updateView();
98
+ // Reactive mode - automatic render!
99
99
  },
100
- updateView(opt) {
101
- this.APP.render(opt);
100
+ updateView(opt) { // Note: render is automatic in reactive mode
101
+ // Reactive mode - automatic render!
102
102
  },
103
103
  };
104
104
 
@@ -106,7 +106,7 @@
106
106
 
107
107
  // main formApp
108
108
  const formApp = dataBind.init(document.querySelector('[data-bind-comp="formApp"]'), formAppViewModel);
109
- formApp.render().then(function() {
109
+ formApp.render().then(() => {
110
110
  // for debug
111
111
  console.log(formApp);
112
112
  window.formApp = formApp;
@@ -115,7 +115,7 @@
115
115
  // formComponentA
116
116
  const formComponentA = dataBind.init(document.querySelector('[data-bind-comp="formComponentA"]'), new FormComponentVewModel());
117
117
 
118
- formComponentA.render().then(function() {
118
+ formComponentA.render().then(() => {
119
119
  // for debug
120
120
  console.log(formComponentA);
121
121
  window.formComponentA = formComponentA;
@@ -124,7 +124,7 @@
124
124
  // formComponentB
125
125
  const formComponentB = dataBind.init(document.querySelector('[data-bind-comp="formComponentB"]'), formComponentBViewModel);
126
126
 
127
- formComponentB.render().then(function() {
127
+ formComponentB.render().then(() => {
128
128
  // for debug
129
129
  console.log(formComponentB);
130
130
  window.formComponentB = formComponentB;
@@ -133,7 +133,7 @@
133
133
  // componentRangeInput
134
134
  const componentRangeInput = dataBind.init(document.querySelector('[data-bind-comp="componentRangeInput"]'), componentRangeInputViewModel);
135
135
 
136
- componentRangeInput.render().then(function() {
136
+ componentRangeInput.render().then(() => {
137
137
  // for debug
138
138
  console.log(componentRangeInput);
139
139
  window.componentRangeInput = componentRangeInput;
@@ -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
+ })();
@@ -1,4 +1,4 @@
1
- /* eslint-disable max-len */
1
+
2
2
  (() => {
3
3
  const myComponentViewModel = {
4
4
  renderIntro: false,
@@ -13,36 +13,36 @@
13
13
  {title: 'The Ugly Duckling', value: 's2'},
14
14
  {title: 'The Giving Tree', value: 's3'},
15
15
  ],
16
- setStoryOptionAttr: function($data, oldAttrObj, $el) {
16
+ setStoryOptionAttr($data, oldAttrObj, $el) {
17
17
  if ($data && $data.value) {
18
18
  return {
19
19
  value: $data.value,
20
20
  };
21
21
  }
22
22
  },
23
- onSelectedStory: function(e, $el, newValue, oldValue) {
23
+ onSelectedStory(e, $el, newValue, oldValue) {
24
24
  e.preventDefault();
25
25
  this.APP.publish('SELECTED_STORY', newValue);
26
26
  },
27
- renderItem: function(e, $el) {
27
+ renderItem(e, $el) {
28
28
  e.preventDefault();
29
29
  this.renderIntro = true;
30
- this.updateView();
30
+ // Reactive mode - automatic render!
31
31
  },
32
- removeItem: function(e, $el) {
32
+ removeItem(e, $el) {
33
33
  e.preventDefault();
34
34
  this.renderIntro = false;
35
- this.updateView();
35
+ // Reactive mode - automatic render!
36
36
  },
37
- updateView(opt) {
38
- this.APP.render(opt);
37
+ updateView(opt) { // Note: render is automatic in reactive mode
38
+ // Reactive mode - automatic render!
39
39
  },
40
40
  };
41
41
 
42
42
  const compStoryDetailViewModel = {
43
43
  selectedStory: '',
44
44
  story: {},
45
- setStoryImgAttr: function() {
45
+ setStoryImgAttr() {
46
46
  const picPath = this.story.pic || '';
47
47
  const ret = {
48
48
  alt: this.story.title,
@@ -55,7 +55,7 @@
55
55
  }
56
56
  return ret;
57
57
  },
58
- onStoryChange: function(id) {
58
+ onStoryChange(id) {
59
59
  if (storiesData[id] && id !== this.selectedStory) {
60
60
  this.story = storiesData[id];
61
61
  this.selectedStory = id;
@@ -63,10 +63,10 @@
63
63
  this.story = '';
64
64
  this.selectedStory = '';
65
65
  }
66
- this.updateView();
66
+ // Reactive mode - automatic render!
67
67
  },
68
- updateView(opt) {
69
- this.APP.render(opt);
68
+ updateView(opt) { // Note: render is automatic in reactive mode
69
+ // Reactive mode - automatic render!
70
70
  },
71
71
  };
72
72
 
@@ -96,7 +96,7 @@
96
96
 
97
97
  // main
98
98
  const myComponent = dataBind.init(document.querySelector('[data-bind-comp="myComponent"]'), myComponentViewModel);
99
- myComponent.render().then(function() {
99
+ myComponent.render().then(() => {
100
100
  // for debug
101
101
  console.log(myComponent);
102
102
  window.myComponent = myComponent;
@@ -104,7 +104,7 @@
104
104
 
105
105
  // story detail componenet
106
106
  const compStoryDetail = dataBind.init(document.querySelector('[data-bind-comp="compStoryDetail"]'), compStoryDetailViewModel);
107
- compStoryDetail.render().then(function(thisComponent) {
107
+ compStoryDetail.render().then((thisComponent) => {
108
108
  thisComponent.subscribe('SELECTED_STORY', thisComponent.viewModel.onStoryChange);
109
109
  // for debug
110
110
  console.log(compStoryDetail);