Skip to content

Commit ada53b2

Browse files
committed
updtade all the utils.js
1 parent 58a4f42 commit ada53b2

6 files changed

Lines changed: 350 additions & 61 deletions

File tree

apps/_dashboard/static/js/utils.js

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
1+
/**
2+
* Utility functions for various common tasks.
3+
*
4+
* version 2.0 - 2025.06.03
5+
* upgrade Vue component registration to Vue3 and Vue.defineAsyncComponent
6+
*
7+
* This file contains a collection of utility functions that can be used for:
8+
* - String formatting
9+
* - DOM manipulation
10+
* - AJAX requests
11+
* - Cookie handling
12+
* - Vue component registration
13+
* - File upload handling
14+
* - Internationalization
15+
* - Debouncing and throttling functions
16+
* - Password strength calculation
17+
* - Form handling
18+
* - Flash message handling
19+
*/
20+
121
"use strict";
222

3-
// Allows "bla {a} bla {b}".format({'a': 'hello', 'b': 'world'})
23+
/**
24+
* Allows "bla {a} bla {b}".format({'a': 'hello', 'b': 'world'})
25+
* @param {Object} args - The arguments to replace in the string.
26+
* @returns {String} - The formatted string.
27+
*/
428
if (!String.prototype.format) {
529
String.prototype.format = function (args) {
630
return this.replace(/\{([^}]+)\}/g, function (match, k) { return args[k]; });
@@ -10,12 +34,20 @@ if (!String.prototype.format) {
1034
// Similar to jQuery $ but lighter
1135
window.Q = function(sel, el) { return (el||document).querySelectorAll(sel); };
1236

13-
// Clone any object
37+
/**
38+
* Clone any object
39+
* @param {Object} data - The object to clone.
40+
* @returns {Object} - The cloned object.
41+
*/
1442
Q.clone = function (data) { return JSON.parse(JSON.stringify(data)); };
1543

1644
Q.eval = function(text) { return eval('('+text+')'); };
1745

18-
// Given a url retuns an object with parsed query string
46+
/**
47+
* Given a URL returns an object with parsed query string
48+
* @param {String} source - The URL to parse.
49+
* @returns {Object} - The parsed query string as an object.
50+
*/
1951
Q.get_query = function (source) {
2052
source = source || window.location.search.substring(1);
2153
var vars = {}, items = source.split('&');
@@ -26,7 +58,14 @@ Q.get_query = function (source) {
2658
return vars;
2759
};
2860

29-
// a wrapper for fetch return a promise
61+
/**
62+
* A wrapper for fetch that returns a promise
63+
* @param {String} method - The HTTP method.
64+
* @param {String} url - The URL to fetch.
65+
* @param {Object} data - The data to send.
66+
* @param {Object} headers - The headers to include.
67+
* @returns {Promise} - The fetch promise.
68+
*/
3069
Q.ajax = function(method, url, data, headers) {
3170
var options = {
3271
method: method,
@@ -55,18 +94,24 @@ Q.post = (url, data, headers) => Q.ajax("POST", url, data, headers);
5594
Q.put = (url, data, headers) => Q.ajax("PUT", url, data, headers);
5695
Q.delete = (url, headers) => Q.ajax("DELETE", url, null, headers);
5796

58-
// Gets a cookie value
97+
/**
98+
* Gets a cookie value
99+
* @param {String} name - The name of the cookie.
100+
* @returns {String|null} - The cookie value or null if not found.
101+
*/
59102
Q.get_cookie = function (name) {
60103
var cookie = RegExp("" + name + "[^;]+").exec(document.cookie);
61104
if (!cookie) return null;
62105
return decodeURIComponent(!!cookie ? cookie.toString().replace(/^[^=]+./, "") : "");
63106
};
64107

65-
// Load components lazily: https://vuejs.org/v2/guide/components.html#Async-Components
108+
// Load components lazily: https://v3.vuejs.org/guide/component-dynamic-async.html#async-components
66109
Q.register_vue_component = function (name, src, onload) {
67-
Vue.component(name, function (resolve, reject) {
68-
Q.ajax('GET', src).then(function(res){resolve(onload(res));});
110+
window.app.component(name, Vue.defineAsyncComponent(() => {
111+
return Q.ajax('GET', src).then(function(res){
112+
return onload(res);
69113
});
114+
}));
70115
};
71116

72117
// Passes binary data to callback on drop of file in elem_id
@@ -88,10 +133,14 @@ Q.upload_helper = function (elem_id, callback) {
88133
}
89134
};
90135

91-
// Internationalization helper
136+
/**
137+
* Internationalization helper
92138
// Usage:
93139
// T.translations = {'dog': {0: 'no cane', 1: 'un case', 2: '{n} cani', 10: 'tanti cani'}};
94140
// T('dog').format({n: 5}) -> "5 cani"
141+
* @param {String} text - The text to translate.
142+
* @returns {Object} - The translation object with toString and format methods.
143+
*/
95144
var T = function (text) {
96145
var obj = {
97146
toString: function () { return T.format(text); },
@@ -100,7 +149,12 @@ var T = function (text) {
100149
return obj;
101150
};
102151

103-
// Adds a convenience format method to the client-side translator object
152+
/**
153+
* Adds a convenience format method to the client-side translator object
154+
* @param {String} text - The text to format.
155+
* @param {Object} args - The arguments for formatting.
156+
* @returns {String} - The formatted text.
157+
*/
104158
T.format = function (text, args) {
105159
args = args || {};
106160
translations = (T.translations || {})[text];
@@ -214,7 +268,11 @@ Q.tags_input = function(elem, options) {
214268
fill(elem, repl);
215269
};
216270

217-
// Password strenght calculator
271+
/**
272+
* Password strength calculator
273+
* @param {String} text - The password text.
274+
* @returns {Number} - The password strength score.
275+
*/
218276
Q.score_password = function(text) {
219277
var score = -10, counters = {};
220278
text.split('').map(function(c){counters[c]=(counters[c]||0)+1; score += 5/counters[c];});
@@ -310,4 +368,4 @@ Q.handle_components();
310368
Q.handle_flash();
311369
Q('input[type=text].type-list-string').forEach(function(elem){Q.tags_input(elem);});
312370
Q('input[type=text].type-list-integer').forEach(function(elem){Q.tags_input(elem, {regex:/[-+]?[\d]+/});});
313-
Q('input[name=password],input[name=new_password]').forEach(Q.score_input);
371+
Q('input[name=password],input[name=new_password]').forEach(Q.score_input);

apps/_scaffold/static/css/no.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,6 @@ ul.tags-list li {
535535
margin: 2px;
536536
cursor: pointer;
537537
opacity: 0.2;
538-
text-transform: capitalize;
539538
}
540539

541540
ul.tags-list li[data-selected=true] {

apps/_scaffold/static/js/utils.js

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
1+
/**
2+
* Utility functions for various common tasks.
3+
*
4+
* version 2.0 - 2025.06.03
5+
* upgrade Vue component registration to Vue3 and Vue.defineAsyncComponent
6+
*
7+
* This file contains a collection of utility functions that can be used for:
8+
* - String formatting
9+
* - DOM manipulation
10+
* - AJAX requests
11+
* - Cookie handling
12+
* - Vue component registration
13+
* - File upload handling
14+
* - Internationalization
15+
* - Debouncing and throttling functions
16+
* - Password strength calculation
17+
* - Form handling
18+
* - Flash message handling
19+
*/
20+
121
"use strict";
222

3-
// Allows "bla {a} bla {b}".format({'a': 'hello', 'b': 'world'})
23+
/**
24+
* Allows "bla {a} bla {b}".format({'a': 'hello', 'b': 'world'})
25+
* @param {Object} args - The arguments to replace in the string.
26+
* @returns {String} - The formatted string.
27+
*/
428
if (!String.prototype.format) {
529
String.prototype.format = function (args) {
630
return this.replace(/\{([^}]+)\}/g, function (match, k) { return args[k]; });
@@ -10,12 +34,20 @@ if (!String.prototype.format) {
1034
// Similar to jQuery $ but lighter
1135
window.Q = function(sel, el) { return (el||document).querySelectorAll(sel); };
1236

13-
// Clone any object
37+
/**
38+
* Clone any object
39+
* @param {Object} data - The object to clone.
40+
* @returns {Object} - The cloned object.
41+
*/
1442
Q.clone = function (data) { return JSON.parse(JSON.stringify(data)); };
1543

1644
Q.eval = function(text) { return eval('('+text+')'); };
1745

18-
// Given a url retuns an object with parsed query string
46+
/**
47+
* Given a URL returns an object with parsed query string
48+
* @param {String} source - The URL to parse.
49+
* @returns {Object} - The parsed query string as an object.
50+
*/
1951
Q.get_query = function (source) {
2052
source = source || window.location.search.substring(1);
2153
var vars = {}, items = source.split('&');
@@ -26,7 +58,14 @@ Q.get_query = function (source) {
2658
return vars;
2759
};
2860

29-
// a wrapper for fetch return a promise
61+
/**
62+
* A wrapper for fetch that returns a promise
63+
* @param {String} method - The HTTP method.
64+
* @param {String} url - The URL to fetch.
65+
* @param {Object} data - The data to send.
66+
* @param {Object} headers - The headers to include.
67+
* @returns {Promise} - The fetch promise.
68+
*/
3069
Q.ajax = function(method, url, data, headers) {
3170
var options = {
3271
method: method,
@@ -55,18 +94,24 @@ Q.post = (url, data, headers) => Q.ajax("POST", url, data, headers);
5594
Q.put = (url, data, headers) => Q.ajax("PUT", url, data, headers);
5695
Q.delete = (url, headers) => Q.ajax("DELETE", url, null, headers);
5796

58-
// Gets a cookie value
97+
/**
98+
* Gets a cookie value
99+
* @param {String} name - The name of the cookie.
100+
* @returns {String|null} - The cookie value or null if not found.
101+
*/
59102
Q.get_cookie = function (name) {
60103
var cookie = RegExp("" + name + "[^;]+").exec(document.cookie);
61104
if (!cookie) return null;
62105
return decodeURIComponent(!!cookie ? cookie.toString().replace(/^[^=]+./, "") : "");
63106
};
64107

65-
// Load components lazily: https://vuejs.org/v2/guide/components.html#Async-Components
108+
// Load components lazily: https://v3.vuejs.org/guide/component-dynamic-async.html#async-components
66109
Q.register_vue_component = function (name, src, onload) {
67-
Vue.component(name, function (resolve, reject) {
68-
Q.ajax('GET', src).then(function(res){resolve(onload(res));});
110+
window.app.component(name, Vue.defineAsyncComponent(() => {
111+
return Q.ajax('GET', src).then(function(res){
112+
return onload(res);
69113
});
114+
}));
70115
};
71116

72117
// Passes binary data to callback on drop of file in elem_id
@@ -88,10 +133,14 @@ Q.upload_helper = function (elem_id, callback) {
88133
}
89134
};
90135

91-
// Internationalization helper
136+
/**
137+
* Internationalization helper
92138
// Usage:
93139
// T.translations = {'dog': {0: 'no cane', 1: 'un case', 2: '{n} cani', 10: 'tanti cani'}};
94140
// T('dog').format({n: 5}) -> "5 cani"
141+
* @param {String} text - The text to translate.
142+
* @returns {Object} - The translation object with toString and format methods.
143+
*/
95144
var T = function (text) {
96145
var obj = {
97146
toString: function () { return T.format(text); },
@@ -100,7 +149,12 @@ var T = function (text) {
100149
return obj;
101150
};
102151

103-
// Adds a convenience format method to the client-side translator object
152+
/**
153+
* Adds a convenience format method to the client-side translator object
154+
* @param {String} text - The text to format.
155+
* @param {Object} args - The arguments for formatting.
156+
* @returns {String} - The formatted text.
157+
*/
104158
T.format = function (text, args) {
105159
args = args || {};
106160
translations = (T.translations || {})[text];
@@ -214,7 +268,11 @@ Q.tags_input = function(elem, options) {
214268
fill(elem, repl);
215269
};
216270

217-
// Password strenght calculator
271+
/**
272+
* Password strength calculator
273+
* @param {String} text - The password text.
274+
* @returns {Number} - The password strength score.
275+
*/
218276
Q.score_password = function(text) {
219277
var score = -10, counters = {};
220278
text.split('').map(function(c){counters[c]=(counters[c]||0)+1; score += 5/counters[c];});
@@ -310,4 +368,4 @@ Q.handle_components();
310368
Q.handle_flash();
311369
Q('input[type=text].type-list-string').forEach(function(elem){Q.tags_input(elem);});
312370
Q('input[type=text].type-list-integer').forEach(function(elem){Q.tags_input(elem, {regex:/[-+]?[\d]+/});});
313-
Q('input[name=password],input[name=new_password]').forEach(Q.score_input);
371+
Q('input[name=password],input[name=new_password]').forEach(Q.score_input);

0 commit comments

Comments
 (0)