@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/Cookie.js +49 -0
- package/CountryCode.js +214 -0
- package/DateTime.js +101 -0
- package/ForgotPassword.js +102 -0
- package/FormHelper.js +268 -0
- package/FormProcessing.js +22 -0
- package/Http.js +150 -0
- package/Loader.js +35 -0
- package/Login.js +43 -0
- package/ShowResponse.js +93 -0
- package/Utility.js +133 -0
- package/UtilityHtml.js +200 -0
- package/index.js +13 -0
- package/package.json +31 -0
- package/theAutoComplete.js +101 -0
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, '&')
|
|
128
|
+
.replace(/</g, '<')
|
|
129
|
+
.replace(/>/g, '>')
|
|
130
|
+
.replace(/"/g, '"')
|
|
131
|
+
.replace(/'/g, ''')
|
|
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
|
+
}
|