homeflowjs 1.0.103 → 1.0.104
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/app/recaptcha.js
CHANGED
|
@@ -12,11 +12,14 @@ window.submitRecaptchaForm = (token) => {
|
|
|
12
12
|
|
|
13
13
|
Homeflow.kickEvent('after_successful_recaptcha', form);
|
|
14
14
|
|
|
15
|
+
console.log('Appending recaptchaTokenField', recaptchaTokenField);
|
|
15
16
|
form.appendChild(recaptchaTokenField);
|
|
16
17
|
form.submit();
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
export default () => {
|
|
21
|
+
console.log('Recaptcha script loaded');
|
|
22
|
+
|
|
20
23
|
window.addEventListener('DOMContentLoaded', () => {
|
|
21
24
|
if (window.noRecaptcha) return null;
|
|
22
25
|
|
|
@@ -29,7 +32,7 @@ export default () => {
|
|
|
29
32
|
'form[action="/user/send_to_friend"]',
|
|
30
33
|
];
|
|
31
34
|
|
|
32
|
-
const initUniqRecaptchaV2Wrapper = ({form, id}) => {
|
|
35
|
+
const initUniqRecaptchaV2Wrapper = ({ form, id }) => {
|
|
33
36
|
const recaptchaId = id || Math.random().toString().substring(2);
|
|
34
37
|
const formRecaptchaWrapper = document.createElement('div');
|
|
35
38
|
formRecaptchaWrapper.classList.add('recaptcha-wrapper');
|
|
@@ -38,14 +41,21 @@ export default () => {
|
|
|
38
41
|
form.appendChild(formRecaptchaWrapper);
|
|
39
42
|
|
|
40
43
|
const onRecaptchaSubmit = () => {
|
|
44
|
+
console.log('Recaptcha V2 submitted');
|
|
45
|
+
|
|
41
46
|
if (form.classList?.contains('async-recaptcha-submit')) {
|
|
47
|
+
console.log('Async form');
|
|
42
48
|
const continueAsyncSubmission = new Event('async-recaptcha-submit');
|
|
43
49
|
document.dispatchEvent(continueAsyncSubmission);
|
|
44
50
|
} else {
|
|
51
|
+
console.log('Calling form.submit()', form);
|
|
45
52
|
form.submit();
|
|
46
53
|
}
|
|
54
|
+
|
|
55
|
+
console.log('After IF statement');
|
|
56
|
+
|
|
47
57
|
Homeflow.kickEvent('after_successful_recaptcha', form);
|
|
48
|
-
}
|
|
58
|
+
};
|
|
49
59
|
|
|
50
60
|
const widget = window.grecaptcha.render(`recaptcha-wrapper-${recaptchaId}`, {
|
|
51
61
|
sitekey: '6Lf16S0UAAAAAL0YaWCLRhChd4Uk77b-4Ai0ZdRY',
|
|
@@ -53,61 +63,76 @@ export default () => {
|
|
|
53
63
|
size: 'invisible',
|
|
54
64
|
});
|
|
55
65
|
|
|
56
|
-
window.widgetIds
|
|
66
|
+
console.log('window.widgetIds', window.widgetIds);
|
|
67
|
+
|
|
68
|
+
window.widgetIds = window.widgetIds
|
|
57
69
|
? [...window.widgetIds, widget]
|
|
58
|
-
: [widget]
|
|
70
|
+
: [widget];
|
|
59
71
|
|
|
60
72
|
form.addEventListener('submit', (e) => {
|
|
73
|
+
console.log('Submit handler called...');
|
|
74
|
+
|
|
61
75
|
if (e.target.classList.contains('hfjs-form-invalid')) {
|
|
62
76
|
return;
|
|
63
77
|
}
|
|
64
78
|
|
|
79
|
+
console.log('Preventing default...');
|
|
65
80
|
e.preventDefault();
|
|
81
|
+
|
|
66
82
|
Homeflow.set('submitted_form', e.target);
|
|
83
|
+
console.log('Running grecaptcha.execute...');
|
|
67
84
|
grecaptcha.execute(widget);
|
|
68
85
|
});
|
|
69
|
-
}
|
|
86
|
+
};
|
|
70
87
|
|
|
71
88
|
const onRecaptchaV2Ready = (triggeredFormEl) => {
|
|
89
|
+
console.log('onRecaptchaV2Ready running');
|
|
90
|
+
|
|
72
91
|
if (window.recaptchaLoadingScriptInterval) {
|
|
73
92
|
clearInterval(window.recaptchaLoadingScriptInterval);
|
|
74
93
|
window.recaptchaLoadingScriptInterval = undefined;
|
|
75
94
|
}
|
|
76
95
|
|
|
77
96
|
if (triggeredFormEl) {
|
|
78
|
-
initUniqRecaptchaV2Wrapper({form: triggeredFormEl})
|
|
97
|
+
initUniqRecaptchaV2Wrapper({ form: triggeredFormEl });
|
|
79
98
|
} else {
|
|
80
99
|
const forms = document.querySelectorAll(formSelectors.join(', '));
|
|
81
100
|
|
|
101
|
+
console.log('forms', forms);
|
|
102
|
+
|
|
82
103
|
forms.forEach((form, i) => {
|
|
83
|
-
initUniqRecaptchaV2Wrapper({ form, id: i })
|
|
104
|
+
initUniqRecaptchaV2Wrapper({ form, id: i });
|
|
84
105
|
});
|
|
85
106
|
}
|
|
86
|
-
}
|
|
107
|
+
};
|
|
87
108
|
|
|
88
109
|
const appendRecaptchaScript = (version) => {
|
|
89
110
|
const srcConfig = {
|
|
90
111
|
v2: 'https://www.google.com/recaptcha/api.js',
|
|
91
112
|
v3: 'https://www.google.com/recaptcha/api.js?render=6LeKPOUUAAAAAEKNWIu2qkNwdOqVxH41v0D7fe-K',
|
|
92
|
-
}
|
|
113
|
+
};
|
|
93
114
|
|
|
94
115
|
const recaptchaScript = document.createElement('script');
|
|
95
116
|
recaptchaScript.src = srcConfig[version];
|
|
96
117
|
recaptchaScript.id = 'recaptcha-script';
|
|
97
118
|
|
|
119
|
+
console.log('Appending recaptcha script...');
|
|
98
120
|
document.body.appendChild(recaptchaScript);
|
|
99
121
|
|
|
100
122
|
if (version === 'v2') {
|
|
101
|
-
|
|
123
|
+
window.recaptchaLoadingScriptInterval = setInterval(() => {
|
|
124
|
+
console.log('Running setInterval callback...');
|
|
102
125
|
if (window.grecaptcha?.render) {
|
|
103
|
-
onRecaptchaV2Ready
|
|
126
|
+
console.log('Calling onRecaptchaV2Ready from inside interval callback...');
|
|
127
|
+
onRecaptchaV2Ready();
|
|
104
128
|
}
|
|
105
129
|
}, 300);
|
|
106
130
|
}
|
|
107
|
-
}
|
|
131
|
+
};
|
|
108
132
|
|
|
109
133
|
const initRecaptchaV3 = (form) => {
|
|
110
134
|
form.addEventListener('submit', (e) => {
|
|
135
|
+
console.log('Recaptcha V3 submitted');
|
|
111
136
|
if (!document.getElementById('g-recaptcha-response') || !document.getElementById('g-recaptcha-response').value) {
|
|
112
137
|
e.preventDefault();
|
|
113
138
|
Homeflow.set('submitted_form', e.target);
|
|
@@ -118,22 +143,23 @@ export default () => {
|
|
|
118
143
|
}
|
|
119
144
|
});
|
|
120
145
|
form.classList.add('has-recaptcha');
|
|
121
|
-
}
|
|
146
|
+
};
|
|
122
147
|
|
|
123
148
|
const handleRecaptchaV3ForTargetForm = (targetFormEl) => {
|
|
124
149
|
if (!document.getElementById('recaptcha-script')) {
|
|
125
|
-
appendRecaptchaScript('v3')
|
|
150
|
+
appendRecaptchaScript('v3');
|
|
126
151
|
}
|
|
127
|
-
|
|
128
|
-
initRecaptchaV3(targetFormEl)
|
|
129
|
-
}
|
|
152
|
+
|
|
153
|
+
initRecaptchaV3(targetFormEl);
|
|
154
|
+
};
|
|
130
155
|
|
|
131
156
|
function addRecaptchaV3(targetFormEl) {
|
|
132
157
|
for (let i = 0; i < formSelectors.length; i++) {
|
|
133
158
|
if (targetFormEl) {
|
|
134
|
-
handleRecaptchaV3ForTargetForm(targetFormEl)
|
|
159
|
+
handleRecaptchaV3ForTargetForm(targetFormEl);
|
|
135
160
|
} else {
|
|
136
161
|
const formInputs = document.querySelectorAll(`${formSelectors[i]} input, ${formSelectors[i]} textarea`);
|
|
162
|
+
|
|
137
163
|
formInputs.forEach((input) => {
|
|
138
164
|
input.addEventListener('focus', () => {
|
|
139
165
|
if (!document.getElementById('recaptcha-script')) {
|
|
@@ -145,7 +171,7 @@ export default () => {
|
|
|
145
171
|
|
|
146
172
|
const forms = document.querySelectorAll(formSelectors[i]);
|
|
147
173
|
forms.forEach((form) => {
|
|
148
|
-
handleRecaptchaV3ForTargetForm(form)
|
|
174
|
+
handleRecaptchaV3ForTargetForm(form);
|
|
149
175
|
});
|
|
150
176
|
}
|
|
151
177
|
}
|
|
@@ -153,31 +179,34 @@ export default () => {
|
|
|
153
179
|
const handleRecaptchaV2ForTargetForm = (targetFormEl) => {
|
|
154
180
|
const hasRecaptcha = targetFormEl?.querySelector('.recaptcha-wrapper');
|
|
155
181
|
|
|
156
|
-
if(hasRecaptcha) {
|
|
182
|
+
if (hasRecaptcha) {
|
|
157
183
|
return;
|
|
158
184
|
}
|
|
159
|
-
|
|
185
|
+
|
|
160
186
|
if (!document.getElementById('recaptcha-script')) {
|
|
161
|
-
appendRecaptchaScript('v2')
|
|
187
|
+
appendRecaptchaScript('v2');
|
|
162
188
|
}
|
|
163
189
|
if (window.grecaptcha) {
|
|
164
|
-
onRecaptchaV2Ready(targetFormEl)
|
|
190
|
+
onRecaptchaV2Ready(targetFormEl);
|
|
165
191
|
}
|
|
166
|
-
}
|
|
192
|
+
};
|
|
167
193
|
|
|
168
194
|
function addRecaptchaV2(targetFormEl) {
|
|
169
195
|
if (targetFormEl) {
|
|
170
|
-
handleRecaptchaV2ForTargetForm(targetFormEl)
|
|
196
|
+
handleRecaptchaV2ForTargetForm(targetFormEl);
|
|
171
197
|
} else {
|
|
172
198
|
for (let i = 0; i < formSelectors.length; i++) {
|
|
173
199
|
const formInputs = document.querySelectorAll(
|
|
174
|
-
`${formSelectors[i]} input, ${formSelectors[i]} textarea, ${formSelectors[i]} select
|
|
200
|
+
`${formSelectors[i]} input, ${formSelectors[i]} textarea, ${formSelectors[i]} select`,
|
|
175
201
|
);
|
|
202
|
+
|
|
203
|
+
console.log('formInputs', formInputs);
|
|
176
204
|
formInputs.forEach((input) => {
|
|
177
205
|
input.addEventListener('focusin', (event) => {
|
|
178
206
|
event.stopPropagation();
|
|
179
207
|
if (!document.getElementById('recaptcha-script')) {
|
|
180
|
-
|
|
208
|
+
console.log('Calling appendRecaptchaScript...');
|
|
209
|
+
appendRecaptchaScript('v2');
|
|
181
210
|
}
|
|
182
211
|
});
|
|
183
212
|
});
|
|
@@ -186,12 +215,13 @@ export default () => {
|
|
|
186
215
|
}
|
|
187
216
|
|
|
188
217
|
const initRecaptcha = (targetFormEl) => {
|
|
218
|
+
console.log('Inside initRecaptcha');
|
|
189
219
|
if (Homeflow.get('recaptcha_version') === 3) {
|
|
190
220
|
addRecaptchaV3(targetFormEl);
|
|
191
221
|
} else {
|
|
192
222
|
addRecaptchaV2(targetFormEl);
|
|
193
223
|
}
|
|
194
|
-
}
|
|
224
|
+
};
|
|
195
225
|
|
|
196
226
|
const handleRecaptchaRelatedBodyFocus = (event) => {
|
|
197
227
|
event.stopPropagation();
|
|
@@ -205,13 +235,18 @@ export default () => {
|
|
|
205
235
|
if (isFormElementFocused && isRecaptchaForm) {
|
|
206
236
|
initRecaptcha(targetFormEl);
|
|
207
237
|
}
|
|
208
|
-
}
|
|
238
|
+
};
|
|
209
239
|
|
|
210
240
|
const initDynamicallyOpenFormsRecaptcha = () => {
|
|
211
241
|
document.body.addEventListener('focusin', handleRecaptchaRelatedBodyFocus);
|
|
212
|
-
}
|
|
242
|
+
};
|
|
213
243
|
|
|
244
|
+
console.log('Calling initDynamicallyOpenFormsRecaptcha...');
|
|
214
245
|
initDynamicallyOpenFormsRecaptcha();
|
|
215
|
-
|
|
246
|
+
|
|
247
|
+
console.log('Calling initRecaptcha...');
|
|
248
|
+
initRecaptcha();
|
|
249
|
+
|
|
250
|
+
return null;
|
|
216
251
|
});
|
|
217
252
|
};
|
package/package.json
CHANGED
package/search/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import SavedSearch from './saved-search/saved-search.component';
|
|
|
15
15
|
import propertySearch from './property-search/property-search';
|
|
16
16
|
import generateSearchDescription from './saved-search/generate-description';
|
|
17
17
|
import TextSearchInput from './text-search/text-search.component';
|
|
18
|
+
import PropertyTypeSelect from './property-type-select/property-type-select.component';
|
|
18
19
|
|
|
19
20
|
export {
|
|
20
21
|
SearchForm,
|
|
@@ -34,4 +35,5 @@ export {
|
|
|
34
35
|
SaveSearchButton,
|
|
35
36
|
SavedSearch,
|
|
36
37
|
propertySearch,
|
|
38
|
+
PropertyTypeSelect,
|
|
37
39
|
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import Select from 'react-dropdown';
|
|
3
|
+
import { useSelector, useDispatch } from 'react-redux';
|
|
4
|
+
import { addTag, removeTag } from '../../actions/search.actions';
|
|
5
|
+
import { capitalizeFirstLetter } from '../../utils';
|
|
6
|
+
|
|
7
|
+
const ReactSelect = ({
|
|
8
|
+
className,
|
|
9
|
+
styles,
|
|
10
|
+
propertyTypes,
|
|
11
|
+
placeholder,
|
|
12
|
+
selectedType,
|
|
13
|
+
onChange,
|
|
14
|
+
}) => {
|
|
15
|
+
|
|
16
|
+
const types = useMemo(
|
|
17
|
+
() => propertyTypes.map((type) => ({ value: type, label: capitalizeFirstLetter(type) })),
|
|
18
|
+
[propertyTypes]
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const searchTypes = selectedType
|
|
22
|
+
? [{ value: '', label: 'Property type' }, ...types]
|
|
23
|
+
: types;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<Select
|
|
27
|
+
classNamePrefix="react-select"
|
|
28
|
+
className={className}
|
|
29
|
+
styles={styles}
|
|
30
|
+
options={searchTypes}
|
|
31
|
+
placeholder={placeholder || 'Property type'}
|
|
32
|
+
value={searchTypes.find((type) => type.value === selectedType) || null}
|
|
33
|
+
onChange={(opt) => onChange(opt.value)}
|
|
34
|
+
isSearchable={false}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const PropertyTypeSelect = ({ propertyTypes, className, placeholder, styles }) => {
|
|
40
|
+
const dispatch = useDispatch();
|
|
41
|
+
const tags = useSelector((state) => state.search.currentSearch.tags) || [];
|
|
42
|
+
const selectedType = propertyTypes.find((type) => tags.includes(type)) || null;
|
|
43
|
+
|
|
44
|
+
const handleChange = (newType) => {
|
|
45
|
+
const previousType = propertyTypes.find((option) => tags.includes(option)) || null;
|
|
46
|
+
|
|
47
|
+
if (previousType) {
|
|
48
|
+
dispatch(removeTag(previousType));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (newType) {
|
|
52
|
+
dispatch(addTag(newType));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<ReactSelect
|
|
58
|
+
className={className}
|
|
59
|
+
styles={styles}
|
|
60
|
+
propertyTypes={propertyTypes}
|
|
61
|
+
placeholder={placeholder}
|
|
62
|
+
selectedType={selectedType}
|
|
63
|
+
onChange={handleChange}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default PropertyTypeSelect;
|