dphelper 3.5.5 → 3.7.2
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/README.md +0 -21
- package/docs/README.md +385 -0
- package/docs/SUMMARY.md +83 -0
- package/docs/_config.yml +1 -0
- package/docs/markdown/ai.md +345 -0
- package/docs/markdown/anchor.md +156 -0
- package/docs/markdown/array.md +208 -0
- package/docs/markdown/audio.md +113 -0
- package/docs/markdown/avoid.md +53 -0
- package/docs/markdown/biometric.md +338 -0
- package/docs/markdown/browser.md +203 -0
- package/docs/markdown/check.md +65 -0
- package/docs/markdown/color.md +159 -0
- package/docs/markdown/compress.md +310 -0
- package/docs/markdown/cookie.md +115 -0
- package/docs/markdown/coords.md +127 -0
- package/docs/markdown/credits.md +56 -0
- package/docs/markdown/date.md +260 -0
- package/docs/markdown/disable.md +109 -0
- package/docs/markdown/dispatch.md +108 -0
- package/docs/markdown/element.md +53 -0
- package/docs/markdown/event.md +85 -0
- package/docs/markdown/fetch.md +122 -0
- package/docs/markdown/form.md +302 -0
- package/docs/markdown/format.md +122 -0
- package/docs/markdown/i18n.md +292 -0
- package/docs/markdown/image.md +298 -0
- package/docs/markdown/json.md +269 -0
- package/docs/markdown/load.md +133 -0
- package/docs/markdown/logging.md +99 -0
- package/docs/markdown/math.md +172 -0
- package/docs/markdown/memory.md +85 -0
- package/docs/markdown/navigation.md +152 -0
- package/docs/markdown/net.md +60 -0
- package/docs/markdown/obj.md +242 -0
- package/docs/markdown/path.md +46 -0
- package/docs/markdown/promise.md +94 -0
- package/docs/markdown/sanitize.md +118 -0
- package/docs/markdown/screen.md +78 -0
- package/docs/markdown/scrollbar.md +82 -0
- package/docs/markdown/security.md +289 -0
- package/docs/markdown/shortcut.md +100 -0
- package/docs/markdown/socket.md +134 -0
- package/docs/markdown/sse.md +120 -0
- package/docs/markdown/svg.md +167 -0
- package/docs/markdown/sync.md +147 -0
- package/docs/markdown/system.md +78 -0
- package/docs/markdown/terminal.md +73 -0
- package/docs/markdown/text.md +245 -0
- package/docs/markdown/timer.md +98 -0
- package/docs/markdown/tools.md +111 -0
- package/docs/markdown/translators.md +65 -0
- package/docs/markdown/trigger.md +99 -0
- package/docs/markdown/triggers.md +133 -0
- package/docs/markdown/type.md +109 -0
- package/docs/markdown/types.md +102 -0
- package/docs/markdown/ui.md +45 -0
- package/docs/markdown/window.md +211 -0
- package/docs/markdown/worker.md +223 -0
- package/index.cjs +1 -1
- package/index.js +1 -1
- package/package.json +4 -6
- package/types/dphelper.d.ts +0 -15
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# audio
|
|
2
|
+
|
|
3
|
+
Audio playback utilities for managing sound effects and background music in web applications.
|
|
4
|
+
|
|
5
|
+
## Functions
|
|
6
|
+
|
|
7
|
+
| Function | Description | Example |
|
|
8
|
+
|----------|-------------|---------|
|
|
9
|
+
| `play` | Plays an audio file or removes all audio elements | `dphelper.audio.play('notification.mp3', '/sounds/')` |
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
|
|
13
|
+
Simple audio management for web applications:
|
|
14
|
+
- **Play Sound** - Load and play audio files with optional looping
|
|
15
|
+
- **Stop All** - Remove all dpHelper audio elements from the DOM
|
|
16
|
+
- **Multiple Sounds** - Play different sounds simultaneously (each gets unique ID)
|
|
17
|
+
|
|
18
|
+
## Usage Examples
|
|
19
|
+
|
|
20
|
+
### Playing Sound Effects
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
// Play a simple notification sound
|
|
24
|
+
dphelper.audio.play('notification.mp3');
|
|
25
|
+
|
|
26
|
+
// Play with custom path
|
|
27
|
+
dphelper.audio.play('click.mp3', '/assets/sounds/');
|
|
28
|
+
|
|
29
|
+
// Loop background music
|
|
30
|
+
dphelper.audio.play('music.mp3', '/assets/audio/', true);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Stopping Audio
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
// Stop all dpHelper audio elements
|
|
37
|
+
dphelper.audio.play();
|
|
38
|
+
|
|
39
|
+
// This removes all audio tags created by dphelper.audio
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Complete Example
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// Sound manager class
|
|
46
|
+
class SoundManager {
|
|
47
|
+
constructor(soundPath = '/sounds/') {
|
|
48
|
+
this.path = soundPath;
|
|
49
|
+
this.enabled = true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
playSound(name, loop = false) {
|
|
53
|
+
if (!this.enabled) return;
|
|
54
|
+
dphelper.audio.play(name, this.path, loop);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
stopAll() {
|
|
58
|
+
dphelper.audio.play(); // No args = remove all
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
toggle(enabled) {
|
|
62
|
+
this.enabled = enabled;
|
|
63
|
+
if (!enabled) this.stopAll();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Usage
|
|
68
|
+
const sounds = new SoundManager('/assets/sounds/');
|
|
69
|
+
|
|
70
|
+
// Play various sounds
|
|
71
|
+
sounds.playSound('click.mp3');
|
|
72
|
+
sounds.playSound('notification.mp3');
|
|
73
|
+
sounds.playSound('background.mp3', true); // Loop
|
|
74
|
+
|
|
75
|
+
// Mute all
|
|
76
|
+
sounds.toggle(false);
|
|
77
|
+
|
|
78
|
+
// Unmute
|
|
79
|
+
sounds.toggle(true);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### UI Sound Effects
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
// Add sounds to UI interactions
|
|
86
|
+
document.querySelectorAll('button').forEach(btn => {
|
|
87
|
+
btn.addEventListener('click', () => {
|
|
88
|
+
dphelper.audio.play('click.mp3', '/sounds/');
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Form submission
|
|
93
|
+
document.querySelector('form').addEventListener('submit', () => {
|
|
94
|
+
dphelper.audio.play('success.mp3', '/sounds/');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Error handling
|
|
98
|
+
function showError() {
|
|
99
|
+
dphelper.audio.play('error.mp3', '/sounds/');
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Details
|
|
104
|
+
|
|
105
|
+
- **Author:** Dario Passariello
|
|
106
|
+
- **Version:** 0.0.2
|
|
107
|
+
- **Creation Date:** 20240924
|
|
108
|
+
- **Last Modified:** 20240924
|
|
109
|
+
- **Environment:** Client-side only (browser)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
*Automatically generated document*
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# avoid
|
|
2
|
+
|
|
3
|
+
Utilities for preventing caching issues in web applications.
|
|
4
|
+
|
|
5
|
+
## Functions
|
|
6
|
+
|
|
7
|
+
| Function | Description | Example |
|
|
8
|
+
|----------|-------------|---------|
|
|
9
|
+
| `cache` | Appends cache-busting query parameter to URL | `dphelper.avoid.cache('/api/data')` |
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
|
|
13
|
+
Prevents browser caching issues:
|
|
14
|
+
- **Cache Busting** - Add unique query params to URLs
|
|
15
|
+
|
|
16
|
+
## Usage Examples
|
|
17
|
+
|
|
18
|
+
### Cache Busting
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
// Add unique query parameter to prevent caching
|
|
22
|
+
const url = '/api/users';
|
|
23
|
+
const uncachedUrl = dphelper.avoid.cache(url);
|
|
24
|
+
console.log(uncachedUrl); // "/api/users?t=abc123xyz"
|
|
25
|
+
|
|
26
|
+
// Useful for:
|
|
27
|
+
// - API calls that need fresh data
|
|
28
|
+
// - Dynamic content
|
|
29
|
+
// - Debugging (force reload)
|
|
30
|
+
dphelper.avoid.cache('/api/latest-data');
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Using with Fetch
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
// Fetch with cache busting
|
|
37
|
+
async function fetchFresh(url) {
|
|
38
|
+
const response = await fetch(dphelper.avoid.cache(url));
|
|
39
|
+
return response.json();
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Details
|
|
44
|
+
|
|
45
|
+
- **Author:** Dario Passariello
|
|
46
|
+
- **Version:** 0.0.2
|
|
47
|
+
- **Creation Date:** 20210101
|
|
48
|
+
- **Last Modified:** 20260220
|
|
49
|
+
- **Environment:** Works in both client and server environments
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
*Automatically generated document*
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# biometric
|
|
2
|
+
|
|
3
|
+
WebAuthn and biometric authentication utilities for secure passwordless login using fingerprint, face recognition, and hardware security keys.
|
|
4
|
+
|
|
5
|
+
## Functions
|
|
6
|
+
|
|
7
|
+
| Function | Description | Example |
|
|
8
|
+
|----------|-------------|---------|
|
|
9
|
+
| `isAvailable` | Check if WebAuthn is available | `dphelper.biometric.isAvailable()` |
|
|
10
|
+
| `getWebAuthnSupport` | Get detailed support info | `dphelper.biometric.getWebAuthnSupport()` |
|
|
11
|
+
| `isSensorAvailable` | Check specific sensor (fingerprint/face/iris) | `await dphelper.biometric.isSensorAvailable('fingerprint')` |
|
|
12
|
+
| `register` | Register new credential | `await dphelper.biometric.register('user123', 'example.com')` |
|
|
13
|
+
| `authenticate` | Authenticate with credential | `await dphelper.biometric.authenticate('user123', 'example.com')` |
|
|
14
|
+
| `getCredential` | Get stored credential by ID | `dphelper.biometric.getCredential(credentialId)` |
|
|
15
|
+
| `deleteCredential` | Delete stored credential | `dphelper.biometric.deleteCredential(credentialId)` |
|
|
16
|
+
| `listCredentials` | List all stored credentials | `dphelper.biometric.listCredentials()` |
|
|
17
|
+
|
|
18
|
+
## Description
|
|
19
|
+
|
|
20
|
+
Secure biometric authentication module providing:
|
|
21
|
+
- **WebAuthn/FIDO2** - Industry-standard passwordless authentication
|
|
22
|
+
- **Platform Authenticators** - Fingerprint, Face ID, Windows Hello
|
|
23
|
+
- **Cross-platform** - Works with hardware security keys (YubiKey, etc.)
|
|
24
|
+
- **Credential Management** - Store, retrieve, and delete credentials
|
|
25
|
+
- **Sensor Detection** - Check availability of specific biometric types
|
|
26
|
+
|
|
27
|
+
## Usage Examples
|
|
28
|
+
|
|
29
|
+
### Checking Availability
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
// Simple availability check
|
|
33
|
+
if (dphelper.biometric.isAvailable()) {
|
|
34
|
+
console.log('Biometric authentication is available!');
|
|
35
|
+
} else {
|
|
36
|
+
console.log('Biometric auth not supported');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Get detailed support information
|
|
40
|
+
const support = dphelper.biometric.getWebAuthnSupport();
|
|
41
|
+
console.log(support);
|
|
42
|
+
// {
|
|
43
|
+
// supported: true,
|
|
44
|
+
// platformAuthenticator: true,
|
|
45
|
+
// hybridTransport: false,
|
|
46
|
+
// uvToken: false
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
// Check specific sensor
|
|
50
|
+
const hasFingerprint = await dphelper.biometric.isSensorAvailable('fingerprint');
|
|
51
|
+
const hasFace = await dphelper.biometric.isSensorAvailable('face');
|
|
52
|
+
console.log('Fingerprint:', hasFingerprint, 'Face:', hasFace);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Registration (Enrolling a Credential)
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
// Register a new biometric credential
|
|
59
|
+
async function registerUser(userId) {
|
|
60
|
+
if (!dphelper.biometric.isAvailable()) {
|
|
61
|
+
return { success: false, error: 'WebAuthn not supported' };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = await dphelper.biometric.register(
|
|
65
|
+
userId, // User ID
|
|
66
|
+
'example.com', // Relying Party ID (your domain)
|
|
67
|
+
'My App', // Relying Party Name
|
|
68
|
+
'john@example.com' // Display name
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (result.success) {
|
|
72
|
+
console.log('Registered! Credential ID:', result.credentialId);
|
|
73
|
+
// Store credentialId in your database for this user
|
|
74
|
+
} else {
|
|
75
|
+
console.error('Registration failed:', result.error);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Usage
|
|
82
|
+
const result = await registerUser('user_123');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Authentication (Login)
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
// Authenticate with stored credential
|
|
89
|
+
async function loginUser(userId, credentialId) {
|
|
90
|
+
if (!dphelper.biometric.isAvailable()) {
|
|
91
|
+
return { success: false, error: 'WebAuthn not supported' };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const result = await dphelper.biometric.authenticate(
|
|
95
|
+
userId, // User ID
|
|
96
|
+
'example.com', // Relying Party ID
|
|
97
|
+
credentialId // Optional: specific credential to use
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
if (result.success) {
|
|
101
|
+
console.log('Authentication successful!');
|
|
102
|
+
} else {
|
|
103
|
+
console.error('Authentication failed:', result.error);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Usage - login with known credential
|
|
110
|
+
const result = await loginUser('user_123', 'stored_credential_id');
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Credential Management
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
// List all stored credentials
|
|
117
|
+
const credentials = dphelper.biometric.listCredentials();
|
|
118
|
+
console.log('Stored credentials:', credentials);
|
|
119
|
+
|
|
120
|
+
// Get a specific credential
|
|
121
|
+
const cred = dphelper.biometric.getCredential('credential_id_123');
|
|
122
|
+
console.log('Credential:', cred);
|
|
123
|
+
|
|
124
|
+
// Delete a credential
|
|
125
|
+
const deleted = dphelper.biometric.deleteCredential('credential_id_123');
|
|
126
|
+
console.log('Deleted:', deleted);
|
|
127
|
+
|
|
128
|
+
// After deletion
|
|
129
|
+
console.log('Remaining:', dphelper.biometric.listCredentials());
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Advanced Usage
|
|
133
|
+
|
|
134
|
+
### Complete Authentication System
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
class BiometricAuth {
|
|
138
|
+
constructor(rpId, rpName) {
|
|
139
|
+
this.rpId = rpId;
|
|
140
|
+
this.rpName = rpName;
|
|
141
|
+
this.available = dphelper.biometric.isAvailable();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async checkSupport() {
|
|
145
|
+
if (!this.available) {
|
|
146
|
+
return { supported: false, reason: 'WebAuthn not supported' };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const support = dphelper.biometric.getWebAuthnSupport();
|
|
150
|
+
const fingerprint = await dphelper.biometric.isSensorAvailable('fingerprint');
|
|
151
|
+
const face = await dphelper.biometric.isSensorAvailable('face');
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
supported: true,
|
|
155
|
+
platformAuthenticator: support.platformAuthenticator,
|
|
156
|
+
fingerprint,
|
|
157
|
+
face
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async register(userId, userName) {
|
|
162
|
+
if (!this.available) {
|
|
163
|
+
throw new Error('Biometric authentication not available');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const result = await dphelper.biometric.register(
|
|
167
|
+
userId,
|
|
168
|
+
this.rpId,
|
|
169
|
+
this.rpName,
|
|
170
|
+
userName
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
if (result.success) {
|
|
174
|
+
// In production: save credentialId to your backend
|
|
175
|
+
console.log('Biometric registered:', result.credentialId);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async login(userId, credentialId) {
|
|
182
|
+
if (!this.available) {
|
|
183
|
+
throw new Error('Biometric authentication not available');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return await dphelper.biometric.authenticate(
|
|
187
|
+
userId,
|
|
188
|
+
this.rpId,
|
|
189
|
+
credentialId
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
getStoredCredentials() {
|
|
194
|
+
return dphelper.biometric.listCredentials();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
removeCredential(credentialId) {
|
|
198
|
+
return dphelper.biometric.deleteCredential(credentialId);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Usage
|
|
203
|
+
const auth = new BiometricAuth('example.com', 'My Application');
|
|
204
|
+
|
|
205
|
+
// Check if biometric is available
|
|
206
|
+
const support = await auth.checkSupport();
|
|
207
|
+
if (support.supported) {
|
|
208
|
+
console.log('Biometric types available:', support);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Register new user
|
|
212
|
+
await auth.register('user_123', 'john@example.com');
|
|
213
|
+
|
|
214
|
+
// Login
|
|
215
|
+
const loginResult = await auth.login('user_123');
|
|
216
|
+
if (loginResult.success) {
|
|
217
|
+
console.log('Logged in with biometric!');
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Passwordless Login Flow
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
// Frontend: Initiate passwordless login
|
|
225
|
+
async function initiatePasswordlessLogin() {
|
|
226
|
+
// 1. Check if biometric is available
|
|
227
|
+
if (!dphelper.biometric.isAvailable()) {
|
|
228
|
+
alert('Please use a supported browser');
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 2. Get available credentials for this user
|
|
233
|
+
const credentials = dphelper.biometric.listCredentials();
|
|
234
|
+
|
|
235
|
+
if (credentials.length === 0) {
|
|
236
|
+
// No credentials - prompt to register
|
|
237
|
+
const register = confirm('No biometric credentials found. Register now?');
|
|
238
|
+
if (register) {
|
|
239
|
+
await registerNewUser();
|
|
240
|
+
}
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// 3. Attempt authentication with any stored credential
|
|
245
|
+
for (const credId of credentials) {
|
|
246
|
+
const result = await dphelper.biometric.authenticate(
|
|
247
|
+
'current_user',
|
|
248
|
+
window.location.hostname,
|
|
249
|
+
credId
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
if (result.success) {
|
|
253
|
+
// 4. Verify with server
|
|
254
|
+
await verifyWithServer(credId);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
console.log('All credentials failed');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Server verification (pseudo-code)
|
|
263
|
+
async function verifyWithServer(credentialId) {
|
|
264
|
+
const response = await fetch('/api/auth/verify', {
|
|
265
|
+
method: 'POST',
|
|
266
|
+
headers: { 'Content-Type': 'application/json' },
|
|
267
|
+
body: JSON.stringify({ credentialId })
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
if (response.ok) {
|
|
271
|
+
const { token } = await response.json();
|
|
272
|
+
localStorage.setItem('auth_token', token);
|
|
273
|
+
window.location.href = '/dashboard';
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Progressive Registration
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
// Offer biometric as an option during existing login
|
|
282
|
+
async function offerBiometricUpgrade(userId, userName) {
|
|
283
|
+
const support = await dphelper.biometric.checkSupport();
|
|
284
|
+
|
|
285
|
+
if (!support.supported) {
|
|
286
|
+
console.log('Biometric not available on this device');
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Show modal or prompt
|
|
291
|
+
const shouldRegister = confirm(
|
|
292
|
+
`Enable ${support.fingerprint ? 'fingerprint' : 'biometric'} login for faster access?`
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
if (shouldRegister) {
|
|
296
|
+
const result = await dphelper.biometric.register(
|
|
297
|
+
userId,
|
|
298
|
+
window.location.hostname,
|
|
299
|
+
'My App',
|
|
300
|
+
userName
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
if (result.success) {
|
|
304
|
+
// Save credential to user account
|
|
305
|
+
await saveCredentialToUser(userId, result.credentialId);
|
|
306
|
+
alert('Biometric authentication enabled!');
|
|
307
|
+
} else {
|
|
308
|
+
alert('Registration failed: ' + result.error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Security Notes
|
|
315
|
+
|
|
316
|
+
### WebAuthn Security Features
|
|
317
|
+
- **Public-key cryptography** - Uses asymmetric keys, never transmitted
|
|
318
|
+
- **User presence** - Requires user action (touch/face) to authenticate
|
|
319
|
+
- **Platform binding** - Credentials bound to specific device
|
|
320
|
+
- **Phishing resistance** - Relying Party ID must match exactly
|
|
321
|
+
|
|
322
|
+
### Best Practices
|
|
323
|
+
- Always verify authentication on the server side
|
|
324
|
+
- Store credential IDs in your database, not the credentials themselves
|
|
325
|
+
- Support multiple credentials per user (different devices)
|
|
326
|
+
- Provide fallback for unsupported browsers
|
|
327
|
+
|
|
328
|
+
## Details
|
|
329
|
+
|
|
330
|
+
- **Author:** Dario Passariello
|
|
331
|
+
- **Version:** 0.0.1
|
|
332
|
+
- **Creation Date:** 20260313
|
|
333
|
+
- **Last Modified:** 20260313
|
|
334
|
+
- **Environment:** Client-side only (browser with WebAuthn support)
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
*Automatically generated document*
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# browser
|
|
2
|
+
|
|
3
|
+
Complete browser navigation and state management utilities with connection monitoring and HTTP status handling.
|
|
4
|
+
|
|
5
|
+
## Functions
|
|
6
|
+
|
|
7
|
+
| Function | Description | Example |
|
|
8
|
+
|----------|-------------|---------|
|
|
9
|
+
| `state` | Pushes a new state to browser history without reload | `dphelper.browser.state(state, title, url)` |
|
|
10
|
+
| `forw` | Moves forward in browser history by n steps | `dphelper.browser.forw(1)` |
|
|
11
|
+
| `back` | Moves backward in browser history by n steps | `dphelper.browser.back(1)` |
|
|
12
|
+
| `reload` | Reloads the current page | `dphelper.browser.reload()` |
|
|
13
|
+
| `href` | Navigates to a specific URL | `dphelper.browser.href('https://example.com')` |
|
|
14
|
+
| `offLine` | Displays an offline message overlay when connection is lost | `dphelper.browser.offLine('Custom offline message')` |
|
|
15
|
+
| `zoom` | Returns the current browser zoom level as percentage | `dphelper.browser.zoom()` |
|
|
16
|
+
| `status` | Returns human-readable description of HTTP status codes | `dphelper.browser.status(404)` |
|
|
17
|
+
| `interlock` | Detects and monitors other active tabs of the same app | `dphelper.browser.interlock((count) => console.log(count))` |
|
|
18
|
+
|
|
19
|
+
## Description
|
|
20
|
+
|
|
21
|
+
Comprehensive browser management tool that provides:
|
|
22
|
+
- **History Navigation** - Push state, go forward/back, reload
|
|
23
|
+
- **URL Management** - Navigate to specific URLs
|
|
24
|
+
- **Connection Monitoring** - Detect online/offline status
|
|
25
|
+
- **Display Information** - Get zoom level, HTTP status descriptions
|
|
26
|
+
- **Multi-tab Detection** - Monitor concurrent tab usage
|
|
27
|
+
|
|
28
|
+
## Usage Examples
|
|
29
|
+
|
|
30
|
+
### Changing URL Without Reload (SPA Routing)
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
// Add a new history entry without page reload
|
|
34
|
+
dphelper.browser.state({ page: 'dashboard', userId: 123 }, 'Dashboard', '/dashboard');
|
|
35
|
+
|
|
36
|
+
// The browser's back button will now work
|
|
37
|
+
window.addEventListener('popstate', (event) => {
|
|
38
|
+
console.log('Navigated to:', event.state);
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Programmatic Navigation
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// Navigate to a specific URL
|
|
46
|
+
dphelper.browser.href('/search?q=javascript');
|
|
47
|
+
|
|
48
|
+
// Navigate to external site
|
|
49
|
+
dphelper.browser.href('https://google.com');
|
|
50
|
+
|
|
51
|
+
// Go forward 2 pages in history
|
|
52
|
+
dphelper.browser.forw(2);
|
|
53
|
+
|
|
54
|
+
// Go back 1 page in history
|
|
55
|
+
dphelper.browser.back(1);
|
|
56
|
+
|
|
57
|
+
// Reload the page
|
|
58
|
+
dphelper.browser.reload();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Offline Detection Overlay
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Show default offline message
|
|
65
|
+
dphelper.browser.offLine();
|
|
66
|
+
|
|
67
|
+
// Show custom offline message (text is sanitized for security)
|
|
68
|
+
dphelper.browser.offLine('⚠️ Connection Lost. Please check your internet.');
|
|
69
|
+
|
|
70
|
+
// The overlay appears automatically when offline
|
|
71
|
+
// and disappears when connection is restored
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Get Browser Zoom Level
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
const zoom = dphelper.browser.zoom();
|
|
78
|
+
console.log(zoom); // 100 (or 150, 200, etc. depending on zoom)
|
|
79
|
+
|
|
80
|
+
// Responsive design based on zoom
|
|
81
|
+
if (zoom > 100) {
|
|
82
|
+
document.body.classList.add('zoomed-in');
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### HTTP Status Code Descriptions
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
// Get description for common status codes
|
|
90
|
+
console.log(dphelper.browser.status(200)); // "200 OK"
|
|
91
|
+
console.log(dphelper.browser.status(201)); // "201 Created"
|
|
92
|
+
console.log(dphelper.browser.status(301)); // "301 Moved Permanently"
|
|
93
|
+
console.log(dphelper.browser.status(400)); // "400 Bad Request"
|
|
94
|
+
console.log(dphelper.browser.status(401)); // "401 Unauthorized"
|
|
95
|
+
console.log(dphelper.browser.status(403)); // "403 Forbidden"
|
|
96
|
+
console.log(dphelper.browser.status(404)); // "404 Not Found"
|
|
97
|
+
console.log(dphelper.browser.status(500)); // "500 Internal Server Error"
|
|
98
|
+
|
|
99
|
+
// Display user-friendly error messages
|
|
100
|
+
function handleApiError(statusCode) {
|
|
101
|
+
const message = dphelper.browser.status(statusCode);
|
|
102
|
+
alert(`Error: ${message}`);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Multi-Tab Synchronization
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
// Monitor active tabs of your application
|
|
110
|
+
dphelper.browser.interlock((tabCount) => {
|
|
111
|
+
console.log(`Active tabs: ${tabCount}`);
|
|
112
|
+
|
|
113
|
+
if (tabCount > 1) {
|
|
114
|
+
// Warn user about multiple tabs
|
|
115
|
+
showNotification('This app is open in multiple tabs. Changes may conflict.');
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Use BroadcastChannel for real-time sync between tabs
|
|
120
|
+
const channel = new BroadcastChannel('app_sync');
|
|
121
|
+
channel.postMessage({ type: 'UPDATE', data: 'new value' });
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Advanced Usage
|
|
125
|
+
|
|
126
|
+
### Complete SPA Navigation Handler
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
class Router {
|
|
130
|
+
constructor() {
|
|
131
|
+
this.routes = {};
|
|
132
|
+
|
|
133
|
+
// Handle browser back/forward
|
|
134
|
+
window.addEventListener('popstate', (e) => {
|
|
135
|
+
this.navigate(window.location.pathname, false);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
addRoute(path, handler) {
|
|
140
|
+
this.routes[path] = handler;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
navigate(path, addToHistory = true) {
|
|
144
|
+
const handler = this.routes[path];
|
|
145
|
+
if (handler) {
|
|
146
|
+
if (addToHistory) {
|
|
147
|
+
dphelper.browser.state({ path }, 'App', path);
|
|
148
|
+
}
|
|
149
|
+
handler();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Usage
|
|
155
|
+
const router = new Router();
|
|
156
|
+
router.addRoute('/', () => renderHome());
|
|
157
|
+
router.addRoute('/about', () => renderAbout());
|
|
158
|
+
router.addRoute('/dashboard', () => renderDashboard());
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Connection Status Manager
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
class ConnectionManager {
|
|
165
|
+
constructor() {
|
|
166
|
+
this.isOnline = navigator.onLine;
|
|
167
|
+
this.listeners = [];
|
|
168
|
+
|
|
169
|
+
window.addEventListener('online', () => {
|
|
170
|
+
this.isOnline = true;
|
|
171
|
+
this.notifyListeners();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
window.addEventListener('offline', () => {
|
|
175
|
+
this.isOnline = false;
|
|
176
|
+
this.notifyListeners();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Show offline overlay
|
|
180
|
+
dphelper.browser.offLine('🔌 You are offline. Some features are disabled.');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
onStatusChange(callback) {
|
|
184
|
+
this.listeners.push(callback);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
notifyListeners() {
|
|
188
|
+
this.listeners.forEach(cb => cb(this.isOnline));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Details
|
|
194
|
+
|
|
195
|
+
- **Author:** Dario Passariello
|
|
196
|
+
- **Version:** 0.0.2
|
|
197
|
+
- **Creation Date:** 20210101
|
|
198
|
+
- **Last Modified:** 20260220
|
|
199
|
+
- **Environment:** Client-side only (browser)
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
*Automatically generated document*
|