sdc_client 0.158.9 → 0.160.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 (57) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/LICENSE +21 -0
  3. package/dist/index.js +23 -13
  4. package/dist/ugly.index.js +2 -1
  5. package/dist/ugly.index.js.LICENSE.txt +1 -8
  6. package/gulp/gulp.jsx +11 -36
  7. package/package.json +23 -12
  8. package/src/index.js +31 -7
  9. package/src/simpleDomControl/AbstractSDC.js +15 -11
  10. package/src/simpleDomControl/sdc_controller.js +3 -3
  11. package/src/simpleDomControl/sdc_dom_events.js +5 -10
  12. package/src/simpleDomControl/sdc_events.js +3 -3
  13. package/src/simpleDomControl/sdc_main.js +34 -13
  14. package/src/simpleDomControl/sdc_model.js +225 -92
  15. package/src/simpleDomControl/sdc_params.js +0 -3
  16. package/src/simpleDomControl/sdc_server_call.js +21 -4
  17. package/src/simpleDomControl/sdc_test_utils.js +0 -1
  18. package/src/simpleDomControl/sdc_utils.js +59 -7
  19. package/src/simpleDomControl/sdc_view.js +16 -1
  20. package/.github/workflows/node.js.yml +0 -38
  21. package/.idea/inspectionProfiles/Project_Default.xml +0 -17
  22. package/.idea/jsLibraryMappings.xml +0 -6
  23. package/.idea/misc.xml +0 -6
  24. package/.idea/modules.xml +0 -8
  25. package/.idea/vcs.xml +0 -6
  26. package/.idea/workspace.xml +0 -403
  27. package/.readthedocs.yaml +0 -13
  28. package/.tool-versions +0 -1
  29. package/SimpleDomControlClient.iml +0 -12
  30. package/docs/api-reference.rst +0 -225
  31. package/docs/conf.py +0 -11
  32. package/docs/controllers.rst +0 -228
  33. package/docs/events-and-dom.rst +0 -120
  34. package/docs/getting-started.rst +0 -143
  35. package/docs/index.rst +0 -22
  36. package/docs/models.rst +0 -351
  37. package/docs/overview.rst +0 -66
  38. package/docs/requirements.txt +0 -1
  39. package/eslint.config.js +0 -43
  40. package/gulpfile.cjs +0 -30
  41. package/jest.config.mjs +0 -197
  42. package/test/controller.test.js +0 -93
  43. package/test/dist.test.js +0 -127
  44. package/test/model.test.js +0 -330
  45. package/test/models/Author.js +0 -145
  46. package/test/models/Book.js +0 -112
  47. package/test/models/BookContent.js +0 -114
  48. package/test/models/SdcUser.js +0 -75
  49. package/test/models/src.js +0 -8
  50. package/test/sdc_model_dates.ai.test.js +0 -57
  51. package/test/sdc_server_call.ai.test.js +0 -267
  52. package/test/utils.js +0 -88
  53. package/test/view.test.js +0 -159
  54. package/test-setup.js +0 -4
  55. package/webpack.config/webpack.default.config.cjs +0 -14
  56. package/webpack.config/webpack.development.config.cjs +0 -14
  57. package/webpack.config/webpack.production.config.cjs +0 -11
