-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplaceholder-autocomplete.js
171 lines (135 loc) · 4.8 KB
/
placeholder-autocomplete.js
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
const createPlaceholder = () => {
const placeholderInput = document.createElement('div');
placeholderInput.classList.add('placeholder-input');
return placeholderInput;
};
const closest = (arr, textToFind) => {
var matches = arr.filter(function (windowValue) {
if (windowValue) {
return windowValue.indexOf(textToFind) >= 0;
}
});
return matches[0] || '';
};
export const getFormattedStringFromInput = ({currentText, terms, onSuggestion}) => {
let finalString = '';
const splitTextBySpace = currentText.split(' ').filter(Boolean);
const triggerEvent = (key, value) => {
if (onSuggestion) {
onSuggestion({key, value});
}
}
splitTextBySpace.forEach((textBlock, textIndex) => {
// if empty return
if (textBlock === '') {
return;
}
const splitTextByColon = textBlock.split(':');
//if were not last we just show key value no need to check
if (textIndex !== splitTextBySpace.length - 1) {
const key = splitTextByColon[0];
const value = splitTextByColon[1];
//space in the end between existing combinations
if (key && value) {
finalString += `${key}:${value} `;
} else if (key) {
finalString += `${key} `;
}
return;
}
//key + value
if (splitTextByColon.length === 2) {
const key = splitTextByColon[0];
// bad combination amazing user
if (!terms[key]) {
finalString = currentText;
return;
}
const textValue = splitTextByColon[1];
const allValues = Object.values(terms[key]);
if (textValue.indexOf(',') === -1) {
const valueToShow = closest(allValues, textValue);
triggerEvent(key, valueToShow || textValue);
finalString += `${key}:${valueToShow || textValue}`;
} else {
// multiple values
const splitValueByCommas = textValue.split(',');
const lastValue = splitValueByCommas.splice(-1);
const lastValueSimilarFound = closest(allValues, lastValue) || lastValue; // for now default 0
const allValuesToShow = [...splitValueByCommas, lastValueSimilarFound];
triggerEvent(key, allValuesToShow);
finalString += `${key}:${allValuesToShow.join(',')}`;
}
return;
}
// only key
if (splitTextByColon.length === 1) {
const key = splitTextByColon[0];
const allKeys = Object.keys(terms);
const keyName = closest(allKeys, key);
if (!keyName) {
finalString = currentText;
return;
}
triggerEvent(keyName, terms[keyName][0]);
finalString += `${keyName}:${terms[keyName][0]}`;
return;
}
});
return finalString;
};
const listenToText = ({input, placeholder, terms, onSuggestion}) => {
const getTextFromEvent = (e) => {
const currentText = e.target.value;
return getFormattedStringFromInput({currentText, terms, onSuggestion});
};
const handleInput = (e) => {
placeholder.innerText = getTextFromEvent(e);
};
const handleTabPress = (e) => {
if (e.key === 'Tab') {
e.preventDefault();
const result = getTextFromEvent(e);
if (result) {
input.value = result;
}
}
};
input.addEventListener('input', handleInput);
input.addEventListener('keydown', handleTabPress);
// placeholder.addEventListener('click', () => input.focus());
};
export const createPlaceholderAutocomplete = ({inputId, styles = {}, terms, onSuggestion}) => {
const realInput = document.getElementById(inputId);
const placeholderInput = createPlaceholder();
//set parent css
realInput.parentElement.style.position = 'relative';
//get css from input to apply on placeholder
const {fontFamily, border, lineHeight, letterSpacing, width, padding, font, fontWeight} = getComputedStyle(realInput);
Object.assign(placeholderInput.style, {
position: 'absolute',
pointerEvents: 'none',
top: 0,
left: 0,
opacity: '0.5',
overflow: 'hidden',
border,
borderColor: 'transparent',
cursor: 'text',
userSelect: 'none',
padding,
font,
fontFamily,
lineHeight,
letterSpacing,
fontWeight,
width
}, styles);
realInput.after(placeholderInput);
listenToText({
input: realInput,
onSuggestion,
placeholder: placeholderInput,
terms
});
};