@modernman00/shared-js-lib 1.2.6 → 1.2.8
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/Login.js +32 -28
- package/README.md +74 -0
- package/ShowResponse.js +42 -84
- package/package.json +1 -1
- package/theAutoComplete.js +88 -95
package/Login.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
import { convertFormData } from './FormProcessing.js';
|
|
3
|
-
import { postFormData } from
|
|
3
|
+
import { postFormData } from './Http.js';
|
|
4
4
|
import { showLoader, clearLoader } from './Loader.js';
|
|
5
|
-
import { showError } from
|
|
5
|
+
import { showError } from './ShowResponse.js';
|
|
6
6
|
|
|
7
7
|
// block the setLoader div
|
|
8
8
|
|
|
@@ -15,29 +15,33 @@ import { showError } from "./ShowResponse.js";
|
|
|
15
15
|
* @returns {void}
|
|
16
16
|
* @throws {Error} - If there is an error with the submission
|
|
17
17
|
*/
|
|
18
|
-
export const loginSubmission = async (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
18
|
+
export const loginSubmission = async (
|
|
19
|
+
formId,
|
|
20
|
+
loginURL,
|
|
21
|
+
redirect,
|
|
22
|
+
css = null, lengthLimit = null
|
|
23
|
+
) => {
|
|
24
|
+
const formData = convertFormData(formId);
|
|
25
|
+
formData.clearError();
|
|
26
|
+
if (lengthLimit) {
|
|
27
|
+
formData.realTimeCheckLen(lengthLimit.maxLength.id, lengthLimit.maxLength.max);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
formData.emailVal();
|
|
32
|
+
formData.massValidate();
|
|
33
|
+
|
|
34
|
+
if (!formData.error.length) {
|
|
35
|
+
showLoader();
|
|
36
|
+
localStorage.setItem('redirect', redirect);
|
|
37
|
+
|
|
38
|
+
await postFormData(loginURL, formId, redirect, css);
|
|
39
|
+
} else {
|
|
40
|
+
alert('The form cannot be submitted. Please check the errors');
|
|
39
41
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
} catch (err) {
|
|
43
|
+
showError(err);
|
|
44
|
+
} finally {
|
|
45
|
+
clearLoader();
|
|
46
|
+
}
|
|
47
|
+
};
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
npm Usage Guide for @modernman00/shared-js-lib
|
|
2
|
+
This guide explains how to install and use the @modernman00/shared-js-lib package, now available on the npm registry, in your Node.js or JavaScript project.
|
|
3
|
+
Installation
|
|
4
|
+
To install the package from npm, run the following command in your project directory:
|
|
5
|
+
npm install @modernman00/shared-js-lib
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
This installs the latest published version from the npm registry.
|
|
9
|
+
Ensure you have an internet connection and npm access to the @modernman00 scope (authentication may be required if the package is private).
|
|
10
|
+
|
|
11
|
+
Usage
|
|
12
|
+
The package exports various utility functions from its modules (e.g., Http.js, Utility.js). Import and use them as follows:
|
|
13
|
+
Example: Using fetchData from Http.js
|
|
14
|
+
Assume Http.js exports a function to fetch data using Axios:
|
|
15
|
+
import { fetchData } from '@modernman00/shared-js-lib';
|
|
16
|
+
|
|
17
|
+
async function getUserData() {
|
|
18
|
+
try {
|
|
19
|
+
const userData = await fetchData('/api/users/1', { method: 'GET' });
|
|
20
|
+
console.log(userData);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Error fetching data:', error.message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getUserData();
|
|
27
|
+
|
|
28
|
+
Example: Using sanitizeInput from Utility.js
|
|
29
|
+
Assume Utility.js exports a sanitization function:
|
|
30
|
+
import { sanitizeInput } from '@modernman00/shared-js-lib';
|
|
31
|
+
|
|
32
|
+
const cleanInput = sanitizeInput('<script>alert("xss")</script>');
|
|
33
|
+
console.log(cleanInput); // Sanitized output
|
|
34
|
+
|
|
35
|
+
Configuration
|
|
36
|
+
|
|
37
|
+
Ensure your project uses ES Modules by adding "type": "module" to your package.json, or use a bundler like Laravel Mix/Webpack.
|
|
38
|
+
If using Laravel Mix, configure an alias in webpack.mix.js:const mix = require('laravel-mix');
|
|
39
|
+
const path = require('path');
|
|
40
|
+
|
|
41
|
+
mix.js('resources/js/app.js', 'public/js')
|
|
42
|
+
.webpackConfig({
|
|
43
|
+
resolve: {
|
|
44
|
+
alias: {
|
|
45
|
+
'@shared': path.resolve(__dirname, 'node_modules/@modernman00/shared-js-lib')
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
Updating the Package
|
|
53
|
+
To update to the latest version, run:
|
|
54
|
+
npm update @modernman00/shared-js-lib
|
|
55
|
+
|
|
56
|
+
Check the latest version on the npm website (https://www.npmjs.com/package/@modernman00/shared-js-lib) or with:
|
|
57
|
+
npm info @modernman00/shared-js-lib version
|
|
58
|
+
|
|
59
|
+
If a specific version is needed, install it directly:
|
|
60
|
+
npm install @modernman00/shared-js-lib@1.0.3
|
|
61
|
+
|
|
62
|
+
Rebuild assets if using a bundler:
|
|
63
|
+
npm run dev
|
|
64
|
+
|
|
65
|
+
Troubleshooting
|
|
66
|
+
|
|
67
|
+
Installation Fails: Ensure you have npm access and the package is published. Use verbose mode for details:npm install @modernman00/shared-js-lib --verbose
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
TypeScript Errors: Add declaration files (e.g., Http.d.ts) to the package if needed, and republish.
|
|
71
|
+
Permission Issues: If the package is scoped and private, log in to npm:npm login
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
package/ShowResponse.js
CHANGED
|
@@ -1,93 +1,51 @@
|
|
|
1
|
-
import { id } from './UtilityHtml.js';
|
|
2
|
-
import axios from "axios"
|
|
3
|
-
export const showError = (e) => console.error(`${e.name} at ${e.fileName}:${e.lineNumber} - ${e.message}\n${e.stack}`);
|
|
1
|
+
import { id, qSel } from './UtilityHtml.js';
|
|
4
2
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
export const showError = (e) =>
|
|
4
|
+
console.error(
|
|
5
|
+
`${e.name} at ${e.fileName}:${e.lineNumber} - ${e.message}\n${e.stack}`,
|
|
6
|
+
);
|
|
9
7
|
|
|
8
|
+
export const msgException = (errorMessage) => {
|
|
9
|
+
throw new Error(errorMessage);
|
|
10
|
+
};
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
+
*
|
|
13
14
|
* @param {*} elementId - element id
|
|
14
15
|
* @param {*} addClass either a success or danger class (green or red)
|
|
15
16
|
* @param {*} message - html message to convey success or failure
|
|
16
17
|
* @param {*} timer - timer for the message to disappear- default is 5 secs
|
|
17
18
|
*/
|
|
18
|
-
export const showNotification = (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const notificationHTML = id(senderId);
|
|
52
|
-
|
|
53
|
-
// Make sure required variables are defined before using them
|
|
54
|
-
if (
|
|
55
|
-
typeof yourId === 'undefined' ||
|
|
56
|
-
typeof famCode === 'undefined'
|
|
57
|
-
) {
|
|
58
|
-
msgException("Required parameters (yourId or famCode) are not defined");
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const url = `/removeNotification/${yourId}/${famCode}/${data}`
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const response = await axios.put(url)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (response.data.message === "Notification marked as read") {
|
|
68
|
-
|
|
69
|
-
// remove a html element with notificationBar after 2 mins
|
|
70
|
-
notificationHTML.remove()
|
|
71
|
-
|
|
72
|
-
// reduce the notification count as you have deleted the notification
|
|
73
|
-
|
|
74
|
-
const newValues = parseInt(sessionStorage.getItem('notificationCount') - 1)
|
|
75
|
-
id('notification_count').innerHTML = newValues;
|
|
76
|
-
} else {
|
|
77
|
-
msgException("Error removing notification" + " " + response.data.message);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export const showResponse = (theId, message, status) => {
|
|
82
|
-
const responseEl = id(theId)
|
|
83
|
-
const col = status ? 'green' : 'red'
|
|
84
|
-
|
|
85
|
-
responseEl.innerHTML = message
|
|
86
|
-
responseEl.style.color = 'green'
|
|
87
|
-
responseEl.style.backgroundColor = col
|
|
88
|
-
responseEl.style.color = 'white';
|
|
89
|
-
setTimeout(() => {
|
|
90
|
-
responseEl.innerHTML = '';
|
|
91
|
-
}, 5000); // Disappear after 5 seconds
|
|
92
|
-
|
|
93
|
-
}
|
|
19
|
+
export const showNotification = (
|
|
20
|
+
elementId,
|
|
21
|
+
addClass,
|
|
22
|
+
message,
|
|
23
|
+
timer = 5000,
|
|
24
|
+
) => {
|
|
25
|
+
// display the success information for 10sec
|
|
26
|
+
id(`${elementId}`).style.display = 'block'; // unblock the notification
|
|
27
|
+
id(`${elementId}`).classList.add(addClass); // add the success class
|
|
28
|
+
id(`${elementId}`).innerHTML = message; // error element
|
|
29
|
+
id('loader').classList.remove('loader'); // remove loader
|
|
30
|
+
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
id(`${elementId}`).style.backgroundColor = '';
|
|
33
|
+
id(`${elementId}`).style.color = '';
|
|
34
|
+
id(`${elementId}`).innerHTML = '';
|
|
35
|
+
}, timer);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
export const showResponse = (theId, message, status) => {
|
|
41
|
+
const responseEl = id(theId);
|
|
42
|
+
const col = status ? 'green' : 'red';
|
|
43
|
+
|
|
44
|
+
responseEl.innerHTML = message;
|
|
45
|
+
responseEl.style.color = 'green';
|
|
46
|
+
responseEl.style.backgroundColor = col;
|
|
47
|
+
responseEl.style.color = 'white';
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
responseEl.innerHTML = '';
|
|
50
|
+
}, 5000); // Disappear after 5 seconds
|
|
51
|
+
};
|
package/package.json
CHANGED
package/theAutoComplete.js
CHANGED
|
@@ -1,101 +1,94 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
}
|
|
1
|
+
import { id } from './UtilityHtml'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {string} inputId
|
|
6
|
+
* @param {Array} arr
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Sets up an autocomplete functionality for an input element.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} inputId - The ID of the input element to attach the autocomplete to.
|
|
13
|
+
* @param {Array<string>} arr - An array of strings containing the autocomplete suggestions.
|
|
14
|
+
*
|
|
15
|
+
* The function converts all strings in the array to lowercase for case-insensitive matching.
|
|
16
|
+
* It initializes the autocomplete with the given input element and array of suggestions,
|
|
17
|
+
* providing real-time suggestions based on user input. On selecting a suggestion,
|
|
18
|
+
* it populates the input element with the selected suggestion.
|
|
19
|
+
*/
|
|
20
|
+
const autocomplete = (inputId, arr) => {
|
|
21
|
+
const whatToBuyInput = id(inputId); // Get the text input
|
|
22
|
+
if (whatToBuyInput) {
|
|
23
|
+
// Create a <ul> for autocomplete suggestions
|
|
24
|
+
const suggestionList = document.createElement("ul");
|
|
25
|
+
suggestionList.classList.add("autocomplete-suggestions");
|
|
26
|
+
suggestionList.id = "suggestions"; // For accessibility
|
|
27
|
+
whatToBuyInput.parentElement.appendChild(suggestionList); // Append to input's parent
|
|
28
|
+
|
|
29
|
+
// Function to show matching suggestions based on user input
|
|
30
|
+
const showSuggestions = (inputValue) => {
|
|
31
|
+
suggestionList.innerHTML = ""; // Clear previous suggestions
|
|
32
|
+
if (!inputValue) return; // Exit if input is empty
|
|
33
|
+
|
|
34
|
+
// Filter items that match the input (case-insensitive), limit to 8
|
|
35
|
+
const matches = arr
|
|
36
|
+
.filter(item => item.toLowerCase().includes(inputValue.toLowerCase()))
|
|
37
|
+
.slice(0, 8);
|
|
38
|
+
|
|
39
|
+
// Create <li> for each match
|
|
40
|
+
matches.forEach((item, index) => {
|
|
41
|
+
const li = document.createElement("li");
|
|
42
|
+
li.textContent = item;
|
|
43
|
+
li.setAttribute("tabindex", "0"); // Make focusable for keyboard
|
|
44
|
+
li.setAttribute("data-index", index); // Store index for navigation
|
|
45
|
+
li.addEventListener("click", () => {
|
|
46
|
+
whatToBuyInput.value = item; // Set input value on click
|
|
47
|
+
suggestionList.innerHTML = ""; // Clear suggestions
|
|
48
|
+
});
|
|
49
|
+
li.addEventListener("keypress", (e) => {
|
|
50
|
+
if (e.key === "Enter") {
|
|
51
|
+
whatToBuyInput.value = item; // Set input value on Enter
|
|
52
|
+
suggestionList.innerHTML = ""; // Clear suggestions
|
|
66
53
|
}
|
|
54
|
+
});
|
|
55
|
+
suggestionList.appendChild(li);
|
|
67
56
|
});
|
|
57
|
+
};
|
|
68
58
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
}
|
|
59
|
+
// Show suggestions as user types
|
|
60
|
+
whatToBuyInput.addEventListener("input", (e) => {
|
|
61
|
+
showSuggestions(e.target.value);
|
|
62
|
+
});
|
|
79
63
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
}
|
|
64
|
+
// Clear suggestions on blur (with delay for click to register)
|
|
65
|
+
whatToBuyInput.addEventListener("blur", () => {
|
|
66
|
+
setTimeout(() => suggestionList.innerHTML = "", 200);
|
|
67
|
+
});
|
|
86
68
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
69
|
+
// Handle keyboard navigation for suggestions
|
|
70
|
+
whatToBuyInput.addEventListener("keydown", (e) => {
|
|
71
|
+
const suggestions = suggestionList.querySelectorAll("li");
|
|
72
|
+
if (!suggestions.length) return; // Exit if no suggestions
|
|
73
|
+
|
|
74
|
+
let focusedIndex = Array.from(suggestions).findIndex(li => li === document.activeElement);
|
|
75
|
+
if (e.key === "ArrowDown") {
|
|
76
|
+
e.preventDefault(); // Prevent cursor movement
|
|
77
|
+
focusedIndex = (focusedIndex + 1) % suggestions.length; // Loop to start
|
|
78
|
+
suggestions[focusedIndex].focus();
|
|
79
|
+
} else if (e.key === "ArrowUp") {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
focusedIndex = (focusedIndex - 1 + suggestions.length) % suggestions.length; // Loop to end
|
|
82
|
+
suggestions[focusedIndex].focus();
|
|
83
|
+
} else if (e.key === "Enter" && focusedIndex >= 0) {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
whatToBuyInput.value = suggestions[focusedIndex].textContent; // Select item
|
|
86
|
+
suggestionList.innerHTML = ""; // Clear suggestions
|
|
87
|
+
} else if (e.key === "Escape") {
|
|
88
|
+
suggestionList.innerHTML = ""; // Clear suggestions
|
|
96
89
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default autocomplete
|