@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
package/index.html ADDED
@@ -0,0 +1,841 @@
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.0, maximum-scale=5.0" />
6
+ <title>dataBind.js - Simple, Fast, Reactive</title>
7
+ <meta name="description" content="Simple, fast, reactive data binding for modern browsers. No build tools required." />
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&family=JetBrains+Mono:wght@400;700&display=swap"
12
+ rel="stylesheet"
13
+ />
14
+ <style>
15
+ :root {
16
+ --bg-color: #0f172a;
17
+ --text-color: #e2e8f0;
18
+ --primary-color: #38bdf8;
19
+ --secondary-color: #818cf8;
20
+ --accent-color: #c084fc;
21
+ --card-bg: #1e293b;
22
+ --code-bg: #020617;
23
+ --border-color: #334155;
24
+ }
25
+
26
+ * {
27
+ margin: 0;
28
+ padding: 0;
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ html {
33
+ overflow-x: hidden;
34
+ }
35
+
36
+ body {
37
+ font-family: "Outfit", sans-serif;
38
+ background-color: var(--bg-color);
39
+ color: var(--text-color);
40
+ line-height: 1.6;
41
+ overflow-x: hidden;
42
+ width: 100%;
43
+ max-width: 100vw;
44
+ }
45
+
46
+ button {
47
+ border: none;
48
+ }
49
+
50
+ a {
51
+ color: var(--primary-color);
52
+ text-decoration: none;
53
+ transition: color 0.2s;
54
+ }
55
+
56
+ a:hover {
57
+ color: var(--accent-color);
58
+ }
59
+
60
+ /* Header */
61
+ header {
62
+ padding: 2rem 5%;
63
+ display: flex;
64
+ justify-content: space-between;
65
+ align-items: center;
66
+ backdrop-filter: blur(10px);
67
+ position: sticky;
68
+ top: 0;
69
+ z-index: 100;
70
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
71
+ }
72
+
73
+ .logo {
74
+ font-weight: 700;
75
+ font-size: 1.5rem;
76
+ background: linear-gradient(135deg, var(--primary-color), var(--accent-color));
77
+ -webkit-background-clip: text;
78
+ -webkit-text-fill-color: transparent;
79
+ }
80
+
81
+ nav a {
82
+ margin-left: 2rem;
83
+ font-weight: 600;
84
+ color: var(--text-color);
85
+ }
86
+
87
+ nav a:hover {
88
+ color: var(--primary-color);
89
+ }
90
+
91
+ /* Hero */
92
+ .hero {
93
+ padding: 8rem 5% 6rem;
94
+ text-align: center;
95
+ max-width: 1200px;
96
+ margin: 0 auto;
97
+ position: relative;
98
+ }
99
+
100
+ .hero::before {
101
+ content: "";
102
+ position: absolute;
103
+ top: -50%;
104
+ left: 50%;
105
+ transform: translateX(-50%);
106
+ width: 600px;
107
+ height: 600px;
108
+ background: radial-gradient(circle, rgba(56, 189, 248, 0.15) 0%, rgba(15, 23, 42, 0) 70%);
109
+ z-index: -1;
110
+ pointer-events: none;
111
+ }
112
+
113
+ h1 {
114
+ font-size: 4rem;
115
+ line-height: 1.1;
116
+ margin-bottom: 1.5rem;
117
+ font-weight: 800;
118
+ }
119
+
120
+ .gradient-text {
121
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color), var(--accent-color));
122
+ -webkit-background-clip: text;
123
+ -webkit-text-fill-color: transparent;
124
+ }
125
+
126
+ .subtitle {
127
+ font-size: 1.25rem;
128
+ color: #94a3b8;
129
+ max-width: 600px;
130
+ margin: 0 auto 3rem;
131
+ }
132
+
133
+ .cta-buttons {
134
+ display: flex;
135
+ gap: 1rem;
136
+ justify-content: center;
137
+ margin-bottom: 4rem;
138
+ }
139
+
140
+ .btn {
141
+ padding: 0.75rem 2rem;
142
+ border-radius: 9999px;
143
+ font-weight: 600;
144
+ transition: transform 0.2s, box-shadow 0.2s;
145
+ }
146
+
147
+ .btn-primary {
148
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
149
+ color: #0f172a;
150
+ }
151
+
152
+ .btn-secondary {
153
+ background: rgba(255, 255, 255, 0.1);
154
+ color: white;
155
+ border: 1px solid rgba(255, 255, 255, 0.1);
156
+ }
157
+
158
+ .btn:hover {
159
+ transform: translateY(-2px);
160
+ box-shadow: 0 10px 20px -10px rgba(56, 189, 248, 0.5);
161
+ color: inherit;
162
+ }
163
+
164
+ /* Features */
165
+ .features {
166
+ display: grid;
167
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
168
+ gap: 2rem;
169
+ padding: 4rem 5%;
170
+ max-width: 1200px;
171
+ margin: 0 auto;
172
+ }
173
+
174
+ .feature-card {
175
+ background: var(--card-bg);
176
+ padding: 2rem;
177
+ border-radius: 1rem;
178
+ border: 1px solid var(--border-color);
179
+ transition: transform 0.2s;
180
+ text-align: center;
181
+ }
182
+
183
+ .feature-card:hover {
184
+ transform: translateY(-5px);
185
+ border-color: var(--primary-color);
186
+ }
187
+
188
+ .feature-icon {
189
+ font-size: 4rem;
190
+ margin-bottom: 1rem;
191
+ }
192
+
193
+ .feature-title {
194
+ font-size: 1.5rem;
195
+ margin-bottom: 1rem;
196
+ font-weight: 700;
197
+ }
198
+
199
+ .feature-desc {
200
+ color: #94a3b8;
201
+ }
202
+
203
+ /* Code Demo */
204
+ .demo-section {
205
+ padding: 6rem 5%;
206
+ background: #0b1120;
207
+ }
208
+
209
+ .demo-container {
210
+ max-width: 1200px;
211
+ margin: 0 auto;
212
+ display: grid;
213
+ grid-template-columns: 1fr 1fr;
214
+ gap: 4rem;
215
+ align-items: center;
216
+ }
217
+
218
+ .code-block {
219
+ background: var(--code-bg);
220
+ padding: 1.5rem;
221
+ border-radius: 0.5rem;
222
+ font-family: "JetBrains Mono", monospace;
223
+ font-size: 0.9rem;
224
+ overflow-x: auto;
225
+ border: 1px solid var(--border-color);
226
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5);
227
+ max-width: 100%;
228
+ word-wrap: break-word;
229
+ }
230
+
231
+ .token.keyword {
232
+ color: #c084fc;
233
+ }
234
+ .token.string {
235
+ color: #86efac;
236
+ }
237
+ .token.function {
238
+ color: #38bdf8;
239
+ }
240
+ .token.comment {
241
+ color: #64748b;
242
+ }
243
+
244
+ /* Footer */
245
+ footer {
246
+ padding: 4rem 5%;
247
+ text-align: center;
248
+ border-top: 1px solid var(--border-color);
249
+ margin-top: 4rem;
250
+ color: #64748b;
251
+ }
252
+
253
+ /* Documentation Section */
254
+ .docs-section {
255
+ padding: 6rem 5%;
256
+ max-width: 1200px;
257
+ margin: 0 auto;
258
+ }
259
+
260
+ .docs-intro {
261
+ text-align: center;
262
+ max-width: 800px;
263
+ margin: 0 auto 4rem;
264
+ }
265
+
266
+ .docs-intro h2 {
267
+ font-size: 2.5rem;
268
+ margin-bottom: 1rem;
269
+ font-weight: 700;
270
+ }
271
+
272
+ .docs-intro p {
273
+ color: #94a3b8;
274
+ font-size: 1.1rem;
275
+ line-height: 1.8;
276
+ }
277
+
278
+ .accordion {
279
+ display: grid;
280
+ gap: 1rem;
281
+ }
282
+
283
+ .accordion-item {
284
+ background: var(--card-bg);
285
+ border: 1px solid var(--border-color);
286
+ border-radius: 0.75rem;
287
+ overflow: hidden;
288
+ transition: all 0.3s ease;
289
+ }
290
+
291
+ .accordion-item:hover {
292
+ border-color: var(--primary-color);
293
+ }
294
+
295
+ .accordion-header {
296
+ padding: 1.5rem;
297
+ cursor: pointer;
298
+ display: flex;
299
+ justify-content: space-between;
300
+ align-items: center;
301
+ user-select: none;
302
+ transition: background 0.2s;
303
+ }
304
+
305
+ .accordion-header:hover {
306
+ background: rgba(56, 189, 248, 0.05);
307
+ }
308
+
309
+ .accordion-title {
310
+ font-family: "JetBrains Mono", monospace;
311
+ font-size: 1rem;
312
+ font-weight: 600;
313
+ color: var(--primary-color);
314
+ }
315
+
316
+ .accordion-icon {
317
+ font-size: 1.2rem;
318
+ transition: transform 0.3s ease;
319
+ color: var(--secondary-color);
320
+ }
321
+
322
+ .accordion-item.active .accordion-icon {
323
+ transform: rotate(180deg);
324
+ }
325
+
326
+ .accordion-content {
327
+ max-height: 0;
328
+ overflow: hidden;
329
+ transition: max-height 0.3s ease, padding 0.3s ease;
330
+ }
331
+
332
+ .accordion-item.active .accordion-content {
333
+ max-height: 1000px;
334
+ padding: 0 1.5rem 1.5rem;
335
+ }
336
+
337
+ .accordion-content p {
338
+ color: #cbd5e1;
339
+ margin-bottom: 1rem;
340
+ line-height: 1.6;
341
+ }
342
+
343
+ .accordion-content .code-block {
344
+ margin-top: 1rem;
345
+ }
346
+
347
+ .example-code {
348
+ background: var(--code-bg);
349
+ padding: 1.5rem;
350
+ border-radius: 0.5rem;
351
+ font-family: "JetBrains Mono", monospace;
352
+ font-size: 0.85rem;
353
+ overflow-x: auto;
354
+ border: 1px solid var(--border-color);
355
+ margin-top: 1rem;
356
+ white-space: pre-wrap;
357
+ word-wrap: break-word;
358
+ line-height: 1.6;
359
+ }
360
+
361
+ @media (max-width: 768px) {
362
+ h1 {
363
+ font-size: 2.5rem;
364
+ }
365
+ .demo-container {
366
+ grid-template-columns: 1fr;
367
+ }
368
+ .hero {
369
+ padding: 4rem 5% 3rem;
370
+ }
371
+ nav {
372
+ display: none;
373
+ } /* Simple mobile hide for now */
374
+ .docs-intro h2 {
375
+ font-size: 2rem;
376
+ }
377
+ .accordion-title {
378
+ font-size: 0.9rem;
379
+ }
380
+ .code-block {
381
+ padding: 1rem;
382
+ font-size: 0.75rem;
383
+ }
384
+ .example-code {
385
+ padding: 1rem;
386
+ font-size: 0.75rem;
387
+ }
388
+ .features {
389
+ padding: 3rem 5%;
390
+ }
391
+ .feature-icon {
392
+ font-size: 2.5rem;
393
+ margin-bottom: 0.75rem;
394
+ }
395
+ .feature-title {
396
+ font-size: 1.25rem;
397
+ }
398
+ .feature-card {
399
+ padding: 1.5rem;
400
+ }
401
+ .docs-section {
402
+ padding: 4rem 5%;
403
+ }
404
+ .demo-section {
405
+ padding: 4rem 5%;
406
+ }
407
+ }
408
+ </style>
409
+ </head>
410
+ <body>
411
+ <header>
412
+ <div class="logo">dataBind.js</div>
413
+ <nav>
414
+ <a href="https://github.com/gogocat/dataBind">GitHub</a>
415
+ <a href="examples/todomvc.html">Examples</a>
416
+ <a href="#docs">Docs</a>
417
+ </nav>
418
+ </header>
419
+
420
+ <section class="hero">
421
+ <h1>
422
+ Simple. Fast. <br />
423
+ <span class="gradient-text">Reactive.</span>
424
+ </h1>
425
+ <p class="subtitle">A lightweight, pragmatic solution for adding reactive data binding to your existing HTML. No build tools required.</p>
426
+ <div class="cta-buttons">
427
+ <a href="https://github.com/gogocat/dataBind" class="btn btn-primary">Get Started</a>
428
+ <a href="examples/todomvc.html" class="btn btn-secondary">View Demo</a>
429
+ </div>
430
+
431
+ <div class="code-block" style="text-align: left; max-width: 600px; margin: 0 auto">
432
+ <div style="color: #64748b; margin-bottom: 0.5rem">// Zero setup. Just drop it in.</div>
433
+ <span class="token keyword">const</span> app = dataBind.<span class="token function">init</span>(document.body, {<br />
434
+ &nbsp;&nbsp;count: 0,<br />
435
+ &nbsp;&nbsp;<span class="token function">increment</span>() {<br />
436
+ &nbsp;&nbsp;&nbsp;&nbsp;<span class="token keyword">this</span>.count++;<br />
437
+ &nbsp;&nbsp;}<br />
438
+ });
439
+ </div>
440
+ <div class="code-block" style="text-align: left; max-width: 600px; margin: 1rem auto 0">
441
+ <div style="color: #64748b; margin-bottom: 0.5rem">// html</div>
442
+ &lt;body&gt;<br />
443
+ &nbsp;&nbsp;&lt;span data-bind-text='count'&gt;&lt;/span&gt;<br />
444
+ &nbsp;&nbsp;&lt;button data-bind-click='increment'&gt;increment&lt;/button&gt;<br />
445
+ &lt;/body&gt;
446
+ </div>
447
+
448
+ <div id="demo-app" style="margin-top: 2rem; display: flex; align-items: center; justify-content: center; gap: 1rem">
449
+ <div style="background: var(--card-bg); padding: 1rem 2rem; border-radius: 999px; border: 1px solid var(--primary-color)">
450
+ <span style="font-size: 1.5rem; font-weight: bold; margin-right: 1rem" data-bind-text="count">0</span>
451
+ <button class="btn btn-primary" data-bind-click="increment" style="padding: 0.5rem 1.5rem; font-size: 0.9rem">Increment</button>
452
+ </div>
453
+ </div>
454
+ </section>
455
+
456
+ <section class="features">
457
+ <div class="feature-card">
458
+ <div class="feature-icon">✨</div>
459
+ <h3 class="feature-title">Simple</h3>
460
+ <p class="feature-desc">Just HTML + JavaScript. No JSX, no virtual DOM, no complex build pipelines. It just works.</p>
461
+ </div>
462
+ <div class="feature-card">
463
+ <div class="feature-icon">⚡</div>
464
+ <h3 class="feature-title">Fast</h3>
465
+ <p class="feature-desc">Extremely small footprint (~15KB) and high performance. Updates only what needs to change.</p>
466
+ <p>
467
+ Compare <a href="./examples/dbmonsterForOfReactive.html" target="_blank">dataBind</a> with
468
+ <a href="./examples/dbmonsterReact.html" target="_blank">React 19</a>
469
+ </p>
470
+ </div>
471
+ <div class="feature-card">
472
+ <div class="feature-icon">🔄</div>
473
+ <h3 class="feature-title">Reactive</h3>
474
+ <p class="feature-desc">Automatic UI updates when data changes using modern JavaScript Proxies. Like Vue 3, but simpler.</p>
475
+ </div>
476
+ </section>
477
+
478
+ <section class="demo-section">
479
+ <div class="demo-container">
480
+ <div>
481
+ <h2 style="font-size: 2.5rem; margin-bottom: 1.5rem">Declarative Bindings</h2>
482
+ <p style="color: #94a3b8; margin-bottom: 2rem">
483
+ Use simple <code>data-bind-*</code> attributes to connect your UI to your data. Supports text, events, loops, conditionals,
484
+ and two-way binding out of the box.
485
+ </p>
486
+ <ul style="list-style: none; color: #cbd5e1; gap: 0.75rem; display: grid; grid-template-columns: repeat(2, 1fr)">
487
+ <li>✓ <strong>data-bind-text</strong></li>
488
+ <li>✓ <strong>data-bind-model</strong></li>
489
+ <li>✓ <strong>data-bind-click</strong></li>
490
+ <li>✓ <strong>data-bind-dblclick</strong></li>
491
+ <li>✓ <strong>data-bind-change</strong></li>
492
+ <li>✓ <strong>data-bind-input</strong></li>
493
+ <li>✓ <strong>data-bind-submit</strong></li>
494
+ <li>✓ <strong>data-bind-blur</strong></li>
495
+ <li>✓ <strong>data-bind-focus</strong></li>
496
+ <li>✓ <strong>data-bind-hover</strong></li>
497
+ <li>✓ <strong>data-bind-if</strong></li>
498
+ <li>✓ <strong>data-bind-show</strong></li>
499
+ <li>✓ <strong>data-bind-for</strong></li>
500
+ <li>✓ <strong>data-bind-switch</strong></li>
501
+ <li>✓ <strong>data-bind-case</strong></li>
502
+ <li>✓ <strong>data-bind-default</strong></li>
503
+ <li>✓ <strong>data-bind-css</strong></li>
504
+ <li>✓ <strong>data-bind-attr</strong></li>
505
+ <li>✓ <strong>data-bind-tmp</strong></li>
506
+ <li>✓ <strong>data-bind-comp</strong></li>
507
+ </ul>
508
+ </div>
509
+ <div class="code-block" style="white-space: pre">&lt;<span class="token keyword">div</span> id="app"&gt;
510
+ &lt;<span class="token keyword">h1</span> data-bind-text="title"&gt;&lt;/<span class="token keyword">h1</span>&gt;
511
+ &lt;<span class="token keyword">ul</span>&gt;
512
+ &lt;<span class="token keyword">li</span> data-bind-for="item in items"&gt;
513
+ &lt;<span class="token keyword">span</span> data-bind-text="item.name"&gt;&lt;/<span class="token keyword">span</span>&gt;
514
+ &lt;/<span class="token keyword">li</span>&gt;
515
+ &lt;/<span class="token keyword">ul</span>&gt;
516
+ &lt;<span class="token keyword">input</span> data-bind-model="newItem"&gt;
517
+ &lt;<span class="token keyword">button</span> data-bind-click="add"&gt;Add&lt;/<span class="token keyword">button</span>&gt;
518
+ &lt;/<span class="token keyword">div</span>&gt;</div>
519
+ </div>
520
+ </section>
521
+
522
+ <section id="docs" class="docs-section">
523
+ <div class="docs-intro">
524
+ <h2>Documentation</h2>
525
+ <p>
526
+ <strong>dataBind.js</strong> is a drop-in JavaScript library that requires no build tools or compilation. Simply include the
527
+ script tag and start using declarative data bindings in your HTML. Click on any binding below to see examples and learn how to use
528
+ them.
529
+ </p>
530
+ </div>
531
+
532
+ <div class="accordion" data-bind-comp="docs-accordion">
533
+ <div class="accordion-item">
534
+ <div class="accordion-header" data-bind-click="toggleAccordion">
535
+ <span class="accordion-title">data-bind-text</span>
536
+ <span class="accordion-icon">▼</span>
537
+ </div>
538
+ <div class="accordion-content">
539
+ <p>Display text content from your viewModel. Supports deep property paths.</p>
540
+ <div class="example-code">&lt;<span class="token keyword">h1</span> data-bind-text=<span class="token string">"title"</span>&gt;&lt;/<span class="token keyword">h1</span>&gt;
541
+ &lt;<span class="token keyword">p</span> data-bind-text=<span class="token string">"user.name"</span>&gt;&lt;/<span class="token keyword">p</span>&gt;</div>
542
+ </div>
543
+ </div>
544
+
545
+ <div class="accordion-item">
546
+ <div class="accordion-header" data-bind-click="toggleAccordion">
547
+ <span class="accordion-title">data-bind-model</span>
548
+ <span class="accordion-icon">▼</span>
549
+ </div>
550
+ <div class="accordion-content">
551
+ <p>Two-way data binding for form inputs. Automatically syncs input values with your viewModel.</p>
552
+ <div class="example-code">&lt;<span class="token keyword">input</span> type=<span class="token string">"text"</span> data-bind-model=<span class="token string">"username"</span>&gt;</div>
553
+ </div>
554
+ </div>
555
+
556
+ <div class="accordion-item">
557
+ <div class="accordion-header" data-bind-click="toggleAccordion">
558
+ <span class="accordion-title">data-bind-click</span>
559
+ <span class="accordion-icon">▼</span>
560
+ </div>
561
+ <div class="accordion-content">
562
+ <p>Handle click events. The handler receives the event and element as parameters.</p>
563
+ <div class="example-code">&lt;<span class="token keyword">button</span> data-bind-click=<span class="token string">"handleClick"</span>&gt;Click Me&lt;/<span class="token keyword">button</span>&gt;
564
+
565
+ <span class="token keyword">const</span> viewModel = {
566
+ <span class="token function">handleClick</span>(event, element) {
567
+ console.<span class="token function">log</span>(<span class="token string">'Clicked!'</span>, event, element);
568
+ }
569
+ };</div>
570
+ </div>
571
+ </div>
572
+
573
+ <div class="accordion-item">
574
+ <div class="accordion-header" data-bind-click="toggleAccordion">
575
+ <span class="accordion-title">data-bind-change</span>
576
+ <span class="accordion-icon">▼</span>
577
+ </div>
578
+ <div class="accordion-content">
579
+ <p>Handle change events on form inputs. Receives event, element, newValue, and oldValue.</p>
580
+ <div class="example-code">&lt;<span class="token keyword">input</span> data-bind-change=<span class="token string">"handleChange"</span> data-bind-model=<span class="token string">"username"</span>&gt;
581
+
582
+ <span class="token keyword">const</span> viewModel = {
583
+ <span class="token function">handleChange</span>(event, element, newValue, oldValue) {
584
+ console.<span class="token function">log</span>(<span class="token string">'Changed from'</span>, oldValue, <span class="token string">'to'</span>, newValue);
585
+ }
586
+ };</div>
587
+ </div>
588
+ </div>
589
+
590
+ <div class="accordion-item">
591
+ <div class="accordion-header" data-bind-click="toggleAccordion">
592
+ <span class="accordion-title">data-bind-for</span>
593
+ <span class="accordion-icon">▼</span>
594
+ </div>
595
+ <div class="accordion-content">
596
+ <p>Render lists from arrays. Use $index for the current index and $root to access the root viewModel.</p>
597
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-for=<span class="token string">"item in items"</span>&gt;
598
+ &lt;<span class="token keyword">p</span> data-bind-text=<span class="token string">"item.name"</span>&gt;&lt;/<span class="token keyword">p</span>&gt;
599
+ &lt;<span class="token keyword">button</span> data-bind-click=<span class="token string">"$root.deleteItem($index)"</span>&gt;Delete&lt;/<span class="token keyword">button</span>&gt;
600
+ &lt;/<span class="token keyword">div</span>&gt;
601
+
602
+ <span class="token keyword">const</span> viewModel = {
603
+ items: [
604
+ { name: <span class="token string">'Item 1'</span> },
605
+ { name: <span class="token string">'Item 2'</span> }
606
+ ],
607
+ <span class="token function">deleteItem</span>(index) {
608
+ <span class="token keyword">this</span>.items.<span class="token function">splice</span>(index, <span class="token string">1</span>);
609
+ }
610
+ };</div>
611
+ </div>
612
+ </div>
613
+
614
+ <div class="accordion-item">
615
+ <div class="accordion-header" data-bind-click="toggleAccordion">
616
+ <span class="accordion-title">data-bind-if</span>
617
+ <span class="accordion-icon">▼</span>
618
+ </div>
619
+ <div class="accordion-content">
620
+ <p>Conditionally render elements. Removes element from DOM when condition is false.</p>
621
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-if=<span class="token string">"isLoggedIn"</span>&gt;
622
+ &lt;<span class="token keyword">p</span> data-bind-text=<span class="token string">"user.name"</span>&gt;&lt;/<span class="token keyword">p</span>&gt;
623
+ &lt;/<span class="token keyword">div</span>&gt;</div>
624
+ </div>
625
+ </div>
626
+
627
+ <div class="accordion-item">
628
+ <div class="accordion-header" data-bind-click="toggleAccordion">
629
+ <span class="accordion-title">data-bind-show</span>
630
+ <span class="accordion-icon">▼</span>
631
+ </div>
632
+ <div class="accordion-content">
633
+ <p>Toggle element visibility with CSS. Element stays in DOM but is hidden when condition is false.</p>
634
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-show=<span class="token string">"isVisible"</span>&gt;
635
+ &lt;<span class="token keyword">p</span>&gt;Visible content&lt;/<span class="token keyword">p</span>&gt;
636
+ &lt;/<span class="token keyword">div</span>&gt;</div>
637
+ </div>
638
+ </div>
639
+
640
+ <div class="accordion-item">
641
+ <div class="accordion-header" data-bind-click="toggleAccordion">
642
+ <span class="accordion-title">data-bind-switch / case / default</span>
643
+ <span class="accordion-icon">▼</span>
644
+ </div>
645
+ <div class="accordion-content">
646
+ <p>Switch statement for multiple conditions. Only the matching case will be rendered.</p>
647
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-switch=<span class="token string">"currentState"</span>&gt;
648
+ &lt;<span class="token keyword">div</span> data-bind-case=<span class="token string">"loading"</span>&gt;Loading...&lt;/<span class="token keyword">div</span>&gt;
649
+ &lt;<span class="token keyword">div</span> data-bind-case=<span class="token string">"error"</span>&gt;An error occurred&lt;/<span class="token keyword">div</span>&gt;
650
+ &lt;<span class="token keyword">div</span> data-bind-case=<span class="token string">"success"</span>&gt;Data loaded successfully!&lt;/<span class="token keyword">div</span>&gt;
651
+ &lt;<span class="token keyword">div</span> data-bind-default&gt;Please wait...&lt;/<span class="token keyword">div</span>&gt;
652
+ &lt;/<span class="token keyword">div</span>&gt;</div>
653
+ </div>
654
+ </div>
655
+
656
+ <div class="accordion-item">
657
+ <div class="accordion-header" data-bind-click="toggleAccordion">
658
+ <span class="accordion-title">data-bind-css</span>
659
+ <span class="accordion-icon">▼</span>
660
+ </div>
661
+ <div class="accordion-content">
662
+ <p>Dynamically add/remove CSS classes based on conditions or bind a string of class names.</p>
663
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-css=<span class="token string">"{ active: isActive, disabled: !isEnabled }"</span>&gt;&lt;/<span class="token keyword">div</span>&gt;
664
+ &lt;<span class="token keyword">div</span> data-bind-css=<span class="token string">"dynamicClass"</span>&gt;&lt;/<span class="token keyword">div</span>&gt;</div>
665
+ </div>
666
+ </div>
667
+
668
+ <div class="accordion-item">
669
+ <div class="accordion-header" data-bind-click="toggleAccordion">
670
+ <span class="accordion-title">data-bind-attr</span>
671
+ <span class="accordion-icon">▼</span>
672
+ </div>
673
+ <div class="accordion-content">
674
+ <p>Dynamically set element attributes from a function or object in your viewModel.</p>
675
+ <div class="example-code">&lt;<span class="token keyword">img</span> data-bind-attr=<span class="token string">"getImageAttrs"</span>&gt;
676
+
677
+ <span class="token keyword">const</span> viewModel = {
678
+ <span class="token function">getImageAttrs</span>() {
679
+ <span class="token keyword">return</span> {
680
+ src: <span class="token string">'image.jpg'</span>,
681
+ alt: <span class="token string">'Description'</span>
682
+ };
683
+ }
684
+ };</div>
685
+ </div>
686
+ </div>
687
+
688
+ <div class="accordion-item">
689
+ <div class="accordion-header" data-bind-click="toggleAccordion">
690
+ <span class="accordion-title">data-bind-tmp</span>
691
+ <span class="accordion-icon">▼</span>
692
+ </div>
693
+ <div class="accordion-content">
694
+ <p>Render templates with data from your viewModel.</p>
695
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-tmp=<span class="token string">"{id: 'userCard', data: 'user'}"</span>&gt;&lt;/<span class="token keyword">div</span>&gt;
696
+
697
+ &lt;<span class="token keyword">template</span> id=<span class="token string">"userCard"</span>&gt;
698
+ &lt;<span class="token keyword">div</span> class=<span class="token string">"card"</span>&gt;
699
+ &lt;<span class="token keyword">h2</span> data-bind-text=<span class="token string">"name"</span>&gt;&lt;/<span class="token keyword">h2</span>&gt;
700
+ &lt;<span class="token keyword">p</span> data-bind-text=<span class="token string">"email"</span>&gt;&lt;/<span class="token keyword">p</span>&gt;
701
+ &lt;/<span class="token keyword">div</span>&gt;
702
+ &lt;/<span class="token keyword">template</span>&gt;</div>
703
+ </div>
704
+ </div>
705
+
706
+ <div class="accordion-item">
707
+ <div class="accordion-header" data-bind-click="toggleAccordion">
708
+ <span class="accordion-title">data-bind-submit</span>
709
+ <span class="accordion-icon">▼</span>
710
+ </div>
711
+ <div class="accordion-content">
712
+ <p>Handle form submit events.</p>
713
+ <div class="example-code">&lt;<span class="token keyword">form</span> data-bind-submit=<span class="token string">"handleSubmit"</span>&gt;
714
+ &lt;<span class="token keyword">input</span> data-bind-model=<span class="token string">"username"</span>&gt;
715
+ &lt;<span class="token keyword">button</span> type=<span class="token string">"submit"</span>&gt;Submit&lt;/<span class="token keyword">button</span>&gt;
716
+ &lt;/<span class="token keyword">form</span>&gt;</div>
717
+ </div>
718
+ </div>
719
+
720
+ <div class="accordion-item">
721
+ <div class="accordion-header" data-bind-click="toggleAccordion">
722
+ <span class="accordion-title">data-bind-blur</span>
723
+ <span class="accordion-icon">▼</span>
724
+ </div>
725
+ <div class="accordion-content">
726
+ <p>Handle blur events when an element loses focus.</p>
727
+ <div class="example-code">&lt;<span class="token keyword">input</span> data-bind-blur=<span class="token string">"onBlur"</span>&gt;</div>
728
+ </div>
729
+ </div>
730
+
731
+ <div class="accordion-item">
732
+ <div class="accordion-header" data-bind-click="toggleAccordion">
733
+ <span class="accordion-title">data-bind-focus</span>
734
+ <span class="accordion-icon">▼</span>
735
+ </div>
736
+ <div class="accordion-content">
737
+ <p>Handle focus events when an element receives focus.</p>
738
+ <div class="example-code">&lt;<span class="token keyword">input</span> data-bind-focus=<span class="token string">"onFocus"</span>&gt;</div>
739
+ </div>
740
+ </div>
741
+
742
+ <div class="accordion-item">
743
+ <div class="accordion-header" data-bind-click="toggleAccordion">
744
+ <span class="accordion-title">data-bind-dblclick</span>
745
+ <span class="accordion-icon">▼</span>
746
+ </div>
747
+ <div class="accordion-content">
748
+ <p>Handle double-click events.</p>
749
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-dblclick=<span class="token string">"onDblClick"</span>&gt;Double-click me&lt;/<span class="token keyword">div</span>&gt;</div>
750
+ </div>
751
+ </div>
752
+
753
+ <div class="accordion-item">
754
+ <div class="accordion-header" data-bind-click="toggleAccordion">
755
+ <span class="accordion-title">data-bind-hover</span>
756
+ <span class="accordion-icon">▼</span>
757
+ </div>
758
+ <div class="accordion-content">
759
+ <p>Handle hover in and out events.</p>
760
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-hover=<span class="token string">"onHover"</span>&gt;Hover over me&lt;/<span class="token keyword">div</span>&gt;</div>
761
+ </div>
762
+ </div>
763
+
764
+ <div class="accordion-item">
765
+ <div class="accordion-header" data-bind-click="toggleAccordion">
766
+ <span class="accordion-title">data-bind-input</span>
767
+ <span class="accordion-icon">▼</span>
768
+ </div>
769
+ <div class="accordion-content">
770
+ <p>Handle input events as user types (fires on every keystroke).</p>
771
+ <div class="example-code">&lt;<span class="token keyword">input</span> data-bind-input=<span class="token string">"onInput"</span> data-bind-model=<span class="token string">"search"</span>&gt;</div>
772
+ </div>
773
+ </div>
774
+
775
+ <div class="accordion-item">
776
+ <div class="accordion-header" data-bind-click="toggleAccordion">
777
+ <span class="accordion-title">data-bind-comp</span>
778
+ <span class="accordion-icon">▼</span>
779
+ </div>
780
+ <div class="accordion-content">
781
+ <p>
782
+ Identifier attribute for selecting component elements. Use it to target specific parts of your page for dataBind
783
+ initialization.
784
+ </p>
785
+ <div class="example-code">&lt;<span class="token keyword">div</span> data-bind-comp=<span class="token string">"todos"</span>&gt;
786
+ <span class="token comment">&lt;!-- todo list content --&gt;</span>
787
+ &lt;/<span class="token keyword">div</span>&gt;
788
+
789
+ <span class="token keyword">const</span> component = dataBind.<span class="token function">init</span>(
790
+ document.<span class="token function">querySelector</span>(<span class="token string">'[data-bind-comp="todos"]'</span>),
791
+ viewModel
792
+ );</div>
793
+ </div>
794
+ </div>
795
+ </div>
796
+ </section>
797
+
798
+ <footer>
799
+ <p>© 2025 dataBind.js. Open source under MIT License.</p>
800
+ <p style="margin-top: 1rem; font-size: 0.9rem">
801
+ <a href="https://github.com/gogocat/dataBind" style="color: #64748b; text-decoration: underline">View on GitHub</a>
802
+ </p>
803
+ </footer>
804
+ <script src="dist/js/dataBind.js"></script>
805
+ <script>
806
+ const app = dataBind.init(document.getElementById("demo-app"), {
807
+ count: 0,
808
+ increment() {
809
+ this.count++;
810
+ },
811
+ });
812
+ </script>
813
+ <script>
814
+ // Smooth scroll to docs section
815
+ document.querySelector('a[href="#docs"]').addEventListener("click", (e) => {
816
+ e.preventDefault();
817
+ document.getElementById("docs").scrollIntoView({ behavior: "smooth" });
818
+ });
819
+
820
+ // Documentation accordion component
821
+ const docsAccordion = dataBind.init(document.querySelector('[data-bind-comp="docs-accordion"]'), {
822
+ toggleAccordion(event, element) {
823
+ const header = element;
824
+ const item = header.parentElement;
825
+ const wasActive = item.classList.contains("active");
826
+
827
+ // Close all accordion items
828
+ document.querySelectorAll(".accordion-item").forEach((i) => {
829
+ i.classList.remove("active");
830
+ });
831
+
832
+ // Open clicked item if it wasn't active
833
+ if (!wasActive) {
834
+ item.classList.add("active");
835
+ }
836
+ },
837
+ });
838
+ </script>
839
+ </body>
840
+ </html>
841
+