@modernman00/shared-js-lib 1.2.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/Utility.js ADDED
@@ -0,0 +1,133 @@
1
+ import {id } from "./UtilityHtml.js";
2
+ import {autocomplete} from './theAutoComplete.js';
3
+
4
+ /**
5
+ * Set maxlength of input fields and display error message and help text in real time
6
+ * @param {string[]} input - array of ids of input fields
7
+ * @param {string[]} maxi - array of maximum lengths of input fields, corresponding to the input array
8
+ * @throws {Error} if any element with id from the input array is not found or is empty
9
+ */
10
+ export const realTimeCheckLen = (input, maxi) => {
11
+ const data = input.map(el => id(`${el}_id`));
12
+ const errors = input.map(el => id(`${el}_error`));
13
+ const helps = input.map(el => id(`${el}_help`));
14
+
15
+ maxi.forEach((max, i) => {
16
+ if (!data[i] || !errors[i] || !helps[i]) {
17
+ throw new Error(`Element with ID '${input[i]}_id' not found or is empty`);
18
+ }
19
+
20
+ data[i].maxLength = parseInt(max, 10) + 1;
21
+ data[i].addEventListener('keyup', () => {
22
+ errors[i].innerHTML = (data[i].value.length > max) ? `You have reached the maximum limit` : "";
23
+ helps[i].style.display = data[i].value.length > max ? '' : 'none';
24
+ setTimeout(() => {
25
+ helps[i].style.display = 'none';
26
+ }, 5000);
27
+ });
28
+ });
29
+ }
30
+
31
+ /**
32
+ * Converts a string to sentence case.
33
+ *
34
+ * Sentence case is a string where the first letter of each word is capitalized, and the rest of the letters are in lowercase.
35
+ *
36
+ * @param {string} str The string to convert to sentence case.
37
+ * @returns {string} A new string in sentence case.
38
+ */
39
+ export const toSentenceCase = (str) => {
40
+ return str
41
+ .toLowerCase() // Convert the string to lowercase
42
+ .split(' ') // Split the string into words
43
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize the first letter of each word
44
+ .join(' '); // Join the words back into a string
45
+ }
46
+
47
+ /**
48
+ * Sets up an autocomplete functionality for an input element.
49
+ *
50
+ * @param {string} inputId - The ID of the input element to attach the autocomplete to.
51
+ * @param {Array<Object>} data - An array of objects containing data for autocomplete suggestions,
52
+ * where each object should have a 'firstName' property.
53
+ *
54
+ * The function converts all `firstName` properties to lowercase for case-insensitive matching.
55
+ * It initializes the autocomplete with the given input element and data, providing real-time
56
+ * suggestions based on user input. On selecting a suggestion, it populates the input element
57
+ * with the selected suggestion's `firstName`.
58
+ */
59
+
60
+ export const autoCompleter = (inputId, data) => {
61
+ const lowerCaseData = data.map(item => ({...item, firstName: item.firstName.toLowerCase()}));
62
+ autocomplete({
63
+ input: inputId,
64
+ fetch: function (text, update) {
65
+ const suggestions = lowerCaseData.filter(n => n.firstName.startsWith(text.toLowerCase()));
66
+ update(suggestions);
67
+ },
68
+ onSelect: function (item) {
69
+ input.value = item.firstName;
70
+ }
71
+ })
72
+ }
73
+
74
+ /**
75
+ * Removes duplicate values from an array.
76
+ *
77
+ * @param {Array} array - The array from which to remove duplicates.
78
+ * @returns {Array} A new array containing only unique values from the original array.
79
+ */
80
+
81
+ export const distinctValue = (array) => {
82
+ return [...new Set(array)]
83
+ }
84
+
85
+ /**
86
+ * Toggles the type of the input element with the given ID between 'password' and 'text'.
87
+ *
88
+ * @param {string} inputId - The ID of the input element to toggle.
89
+ */
90
+ export const showPassword = (inputId) => {
91
+ const y = id(inputId);
92
+ y.type = y.type === "password" ? "text" : "password";
93
+ }
94
+
95
+
96
+ /**
97
+ * Validates an email address and updates the error message if invalid.
98
+ *
99
+ * @param {string} email - The email address to validate.
100
+ * @returns {number} Returns 1 if the email is invalid and sets an error message, otherwise returns 0.
101
+ */
102
+
103
+ export const emailVal = (email) => {
104
+ const emailExp = /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-Z0-9]{2,4}$/;
105
+ if (!emailExp.test(email)) {
106
+ const errorElement = id('email_error');
107
+ errorElement.innerHTML = `<li style="color:red;">Please enter a valid email</li>`;
108
+ errorElement.style.color = "red";
109
+ return 1;
110
+ }
111
+ return 0;
112
+ }
113
+
114
+
115
+ /**
116
+ * Sanitizes a string input by escaping special HTML characters to prevent XSS attacks.
117
+ * Converts &, <, >, ", and ' to their respective HTML entities.
118
+ * Trims leading and trailing whitespace from the input.
119
+ *
120
+ * @param {string} input - The input string to sanitize.
121
+ * @returns {string} Sanitized string with HTML special characters escaped.
122
+ */
123
+
124
+ export const sanitizeInput = (input) => {
125
+ if (typeof input !== 'string') return '';
126
+ return input
127
+ .replace(/&/g, '&amp;')
128
+ .replace(/</g, '&lt;')
129
+ .replace(/>/g, '&gt;')
130
+ .replace(/"/g, '&quot;')
131
+ .replace(/'/g, '&#39;')
132
+ .trim();
133
+ };
package/UtilityHtml.js ADDED
@@ -0,0 +1,200 @@
1
+ // Environment detection
2
+ const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
3
+
4
+ // Log warning for browser-only functions when in Node environment
5
+ const browserOnly = (functionName) => {
6
+ if (!isBrowser) {
7
+ console.warn(`Warning: ${functionName} is only available in browser environments`);
8
+ return null;
9
+ }
10
+ return true;
11
+ };
12
+
13
+ // DOM manipulation functions that are safe for both environments
14
+ export const id = (x) => {
15
+ if (!isBrowser) return null;
16
+ return document.getElementById(x);
17
+ };
18
+
19
+ export const idValue = (elementId) => {
20
+ if (!isBrowser) return null;
21
+ const element = id(elementId);
22
+ return element ? element.value : null;
23
+ };
24
+
25
+ export const idInnerHTML = (elementId) => {
26
+ if (!isBrowser) return null;
27
+ const element = id(elementId);
28
+ return element ? element.innerHTML : null;
29
+ };
30
+
31
+ export const warningSign = "\u26A0"; // danger warning sign - safe in any environment
32
+
33
+ export const qSel = (name) => {
34
+ if (!isBrowser) return null;
35
+ return document.querySelector(name);
36
+ };
37
+
38
+ export const qSelAll = (name) => {
39
+ if (!isBrowser) return [];
40
+ return document.querySelectorAll(name);
41
+ };
42
+
43
+ export const qSelValue = (name) => {
44
+ if (!isBrowser) return null;
45
+ const element = qSel(name);
46
+ return element ? element.value : null;
47
+ };
48
+
49
+ export const qSelInnerHTML = (name) => {
50
+ if (!isBrowser) return null;
51
+ const element = qSel(name);
52
+ return element ? element.innerHTML : null;
53
+ };
54
+
55
+ // This is safe for both environments
56
+ export const log = (id, identifier = null) => {
57
+ console.log(' start' + " " + identifier);
58
+ console.log(id);
59
+ console.log(' end' + " " + identifier);
60
+ };
61
+
62
+ export const write = (input) => {
63
+ if (!browserOnly('write')) return;
64
+ document.write(input);
65
+ };
66
+
67
+ export const hideElement = (elementId) => {
68
+ if (!browserOnly('hideElement')) return;
69
+ const element = id(elementId);
70
+ if (element) element.style.display = "none";
71
+ };
72
+
73
+ export const showElement = (elementId) => {
74
+ if (!browserOnly('showElement')) return;
75
+ const element = id(elementId);
76
+ if (element) element.style.display = "block";
77
+ };
78
+
79
+ export const removeDiv = (div_id) => {
80
+ if (!browserOnly('removeDiv')) return;
81
+ const div = document.getElementById(div_id);
82
+ if (div) {
83
+ return div.remove();
84
+ }
85
+ };
86
+
87
+ /**
88
+ * @description Manipulates an attribute of a specified HTML element
89
+ * @param {string} idName - The ID of the element to manipulate
90
+ * @param {string} removeOrSet - Specify "remove" to remove the attribute, otherwise set the attribute
91
+ * @param {string} attributeType - The type of attribute to manipulate
92
+ * @param {string|null} [nameValue=null] - The value to set for the attribute if adding it
93
+ * @returns {void}
94
+ */
95
+ export const manipulateAttribute = (idName, removeOrSet, attributeType, nameValue = null) => {
96
+ if (!browserOnly('manipulateAttribute')) return;
97
+ const element = id(idName);
98
+ if (!element) return;
99
+
100
+ if (removeOrSet === "remove") {
101
+ element.removeAttribute(attributeType);
102
+ } else {
103
+ element.setAttribute(attributeType, nameValue);
104
+ }
105
+ };
106
+
107
+ // Function to check for elements and render if they exist
108
+ export const checkElements = (idOrClass, classString, theFunction = null) => {
109
+ if (!browserOnly('checkElements')) return;
110
+
111
+ const doesElementExist = (idOrClass === "id") ? id(classString) : qSel(classString);
112
+ // Check if elements exist before calling render function
113
+ if (doesElementExist && doesElementExist.length) {
114
+ theFunction(doesElementExist);
115
+ }
116
+ };
117
+
118
+ /**
119
+ * @description Check if elements exist before calling render function
120
+ * @param {string} idOrClass - whether to use id or class
121
+ * @param {string} classString - the class or id name
122
+ * @param {function} [theFunction] - the function to call if elements exist
123
+ * @returns {void}
124
+ */
125
+ export const checkManyElements = (idOrClass, classString, theFunction = null) => {
126
+ if (!browserOnly('checkManyElements')) return;
127
+
128
+ const doesElementExist = (idOrClass === "id") ? id(classString) : qSelAll(classString);
129
+ // Check if elements exist before calling render function
130
+ if (doesElementExist && doesElementExist.length > 0) {
131
+ theFunction(doesElementExist);
132
+ }
133
+ };
134
+
135
+ /**
136
+ * @description Create a new element and append it to a parent element
137
+ * @param {string} elementType - the type of element to create
138
+ * @param {string} setId - the id of the new element
139
+ * @param {string} parent - the id of the parent element
140
+ * @param {string} [setClass] - an optional class to set on the new element
141
+ * @returns {HTMLElement|null} The created element or null if in Node.js environment
142
+ */
143
+ export const createAndAppendElement = (elementType, setId, parent, setClass = null) => {
144
+ if (!browserOnly('createAndAppendElement')) return null;
145
+
146
+ const newDiv = document.createElement(elementType);
147
+ newDiv.setAttribute('id', setId);
148
+ newDiv.setAttribute('class', `field ${setClass}`);
149
+ const parentDiv = id(parent);
150
+ if (parentDiv) {
151
+ return parentDiv.appendChild(newDiv);
152
+ }
153
+ return newDiv;
154
+ };
155
+
156
+ // These HTML template functions are safe in any environment since they just return strings
157
+ export const checkBox = (subject) => {
158
+ return `<div class="control">
159
+ <label class="radio">
160
+ <input type="radio" name="send${subject}" value="yes" id=${subject}Yes > Yes
161
+ </label>
162
+ <label class="radio">
163
+ <input type="radio" name="send${subject}" value="no" id=${subject}No checked> No
164
+ </label>
165
+ </div>`;
166
+ };
167
+
168
+ export const checkBox2 = (subject) => {
169
+ return `<div class="control">
170
+ <label class="checkbox">
171
+ <input type="checkbox" name="send${subject}" value="yes" id=${subject}Yes> Yes
172
+ </label>
173
+ <label class="checkbox">
174
+ <input type="checkbox" name="send${subject}" value="no" id=${subject}No> No
175
+ </label>
176
+ </div>`;
177
+ };
178
+
179
+ export const isChecked = (name, fn) => {
180
+ if (!browserOnly('isChecked')) return;
181
+
182
+ const yesId = (`${name}Yes`);
183
+ const noId = `${name}No`;
184
+ const yesElement = id(yesId);
185
+ const noElement = id(noId);
186
+
187
+ if (!yesElement || !noElement) return;
188
+
189
+ const checked = () => {
190
+ if (yesElement.checked) {
191
+ alert('check');
192
+ fn();
193
+ } else if (noElement.checked) {
194
+ alert('check No');
195
+ }
196
+ };
197
+
198
+ yesElement.addEventListener('click', checked);
199
+ noElement.addEventListener('click', checked);
200
+ };
package/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export * from './Http.js';
2
+ export * from './UtilityHtml.js';
3
+ export * from './FormProcessing.js';
4
+ export * from './Utility.js';
5
+ export * from './Loader.js';
6
+ export * from './ForgotPassword.js';
7
+ export * from './Login.js';
8
+ export * from './Cookie.js';
9
+ export * from './FormHelper.js';
10
+ export * from './Loader.js';
11
+ export * from './ShowResponse.js';
12
+ export * from './DateTime.js';
13
+ export * from './CountryCode.js'
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@modernman00/shared-js-lib",
3
+ "version": "1.2.2",
4
+ "description": "Reusable JS utilities for numerous js problems",
5
+ "homepage": "https://github.com/modernman00/shared-js-lib#readme",
6
+ "keywords": [
7
+ "javascript",
8
+ "shared",
9
+ "utils"
10
+ ],
11
+ "type": "module",
12
+ "bugs": {
13
+ "url": "https://github.com/modernman00/shared-js-lib/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/modernman00/shared-js-lib.git"
18
+ },
19
+ "license": "MIT",
20
+ "author": "olawale olaogun",
21
+ "main": "index.js",
22
+ "scripts": {
23
+ "test": "echo \"Error: no test specified\" && exit 1"
24
+ },
25
+ "dependencies": {
26
+ "axios": "^1.9.0",
27
+ "axios-retry": "^4.5.0"
28
+ }, "publishConfig": {
29
+ "access": "public"
30
+ }
31
+ }
@@ -0,0 +1,101 @@
1
+ export const autocomplete = (inp, arr) => {
2
+ /*the autocomplete function takes two arguments,
3
+ the text field element and an array of possible autocompleted values:*/
4
+ let currentFocus;
5
+ /*execute a function when someone writes in the text field:*/
6
+ inp.addEventListener("input", function(e) {
7
+ let a, b, i, val = this.value;
8
+ /*close any already open lists of autocompleted values*/
9
+ closeAllLists();
10
+ if (!val) { return false; }
11
+ currentFocus = -1;
12
+ /*create a DIV element that will contain the items (values):*/
13
+ a = document.createElement("DIV");
14
+ a.setAttribute("id", this.id + "autocomplete-list");
15
+ a.setAttribute("class", "autocomplete-items");
16
+ /*append the DIV element as a child of the autocomplete container:*/
17
+ this.parentNode.appendChild(a);
18
+ /*for each item in the array...*/
19
+ for (i = 0; i < arr.length; i++) {
20
+ /*check if the item starts with the same letters as the text field value:*/
21
+ if (arr[i] && arr[i].substr(0, val.length).toUpperCase() === val.toUpperCase()) {
22
+ if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) {
23
+ /*create a DIV element for each matching element:*/
24
+ b = document.createElement("DIV");
25
+ /*make the matching letters bold:*/
26
+ b.innerHTML = "<strong>" + arr[i].substr(0, val.length) + "</strong>";
27
+ b.innerHTML += arr[i].substr(val.length);
28
+ /*insert a input field that will hold the current array item's value:*/
29
+ b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
30
+ /*execute a function when someone clicks on the item value (DIV element):*/
31
+ b.addEventListener("click", function(e) {
32
+ /*insert the value for the autocomplete text field:*/
33
+ inp.value = this.getElementsByTagName("input")[0].value;
34
+ /*close the list of autocompleted values,
35
+ (or any other open lists of autocompleted values:*/
36
+ closeAllLists();
37
+ });
38
+ a.appendChild(b);
39
+ }
40
+ }
41
+ }
42
+ });
43
+ /*execute a function presses a key on the keyboard:*/
44
+ inp.addEventListener("keydown", function(e) {
45
+ var x = document.getElementById(this.id + "autocomplete-list");
46
+ if (x) x = x.getElementsByTagName("div");
47
+ if (e.keyCode == 40) {
48
+ /*If the arrow DOWN key is pressed,
49
+ increase the currentFocus variable:*/
50
+ currentFocus++;
51
+ /*and and make the current item more visible:*/
52
+ addActive(x);
53
+ } else if (e.keyCode == 38) { //up
54
+ /*If the arrow UP key is pressed,
55
+ decrease the currentFocus variable:*/
56
+ currentFocus--;
57
+ /*and and make the current item more visible:*/
58
+ addActive(x);
59
+ } else if (e.keyCode == 13) {
60
+ /*If the ENTER key is pressed, prevent the form from being submitted,*/
61
+ e.preventDefault();
62
+ if (currentFocus > -1) {
63
+ /*and simulate a click on the "active" item:*/
64
+ if (x) x[currentFocus].click();
65
+ }
66
+ }
67
+ });
68
+
69
+ function addActive(x) {
70
+ /*a function to classify an item as "active":*/
71
+ if (!x) return false;
72
+ /*start by removing the "active" class on all items:*/
73
+ removeActive(x);
74
+ if (currentFocus >= x.length) currentFocus = 0;
75
+ if (currentFocus < 0) currentFocus = (x.length - 1);
76
+ /*add class "autocomplete-active":*/
77
+ x[currentFocus].classList.add("autocomplete-active");
78
+ }
79
+
80
+ function removeActive(x) {
81
+ /*a function to remove the "active" class from all autocomplete items:*/
82
+ for (var i = 0; i < x.length; i++) {
83
+ x[i].classList.remove("autocomplete-active");
84
+ }
85
+ }
86
+
87
+ function closeAllLists(elmnt) {
88
+ /*close all autocomplete lists in the document,
89
+ except the one passed as an argument:*/
90
+ var x = document.getElementsByClassName("autocomplete-items");
91
+ for (var i = 0; i < x.length; i++) {
92
+ if (elmnt != x[i] && elmnt != inp) {
93
+ x[i].parentNode.removeChild(x[i]);
94
+ }
95
+ }
96
+ }
97
+ /*execute a function when someone clicks in the document:*/
98
+ document.addEventListener("click", function(e) {
99
+ closeAllLists(e.target);
100
+ });
101
+ }