odac 0.9.0 → 1.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.
- package/.github/workflows/auto-pr-description.yml +0 -2
- package/.github/workflows/codeql.yml +46 -0
- package/.github/workflows/release.yml +13 -6
- package/.github/workflows/test-coverage.yml +10 -9
- package/.releaserc.js +9 -6
- package/CHANGELOG.md +62 -150
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTING.md +8 -8
- package/LICENSE +21 -661
- package/README.md +12 -12
- package/SECURITY.md +4 -4
- package/bin/odac.js +101 -0
- package/{framework/web/candy.js → client/odac.js} +310 -44
- package/docs/backend/01-overview/{01-whats-in-the-candy-box.md → 01-whats-in-the-odac-box.md} +4 -2
- package/docs/backend/01-overview/02-super-handy-helper-functions.md +29 -1
- package/docs/backend/01-overview/03-development-server.md +11 -11
- package/docs/backend/02-structure/01-typical-project-layout.md +4 -4
- package/docs/backend/03-config/00-configuration-overview.md +6 -6
- package/docs/backend/03-config/01-database-connection.md +1 -1
- package/docs/backend/03-config/02-static-route-mapping-optional.md +4 -4
- package/docs/backend/03-config/04-environment-variables.md +20 -20
- package/docs/backend/03-config/05-early-hints.md +4 -4
- package/docs/backend/04-routing/01-basic-page-routes.md +4 -4
- package/docs/backend/04-routing/02-controller-less-view-routes.md +5 -5
- package/docs/backend/04-routing/03-api-and-data-routes.md +3 -3
- package/docs/backend/04-routing/04-authentication-aware-routes.md +5 -5
- package/docs/backend/04-routing/05-advanced-routing.md +3 -3
- package/docs/backend/04-routing/06-error-pages.md +17 -17
- package/docs/backend/04-routing/07-cron-jobs.md +13 -13
- package/docs/backend/04-routing/08-middleware.md +214 -0
- package/docs/backend/04-routing/09-websocket-auth-middleware.md +292 -0
- package/docs/backend/04-routing/09-websocket-examples.md +381 -0
- package/docs/backend/04-routing/09-websocket-quick-reference.md +211 -0
- package/docs/backend/04-routing/09-websocket.md +298 -0
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +3 -3
- package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +41 -0
- package/docs/backend/05-controllers/03-controller-classes.md +19 -19
- package/docs/backend/05-forms/01-custom-forms.md +114 -114
- package/docs/backend/05-forms/02-automatic-database-insert.md +82 -82
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +26 -26
- package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +10 -10
- package/docs/backend/07-views/01-the-view-directory.md +1 -1
- package/docs/backend/07-views/02-rendering-a-view.md +22 -22
- package/docs/backend/07-views/03-template-syntax.md +52 -52
- package/docs/backend/07-views/03-variables.md +84 -84
- package/docs/backend/07-views/04-request-data.md +57 -57
- package/docs/backend/07-views/05-conditionals.md +78 -78
- package/docs/backend/07-views/06-loops.md +114 -114
- package/docs/backend/07-views/07-translations.md +66 -66
- package/docs/backend/07-views/08-backend-javascript.md +103 -103
- package/docs/backend/07-views/09-comments.md +71 -71
- package/docs/backend/08-database/01-database-connection.md +8 -8
- package/docs/backend/08-database/02-using-mysql.md +49 -49
- package/docs/backend/09-validation/01-the-validator-service.md +38 -38
- package/docs/backend/10-authentication/01-user-logins-with-authjs.md +15 -15
- package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +10 -10
- package/docs/backend/10-authentication/03-register.md +12 -12
- package/docs/backend/10-authentication/{04-candy-register-forms.md → 04-odac-register-forms.md} +141 -141
- package/docs/backend/10-authentication/05-session-management.md +10 -10
- package/docs/backend/10-authentication/{06-candy-login-forms.md → 06-odac-login-forms.md} +125 -125
- package/docs/backend/11-mail/01-the-mail-service.md +5 -5
- package/docs/backend/12-streaming/01-streaming-overview.md +96 -54
- package/docs/backend/13-utilities/{01-candy-var.md → 01-odac-var.md} +109 -109
- package/docs/frontend/01-overview/01-introduction.md +30 -30
- package/docs/frontend/02-ajax-navigation/01-quick-start.md +45 -45
- package/docs/frontend/02-ajax-navigation/02-configuration.md +14 -14
- package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +36 -36
- package/docs/frontend/03-forms/01-form-handling.md +32 -32
- package/docs/frontend/04-api-requests/01-get-post.md +33 -33
- package/docs/frontend/05-streaming/01-client-streaming.md +15 -15
- package/docs/frontend/06-websocket/00-overview.md +76 -0
- package/docs/frontend/06-websocket/01-websocket-client.md +139 -0
- package/docs/frontend/06-websocket/02-shared-websocket.md +149 -0
- package/docs/index.json +49 -11
- package/eslint.config.mjs +6 -6
- package/{framework/index.js → index.js} +1 -1
- package/package.json +14 -39
- package/{framework/src → src}/Auth.js +59 -59
- package/{framework/src → src}/Config.js +3 -3
- package/{framework/src → src}/Lang.js +7 -7
- package/{framework/src → src}/Mail.js +5 -5
- package/{framework/src → src}/Mysql.js +42 -42
- package/src/Odac.js +112 -0
- package/{framework/src → src}/Request.js +38 -36
- package/{framework/src → src}/Route/Internal.js +116 -116
- package/src/Route/Middleware.js +75 -0
- package/src/Route.js +621 -0
- package/src/Server.js +22 -0
- package/{framework/src → src}/Stream.js +11 -3
- package/{framework/src → src}/Validator.js +21 -21
- package/{framework/src → src}/Var.js +5 -5
- package/{framework/src → src}/View/EarlyHints.js +1 -1
- package/{framework/src → src}/View/Form.js +69 -69
- package/{framework/src → src}/View.js +78 -81
- package/src/WebSocket.js +403 -0
- package/template/config.json +5 -0
- package/{web → template}/controller/page/about.js +6 -6
- package/{web → template}/controller/page/index.js +9 -9
- package/{web → template}/package.json +4 -5
- package/{web → template}/public/assets/css/style.css +4 -4
- package/{web → template}/public/assets/js/app.js +6 -6
- package/{web → template}/route/www.js +6 -6
- package/{web → template}/skeleton/main.html +1 -1
- package/{web → template}/view/content/about.html +5 -5
- package/{web → template}/view/content/home.html +12 -12
- package/template/view/footer/main.html +11 -0
- package/{web → template}/view/head/main.html +1 -1
- package/{web → template}/view/header/main.html +2 -2
- package/test/core/Candy.test.js +58 -58
- package/test/core/Commands.test.js +7 -7
- package/test/core/Config.test.js +82 -85
- package/test/core/Lang.test.js +2 -2
- package/test/core/Process.test.js +6 -6
- package/test/framework/Route.test.js +56 -37
- package/test/framework/View/EarlyHints.test.js +2 -2
- package/test/framework/WebSocket.test.js +100 -0
- package/test/framework/middleware.test.js +85 -0
- package/test/server/Api.test.js +31 -31
- package/test/server/DNS.test.js +11 -11
- package/test/server/Hub.test.js +497 -0
- package/test/server/Mail.account.test_.js +3 -3
- package/test/server/Mail.init.test_.js +10 -10
- package/test/server/Mail.test_.js +20 -20
- package/test/server/SSL.test_.js +54 -54
- package/test/server/Server.test.js +39 -39
- package/test/server/Service.test_.js +7 -7
- package/test/server/Subdomain.test.js +7 -7
- package/test/server/Web/Firewall.test.js +87 -87
- package/test/server/Web/Proxy.test.js +397 -0
- package/test/server/{Web.test_.js → Web.test.js} +137 -205
- package/test/server/__mocks__/fs.js +2 -2
- package/test/server/__mocks__/{globalCandy.js → globalOdac.js} +5 -5
- package/test/server/__mocks__/index.js +6 -6
- package/test/server/__mocks__/testFactories.js +1 -1
- package/test/server/__mocks__/testHelpers.js +7 -7
- package/.husky/pre-commit +0 -2
- package/.kiro/steering/code-style.md +0 -56
- package/.kiro/steering/product.md +0 -20
- package/.kiro/steering/structure.md +0 -77
- package/.kiro/steering/tech.md +0 -87
- package/AGENTS.md +0 -84
- package/bin/candy +0 -10
- package/bin/candypack +0 -10
- package/cli/index.js +0 -3
- package/cli/src/Cli.js +0 -348
- package/cli/src/Connector.js +0 -93
- package/cli/src/Monitor.js +0 -416
- package/core/Candy.js +0 -87
- package/core/Commands.js +0 -239
- package/core/Config.js +0 -1094
- package/core/Lang.js +0 -52
- package/core/Log.js +0 -43
- package/core/Process.js +0 -26
- package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +0 -20
- package/docs/server/01-installation/01-quick-install.md +0 -19
- package/docs/server/01-installation/02-manual-installation-via-npm.md +0 -9
- package/docs/server/02-get-started/01-core-concepts.md +0 -7
- package/docs/server/02-get-started/02-basic-commands.md +0 -57
- package/docs/server/02-get-started/03-cli-reference.md +0 -276
- package/docs/server/02-get-started/04-cli-quick-reference.md +0 -102
- package/docs/server/03-service/01-start-a-new-service.md +0 -57
- package/docs/server/03-service/02-delete-a-service.md +0 -48
- package/docs/server/04-web/01-create-a-website.md +0 -36
- package/docs/server/04-web/02-list-websites.md +0 -9
- package/docs/server/04-web/03-delete-a-website.md +0 -29
- package/docs/server/05-subdomain/01-create-a-subdomain.md +0 -32
- package/docs/server/05-subdomain/02-list-subdomains.md +0 -33
- package/docs/server/05-subdomain/03-delete-a-subdomain.md +0 -41
- package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +0 -34
- package/docs/server/07-mail/01-create-a-mail-account.md +0 -23
- package/docs/server/07-mail/02-delete-a-mail-account.md +0 -20
- package/docs/server/07-mail/03-list-mail-accounts.md +0 -20
- package/docs/server/07-mail/04-change-account-password.md +0 -23
- package/framework/src/Candy.js +0 -81
- package/framework/src/Route.js +0 -455
- package/framework/src/Server.js +0 -15
- package/locale/de-DE.json +0 -80
- package/locale/en-US.json +0 -79
- package/locale/es-ES.json +0 -80
- package/locale/fr-FR.json +0 -80
- package/locale/pt-BR.json +0 -80
- package/locale/ru-RU.json +0 -80
- package/locale/tr-TR.json +0 -85
- package/locale/zh-CN.json +0 -80
- package/server/index.js +0 -5
- package/server/src/Api.js +0 -88
- package/server/src/DNS.js +0 -940
- package/server/src/Hub.js +0 -535
- package/server/src/Mail.js +0 -571
- package/server/src/SSL.js +0 -180
- package/server/src/Server.js +0 -27
- package/server/src/Service.js +0 -248
- package/server/src/Subdomain.js +0 -64
- package/server/src/Web/Firewall.js +0 -170
- package/server/src/Web/Proxy.js +0 -134
- package/server/src/Web.js +0 -451
- package/server/src/mail/imap.js +0 -1091
- package/server/src/mail/server.js +0 -32
- package/server/src/mail/smtp.js +0 -786
- package/test/server/Client.test.js +0 -338
- package/test/server/__mocks__/http-proxy.js +0 -105
- package/watchdog/index.js +0 -3
- package/watchdog/src/Watchdog.js +0 -156
- package/web/config.json +0 -5
- package/web/view/footer/main.html +0 -11
- /package/{framework/src → src}/Env.js +0 -0
- /package/{framework/src → src}/Route/Cron.js +0 -0
- /package/{framework/src → src}/Token.js +0 -0
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
# Frontend Javascript Framework:
|
|
1
|
+
# Frontend Javascript Framework: odac.js
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`odac.js` is a lightweight frontend JavaScript framework designed to simplify interactions with the backend, handle forms, and manage page-specific logic within the Odac ecosystem. It provides a set of tools for event handling, AJAX requests, and more, all accessible through the global `odac` object.
|
|
4
4
|
|
|
5
|
-
## The Global `
|
|
5
|
+
## The Global `odac` Object
|
|
6
6
|
|
|
7
|
-
After including `
|
|
7
|
+
After including `odac.js` in your page, you will have access to a global `odac` object. This object is the main entry point for all the features of the framework.
|
|
8
8
|
|
|
9
9
|
## Core Concepts
|
|
10
10
|
|
|
11
11
|
### Actions
|
|
12
12
|
|
|
13
|
-
Actions are the fundamental building block of `
|
|
13
|
+
Actions are the fundamental building block of `odac.js`. An action is a collection of event handlers and lifecycle callbacks that define the behavior of a page or a component.
|
|
14
14
|
|
|
15
15
|
### Pages
|
|
16
16
|
|
|
17
|
-
`
|
|
17
|
+
`odac.js` has a concept of "pages", which allows you to scope your JavaScript to a specific page. The current page identifier is determined by the backend based on:
|
|
18
18
|
- **Controller name** when using controller files (e.g., `'user'` for `controller/page/user.js`)
|
|
19
19
|
- **View name** when using view objects (e.g., `'dashboard'` from `{content: 'dashboard'}`)
|
|
20
|
-
- This identifier is accessible via `
|
|
20
|
+
- This identifier is accessible via `Odac.page()` and stored in `data-odac-page` attribute on the `<html>` element.
|
|
21
21
|
|
|
22
22
|
### Lifecycle Events
|
|
23
23
|
|
|
24
|
-
`
|
|
24
|
+
`odac.js` provides several lifecycle events that you can hook into:
|
|
25
25
|
- `start`: Fired once when the script is initialized.
|
|
26
26
|
- `load`: Fired on every page load, after the DOM is ready.
|
|
27
27
|
- `page`: Fired on a specific page, after the DOM is ready.
|
|
28
28
|
- `interval`: Fired repeatedly at a specified interval.
|
|
29
29
|
|
|
30
|
-
## Event Handling with `
|
|
30
|
+
## Event Handling with `Odac.action()`
|
|
31
31
|
|
|
32
|
-
The `
|
|
32
|
+
The `Odac.action()` method is the most important method in the framework. It allows you to register event handlers and lifecycle callbacks.
|
|
33
33
|
|
|
34
34
|
```javascript
|
|
35
|
-
|
|
35
|
+
Odac.action({
|
|
36
36
|
// Fired once on DOMContentLoaded
|
|
37
37
|
start: function() {
|
|
38
|
-
console.log('
|
|
38
|
+
console.log('odac.js started!');
|
|
39
39
|
},
|
|
40
40
|
|
|
41
41
|
// Fired on every page load
|
|
@@ -82,19 +82,19 @@ Candy.action({
|
|
|
82
82
|
});
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
## Working with Forms using `
|
|
85
|
+
## Working with Forms using `Odac.form()`
|
|
86
86
|
|
|
87
|
-
`
|
|
87
|
+
`Odac.form()` simplifies AJAX form submissions. It handles serialization, validation feedback, success messages, and file uploads automatically.
|
|
88
88
|
|
|
89
89
|
```javascript
|
|
90
90
|
// Basic usage
|
|
91
|
-
|
|
91
|
+
odac.form('#my-form', function(data) {
|
|
92
92
|
// This callback is executed on success
|
|
93
93
|
console.log('Form submitted successfully!', data);
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
// With options
|
|
97
|
-
|
|
97
|
+
odac.form({
|
|
98
98
|
form: '#my-form',
|
|
99
99
|
messages: ['success', 'error'], // Show both success and error messages
|
|
100
100
|
loading: function(percent) {
|
|
@@ -107,40 +107,40 @@ Candy.form({
|
|
|
107
107
|
}
|
|
108
108
|
});
|
|
109
109
|
```
|
|
110
|
-
To display validation errors, you can add elements with the `
|
|
110
|
+
To display validation errors, you can add elements with the `odac-form-error` attribute to your form. The value of the attribute should be the `name` of the input field.
|
|
111
111
|
|
|
112
112
|
```html
|
|
113
113
|
<input type="text" name="email">
|
|
114
|
-
<span
|
|
114
|
+
<span odac-form-error="email"></span>
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
## Making AJAX requests with `
|
|
117
|
+
## Making AJAX requests with `Odac.get()`
|
|
118
118
|
|
|
119
|
-
For simple GET requests, you can use the `
|
|
119
|
+
For simple GET requests, you can use the `Odac.get()` method.
|
|
120
120
|
|
|
121
121
|
```javascript
|
|
122
|
-
|
|
122
|
+
odac.get('/api/users', function(data) {
|
|
123
123
|
console.log('Users:', data);
|
|
124
124
|
});
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
## Managing CSRF tokens with `
|
|
127
|
+
## Managing CSRF tokens with `Odac.token()`
|
|
128
128
|
|
|
129
|
-
`
|
|
129
|
+
`odac.js` automatically manages CSRF tokens for you. The `Odac.token()` method will return a valid token for your requests. The `Odac.form()` and `Odac.get()` methods use this automatically, so you usually don't need to call it yourself.
|
|
130
130
|
|
|
131
131
|
## Other Utility Functions
|
|
132
132
|
|
|
133
|
-
- **`
|
|
134
|
-
- **`
|
|
135
|
-
- **`
|
|
136
|
-
- **`
|
|
133
|
+
- **`Odac.client()`**: Returns a unique client identifier from a cookie.
|
|
134
|
+
- **`Odac.data()`**: Returns data from the `candy_data` cookie, which is set by the backend. This data includes the current page and the initial CSRF token.
|
|
135
|
+
- **`Odac.page()`**: Returns the identifier of the current page. This is the controller name (e.g., `'user'`) or view name (e.g., `'dashboard'`) set by the backend. Use this to conditionally run code for specific pages.
|
|
136
|
+
- **`Odac.storage()`**: A wrapper for `localStorage`.
|
|
137
137
|
```javascript
|
|
138
138
|
// Set a value
|
|
139
|
-
|
|
139
|
+
odac.storage('my-key', 'my-value');
|
|
140
140
|
|
|
141
141
|
// Get a value
|
|
142
|
-
let value =
|
|
142
|
+
let value = odac.storage('my-key');
|
|
143
143
|
|
|
144
144
|
// Remove a value
|
|
145
|
-
|
|
145
|
+
odac.storage('my-key', null);
|
|
146
146
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AJAX Navigation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Odac framework includes a built-in AJAX navigation system that enables smooth, single-page application (SPA) style navigation without full page reloads.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ CandyPack framework includes a built-in AJAX navigation system that enables smoo
|
|
|
19
19
|
Just enable navigation - it automatically handles all internal links:
|
|
20
20
|
|
|
21
21
|
```javascript
|
|
22
|
-
|
|
22
|
+
Odac.action({
|
|
23
23
|
navigate: 'main' // Update <main> element on navigation
|
|
24
24
|
})
|
|
25
25
|
```
|
|
@@ -31,7 +31,7 @@ That's it! All links starting with `/` will now load via AJAX.
|
|
|
31
31
|
Add a callback for post-navigation actions:
|
|
32
32
|
|
|
33
33
|
```javascript
|
|
34
|
-
|
|
34
|
+
Odac.action({
|
|
35
35
|
navigate: {
|
|
36
36
|
update: 'main',
|
|
37
37
|
on: function(page, variables) {
|
|
@@ -47,7 +47,7 @@ Candy.action({
|
|
|
47
47
|
Full control over navigation behavior:
|
|
48
48
|
|
|
49
49
|
```javascript
|
|
50
|
-
|
|
50
|
+
Odac.action({
|
|
51
51
|
navigate: {
|
|
52
52
|
links: 'a[href^="/"]', // Which links to intercept
|
|
53
53
|
update: { // Which elements to update
|
|
@@ -94,7 +94,7 @@ Example `skeleton/main.html`:
|
|
|
94
94
|
<html>
|
|
95
95
|
<head>
|
|
96
96
|
<title>My Site</title>
|
|
97
|
-
<script src="/assets/js/
|
|
97
|
+
<script src="/assets/js/odac.js"></script>
|
|
98
98
|
<script src="/assets/js/app.js"></script>
|
|
99
99
|
</head>
|
|
100
100
|
<body>
|
|
@@ -120,22 +120,22 @@ Example `skeleton/main.html`:
|
|
|
120
120
|
|
|
121
121
|
### Controller Setup
|
|
122
122
|
|
|
123
|
-
Controllers automatically support AJAX loading. Use `
|
|
123
|
+
Controllers automatically support AJAX loading. Use `Odac.View.skeleton()` to specify which skeleton to use:
|
|
124
124
|
|
|
125
125
|
```javascript
|
|
126
|
-
module.exports = function (
|
|
126
|
+
module.exports = function (Odac) {
|
|
127
127
|
// Define the skeleton template
|
|
128
|
-
|
|
128
|
+
odac.View.skeleton('main')
|
|
129
129
|
|
|
130
130
|
// Set view parts - lowercase keys map to UPPERCASE placeholders
|
|
131
|
-
|
|
131
|
+
odac.View.set({
|
|
132
132
|
header: 'main', // Loads view/header/main.html into {{ HEADER }}
|
|
133
133
|
content: 'about', // Loads view/content/about.html into {{ CONTENT }}
|
|
134
134
|
footer: 'main' // Loads view/footer/main.html into {{ FOOTER }}
|
|
135
135
|
})
|
|
136
136
|
|
|
137
137
|
// Optional: Send variables to frontend (AJAX only)
|
|
138
|
-
|
|
138
|
+
odac.set({
|
|
139
139
|
pageTitle: 'About',
|
|
140
140
|
data: {foo: 'bar'}
|
|
141
141
|
}, true) // true = include in AJAX responses
|
|
@@ -159,8 +159,8 @@ module.exports = function (Candy) {
|
|
|
159
159
|
|
|
160
160
|
1. User clicks `<a href="/about">`
|
|
161
161
|
2. JavaScript intercepts click and sends AJAX request with:
|
|
162
|
-
- Header: `X-
|
|
163
|
-
- Header: `X-
|
|
162
|
+
- Header: `X-Odac: ajaxload`
|
|
163
|
+
- Header: `X-Odac-Load: content,header` (requested sections)
|
|
164
164
|
3. Server detects AJAX request and returns only requested sections as JSON:
|
|
165
165
|
```json
|
|
166
166
|
{
|
|
@@ -179,20 +179,20 @@ module.exports = function (Candy) {
|
|
|
179
179
|
6. Page-specific callbacks execute
|
|
180
180
|
|
|
181
181
|
**Key Points:**
|
|
182
|
-
- The `output` keys in the JSON response match the lowercase keys from `
|
|
182
|
+
- The `output` keys in the JSON response match the lowercase keys from `Odac.View.set()` in your controller
|
|
183
183
|
- These keys correspond to UPPERCASE placeholders in your skeleton (e.g., `content` → `{{ CONTENT }}`)
|
|
184
184
|
- Only the sections specified in `navigate.update` are sent and updated
|
|
185
185
|
- Frontend selectors target the HTML tags wrapping the placeholders
|
|
186
186
|
|
|
187
187
|
## API Reference
|
|
188
188
|
|
|
189
|
-
###
|
|
189
|
+
### Odac.action({ navigate: ... })
|
|
190
190
|
|
|
191
191
|
Initialize AJAX navigation using the action system.
|
|
192
192
|
|
|
193
193
|
#### Minimal Usage
|
|
194
194
|
```javascript
|
|
195
|
-
|
|
195
|
+
Odac.action({
|
|
196
196
|
navigate: 'main' // Just specify element to update
|
|
197
197
|
})
|
|
198
198
|
```
|
|
@@ -201,7 +201,7 @@ Candy.action({
|
|
|
201
201
|
|
|
202
202
|
#### Medium Usage
|
|
203
203
|
```javascript
|
|
204
|
-
|
|
204
|
+
Odac.action({
|
|
205
205
|
navigate: {
|
|
206
206
|
update: 'main', // Element to update
|
|
207
207
|
on: function(page, vars) { // Callback after navigation
|
|
@@ -213,7 +213,7 @@ Candy.action({
|
|
|
213
213
|
|
|
214
214
|
#### Advanced Usage
|
|
215
215
|
```javascript
|
|
216
|
-
|
|
216
|
+
Odac.action({
|
|
217
217
|
navigate: {
|
|
218
218
|
links: 'a[href^="/"]', // Which links to intercept
|
|
219
219
|
update: { // Multiple elements to update
|
|
@@ -232,12 +232,12 @@ Candy.action({
|
|
|
232
232
|
|
|
233
233
|
#### Boolean Usage
|
|
234
234
|
```javascript
|
|
235
|
-
|
|
235
|
+
Odac.action({
|
|
236
236
|
navigate: true // Enable with all defaults
|
|
237
237
|
})
|
|
238
238
|
|
|
239
239
|
// Or disable completely
|
|
240
|
-
|
|
240
|
+
Odac.action({
|
|
241
241
|
navigate: false // Disable AJAX navigation
|
|
242
242
|
})
|
|
243
243
|
```
|
|
@@ -296,13 +296,13 @@ Both methods work automatically - no additional configuration needed!
|
|
|
296
296
|
}
|
|
297
297
|
```
|
|
298
298
|
|
|
299
|
-
###
|
|
299
|
+
### odac.loader(selector, elements, callback)
|
|
300
300
|
|
|
301
301
|
Low-level method for direct initialization (not recommended for new code).
|
|
302
302
|
|
|
303
303
|
**Parameters:** Same as navigate configuration, but as separate arguments.
|
|
304
304
|
|
|
305
|
-
###
|
|
305
|
+
### odac.load(url, callback, push)
|
|
306
306
|
|
|
307
307
|
Programmatically load a page via AJAX.
|
|
308
308
|
|
|
@@ -313,7 +313,7 @@ Programmatically load a page via AJAX.
|
|
|
313
313
|
|
|
314
314
|
**Example:**
|
|
315
315
|
```javascript
|
|
316
|
-
|
|
316
|
+
odac.load('/about', function(page, variables) {
|
|
317
317
|
console.log('Loaded:', page)
|
|
318
318
|
})
|
|
319
319
|
```
|
|
@@ -323,7 +323,7 @@ Candy.load('/about', function(page, variables) {
|
|
|
323
323
|
Run code when specific pages load. The page identifier is based on the controller name or view name:
|
|
324
324
|
|
|
325
325
|
```javascript
|
|
326
|
-
|
|
326
|
+
Odac.action({
|
|
327
327
|
page: {
|
|
328
328
|
// Runs when controller/page/index.js is used
|
|
329
329
|
index: function(variables) {
|
|
@@ -347,7 +347,7 @@ Candy.action({
|
|
|
347
347
|
**Page Identifier Rules:**
|
|
348
348
|
- **With controller**: Uses controller filename (e.g., `user.js` → `'user'`)
|
|
349
349
|
- **With view object**: Uses `content` or `all` value (e.g., `{content: 'dashboard'}` → `'dashboard'`)
|
|
350
|
-
- Accessible via `
|
|
350
|
+
- Accessible via `Odac.page()` or `document.documentElement.dataset.candyPage`
|
|
351
351
|
|
|
352
352
|
## Server Variables
|
|
353
353
|
|
|
@@ -355,7 +355,7 @@ Send data from server to client in AJAX responses:
|
|
|
355
355
|
|
|
356
356
|
```javascript
|
|
357
357
|
// In controller
|
|
358
|
-
|
|
358
|
+
odac.set({
|
|
359
359
|
user: {name: 'John', role: 'admin'},
|
|
360
360
|
stats: {views: 1234}
|
|
361
361
|
}, true) // true = include in AJAX
|
|
@@ -364,7 +364,7 @@ Candy.set({
|
|
|
364
364
|
Access in client:
|
|
365
365
|
|
|
366
366
|
```javascript
|
|
367
|
-
|
|
367
|
+
Odac.action({
|
|
368
368
|
navigate: {
|
|
369
369
|
update: 'main',
|
|
370
370
|
on: function(page, variables) {
|
|
@@ -388,25 +388,25 @@ Candy.action({
|
|
|
388
388
|
### Minimal Example
|
|
389
389
|
```javascript
|
|
390
390
|
// Just enable AJAX navigation
|
|
391
|
-
|
|
391
|
+
Odac.action({
|
|
392
392
|
navigate: 'main'
|
|
393
393
|
})
|
|
394
394
|
```
|
|
395
395
|
|
|
396
396
|
### Real-World Example
|
|
397
397
|
```javascript
|
|
398
|
-
// app.js - Everything in one
|
|
399
|
-
|
|
398
|
+
// app.js - Everything in one Odac.action() call
|
|
399
|
+
Odac.action({
|
|
400
400
|
// AJAX Navigation - automatically handles all internal links
|
|
401
401
|
navigate: {
|
|
402
402
|
update: 'main',
|
|
403
403
|
on: function(page, variables) {
|
|
404
|
-
|
|
404
|
+
odac.fn.updateActiveNav(window.location.pathname)
|
|
405
405
|
console.log('Navigated to:', page)
|
|
406
406
|
}
|
|
407
407
|
},
|
|
408
408
|
|
|
409
|
-
// Custom functions (accessible as
|
|
409
|
+
// Custom functions (accessible as odac.fn.functionName)
|
|
410
410
|
function: {
|
|
411
411
|
updateActiveNav: function(url) {
|
|
412
412
|
document.querySelectorAll('nav a').forEach(link => {
|
|
@@ -418,14 +418,14 @@ Candy.action({
|
|
|
418
418
|
// App initialization
|
|
419
419
|
load: function() {
|
|
420
420
|
console.log('App initialized')
|
|
421
|
-
|
|
421
|
+
odac.fn.updateActiveNav(window.location.pathname)
|
|
422
422
|
},
|
|
423
423
|
|
|
424
424
|
// Page-specific code
|
|
425
425
|
page: {
|
|
426
426
|
index: function(variables) {
|
|
427
427
|
// Home page specific code
|
|
428
|
-
|
|
428
|
+
odac.form('#contact-form', function(data) {
|
|
429
429
|
if (data.result.success) {
|
|
430
430
|
alert('Message sent!')
|
|
431
431
|
}
|
|
@@ -441,7 +441,7 @@ Candy.action({
|
|
|
441
441
|
// Event handlers
|
|
442
442
|
click: {
|
|
443
443
|
'#refresh-btn': function() {
|
|
444
|
-
|
|
444
|
+
odac.load(window.location.pathname)
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
})
|
|
@@ -449,7 +449,7 @@ Candy.action({
|
|
|
449
449
|
|
|
450
450
|
### Advanced Multi-Section Example
|
|
451
451
|
```javascript
|
|
452
|
-
|
|
452
|
+
Odac.action({
|
|
453
453
|
navigate: {
|
|
454
454
|
update: {
|
|
455
455
|
content: 'main',
|
|
@@ -473,7 +473,7 @@ Candy.action({
|
|
|
473
473
|
|
|
474
474
|
### Disable Completely
|
|
475
475
|
```javascript
|
|
476
|
-
|
|
476
|
+
Odac.action({
|
|
477
477
|
navigate: false // Disable AJAX navigation entirely
|
|
478
478
|
})
|
|
479
479
|
```
|
|
@@ -505,7 +505,7 @@ Candy.action({
|
|
|
505
505
|
### 1. Use Minimal Configuration
|
|
506
506
|
```javascript
|
|
507
507
|
// Simple and effective
|
|
508
|
-
|
|
508
|
+
Odac.action({
|
|
509
509
|
navigate: 'main'
|
|
510
510
|
})
|
|
511
511
|
```
|
|
@@ -524,7 +524,7 @@ Candy.action({
|
|
|
524
524
|
|
|
525
525
|
### 3. Handle Loading States
|
|
526
526
|
```javascript
|
|
527
|
-
|
|
527
|
+
Odac.action({
|
|
528
528
|
navigate: {
|
|
529
529
|
update: 'main',
|
|
530
530
|
on: (page, vars) => {
|
|
@@ -546,7 +546,7 @@ Candy.action({
|
|
|
546
546
|
### Links not loading via AJAX
|
|
547
547
|
|
|
548
548
|
- Check browser console for errors
|
|
549
|
-
- Verify navigate is enabled in `
|
|
549
|
+
- Verify navigate is enabled in `Odac.action()`
|
|
550
550
|
- Ensure links start with `/` for internal navigation
|
|
551
551
|
|
|
552
552
|
### Specific links should not use AJAX
|
|
@@ -573,8 +573,8 @@ This is usually caused by mismatched keys between your skeleton, controller, and
|
|
|
573
573
|
|
|
574
574
|
2. **Controller** (`controller/page/about.js`):
|
|
575
575
|
```javascript
|
|
576
|
-
|
|
577
|
-
|
|
576
|
+
odac.View.skeleton('main')
|
|
577
|
+
odac.View.set({
|
|
578
578
|
header: 'main', // Lowercase → {{ HEADER }}
|
|
579
579
|
content: 'about' // Lowercase → {{ CONTENT }}
|
|
580
580
|
})
|
|
@@ -582,7 +582,7 @@ This is usually caused by mismatched keys between your skeleton, controller, and
|
|
|
582
582
|
|
|
583
583
|
3. **Frontend** (`public/assets/js/app.js`):
|
|
584
584
|
```javascript
|
|
585
|
-
|
|
585
|
+
Odac.action({
|
|
586
586
|
navigate: {
|
|
587
587
|
update: {
|
|
588
588
|
header: 'header', // Targets <header> tag
|
|
@@ -599,10 +599,10 @@ This is usually caused by mismatched keys between your skeleton, controller, and
|
|
|
599
599
|
|
|
600
600
|
**Also verify:**
|
|
601
601
|
- Element selectors match actual DOM elements (e.g., `'main'` matches `<main>`)
|
|
602
|
-
- Skeleton template is defined with `
|
|
603
|
-
- View parts are defined in controller with `
|
|
602
|
+
- Skeleton template is defined with `Odac.View.skeleton('main')`
|
|
603
|
+
- View parts are defined in controller with `Odac.View.set()`
|
|
604
604
|
|
|
605
605
|
### Variables not available
|
|
606
606
|
|
|
607
|
-
- Confirm `
|
|
607
|
+
- Confirm `Odac.set(data, true)` has `true` as second parameter
|
|
608
608
|
- Check that variables are set before `View.print()` is called
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AJAX Navigation Configuration
|
|
2
2
|
|
|
3
|
-
Learn how to configure and customize AJAX navigation in your
|
|
3
|
+
Learn how to configure and customize AJAX navigation in your Odac application.
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ Before configuring AJAX navigation, ensure your skeleton template is properly se
|
|
|
23
23
|
The simplest way to enable AJAX navigation:
|
|
24
24
|
|
|
25
25
|
```javascript
|
|
26
|
-
|
|
26
|
+
Odac.action({
|
|
27
27
|
navigate: 'main' // Update <main> element
|
|
28
28
|
})
|
|
29
29
|
```
|
|
@@ -33,7 +33,7 @@ Candy.action({
|
|
|
33
33
|
All available options:
|
|
34
34
|
|
|
35
35
|
```javascript
|
|
36
|
-
|
|
36
|
+
Odac.action({
|
|
37
37
|
navigate: {
|
|
38
38
|
// Which links to intercept
|
|
39
39
|
links: 'a[href^="/"]', // Default: all internal links
|
|
@@ -129,7 +129,7 @@ The keys (content, header, etc.) must match the view parts defined in your contr
|
|
|
129
129
|
|
|
130
130
|
```javascript
|
|
131
131
|
// In controller
|
|
132
|
-
|
|
132
|
+
odac.View.set({
|
|
133
133
|
header: 'main',
|
|
134
134
|
content: 'about',
|
|
135
135
|
sidebar: 'main'
|
|
@@ -170,7 +170,7 @@ navigate: {
|
|
|
170
170
|
Run code for specific pages:
|
|
171
171
|
|
|
172
172
|
```javascript
|
|
173
|
-
|
|
173
|
+
Odac.action({
|
|
174
174
|
navigate: {
|
|
175
175
|
update: 'main',
|
|
176
176
|
on: (page, vars) => console.log('Navigated to:', page)
|
|
@@ -192,7 +192,7 @@ Candy.action({
|
|
|
192
192
|
### Disable Completely
|
|
193
193
|
|
|
194
194
|
```javascript
|
|
195
|
-
|
|
195
|
+
Odac.action({
|
|
196
196
|
navigate: false // No AJAX navigation
|
|
197
197
|
})
|
|
198
198
|
```
|
|
@@ -217,16 +217,16 @@ Candy.action({
|
|
|
217
217
|
In your controller, send data to the client:
|
|
218
218
|
|
|
219
219
|
```javascript
|
|
220
|
-
module.exports = function(
|
|
220
|
+
module.exports = function(Odac) {
|
|
221
221
|
// Set variables for AJAX responses
|
|
222
|
-
|
|
222
|
+
odac.set({
|
|
223
223
|
title: 'About Page',
|
|
224
224
|
user: {name: 'John', role: 'admin'},
|
|
225
225
|
stats: {views: 1234}
|
|
226
226
|
}, true) // true = include in AJAX
|
|
227
227
|
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
odac.View.skeleton('main')
|
|
229
|
+
odac.View.set({
|
|
230
230
|
header: 'main',
|
|
231
231
|
content: 'about',
|
|
232
232
|
footer: 'main'
|
|
@@ -256,7 +256,7 @@ navigate: {
|
|
|
256
256
|
Show a loading spinner during navigation:
|
|
257
257
|
|
|
258
258
|
```javascript
|
|
259
|
-
|
|
259
|
+
Odac.action({
|
|
260
260
|
navigate: {
|
|
261
261
|
update: 'main',
|
|
262
262
|
on: (page, vars) => {
|
|
@@ -290,7 +290,7 @@ Animated progress bar:
|
|
|
290
290
|
```javascript
|
|
291
291
|
let progressBar = document.getElementById('progress')
|
|
292
292
|
|
|
293
|
-
|
|
293
|
+
Odac.action({
|
|
294
294
|
navigate: {
|
|
295
295
|
update: 'main',
|
|
296
296
|
on: () => {
|
|
@@ -316,7 +316,7 @@ Candy.action({
|
|
|
316
316
|
Confirm before navigating:
|
|
317
317
|
|
|
318
318
|
```javascript
|
|
319
|
-
|
|
319
|
+
Odac.action({
|
|
320
320
|
navigate: {
|
|
321
321
|
update: 'main'
|
|
322
322
|
},
|
|
@@ -360,7 +360,7 @@ Candy.action({
|
|
|
360
360
|
|
|
361
361
|
### Variables Not Available
|
|
362
362
|
|
|
363
|
-
- Confirm `
|
|
363
|
+
- Confirm `Odac.set(data, true)` has `true` parameter
|
|
364
364
|
- Check variables are set before `View.print()`
|
|
365
365
|
|
|
366
366
|
## Next Steps
|