@@ -1,228 +0,0 @@
1
- Controllers
2
- ===========
3
-
4
- Base class
5
- ----------
6
-
7
- All controllers extend ``AbstractSDC``.
8
-
9
- Common properties
10
- -----------------
11
-
12
- ``contentUrl``
13
- Backend URL used to load the controller's HTML fragment.
14
-
15
- ``contentReload``
16
- If ``true``, the content is always reloaded instead of using the cached
17
- HTML fragment.
18
-
19
- ``events``
20
- List of event definition objects merged into one event map.
21
-
22
- ``load_async``
23
- If ``true``, the controller lifecycle does not block parent initialization.
24
-
25
- ``$container``
26
- jQuery wrapper for the DOM element associated with the controller.
27
-
28
- ``parentController`` / ``childController``
29
- Accessors for the controller tree.
30
-
31
- Lifecycle
32
- ---------
33
-
34
- ``onInit(...args)``
35
- Runs immediately after the controller is created. Arguments are resolved
36
- from DOM ``data-*`` attributes.
37
-
38
- ``onLoad(html)``
39
- Runs after the controller HTML has been fetched but before child controller
40
- tags are replaced. This is a common place to mutate the loaded fragment.
41
-
42
- ``willShow()``
43
- Runs after child controller content has been prepared and before refresh.
44
-
45
- ``onRefresh(originController)``
46
- Runs after DOM updates and event wiring are complete.
47
-
48
- ``onRemove()``
49
- Runs when the controller is being removed. Return ``false`` to block
50
- removal.
51
-
52
- Example lifecycle
53
- -----------------
54
-
55
- .. code-block:: javascript
56
-
57
- class ProductList extends AbstractSDC {
58
- constructor() {
59
- super();
60
- this.contentUrl = "/sdc_view/shop/product-list/";
61
- }
62
-
63
- onInit(categoryId) {
64
- this.categoryId = categoryId;
65
- }
66
-
67
- onLoad(html) {
68
- $(html).find(".title").text(`Category ${this.categoryId}`);
69
- return super.onLoad(html);
70
- }
71
-
72
- willShow() {
73
- this.loadedAt = Date.now();
74
- }
75
-
76
- onRefresh() {
77
- console.log("ProductList refreshed");
78
- }
79
- }
80
-
81
- DOM events
82
- ----------
83
-
84
- Controller events are delegated through the document window and stored as
85
- ``sdc_<event-name>`` attributes on matching elements.
86
-
87
- Example:
88
-
89
- .. code-block:: javascript
90
-
91
- class TodoList extends AbstractSDC {
92
- constructor() {
93
- super();
94
- this.events.unshift({
95
- click: {
96
- ".add-button": "addItem",
97
- ".delete-button": "deleteItem",
98
- },
99
- submit: {
100
- "form": "saveForm",
101
- },
102
- });
103
- }
104
-
105
- addItem($element, event) {}
106
- deleteItem($element, event) {}
107
- saveForm($element, event) {}
108
- }
109
-
110
- The handler receives:
111
-
112
- - the matched jQuery element
113
- - the original browser event
114
-
115
- You can also register events at runtime with ``addEvent(event, selector,
116
- handler)``.
117
-
118
- Mixins
119
- ------
120
-
121
- Controllers can aggregate other registered controller classes as mixins.
122
-
123
- .. code-block:: javascript
124
-
125
- app.register(BaseList);
126
- app.register(Sortable);
127
- app.register(Filterable);
128
-
129
- app.register(ProductList)
130
- .addMixin(Sortable, Filterable);
131
-
132
- Mixin methods and event definitions are merged into the controller instance.
133
- Lifecycle methods on mixins are invoked through ``AbstractSDC._runLifecycle()``.
134
-
135
- Refresh, reload, and reconciliation
136
- -----------------------------------
137
-
138
- ``refresh()``
139
- Re-runs nested controller replacement and handler-bound ``<this.*>`` DOM
140
- fragments inside the controller container.
141
-
142
- ``reload()``
143
- Reloads the controller HTML from ``contentUrl`` and reconciles it into the
144
- existing DOM tree.
145
-
146
- ``reconcile($virtualNode, $realNode = null)``
147
- Diffs the virtual and real DOM trees and preserves matching elements where
148
- possible. This is used to keep elements such as form inputs stable across
149
- updates.
150
-
151
- Safe DOM helpers
152
- ----------------
153
-
154
- The runtime installs jQuery helpers:
155
-
156
- - ``$elem.safeReplace($new)``
157
- - ``$elem.safeEmpty()``
158
- - ``$elem.safeRemove()``
159
-
160
- These helpers call controller removal logic before modifying the DOM so child
161
- controllers can clean up sockets, events, and internal state.
162
-
163
- Rendering dynamic fragments with ``sdcDom`` and ``<this.*>``
164
- ------------------------------------------------------------
165
-
166
- The global ``window.sdcDom()`` helper creates DOM fragments compatible with
167
- the controller refresh pipeline.
168
-
169
- When the tag name is a function, the runtime creates a ``<this.functionName>``
170
- placeholder that is rebound during refresh.
171
-
172
- This enables patterns like:
173
-
174
- .. code-block:: javascript
175
-
176
- class Demo extends AbstractSDC {
177
- onLoad(html) {
178
- $(html).append("<this.listview></this.listview>");
179
- return super.onLoad(html);
180
- }
181
-
182
- listview() {
183
- return "<div>Dynamic content</div>";
184
- }
185
- }
186
-
187
- During ``refresh()``, the runtime resolves these placeholders by calling the
188
- matching controller method and reconciling the result into the current DOM.
189
-
190
- Backend method calls
191
- --------------------
192
-
193
- Use ``serverCall(methodName, args)`` to invoke a backend controller method.
194
-
195
- .. code-block:: javascript
196
-
197
- class InvoiceEditor extends AbstractSDC {
198
- approve() {
199
- return this.serverCall("approve", { approved: true });
200
- }
201
- }
202
-
203
- ``serverCall()`` uses:
204
-
205
- - AJAX if ``window.SERVER_CALL_VIA_WEB_SOCKET`` is falsy
206
- - WebSockets if it is truthy
207
-
208
- For ``serverCall()`` to work, ``contentUrl`` must contain an ``sdc_view/<app>/``
209
- segment so the client can infer the backend app name.
210
-
211
- Model-aware forms
212
- -----------------
213
-
214
- ``AbstractSDC`` includes a default model form submit pipeline.
215
-
216
- ``submitModelFormDistributor($form, event)``
217
- Dispatches to ``_submitModelForm()``, ``submitModelForm()``, or
218
- ``defaultSubmitModelForm()``.
219
-
220
- ``defaultSubmitModelForm($form, event)``
221
- Reads the model from form metadata, submits ``save()`` or ``create()``,
222
- clears validation errors on success, and reconciles returned error HTML on
223
- failure.
224
-
225
- Controllers and their descendants can react to the result through:
226
-
227
- - ``submit_model_form_success(result)``
228
- - ``submit_model_form_error(errorData)``
@@ -1,120 +0,0 @@
1
- Events and DOM
2
- ==============
3
-
4
- Application event bus
5
- ---------------------
6
-
7
- SimpleDomControlClient includes a small application-level event bus in addition
8
- to browser DOM events.
9
-
10
- Exports:
11
-
12
- - ``setEvent(name, functionName = name)``
13
- - ``on(name, controller)``
14
- - ``trigger(name, ...args)``
15
- - ``allOff(controller)``
16
-
17
- Usage:
18
-
19
- .. code-block:: javascript
20
-
21
- import { setEvent, on, trigger } from "sdc_client";
22
-
23
- setEvent("pushMsg", "handleMessage");
24
-
25
- class Toasts {
26
- handleMessage(title, message) {
27
- console.log(title, message);
28
- }
29
- }
30
-
31
- const toasts = new Toasts();
32
- on("pushMsg", toasts);
33
- trigger("pushMsg", "Saved", "The item was stored.");
34
-
35
- The server transport uses this event bus to emit:
36
-
37
- - ``pushMsg`` for non-error messages
38
- - ``pushErrorMsg`` for error messages
39
- - ``onNavLink`` for redirects
40
-
41
- DOM event delegation
42
- --------------------
43
-
44
- The DOM event system listens on ``window`` for standard browser events and
45
- dispatches them to controller handlers declared on matching elements.
46
-
47
- The pipeline works as follows:
48
-
49
- 1. ``initEvents()`` subscribes to standard browser events.
50
- 2. When jQuery triggers a previously unseen custom event, the runtime adds it
51
- to the watched event list automatically.
52
- 3. ``windowEventHandler()`` walks from the event target upward through the DOM.
53
- 4. For each element with a matching ``sdc_<event>`` attribute, the handler
54
- resolves the owning controller.
55
- 5. The handler name is matched either directly on the controller or through the
56
- controller event map.
57
-
58
- Declarative event attributes
59
- ----------------------------
60
-
61
- Elements can carry event attributes directly:
62
-
63
- .. code-block:: html
64
-
65
- <button sdc_click="save">Save</button>
66
-
67
- If ``save`` exists on the current controller, it will be called with:
68
-
69
- - ``$element``: the matched jQuery element
70
- - ``event``: the native event object
71
-
72
- Controller event maps
73
- ---------------------
74
-
75
- A more maintainable pattern is to define events in the controller:
76
-
77
- .. code-block:: javascript
78
-
79
- this.events.unshift({
80
- click: {
81
- ".save-button": "save",
82
- ".delete-button": "removeItem",
83
- },
84
- });
85
-
86
- At refresh time, ``setControllerEvents()`` finds the matching selectors and
87
- adds internal ``sdc_<event>`` attributes to the corresponding DOM nodes.
88
-
89
- DOM reconciliation
90
- ------------------
91
-
92
- The client contains a custom reconciliation step used by ``app.reconcile()``
93
- and controller refresh operations.
94
-
95
- Goals of reconciliation:
96
-
97
- - keep matching DOM branches when possible
98
- - update attributes and data bindings
99
- - preserve stable nodes such as input elements
100
- - remove and insert only what changed
101
-
102
- The implementation builds trees for the virtual and real DOM, computes a
103
- longest-common-branch style diff, then applies keep, delete, and insert
104
- operations in index order.
105
-
106
- This is the main reason refreshed content can preserve existing input elements
107
- instead of replacing them outright.
108
-
109
- Safe removal semantics
110
- ----------------------
111
-
112
- Always prefer the SDC-safe helpers over direct jQuery removal when a subtree may
113
- contain controllers:
114
-
115
- - ``app.safeRemove($elem)``
116
- - ``app.safeEmpty($elem)``
117
- - ``app.safeReplace($elem, $new)``
118
-
119
- These helpers call controller ``remove()`` methods first so child controllers
120
- can unregister application events, close sockets, and clean up forms.
@@ -1,143 +0,0 @@
1
- Getting Started
2
- ===============
3
-
4
- Requirements
5
- ------------
6
-
7
- SimpleDomControlClient is designed to be used together with the Django package
8
- ``simpledomcontrol``. The backend is expected to provide:
9
-
10
- - Controller content endpoints referenced by ``contentUrl``.
11
- - Optional server controller methods for ``serverCall()``.
12
- - Model WebSocket endpoints for ``SdcQuerySet`` and ``SdcModel`` usage.
13
- - Global values such as ``window.CSRF_TOKEN`` and optionally
14
- ``window.SERVER_CALL_VIA_WEB_SOCKET``.
15
-
16
- Installation
17
- ------------
18
-
19
- Install the package in a frontend project:
20
-
21
- .. code-block:: bash
22
-
23
- yarn add sdc_client
24
-
25
- or:
26
-
27
- .. code-block:: bash
28
-
29
- npm install sdc_client
30
-
31
- Basic bootstrap
32
- ---------------
33
-
34
- Import the runtime, define a controller, register it, and call ``init_sdc()``.
35
-
36
- .. code-block:: javascript
37
-
38
- import { app, AbstractSDC } from "sdc_client";
39
-
40
- class HelloWorld extends AbstractSDC {
41
- constructor() {
42
- super();
43
- this.contentUrl = "/sdc_view/demo/hello-world/";
44
- this.events.unshift({
45
- click: {
46
- ".reload-button": "handleReload",
47
- },
48
- });
49
- }
50
-
51
- onInit(name = "World") {
52
- this.name = name;
53
- }
54
-
55
- handleReload() {
56
- return this.reload();
57
- }
58
- }
59
-
60
- app.register(HelloWorld);
61
- app.init_sdc();
62
-
63
- In the HTML:
64
-
65
- .. code-block:: html
66
-
67
- <hello-world data-name='"Ada"'></hello-world>
68
-
69
- Tag name mapping
70
- ----------------
71
-
72
- Controller classes are mapped to tag names automatically.
73
-
74
- - ``HelloWorld`` becomes ``<hello-world>``.
75
- - A class ending in ``Controller`` has the suffix removed.
76
- - ``UserListController`` becomes ``<user-list>``.
77
-
78
- The mapping is implemented by ``app.controllerToTag()``.
79
-
80
- Controller content loading
81
- --------------------------
82
-
83
- If a controller sets ``contentUrl``, the runtime fetches HTML for that
84
- controller before rendering nested child controllers.
85
-
86
- Important behavior:
87
-
88
- - ``contentUrl = ""`` means no remote HTML is fetched.
89
- - URLs containing placeholder values such as ``"%(user_id)s"`` are re-parsed
90
- from DOM data attributes and force ``contentReload = true``.
91
- - Responses are cached per controller tag unless ``contentReload`` is true.
92
-
93
- Using ``data-*`` parameters
94
- ---------------------------
95
-
96
- ``onInit()`` arguments are populated from the DOM element's ``data-*``
97
- attributes. The final argument is always an object with the remaining data
98
- values.
99
-
100
- Example:
101
-
102
- .. code-block:: html
103
-
104
- <user-card
105
- data-user-id="7"
106
- data-title='"Admin"'
107
- data-active="true">
108
- </user-card>
109
-
110
- .. code-block:: javascript
111
-
112
- class UserCard extends AbstractSDC {
113
- onInit(userId, title, active, rest) {
114
- this.userId = userId; // 7
115
- this.title = title; // "Admin"
116
- this.active = active; // true
117
- this.rest = rest; // remaining data attributes
118
- }
119
- }
120
-
121
- The parameter parser converts:
122
-
123
- - integers to ``number``
124
- - floats to ``number``
125
- - ``true`` and ``false`` to ``boolean``
126
- - ``none`` to ``null``
127
- - ``undefined`` to ``undefined``
128
- - quoted strings to plain strings
129
- - controller property names to the corresponding controller value or method
130
-
131
- Global controllers
132
- ------------------
133
-
134
- Register a controller as global when it should be instantiated once and exposed
135
- through the global controller tree rather than repeated per matching DOM
136
- container.
137
-
138
- .. code-block:: javascript
139
-
140
- app.registerGlobal(NotificationsController);
141
-
142
- Global controllers are created during ``app.init_sdc()`` before regular body
143
- controllers are resolved.
package/docs/index.rst DELETED
@@ -1,22 +0,0 @@
1
- SimpleDomControlClient
2
- ======================
3
-
4
- SimpleDomControlClient is the browser-side runtime for the Django package
5
- ``simpledomcontrol``. It scans the DOM for registered custom tags, creates
6
- controller instances, loads HTML fragments from the server, binds DOM events,
7
- and synchronizes model data through AJAX and WebSockets.
8
-
9
- This documentation is organized around the way the library is used in a real
10
- application: bootstrap the runtime, register controllers, render content,
11
- handle events, and talk to server-backed models.
12
-
13
- .. toctree::
14
- :maxdepth: 2
15
- :caption: Contents
16
-
17
- overview
18
- getting-started
19
- controllers
20
- models
21
- events-and-dom
22
- api-reference