PluginProbe
WP Directory Kit / 1.5.9
WP Directory Kit v1.5.9
1.5.9 1.5.7 1.5.6 1.5.5 1.5.4 1.5.3 trunk 1.1.0 1.1.6 1.1.8 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.8 All 37 releases
wpdirectorykit / public / js / wpdirectorykit-public.js

wpdirectorykit-public.js in WP Directory Kit 1.5.9, at public/js/wpdirectorykit-public.js

1,122 lines 46.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function( $ ) {
2 'use strict';
3
4 /**
5 * All of the code for your public-facing JavaScript source
6 * should reside in this file.
7 *
8 * Note: It has been assumed you will write jQuery code here, so the
9 * $ function reference has been prepared for usage within the scope
10 * of this function.
11 *
12 * This enables you to define handlers, for when the DOM is ready:
13 *
14 * $(function() {
15 *
16 * });
17 *
18 * When the window is loaded:
19 *
20 * $( window ).load(function() {
21 *
22 * });
23 *
24 * ...and/or other possibilities.
25 *
26 * Ideally, it is not considered best practise to attach more than a
27 * single DOM-ready or window-load handler for a particular page.
28 * Although scripts in the WordPress core, Plugins and Themes may be
29 * practising this, we should strive to set a better example in our own work.
30 */
31
32 $(function () {
33 $('.wdk-click-load-animation').on('click', function () {
34 $(this).find('.fa-ajax-indicator').css('display', 'inline-block');
35
36 if ($(this).closest('form').length) {
37 if (!$(this).closest('form')[0].checkValidity()) {
38 $(this).find('.fa-ajax-indicator').css('display', 'none');
39 }
40 }
41 });
42
43 $('.wdk-form-animation').on('submit', function () {
44 var form, indicator;
45 form = $(this);
46 indicator = form.find('.fa-ajax-indicator');
47 indicator.css('display', 'inline-block');
48
49 if(form[0].checkValidity())
50 indicator.css('display', 'none');
51 });
52
53
54 $('.wdk-submit-loading').on('click', function () {
55 var form;
56 form = $(this).closest('form');
57
58 if( $(this).hasClass('wdk_btn_load_indicator')) {
59 return false;
60 }
61
62 $(this).addClass('wdk_btn_load_indicator disabled');
63 });
64
65 $('.wdk-click-loading').on('click', function (e) {
66
67 if( $(this).hasClass('wdk_btn_load_indicator')) {
68 return false;
69 }
70 $(this).addClass('wdk_btn_load_indicator disabled');
71 });
72
73 const wdk_start_search = (form, formData = null) => {
74 var url,scrollTo, data = {};
75 url = form.attr('action').replace(/#results/, '');
76 if (url.indexOf('?') == -1) {
77 url += '?';
78 } else {
79 url += '&';
80 }
81 var str_parameters = "";
82
83 if (formData) {
84
85 $.each(formData, function (name, value) {
86 if (
87 value != '' &&
88 name.indexOf('skip') == -1
89 ) {
90 if (str_parameters != "") {
91 str_parameters += "&";
92 }
93
94 str_parameters += name + "=" + encodeURIComponent(value);
95 }
96 });
97
98 } else {
99 $.each($("form.wdk-search-form:visible").serializeArray(), function (i, k) {
100 if (k.value != '' && k.name.indexOf('skip') == -1) {
101 if (str_parameters != "") {
102 str_parameters += "&";
103 }
104 str_parameters += k.name + "=" + encodeURIComponent(k.value);
105 }
106 });
107
108 $.each($("form.wdk-search-form.map").serializeArray(), function (i, k) {
109 if (k.value != '' && k.name.indexOf('skip') == -1) {
110 if (str_parameters != "") {
111 str_parameters += "&";
112 }
113 str_parameters += k.name + "=" + encodeURIComponent(k.value);
114 }
115 });
116
117 $.each($(".wdk-search-popup .toggle-btn:visible"), function (i, k) {
118 let el = $($(this).attr('data-wdk-target'));
119 if(el && el.length) {
120 $.each(el.find('.wdk-search-form').serializeArray(), function (i, k) {
121 if (k.value != '' && k.name.indexOf('skip') == -1) {
122 if (str_parameters != "") {
123 str_parameters += "&";
124 }
125 str_parameters += k.name + "=" + encodeURIComponent(k.value);
126 }
127 });
128 }
129 });
130 }
131 /* view_type */
132 if($('.wmvc-view-type .nav-link.active').length) {
133 str_parameters += "&wmvc_view_type="+$('.wmvc-view-type .nav-link.active').attr('data-id');
134 }
135
136 /* order by */
137 if($('.wdk-order').val() != '' && $('.wdk-order').val()) {
138 str_parameters += "&order_by="+$('.wdk-order').val();
139 }
140
141 if ($('.wdk-search-form[data-scrollto]').length)
142 scrollTo = '#'+$('.wdk-search-form[data-scrollto]').attr('data-scrollto');
143
144
145
146 var setCookie = (cname, cvalue, exdays) => {
147 var d = new Date();
148 d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
149 var expires = "expires="+d.toUTCString();
150 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
151 }
152 setCookie('wdk_last_search', str_parameters);
153
154 return url+str_parameters+scrollTo;
155 }
156
157 /* set current page for search results if exists results widget and enabled in setttings*/
158 $('form.wdk-search-form').each(function() {
159 var $form = $(this);
160 if ($('.wdk-listings-results').length && $('.wdk-listings-results#results').length && $form.attr('data-current-link')) {
161 $form.attr('action', $form.attr('data-current-link'));
162 }
163 });
164
165 $("form.wdk-search-form").on('submit', function (e) {
166 e.preventDefault();
167 var url = wdk_start_search($(this));
168 $(this).closest('form').addClass('loading')
169 if (decodeURI(window.location.href) == decodeURI(url)) {
170 window.location.reload();
171 } else {
172 window.location.href = url;
173 }
174 return false;
175 });
176
177 $("form.wdk-search-form.auto_search").find('input, select').on('input', function (e) {
178 $("form.wdk-search-form").first().trigger('submit')
179 });
180
181 $("form.wdk-search-form .wdk-search-start:not(.wdk-search-reset)").on('click', function (e) {
182 e.preventDefault();
183 var url = wdk_start_search($(this).closest('form'));
184 $(this).closest('form').addClass('loading')
185
186 if($(this).closest('.ajax_results_enabled').length) {
187 if (typeof wdk_ajax_loading_listings == 'function') {
188 wdk_ajax_loading_listings(url);
189 }
190 } else if (decodeURI(window.location.href) == decodeURI(url)) {
191 window.location.reload(url);
192 } else {
193 window.location.href = url;
194 }
195 return false;
196 })
197
198 $('.wdk-listings-results.ajax_results_enabled .wdk-pagination .page-numbers').on('click', function (e) {
199 e.preventDefault();
200 if (typeof wdk_ajax_loading_listings == 'function') {
201 wdk_ajax_loading_listings($(this).attr('href'));
202 }
203 })
204
205 /* elementor popup */
206 jQuery( document ).on( 'elementor/popup/show', () => {
207 wdk_reset_form();
208 } );
209
210 const wdk_reset_form = () => {
211 $("form.wdk-search-form .wdk-search-reset").off().on('click', function (e) {
212 e.preventDefault();
213 let this_form = jQuery(this).closest('form');
214 jQuery('input:not([type="checkbox"]):not([name="element_id"]):not([type="radio"]):not([type="hidden"]),textarea,select').val('');
215 jQuery('select').val(jQuery(this).find('option:first').val())
216 jQuery('input[type="checkbox"]').prop('checked', false);
217 jQuery('input[type="radio"]').prop('checked', false);
218 jQuery('.wdk-field.LOCATION .wdk_dropdown_tree button:first-child').html(jQuery('.wdk-field.LOCATION .list_items li:first').text());
219 jQuery('.wdk-field.CATEGORY .wdk_dropdown_tree button:first-child').html(jQuery('.wdk-field.CATEGORY .list_items li:first').text());
220 jQuery('input[name="rectangle_ne"],input[name="rectangle_sw"] ').val('');
221
222 // Reset Select2 fields with .select_ajax class
223 jQuery('.select_ajax').each(function() {
224 if (typeof jQuery(this).select2 === 'function') {
225 jQuery(this).val(null).trigger('change'); // Clear selection and notify Select2
226 }
227 });
228
229 $('.wdk-slider-range-field').each(function () {
230
231 var instance = $(this).data('fieldSliderRange');
232
233 if(instance) {
234 instance.reset();
235 }
236
237 });
238
239 // Remove all query params starting with 'search_' or 'field_' and hash '#results' from the URL on reset
240 if (window.history && window.history.replaceState) {
241 let url = window.location.href;
242 let parser = document.createElement('a');
243 parser.href = url;
244
245 // Get query string and hash
246 let query = parser.search.replace(/^\?/, '');
247 let hash = parser.hash;
248
249 // Split query into key-value pairs
250 let params = query ? query.split('&') : [];
251 let filteredParams = [];
252
253 // Remove params whose key starts with 'search_' or 'field_'
254 params.forEach(function(param) {
255 let key = param.split('=')[0];
256 if (!(key.startsWith('search_') || key.startsWith('field_'))) {
257 filteredParams.push(param);
258 }
259 });
260
261 // Rebuild the URL without the removed params and hash
262 let newQuery = filteredParams.length ? '?' + filteredParams.join('&') : '';
263 let newUrl = parser.protocol + '//' + parser.host + parser.pathname + newQuery;
264
265 // Remove hash if it is '#results'
266 if (hash && hash !== '#results') {
267 newUrl += hash;
268 }
269
270 window.history.replaceState({}, document.title, newUrl);
271 }
272
273 if(this_form.hasClass('auto_search')) {
274 $("form.wdk-search-form").first().trigger('submit')
275 }
276 return false;
277 })
278 };
279 wdk_reset_form();
280
281 /* date time fields init */
282 if ($('.wdk-fielddate').length && typeof $.datepicker != 'undefined') {
283
284 $('.wdk-fielddate').each(function () {
285 let dateFormat = wdk_script_parameters.format_date_js;
286 var self = $(this);
287
288 if (self.attr('date-format'))
289 dateFormat = self.attr('date-format');
290
291 self.datepicker({ dateFormat: dateFormat, onSelect: function() {
292 self.parent().find('.db-date').val(wdk_date_sql_normalize(self.datepicker("getDate"), self)).trigger('input');
293 }
294 }).on( "change", function() {
295 if(self.val() == '') {
296 self.parent().find('.db-date').val('');
297 } else {
298 self.parent().find('.db-date').val(wdk_date_sql_normalize(self.datepicker("getDate"), self));
299 }
300 });
301
302 if(self.parent().find('.db-date').val() == '' && false) {
303 self.parent().find('.db-date').val(wdk_date_notime_sql_normalize());
304 }
305 })
306 } ;
307
308
309 if ($('.wdk-fielddatetime').length && typeof $.datepicker != 'undefined') {
310
311 $('.wdk-fielddatetime').each(function () {
312 let dateFormat = wdk_script_parameters.format_datetime_js;
313
314 var self = $(this);
315 if (self.attr('date-format'))
316 dateFormat = self.attr('date-format');
317
318 self.datepicker({ dateFormat: dateFormat, onSelect: function() {
319 var datetime = wdk_date_notime_sql_normalize(self.datepicker("getDate"), self);
320 if(self.parent().find('[name="hours_mask"]').val() !='') {
321 datetime += ' '+wdk_pad(self.parent().find('[name="hours_mask"]').val());
322 } else {
323 datetime += ' 00';
324 }
325 if(self.parent().find('[name="minutes_mask"]').val() !='') {
326 datetime += ':'+wdk_pad(self.parent().find('[name="minutes_mask"]').val());
327 } else {
328 datetime += ':00';
329 }
330 datetime += ':00';
331
332 self.parent().find('.db-date').val(datetime).trigger('input');
333 }
334 }).on( "change", function() {
335
336 var datetime = wdk_date_notime_sql_normalize(self.datepicker("getDate"), self);
337 if(self.parent().find('[name="hours_mask"]').val() !='') {
338 datetime += ' '+wdk_pad(self.parent().find('[name="hours_mask"]').val());
339 } else {
340 datetime += ' 00';
341 }
342 if(self.parent().find('[name="minutes_mask"]').val() !='') {
343 datetime += ':'+wdk_pad(self.parent().find('[name="minutes_mask"]').val());
344 } else {
345 datetime += ':00';
346 }
347 datetime += ':00';
348 self.parent().find('.db-date').val(datetime);
349 });
350
351 if(self.parent().find('.db-date').val() == '') {
352 self.parent().find('.db-date').val(wdk_date_sql_normalize());
353 }
354
355 self.parent().find('[name="hours_mask"],[name="minutes_mask"]').on('input', function(){
356 var datetime = wdk_date_notime_sql_normalize(self.datepicker("getDate"), self);
357 if(self.parent().find('[name="hours_mask"]').val() !='') {
358 datetime += ' '+wdk_pad(self.parent().find('[name="hours_mask"]').val());
359 } else {
360 datetime += ' 00';
361 }
362 if(self.parent().find('[name="minutes_mask"]').val() !='') {
363 datetime += ':'+wdk_pad(self.parent().find('[name="minutes_mask"]').val());
364 } else {
365 datetime += ':00';
366 }
367 datetime += ':00';
368 self.parent().find('.db-date').val(datetime);
369 });
370 })
371 };
372
373 if ($('.wdk-fielddate_from').length && $('.wdk-fielddate_to').length && typeof $.datepicker != 'undefined') {
374 var dateFormat, from, to;
375 const getDate = ( element ) => {
376 var date;
377 try {
378 date = $.datepicker.parseDate( dateFormat, element.value );
379 } catch( error ) {
380 date = null;
381 }
382 return date;
383 }
384
385 dateFormat = wdk_script_parameters.format_date_js;
386 if ($('.wdk-fielddate_from').attr('date-format'))
387 dateFormat = $('.wdk-fielddate_from').attr('date-format');
388
389 from = $('.wdk-fielddate_from')
390 .datepicker({
391 dateFormat: dateFormat,
392 onSelect: function( selectedDate ) {
393 to.datepicker("option", "minDate", selectedDate );
394 setTimeout(function(){
395 to.datepicker('show');
396 }, 16);
397
398 from.parent().find('.db-date').val(wdk_date_sql_normalize(from.datepicker("getDate"), from));
399 wdk_date_add_hours(from);
400 }
401 }).on( "change", function() {
402 from.parent().find('.db-date').val(wdk_date_sql_normalize(from.datepicker("getDate"), from)).trigger('input');
403 });
404
405 to = $('.wdk-fielddate_to').datepicker({
406 dateFormat: dateFormat
407 })
408 .on( "change", function() {
409 from.datepicker( "option", "maxDate", getDate( this ) );
410 to.parent().find('.db-date').val(wdk_date_sql_normalize(to.datepicker("getDate"), to)).trigger('input');
411 wdk_date_add_hours(to);
412 });
413
414 if(to.parent().find('.db-date').val() == '') {
415 to.parent().find('.db-date').val(wdk_date_sql_normalize());
416 }
417
418 if(from.parent().find('.db-date').val() == '') {
419 from.parent().find('.db-date').val(wdk_date_sql_normalize());
420 }
421
422 from.parent().find('[name="hours_mask"],[name="minutes_mask"]').on('input', function(){
423 wdk_date_add_hours(from);
424 });
425
426 to.parent().find('[name="hours_mask"],[name="minutes_mask"]').on('input', function(){
427 wdk_date_add_hours(to);
428 });
429 }
430 if(typeof $.fn.wdkSuggestion == 'function') {
431
432 if(typeof wdk_script_parameters.settings_wdk_field_search_suggestion_disable != 'undefined' && wdk_script_parameters.settings_wdk_field_search_suggestion_disable == 1) {
433
434 } else {
435 $('#wdk_field_search').wdkSuggestion({
436 ajax_url: wdk_script_parameters.ajax_url,
437 ajax_param: {
438 "action": 'wdk_public_action',
439 "page": 'wdk_frontendajax',
440 "function": 'search_suggestion',
441 },
442 language_id: '',
443 text_search: 'Search',
444 callback_selected: function(key) {
445
446 }
447 });
448 }
449
450 }
451
452 $('.wdk-control[type="number"]').on('change',function(){
453 let val = $(this).val();
454 let step = 1;
455 if(val.length>=7){
456 step = 10000;
457 } else if(val.length>=4) {
458 step = 10;
459 }
460 $(this).attr('step', step);
461 })
462
463
464 if(typeof $.fn.fieldSliderRange == 'function' && typeof $.fn.ionRangeSlider == 'function') {
465 $('.wdk-slider-range-field').fieldSliderRange();
466 }
467
468 wdk_result_listings_thumbnail_slider();
469
470 /* if video exists on thumbnail css trick */
471 $('.wdk-listing-card .wdk-thumbnail .wdk-image.media').find('iframe,video').css('padding-bottom', +($('.wdk-listing-card .wdk-thumbnail .wdk-over-image-bottom').outerHeight())+'px');
472
473
474 if(typeof $.fn.WdkScrollMobileSwipe == 'function') {
475 $('.WdkScrollMobileSwipe_enable').WdkScrollMobileSwipe();
476 $('.WdkScrollMobileSwipe_elementor_enable .elementor-container').WdkScrollMobileSwipe();
477 }
478
479 if($('.wl-menu-toggle').length) {
480 $('.wdk-footer-menu .wdk_mobile_footer_menu_gumb-open').addClass('trigger')
481 $('.wdk-footer-menu .wdk_mobile_footer_menu_gumb-open').on('click', function(e){
482 e.preventDefault();
483 $('.wl-menu-toggle').trigger('click');
484 });
485 }
486
487
488 /* Read More Button */
489 jQuery('.wdk-field-value.TEXTAREA').each(function(){
490 // Find the target div containing additional content
491 var moreContentDiv = $(this).find("[id*='more-']");
492 // Hide the additional content initially
493 var additionalContent = moreContentDiv.nextUntil(":not(p)");
494 additionalContent.hide();
495
496 // Create a "Read More" button
497 var readMoreButtonWrapper = $("<div class='wdk-textarea-load-more-wrapper'><a class='wdk-textarea-load-more-button'></a></div>"),
498 readMoreButton = readMoreButtonWrapper.find('a').text(wdk_script_parameters.text.read_more || '');
499 readMoreButton.on("click", function() {
500 // Toggle the visibility of the additional content
501 additionalContent.slideToggle();
502 if (readMoreButton.text() === wdk_script_parameters.text.read_more) {
503 readMoreButton.text(wdk_script_parameters.text.read_less);
504 } else {
505 readMoreButton.text(wdk_script_parameters.text.read_more);
506 }
507 });
508
509 // Replace the target div with the "Read More" button
510 moreContentDiv.before(readMoreButtonWrapper);
511 moreContentDiv.remove();
512 });
513
514 $('.wdk-language-switcher-drop .wdk-language-switcher-btn-toggle').on('click', function (e) {
515 e.preventDefault();
516 $(this).closest('.wdk-language-switcher-drop').toggleClass('wdk-show');
517 });
518 // Add click event to each share link
519 document.querySelectorAll('.wdk-device-share-link').forEach(link => {
520 link.addEventListener('click', function(event) {
521 event.preventDefault();
522 shareUrl(link.getAttribute('href'));
523 });
524 });
525
526 $('.wdk-search_sensitive_link').on('click',function(e) {
527 e.preventDefault();
528 var href = $(this).attr('href'),
529 search_url = wdk_start_search($("form.wdk-search-form"));
530
531 if(search_url == href) {
532 window.location.href = href;
533 return;
534 }
535
536 // Parse the href to extract search_location and search_category
537 var urlParams = new URLSearchParams(href.split('?')[1]);
538 var searchLocation = urlParams.get('search_location');
539 var searchCategory = urlParams.get('search_category');
540
541 // Parse the search_url to update with new params
542 var searchParams = new URLSearchParams(search_url.split('?')[1]);
543
544 if (searchLocation) {
545 searchParams.set('search_location', searchLocation);
546 }
547 if (searchCategory) {
548 searchParams.set('search_category', searchCategory);
549 }
550
551 var updatedSearchUrl = search_url.split('?')[0] + '?' + searchParams.toString();
552 window.location.href = updatedSearchUrl;
553
554 })
555 resetSearchFields();
556
557 if(typeof fpai_ajax_obj != 'undefined') {
558 const { __ } = wp.i18n;
559 jQuery('.wdk-ai-search').on('click', function(e) {
560 e.preventDefault();
561 e.stopPropagation();
562 var self = jQuery(this);
563 jQuery.confirm({
564 backgroundDismiss: true,
565 closeIcon: true,
566 boxWidth: '400px',
567 useBootstrap: false,
568 title: __('Search with AI', 'wpdirectorykit'),
569 onOpenBefore: function () {
570 this.$el.addClass('wdk-ai-search-popup');
571 jQuery('body').addClass('wdk-popup-open');
572 },
573 onClose: function () {
574 jQuery('body').removeClass('wdk-popup-open');
575 },
576 content: '' +
577 `<form action="" class="">
578 <div class="form-alerts">
579 </div>
580 <div class="form-group">
581 <textarea
582 rows="6"
583 name="query"
584 class="form-control"
585 placeholder="${__("I'm searching for red apartment with balcony and pool near London...", 'wpdirectorykit')}"
586 ></textarea>
587 </div>
588 </form>`,
589 buttons: {
590 formSubmit: {
591 text: `✨ ${__('Search with AI', 'wpdirectorykit')}`,
592 btnClass: 'wdk-ai-search',
593 action: function(e) {
594 const popup = this;
595 const jc = this.$content;
596 const query = jc.find('textarea[name="query"]').val();
597 const $responseDiv = jc.find('.form-alerts');
598 let $btn = jc.closest('.jconfirm').find('.wdk-ai-search');
599
600 // Check if the query textarea in the first form is empty, if so add error class and do not proceed
601 var $aiQueryTextarea = jc.find('textarea[name="query"]');
602 $aiQueryTextarea.off('focus.fpaiError').on('focus.fpaiError', function() {
603 $aiQueryTextarea.removeClass('fpai-error');
604 });
605
606 if (!query || query.trim() === "") {
607 $aiQueryTextarea.addClass('fpai-error');
608 return false; // prevent the popup from closing and block further processing
609 } else {
610 $aiQueryTextarea.removeClass('fpai-error');
611 }
612
613 $btn.prop('disabled', true).html(`🤖 ${__('AI is working...', 'wpdirectorykit')} <div class="fpai-loading-spinner"></div>`);
614 $responseDiv.show().html(`${__('Processing... Please wait...', 'wpdirectorykit')} <div class="fpai-loading-spinner"></div>`).removeClass('fpai-success fpai-error');
615
616 // Build "form_1" fields structure dynamically from wdk_script_parameters.fields_data
617 const formFieldsObj = {};
618 if (Array.isArray(wdk_script_parameters.fields_data)) {
619 wdk_script_parameters.fields_data.forEach(field => {
620 // Construct the field key (e.g. "field_2") based on your data structure
621 const fieldKey = 'field_' + field.idfield;
622 // Only include fields if field.field_type is one of the allowed types.
623 const allowedTypes = ['INPUTBOX', 'NUMBER', 'DROPDOWN', 'DROPDOWNMULTIPLE', 'CHECKBOX'];
624 if (!allowedTypes.includes(field.field_type)) {
625 return; // skip this field
626 }
627
628 let type = "text";
629 if(field.field_type == 'NUMBER')
630 type = "number";
631
632 if(field.field_type == 'CHECKBOX')
633 type = "checkbox";
634
635 formFieldsObj[fieldKey] = {
636 // Optionally: default value or empty, since the user may fill via AI
637 value: field.value !== undefined ? field.value : "",
638 type: type, // fallback type "text" if not set
639 label: field.field_label || '',// fallback to title if label isn't present
640 placeholder: field.placeholder || '', // fallback to empty if not set
641 options: field.values_list || '', // fallback to empty if not set
642 };
643 });
644 }
645
646 // Use only the first 15 fields
647 let formFieldsObjLimited;
648 if (
649 Array.isArray(wdk_script_parameters.wdk_ai_search_fields) &&
650 wdk_script_parameters.wdk_ai_search_fields.length > 0
651 ) {
652 const allowedIds = wdk_script_parameters.wdk_ai_search_fields.map(String);
653 formFieldsObjLimited = Object.fromEntries(
654 Object.entries(formFieldsObj).filter(([key, field]) => {
655 const id = key.replace(/^field_/, '');
656 return allowedIds.includes(id);
657 })
658 );
659 } else {
660 // fallback: limit to 12, as before
661 formFieldsObjLimited = Object.fromEntries(
662 Object.entries(formFieldsObj).slice(0, 12)
663 );
664 }
665
666
667 // Prepend system/required fields if needed, demo here:
668 const form1 = {
669 field_search: { value: "", type: "text", label: "locations, country, city", placeholder: "",},
670 address: { value: "", type: "text", label: "Address", placeholder: "Address" },
671 ...formFieldsObjLimited
672 };
673
674 // Additional forms if needed (leave as static if not dynamic)
675 const formsData = JSON.stringify({
676 "form_1": form1,
677 });
678
679 // Send data via fetch API using FormData for better handling
680 const formData = new FormData();
681 formData.append('action', 'fpai_generate_form_data');
682 formData.append('nonce', fpai_ajax_obj.nonce);
683 formData.append('ai_input', query);
684 formData.append('forms_data', formsData);
685
686 fetch(fpai_ajax_obj.ajax_url, {
687 method: 'POST',
688 body: formData
689 })
690 .then(response => response.json())
691 .then(data => {
692 if (data.success && data.data) {
693 $responseDiv.html(data.data.message || 'Form populated successfully').addClass('fpai-success');
694 // Populate form fields
695 const formData = data.data.form_data;
696
697 const searchData = {};
698
699 jQuery.each(formData, function (name, field) {
700 if (
701 field &&
702 typeof field === 'object' &&
703 'value' in field &&
704 field.value !== '' &&
705 field.value !== null &&
706 typeof field.value !== 'undefined'
707 ) {
708 searchData[name] = field.value;
709 }
710 });
711
712 var url = wdk_start_search(self.closest('form'), searchData);
713
714 $(this).closest('form').addClass('loading')
715
716 if($(this).closest('.ajax_results_enabled').length) {
717 if (typeof wdk_ajax_loading_listings == 'function') {
718 wdk_ajax_loading_listings(url);
719 }
720 } else if (decodeURI(window.location.href) == decodeURI(url)) {
721 window.location.reload(url);
722 } else {
723 window.location.href = url;
724 }
725
726
727 setTimeout(() => {
728 popup.close();
729 }, 2000);
730
731 } else {
732 $responseDiv.html(data.data ? data.data.message : 'Error: Invalid response format').addClass('fpai-error');
733 }
734 })
735 .catch(error => {
736 $responseDiv.html(__('Error occurred while processing request', 'wpdirectorykit')).addClass('fpai-error');
737 })
738 .finally((data) => {
739 $btn.prop('disabled', false).html(`<span class="fpai-btn-icon">✨</span> ${__('Populate form with AI', 'wpdirectorykit')}`);
740
741 });
742
743 return false;
744 }
745 },
746 /*
747 cancel: {
748 text: __('Close', 'wpdirectorykit'),
749 btnClass: 'wdk-ai-close',
750 action: function() {
751 //close
752 }
753 },*/
754
755 },
756 });
757 return false;
758 })
759 }
760 });
761
762 })(jQuery);
763
764
765
766 var resetSearchFields = () => {
767 jQuery(".wdk-control[type='text']:not(.wdk-hidden)").each(function(){
768 var $searchField = jQuery(this);
769 // Create reset button
770 var $resetButton = jQuery("<span>&times;</span>")
771 .css({
772 cursor: "pointer",
773 display: "none", // Initially hidden
774 position: "absolute",
775 right: "10px",
776 top: "50%",
777 transform: "translateY(-50%)",
778 fontSize: "18px"
779 });
780
781 /* Text Fields */
782
783 // Wrap input field in a relative container
784 var $wrapper = jQuery("<div></div>")
785 .css({ position: "relative" })
786 .insertBefore($searchField);
787
788 $wrapper.append($searchField).append($resetButton);
789
790 // Show/hide reset button based on input
791 $searchField.on("input", function () {
792 $resetButton.toggle(!!$searchField.val()); // Toggle visibility based on input
793 });
794
795 // Clear field when reset button is clicked
796 $resetButton.on("click", function () {
797 $searchField.val("").trigger("input").focus(); // Reset field and trigger input event to hide button
798 });
799 });
800 /* Tree Fields */
801
802 jQuery(`input[name="search_location"],input[name="search_category"]`).each(function(){
803
804 var $searchField = jQuery(this);
805 var resetButton;
806
807 // Show/hide reset button based on input
808 $searchField.on("change", function () {
809 if (jQuery(this).val() !== "") {
810 // Wrap input field in a relative container
811 var $wrapper = $searchField.closest('.wdk-field-group').find('.wdk_dropdown_tree button:first-child')
812 .css({ position: "relative" });
813 if (!resetButton) {
814 resetButton = jQuery("<span>&times;</span>")
815 .css({
816 cursor: "pointer",
817 position: "absolute",
818 right: "10px",
819 top: "50%",
820 transform: "translateY(-50%)",
821 fontSize: "18px"
822 })
823 .on("click", function (e) {
824 e.stopPropagation();
825 e.preventDefault();
826
827 $searchField.val("").trigger("input").focus();
828 resetButton.remove();
829 resetButton = null;
830 $searchField.closest('.wdk-field-group').find('.wdk_dropdown_tree button:first-child').html( $searchField.closest('.wdk-field-group').find('.list_items li:first').text());
831
832 return false;
833 });
834 $wrapper.append(resetButton);
835 }
836 } else if (resetButton) {
837 resetButton.remove();
838 resetButton = null;
839 }
840 });
841
842 });
843
844 };
845
846 /* slider for result listings thumbnails */
847 if (typeof wdk_result_listings_thumbnail_slider != 'function') {
848 var wdk_result_listings_thumbnail_slider = ($wrapper = 'body') => {
849 if(typeof jQuery.fn.slick == 'function') {
850 jQuery('.wdk_js_gallery_slider_box', $wrapper).each(function(){
851 var _this = jQuery(this);
852
853 if($wrapper == 'body') {
854 if(_this.closest('.wdk_results_listings_slider_ini').length){return true;}
855 }
856
857 if (_this.closest('.slick-slide').hasClass('slick-cloned')) {
858 return true;
859 }
860
861 // Check if the slider exists and is initialized
862 if (_this.find('.wdk_js_gallery_slider').length > 0 && _this.find('.wdk_js_gallery_slider').hasClass('slick-initialized')) {
863 _this.find('.wdk_js_gallery_slider').slick('unslick');
864 }
865
866
867 _this.find('.wdk_js_gallery_slider').slick({
868 dots: true,
869 infinite: true,
870 speed: 500,
871 fade: true,
872 arrows: true,
873 cssEase: 'linear',
874 nextArrow: _this.find('.wdk_js_gallery_slider-carousel_arrows .wdk-slider-next'),
875 prevArrow: _this.find('.wdk_js_gallery_slider-carousel_arrows .wdk-slider-prev'),
876 });
877 });
878 }
879 };
880 }
881 /*
882 Fix for slick slider, event after init slick
883
884 @param object el slick object
885 @param function callback
886 */
887
888 if (typeof wdk_slick_slider_init != 'function') {
889 var wdk_slick_slider_init = (el, callback) => {
890 try {
891 el.slick("slickGoTo", 0, true);
892 }
893 catch(error) {
894 setTimeout(wdk_slick_slider_init, 1000);
895 return;
896 }
897
898 if(callback) {
899 callback.call();
900 }
901 };
902 }
903 if (typeof wdk_pad != 'function') {
904 var wdk_pad = (num = '') => {
905 return ('00'+num).slice(-2);
906 };
907 }
908
909 if (typeof wdk_date_add_hours != 'function') {
910 var wdk_date_add_hours = (selector = '') => {
911 if(typeof selector !='undefined' && selector.parent().find('[name="hours_mask"]').length) {
912 var datetime = wdk_date_notime_sql_normalize(selector.datepicker("getDate"), selector);
913 if(selector.parent().find('[name="hours_mask"]').val() !='') {
914 datetime += ' '+wdk_pad(selector.parent().find('[name="hours_mask"]').val());
915 } else {
916 datetime += ' 00';
917 }
918 if(selector.parent().find('[name="minutes_mask"]').val() !='') {
919 datetime += ':'+wdk_pad(selector.parent().find('[name="minutes_mask"]').val());
920 } else {
921 datetime += ':00';
922 }
923 datetime += ':00';
924 selector.parent().find('.db-date').val(datetime);
925 }
926 };
927 }
928 /*
929 Convert date to sql format
930
931 @param string $date, string of date
932
933 @return string normalize date or Current date/time
934 */
935 if (typeof wdk_date_sql_normalize != 'function') {
936 var wdk_date_sql_normalize = (date = '', datepicker_el = null) => {
937 if(date == '') {
938 var d = new Date();
939 } else {
940 var d = new Date(date);
941 }
942
943 if(d == 'Invalid Date' && datepicker_el) {
944 var d = new Date(+(jQuery.datepicker.formatDate("@", datepicker_el.datepicker("getDate"))));
945 }
946
947 d = d.getUTCFullYear() + '-' +
948 wdk_pad(d.getMonth() + 1) + '-' +
949 wdk_pad(d.getDate()) + ' ' +
950 wdk_pad(d.getHours()) + ':' +
951 wdk_pad(d.getMinutes()) + ':' +
952 wdk_pad(d.getSeconds());
953 return d;
954 };
955 }
956
957 if (typeof wdk_date_notime_sql_normalize != 'function') {
958 var wdk_date_notime_sql_normalize = (date = '', datepicker_el = null) => {
959 if(date == '') {
960 var d = new Date();
961 } else {
962 var d = new Date(date);
963 }
964
965 if(d == 'Invalid Date' && datepicker_el) {
966 var d = new Date(+(jQuery.datepicker.formatDate("@", datepicker_el.datepicker("getDate"))));
967 }
968
969 d = d.getUTCFullYear() + '-' +
970 wdk_pad(d.getMonth() + 1) + '-' +
971 wdk_pad(d.getDate());
972 return d;
973 };
974 }
975
976 if (typeof wdk_generate_marker_ajax_popup != 'function') {
977 var wdk_generate_marker_ajax_popup = (ajax_url, listing_post_id, lat, lng,innerMarker, wdk_jpopup_customOptions, auto = false, clusters_enabled = true, custom_layout_id = '') => {
978
979 if(auto) {
980 var marker = L.marker(
981 [lat, lng],
982 {icon: L.divIcon({
983 html: innerMarker,
984 className: 'open_steet_map_marker',
985 iconSize: 'auto',
986 })
987 }
988 );
989 } else {
990 var marker = L.marker(
991 [lat, lng],
992 {icon: L.divIcon({
993 html: innerMarker,
994 className: 'open_steet_map_marker',
995 iconSize: [40, 60],
996 popupAnchor: [-1, -35],
997 iconAnchor: [23, 73],
998 })
999 }
1000 );
1001 }
1002
1003 var data = {
1004 "action": 'wdk_public_action',
1005 "page": 'wdk_frontendajax',
1006 "function": 'map_infowindow',
1007 "listing_post_id": listing_post_id,
1008 "custom_layout_id": custom_layout_id,
1009 };
1010
1011 let favorite_init = false;
1012 let compare_init = false;
1013 marker.bindPopup(function () {
1014 var content = '<div class="infobox"><div class="map_infowindow"><div class="loading_content animated-background"><div class="box_line m170"></div><div class="box_line m20"></div><div class="box_line m20"></div><div class="box_line m20"></div><div class="box_line m20"></div><div class="box_line m20"></div></div></div></div>';
1015 marker.getPopup().setContent(content);
1016 marker.getPopup().update();
1017 jQuery.ajax({
1018 url : ajax_url,
1019 type : "POST",
1020 data: data,
1021 success: function (data) {
1022 marker.getPopup().setContent(data.popup_content);
1023 marker.getPopup().update();
1024 if (!favorite_init && typeof wdk_favorite == 'function')
1025 wdk_favorite('.infobox');
1026
1027 favorite_init = false;
1028
1029 if (!compare_init && typeof wdk_init_compare_elem == 'function')
1030 wdk_init_compare_elem();
1031
1032 compare_init = false;
1033 },
1034 });
1035 return content;
1036 }, wdk_jpopup_customOptions);
1037
1038 if (typeof wdk_favorite == 'function')
1039 marker.on('popupopen', function (popup) {
1040 if (!favorite_init)
1041 wdk_favorite('.infobox');
1042 });
1043
1044 if (typeof wdk_init_compare_elem == 'function')
1045 marker.on('popupopen', function (popup) {
1046 if (!compare_init)
1047 wdk_init_compare_elem();
1048 });
1049
1050 if (typeof wdk_favorite == 'function')
1051 marker.on('popupclose', function (popup) {
1052 marker.getPopup().setContent(jQuery('.leaflet-popup-content-wrapper .leaflet-popup-content').html());
1053 marker.getPopup().update();
1054 });
1055
1056 if(clusters_enabled) {
1057 wdk_clusters.addLayer(marker);
1058 } else {
1059 wdk_map.addLayer(marker);
1060 }
1061 return marker;
1062 }
1063 }
1064
1065 if (typeof wdk_generate_marker_basic_popup != 'function') {
1066 var wdk_generate_marker_basic_popup = (lat, lng, innerMarker, wdk_jpopup_content, wdk_jpopup_customOptions) => {
1067 var marker = L.marker(
1068 [lat, lng],
1069 {icon: L.divIcon({
1070 html: innerMarker,
1071 className: 'open_steet_map_marker',
1072 iconSize: [40, 60],
1073 popupAnchor: [-1, -35],
1074 iconAnchor: [23, 73],
1075 })
1076 }
1077 );
1078
1079 marker.bindPopup(wdk_jpopup_content, wdk_jpopup_customOptions);
1080
1081 return marker;
1082 }
1083 }
1084
1085 if (typeof wdk_generate_marker_nopopup != 'function') {
1086 var wdk_generate_marker_nopopup = (lat, lng,innerMarker) => {
1087 var marker = L.marker(
1088 [lat, lng],
1089 {icon: L.divIcon({
1090 html: innerMarker,
1091 className: 'open_steet_map_marker',
1092 iconSize: [40, 60],
1093 popupAnchor: [-1, -35],
1094 iconAnchor: [23, 73],
1095 })
1096 }
1097 );
1098
1099 return marker;
1100 }
1101 }
1102
1103 // Share URL function
1104 var shareUrl = (url = window.location.href) => {
1105 // Check if the browser supports the Web Share API
1106 if (!navigator.share) {
1107 console.log("Web Share API not supported.");
1108 return;
1109 }
1110
1111 navigator.share({
1112 url: url, // Share the current page URL
1113 })
1114 .then(() => {
1115 console.log("Shared successfully!");
1116 })
1117 .catch((error) => {
1118 console.error("Sharing failed:", error);
1119 });
1120 };
1121
1122