1/*global $, jQuery, ajaxcalls_vars, document, control_vars, window, control_vars,Modernizr,mapfunctions_vars,wpestate_open_menu,grecaptcha,wpestate_show_no_results,wpestate_load_on_demand_pins,get_custom_value,wpestate_enable_half_map_pin_action,wpestate_lazy_load_carousel_property_unit,Chart,widgetId1,widgetId2,widgetId3,widgetId4,wpestate_get_custom_value_tab_search*/ 2/////////////////////////////////////////////////////////////////////////////////////////// 3 4/** 5 * Safe redirect helper â mitigates XSS-5 (Open Redirect via AJAX Response). 6 * 7 * PayPal-related AJAX handlers return a URL string that the client uses to 8 * redirect the user to the payment gateway. A manipulated / compromised 9 * response could supply an attacker-controlled URL (phishing, malware). 10 * 11 * This helper validates the returned URL before assigning it to 12 * `window.location.href`. Only http(s) URLs that are either same-origin 13 * or on the paypal.com domain family (including sandbox) are allowed. 14 * Anything else (javascript:, data:, other hosts) is silently dropped. 15 * 16 * @param {string} data URL string returned from the AJAX endpoint. 17 */ 18function wpestate_safe_redirect(data) { 19 "use strict"; 20 21 // Reject non-string / empty payloads outright. 22 if (typeof data !== 'string' || data === '') { 23 return; 24 } 25 26 try { 27 // Parse relative to current origin so bare paths ("/checkout") still resolve. 28 var url = new URL(data, window.location.origin); 29 30 // Block dangerous schemes such as javascript:, data:, file:, vbscript:, etc. 31 if (url.protocol !== 'http:' && url.protocol !== 'https:') { 32 return; 33 } 34 35 var host = url.hostname.toLowerCase(); 36 37 // Same-origin is always safe (theme-hosted redirect targets). 38 var isSameOrigin = (url.origin === window.location.origin); 39 40 // Whitelist PayPal production + sandbox hostnames. 41 // Regex covers paypal.com and any subdomain (www, sandbox, checkout, etc.). 42 var isPaypal = (host === 'paypal.com' || host === 'www.paypal.com' || 43 host === 'sandbox.paypal.com' || host === 'www.sandbox.paypal.com' || 44 /(^|\.)paypal\.com$/.test(host)); 45 46 if (isSameOrigin || isPaypal) { 47 // URL is trusted â perform the redirect using the normalized href. 48 window.location.href = url.href; 49 } 50 // Fallthrough: untrusted host â silently ignore (fail closed). 51 } catch (e) { 52 // Malformed URL â ignore; do not redirect. 53 } 54} 55 56function wpestate_load_stats_tabs(listing_id) { 57 "use strict"; 58 var ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 59 var nonce = jQuery('#wpestate_tab_stats').val(); 60 jQuery.ajax({ 61 type: 'POST', 62 url: ajaxurl, 63 dataType: 'json', 64 data: { 65 'action': 'wpestate_load_stats_property', 66 'postid': listing_id, 67 'security': nonce, 68 }, 69 success: function (data) { 70 wpestate_show_prop_stat_graph_tab(data.array_values, data.labels, listing_id); 71 }, 72 error: function (errorThrown) {} 73 });//end ajax 74} 75 76 77 78function wpestate_show_prop_stat_graph_tab(values, labels, listing_id) { 79 if (!document.getElementById('myChart')) { 80 return; 81 } 82 83 var ctx = jQuery("#myChart").get(0).getContext("2d"); 84 var myNewChart = new Chart(ctx); 85 // var labels = ''; 86 var traffic_data = ' '; 87 88 // labels = jQuery.parseJSON ( wpestate_property_vars.singular_label); 89 traffic_data = values; 90 91 var data = { 92 labels: labels, 93 datasets: [ 94 { 95 label: ajaxcalls_vars.property_views, 96 fillColor: "rgba(220,220,220,0.5)", 97 strokeColor: "rgba(220,220,220,0.8)", 98 highlightFill: "rgba(220,220,220,0.75)", 99 highlightStroke: "rgba(220,220,220,1)", 100 data: traffic_data 101 }, 102 ] 103 }; 104 105 var options = { 106 title: 'page views', 107 //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value 108 scaleBeginAtZero: true, 109 110 //Boolean - Whether grid lines are shown across the chart 111 scaleShowGridLines: true, 112 113 //String - Colour of the grid lines 114 scaleGridLineColor: "rgba(0,0,0,.05)", 115 116 //Number - Width of the grid lines 117 scaleGridLineWidth: 1, 118 119 //Boolean - Whether to show horizontal lines (except X axis) 120 scaleShowHorizontalLines: true, 121 122 //Boolean - Whether to show vertical lines (except Y axis) 123 scaleShowVerticalLines: true, 124 125 //Boolean - If there is a stroke on each bar 126 barShowStroke: true, 127 128 //Number - Pixel width of the bar stroke 129 barStrokeWidth: 2, 130 131 //Number - Spacing between each of the X value sets 132 barValueSpacing: 5, 133 134 //Number - Spacing between data sets within X values 135 barDatasetSpacing: 1, 136 137 //String - A legend template 138 legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>" 139 140 }; 141 142 // var myBarChart = new Chart(ctx).Bar(data, options); 143 var myBarChart = new Chart(ctx, { 144 type: 'bar', 145 data: data, 146 options: options 147 }); 148} 149 150/** 151 * Remaps half-map listing card column sizes for list-mode rendering. 152 * 153 * @param {string} markup - HTML string containing listing_wrapper elements. 154 * @returns {string} Updated markup with transformed column classes and data-org values. 155 */ 156function wpestate_half_map_remap_list_columns(markup) { 157 158 159 160 if (typeof ajaxcalls_vars !== 'undefined' && ajaxcalls_vars.wp_estate_prop_unit === 'list') { 161 162 return markup; 163 } 164 165 if (typeof markup !== 'string' || markup === '') { 166 return markup; 167 } 168 169 var tempWrapper = jQuery('<div/>').html(markup); 170 171 tempWrapper.find('.listing_wrapper').each(function () { 172 var wrapper = jQuery(this); 173 var originalClasses = wrapper.attr('class') || ''; 174 175 var mdMatch = originalClasses.match(/col-md-(\d+)/); 176 var originalOrg = wrapper.attr('data-org') || (mdMatch ? mdMatch[1] : '') || '6'; 177 178 // Persist the original column sizing so grid view can be restored later. 179 var lgMatch = originalClasses.match(/col-lg-(\d+)/); 180 var smMatch = originalClasses.match(/col-sm-(\d+)/); 181 182 wrapper.attr('data-half-map-original-md-class', mdMatch ? mdMatch[0] : ''); 183 wrapper.attr('data-half-map-original-lg-class', lgMatch ? lgMatch[0] : ''); 184 wrapper.attr('data-half-map-original-sm-class', smMatch ? smMatch[0] : ''); 185 wrapper.attr('data-half-map-original-org', originalOrg); 186 var targetOrg = originalOrg; 187 188 switch (originalOrg) { 189 case '6': 190 targetOrg = '3'; 191 break; 192 case '4': 193 case '3': 194 targetOrg = '2'; 195 break; 196 case '12': 197 targetOrg = '12'; 198 break; 199 default: 200 targetOrg = originalOrg; 201 } 202 203 ['md', 'lg', 'sm'].forEach(function (breakpoint) { 204 var regex = new RegExp('col-' + breakpoint + '-\\d+', 'g'); 205 var matches = (wrapper.attr('class') || '').match(regex); 206 207 if (matches) { 208 wrapper.removeClass(matches.join(' ')); 209 } 210 211 wrapper.addClass('col-' + breakpoint + '-' + targetOrg); 212 }); 213 214 wrapper.attr('data-org', targetOrg); 215 }); 216 217 return tempWrapper.html(); 218} 219 220 221 222function wpestate_load_stats(listing_id) { 223 "use strict"; 224 var ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 225 var nonce = jQuery('#wpestate_tab_stats').val(); 226 227 jQuery.ajax({ 228 type: 'POST', 229 url: ajaxurl, 230 dataType: 'json', 231 data: { 232 'action': 'wpestate_load_stats_property', 233 'postid': listing_id, 234 'security': nonce, 235 }, 236 success: function (data) { 237 wpestate_show_prop_stat_graph(data.array_values, data.labels, listing_id); 238 }, 239 error: function (errorThrown) {} 240 });//end ajax 241} 242 243function wpestate_show_prop_stat_graph(values, labels, listing_id) { 244 "use strict"; 245 246 var ctx = jQuery("#myChart_" + listing_id).get(0).getContext('2d'); 247 var myNewChart = new Chart(ctx); 248 var data = { 249 labels: labels, 250 datasets: [ 251 { 252 label: ajaxcalls_vars.property_views, 253 fillColor: "rgba(220,220,220,0.5)", 254 strokeColor: "rgba(220,220,220,0.8)", 255 highlightFill: "rgba(220,220,220,0.75)", 256 highlightStroke: "rgba(220,220,220,1)", 257 data: values 258 }, 259 ] 260 }; 261 262 var options = { 263 scaleBeginAtZero: true, 264 scaleShowGridLines: true, 265 scaleGridLineColor: "rgba(0,0,0,.05)", 266 scaleGridLineWidth: 1, 267 scaleShowHorizontalLines: true, 268 scaleShowVerticalLines: true, 269 barShowStroke: true, 270 barStrokeWidth: 2, 271 barValueSpacing: 5, 272 barDatasetSpacing: 1, 273 legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>" 274 }; 275 276 // var myBarChart = new Chart(ctx).Bar(data, options); 277 var myBarChart = new Chart(ctx, { 278 type: 'bar', 279 data: data, 280 options: options 281 }); 282} 283 284 285/** 286 * Run standard AJAX filtering for the classic search wrapper. 287 * 288 * Builds the request payload from the current search UI state and sends it to 289 * `wpestate_ajax_filter_listings_search`. Taxonomy filters are sent by their 290 * taxonomy keys and term-id values plus meta_query clauses prepared by 291 * `wpestate_prepare_custom_search_ajax_data`. 292 * 293 * @param {number} newpage Target results page for pagination. 294 * @returns {void} 295 */ 296function wpestate_start_filtering_ajax(newpage) { 297 "use strict"; 298 299 300 301 // Step 1: Read scalar filters and request defaults. 302 var action = ''; 303 var category = ''; 304 var city = ''; 305 var area = ''; 306 var county_state = ''; 307 var status = ''; 308 var min_price = parseFloat(jQuery('#price_low').val(), 10); 309 var price_max = parseFloat(jQuery('#price_max').val(), 10); 310 var ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 311 var postid = 1; 312 var halfmap = 0; 313 var all_checkers = []; 314 var meta_query = []; 315 var order = jQuery('#a_filter_order').attr('data-value'); 316 var nonce = jQuery('#wpestate_ajax_filtering').val(); 317 var search_wrapper = jQuery('.search_wrapper'); 318 319 // Step 2: Resolve search wrapper post id and half-map mode. 320 if (document.getElementById('search_wrapper')) {
321 postid = parseInt(jQuery('#search_wrapper').attr('data-postid'), 10); 322 } 323 if (jQuery('#google_map_prop_list_sidebar').length) { 324 halfmap = 1; 325 } 326 327 // Step 3: Collect shared features, geo and beds/baths values. 328 all_checkers = wpestate_collect_property_features_values(search_wrapper); 329 330 var geoValues = wpestate_collect_geo_values(); 331 var geo_lat = geoValues.geo_lat; 332 var geo_long = geoValues.geo_long; 333 var geo_rad = geoValues.geo_rad; 334 335 var bedsBathsValues = wpestate_collect_beds_baths_component_values(); 336 var componentsbeds = bedsBathsValues.componentsbeds; 337 var componentsbaths = bedsBathsValues.componentsbaths; 338 339 // Step 4: Build taxonomy/meta payload using the shared custom-search resolver. 340 var helperAjaxData = {}; 341 var helperMetaQuery = wpestate_prepare_custom_search_ajax_data( 342 search_wrapper, 343 helperAjaxData, 344 componentsbeds, 345 componentsbaths 346 ); 347 348 action = helperAjaxData.property_action_category || ''; 349 category = helperAjaxData.property_category || ''; 350 city = helperAjaxData.property_city || ''; 351 area = helperAjaxData.property_area || ''; 352 county_state = helperAjaxData.property_county_state || ''; 353 status = helperAjaxData.property_status || ''; 354 meta_query = jQuery.isArray(helperMetaQuery) ? helperMetaQuery : []; 355 356 // Step 5: Reset container and show loader before requesting new results. 357 jQuery('#listing_ajax_container').empty(); 358 jQuery('#listing_loader').show(); 359 360 // Step 6: Send AJAX request with taxonomy and meta query filters. 361 jQuery.ajax({ 362 type: 'POST', 363 url: ajaxurl, 364 dataType: 'json', 365 data: { 366 'action': 'wpestate_ajax_filter_listings_search', 367 'property_action_category': action, 368 'property_category': category, 369 'property_city': city, 370 'property_area': area, 371 'property_county_state': county_state, 372 'property_status': status, 373 'price_min': min_price, 374 'price_max': price_max, 375 'meta_query': meta_query, 376 'newpage': newpage, 377 'postid': postid, 378 'halfmap': halfmap, 379 'property_features': all_checkers, 380 'geo_lat': geo_lat, 381 'geo_long': geo_long, 382 'geo_rad': geo_rad, 383 'order': order, 384 'security': nonce 385 386 387 }, 388 // Step 7: Update UI with returned cards and rebind JS behaviors. 389 success: function (data) { 390 391 jQuery('#listing_loader').hide(); 392 jQuery('.listing_loader_title').show(); 393 jQuery('.pagination_nojax').hide(); 394 //jQuery('#listing_ajax_container').empty().append(data); 395 jQuery('.entry-title.title_prop').addClass('half_results').text(data.no_founs); 396 397 jQuery('#listing_ajax_container').empty().append(data.cards); 398 399 400 wpestate_restart_js_after_ajax(); 401 402 }, 403 // Step 8: Keep default silent error handler behavior. 404 error: function (errorThrown) {} 405 });//end ajax 406} 407 408////////////////////////////////////////////////////////////////////////////////////////////// 409/// ajax filtering on header search ; jslint checked 410//////////////////////////////////////////////////////////////////////////////////////////// 411 412 413/** 414 * Collect taxonomy values from multi-select controls in active scope. 415 * 416 * Reads taxonomy name from select/option data attributes, normalizes known 417 * aliases, then stores selected term ids (or values) as arrays on ajaxData. 418 * 419 * @param {jQuery} activeTabScope Scope used for tab-aware search extraction. 420 * @param {Object} ajaxData AJAX payload object to enrich. 421 * @returns {void} 422 */ 423function wpestate_collect_multiselect_taxonomies(activeTabScope, ajaxData) { 424 "use strict"; 425 426 // Step 1: Alias map for non-canonical taxonomy names from markup. 427 var taxonomyAliasMap = { 428 'cities': 'property_city', 429 'city': 'property_city', 430 'areas': 'property_area', 431 'area': 'property_area', 432 'countystate': 'property_county_state', 433 'county_state': 'property_county_state', 434 'county / state': 'property_county_state', 435 'types': 'property_action_category', 436 'actions': 'property_action_category', 437 'categories': 'property_category', 438 'status': 'property_status', 439 'features': 'property_features' 440 }; 441 442 // Step 2: Process each multi-select field in the active scope. 443 activeTabScope.find('select[multiple]').each(function () { 444 var selectElement = jQuery(this); 445 var taxonomyName = ''; 446 var optionValues = []; 447 448 // Step 2.1: Resolve taxonomy from select/selected-option metadata. 449 taxonomyName = (selectElement.attr('data-search-taxonomy') || '').trim(); 450 if (taxonomyName === '') { 451 var firstSelectedOption = selectElement.find('option:selected').first(); 452 if (firstSelectedOption.length > 0) { 453 taxonomyName = ( 454 firstSelectedOption.attr('data-search-taxonomy') || 455 firstSelectedOption.attr('data-taxonomy') || 456 '' 457 ).trim(); 458 } 459 } 460 461 // Step 2.2: Normalize key format and map aliases to canonical keys. 462 taxonomyName = taxonomyName.toLowerCase(); 463 taxonomyName = taxonomyName.replace(/\[\]$/g, '').trim(); 464 if (taxonomyAliasMap[taxonomyName]) { 465 taxonomyName = taxonomyAliasMap[taxonomyName]; 466 } 467 if (taxonomyName === '') { 468 return; 469 } 470 471 // Step 2.3: Collect selected option values (prefer term ids). 472 selectElement.find('option:selected').each(function () { 473 var selectedOption = jQuery(this); 474 var optionTermId = wpestate_get_term_id_from_element
474(selectedOption); 475 var optionValue = selectedOption.val() || ''; 476 var resolvedValue = (optionTermId !== '') ? optionTermId : optionValue; 477 478 if (resolvedValue !== '' && String(resolvedValue).toLowerCase() !== 'all') { 479 optionValues.push(resolvedValue); 480 } 481 }); 482 483 // Step 2.4: Store unique values under the resolved taxonomy key. 484 if (optionValues.length > 0) { 485 optionValues = optionValues.filter(function (value, index, array) { 486 return array.indexOf(value) === index; 487 }); 488 ajaxData[taxonomyName] = optionValues; 489 } 490 }); 491} 492 493/** 494 * Start advanced custom AJAX filtering for listings. 495 * 496 * This function collects active search values from `.search_wrapper`, 497 * normalizes taxonomy/meta inputs (including term-id aware fields), 498 * and sends the payload to `wpestate_custom_adv_ajax_filter_listings_search`. 499 * 500 * @param {number|string} newpage Requested pagination page. 501 * @returns {void} 502 */ 503function wpestate_custom_search_start_filtering_ajax(newpage) { 504 "use strict"; 505 506 // Step 1: search_wrapper is the form container. 507 var search_wrapper = jQuery('.search_wrapper'); 508 var active_tab_scope = search_wrapper.find('.tab-pane.active').first(); 509 510 // Step 1.1: When tabs exist, collect field values only from the active tab. 511 // This prevents hidden fields from inactive tabs from leaking into the request. 512 if (active_tab_scope.length === 0) { 513 active_tab_scope = search_wrapper; 514 } 515 516 // Step 2: active tab term id. 517 var term_id = jQuery('.tab-pane.active .term_id_class').val(); 518 519 // Step 3: Define payload variables that will be populated from the UI. 520 var ajaxurl = ajaxcalls_vars.wpestate_ajax; 521 522 var postid = ''; 523 var slider_min = ''; 524 var slider_max = ''; 525 var halfmap = 0; 526 var property_features_values = []; 527 var filter_search_action10 = ''; 528 var adv_location10 = ''; 529 var filter_search_action11 = ''; 530 var filter_search_categ11 = ''; 531 var geo_lat = ''; 532 var geo_long = ''; 533 var geo_rad = ''; 534 var componentsbeds = ''; 535 var componentsbaths = ''; 536 var location = ''; 537 var term_counter = ''; 538 539 // Step 3.1: If body has data-postid, use it as ajax postid. 540 var bodyPostId = jQuery('body').attr('data-postid'); 541 if (typeof bodyPostId === 'undefined' || bodyPostId === null || bodyPostId === '') { 542 bodyPostId = jQuery('body').data('postid'); 543 } 544 if (typeof bodyPostId !== 'undefined' && bodyPostId !== null && bodyPostId !== '') { 545 postid = bodyPostId; 546 } 547 548 // Step 4: Read slider values via dedicated collector. 549 var sliderValues = wpestate_collect_slider_values(); 550 slider_min = sliderValues.slider_min; 551 slider_max = sliderValues.slider_max; 552 553 // Step 5: Keep tab term id synced for tabbed search layouts. 554 if ((mapfunctions_vars.adv_search_type === '6' || mapfunctions_vars.adv_search_type === '7')) { // && !jQuery('.halfsearch')[0] 555 term_id = jQuery('.tab-pane.active .term_id_class').val(); 556 } 557 558 // Step 6: Read selected feature term ids via dedicated collector. 559 property_features_values = wpestate_collect_property_features_values(search_wrapper); 560 561 // Step 7: Read geolocation values via dedicated collector. 562 var geoValues = wpestate_collect_geo_values(); 563 geo_lat = geoValues.geo_lat; 564 geo_long = geoValues.geo_long; 565 geo_rad = geoValues.geo_rad; 566 567 // Step 8: Read beds/baths component values via dedicated collector. 568 var bedsBathsValues = wpestate_collect_beds_baths_component_values(); 569 componentsbeds = bedsBathsValues.componentsbeds; 570 componentsbaths = bedsBathsValues.componentsbaths; 571 572 // Step 8.1: Read the canonical location field from the active search scope. 573 location = active_tab_scope.find('input[name="location"]').first().val() || ''; 574 575 // Step 9: Keep term counter linked to the active tab term id. 576 term_counter = term_id; 577 578 var nonce = jQuery('#wpestate_ajax_filtering').val(); 579 var order = jQuery('#a_filter_order').attr('data-value'); 580 581 582 const listingContainer = jQuery('#listing_ajax_container'); 583 wpestate_createSkeletons(listingContainer); 584 585 586 //jQuery('#listing_ajax_container').empty(); 587// jQuery('#listing_loader').show(); 588 var ajaxData = { 589 'action': 'wpestate_custom_adv_ajax_filter_listings_search', 590 'newpage': newpage, 591 'postid': postid, 592 'halfmap': halfmap, 593 'property_features': property_features_values, 594 'filter_search_action10': filter_search_action10, 595 'location': location, 596 'adv_location10': adv_location10, 597 'filter_search_action11': filter_search_action11, 598 'filter_search_categ11': filter_search_categ11, 599 'order': order, 600 'term_counter': term_counter, 601 'componentsbeds' : componentsbeds, 602 'componentsbaths' : componentsbaths, 603 'security': nonce,
604 /////////////////////////////////////////////////////////// 605 'post_status': '', 606 'paged': '', 607 'posts_per_page': '', 608 'geo_lat': geo_lat, 609 'geo_long': geo_long, 610 'geo_rad': geo_rad, 611 'price_min': slider_min, 612 'price_max': slider_max, 613 }; 614 615 // Step 10: Prepare taxonomy + post-meta ajax data from search controls. 616 var metaQueryPayload = wpestate_prepare_custom_search_ajax_data( 617 active_tab_scope, 618 ajaxData, 619 componentsbeds, 620 componentsbaths 621 ); 622 623 // Step 11: Attach collected meta_query clauses to the AJAX payload. 624 ajaxData.meta_query = metaQueryPayload; 625 626 // Step 13: Fallback mapping for legacy templates missing `data-search-*`. 627 // Generic active-tab taxonomy fallback (no hardcoded field names). 628 var activeTabButton = search_wrapper.find('.adv_search_tab_item.active').first(); 629 if (activeTabButton.length > 0) { 630 var activeTabTaxonomy = (activeTabButton.attr('data-tax') || '').trim(); 631 var activeTabTermId = wpestate_get_term_id_from_element(activeTabButton); 632 var activeTabTermValue = (activeTabButton.attr('data-term') || '').trim(); 633 634 if (activeTabTaxonomy !== '') { 635 if (activeTabTermId !== '') { 636 ajaxData[activeTabTaxonomy] = activeTabTermId; 637 } else if (activeTabTermValue !== '' && activeTabTermValue.toLowerCase() !== 'all') { 638 ajaxData[activeTabTaxonomy] = activeTabTermValue; 639 } 640 641 if (activeTabTaxonomy === 'property_action_category' && typeof ajaxData[activeTabTaxonomy] !== 'undefined') { 642 ajaxData.query_action = ajaxData[activeTabTaxonomy]; 643 } 644 } 645 } 646 647 jQuery.ajax({ 648 type: 'POST', 649 url: ajaxurl, 650 dataType: 'json', 651 data: ajaxData, 652 success: function (data) { 653 654 655 656 jQuery('#listing_loader').hide(); 657 jQuery('.listing_loader_title').show(); 658 jQuery('.entry-title.title_prop').addClass('half_results').text(data.no_founs); 659 660 var cardsMarkup = data.cards; 661 662 // When half-map list view is active, remap the returned column sizes 663 // before injecting the new cards so they respect the list-mode sizing rules. 664 if (window.wpestateHalfMapState && 665 typeof window.wpestateHalfMapState.getMode === 'function' && 666 window.wpestateHalfMapState.getMode() === 'list') { 667 cardsMarkup = wpestate_half_map_remap_list_columns(cardsMarkup); 668 } 669 670 // jQuery('#listing_ajax_container').empty().append(cardsMarkup); 671 wpestate_replaceSkeletons(listingContainer, cardsMarkup); 672 673 if (window.wpestateHalfMapState && typeof window.wpestateHalfMapState.applyCurrentLayout === 'function') { 674 window.wpestateHalfMapState.applyCurrentLayout(); 675 } 676 677 678 wpestate_restart_js_after_ajax(); 679 jQuery('.col-md-12.listing_wrapper .property_unit_custom_element.image').each(function () { 680 jQuery(this).parent().addClass('wrap_custom_image'); 681 }); 682 683 if (data.saved_search !== null) { 684 jQuery(".search_param").html(data.saved_search); 685 jQuery("#search_args").val( JSON.stringify(data.args) ); 686 jQuery("#meta_args").val( JSON.stringify(data.search_meta) ); 687 688 } 689 }, 690 error: function (errorThrown) { 691 692 } 693 });//end ajax 694} 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735function wpestate_js_pagination_ajax(){ 736 "use strict"; 737 738 jQuery('.pagination_ajax a').on('click', function (event) { 739 event.preventDefault(); 740 var newpage = parseInt(jQuery(this).attr('data-future'), 10); 741 wpestate_start_filtering(newpage); 742 }); 743 744} 745 746 747//////////////////////////////////////////////////////////////////////////////////////////// 748/// redo js after ajax calls - jslint checked 749//////////////////////////////////////////////////////////////////////////////////////////// 750function wpestate_restart_js_after_ajax() { 751 "use strict"; 752 wpestate_lazy_load_carousel_property_unit(); 753 wpestate_card_unit_contact_actions(); 754 755 756 // wpestate_enable_half_map_pin_action(); 757 if (typeof wpestate_enable_half_map_pin_action == 'function') { 758 wpestate_enable_half_map_pin_action(); 759 } 760 var newpage, post_id, post_image, to_add, icon; 761 762 jQuery('.pagination_ajax_search a').on('click', function (event) { 763 event.preventDefault(); 764
765 newpage = parseInt(jQuery(this).attr('data-future'), 10); 766 document.getElementById('scrollhere').scrollIntoView(); 767 if (mapfunctions_vars.custom_search === 'yes') { 768 wpestate_custom_search_start_filtering_ajax(newpage); // should be custom 769 } else { 770 wpestate_start_filtering_ajax(newpage);// 771 } 772 }); 773 774 jQuery('.pagination_ajax a').on('click', function (event) { 775 event.preventDefault(); 776 newpage = parseInt(jQuery(this).attr('data-future'), 10); 777 document.getElementById('scrollhere').scrollIntoView(); 778 wpestate_start_filtering(newpage); 779 }); 780 781 782 783 jQuery('.property_listing').on('click', function (event) { 784 if ( 785 event.target.classList.contains('demo-icon') || 786 event.target.classList.contains('carousel-control-next-icon') || 787 event.target.classList.contains('carousel-control-prev-icon') 788 ){ 789 return; 790 } 791 792 793 if (control_vars.property_modal === '1' && !Modernizr.mq('only all and (max-width: 1024px)')) { 794 event.preventDefault(); 795 event.stopPropagation(); 796 scroll_modal_save = scroll_modal; 797 798 var listing_id = jQuery(this).parent().attr('data-listid'); 799 var main_img_url = jQuery(this).parent().attr('data-main-modal'); 800 var main_title = jQuery(this).parent().attr('data-modal-title'); 801 var link = jQuery(this).parent().attr('data-modal-link'); 802 wpestate_enable_property_modal(listing_id, main_img_url, main_title, link); 803 } else { 804 if (control_vars.new_page_link === '_blank') { 805 return; 806 } 807 var link; 808 link = jQuery(this).attr('data-link'); 809 810 window.open(link, '_self'); 811 } 812 }); 813 814 815 816 817 818 jQuery('.share_unit').on('click', function (event) { 819 event.stopPropagation(); 820 }); 821 822 var already_in = []; 823 824 jQuery('.compare-action').unbind('click'); 825 jQuery('.compare-action').on('click', function (event) { 826 event.stopPropagation(); 827 jQuery('.prop-compare').animate({ 828 right: "0px" 829 }); 830 post_id = jQuery(this).attr('data-pid'); 831 for (var i = 0; i < already_in.length; i++) { 832 if (already_in[i] === post_id) { 833 return; 834 } 835 } 836 837 already_in.push(post_id); 838 post_image = jQuery(this).attr('data-pimage'); 839 840 to_add = '<div class="items_compare ajax_compare" style="display:none;"><img src="' + post_image + '" class="img-responsive"><input type="hidden" value="' + post_id + '" name="selected_id[]" /></div>'; 841 jQuery('div.items_compare:first-child').css('background', 'red'); 842 if (parseInt(jQuery('.items_compare').length, 10) > 3) { 843 jQuery('.items_compare:first').remove(); 844 } 845 jQuery('#submit_compare').before(to_add); 846 jQuery('.items_compare').fadeIn(800); 847 }); 848 849 jQuery('#submit_compare').unbind('click'); 850 jQuery('#submit_compare').on('click', function (event) { 851 jQuery('#form_compare').trigger('submit'); 852 }); 853 854 jQuery('.icon-fav').on('click', function (event) { 855 event.stopPropagation(); 856 icon = jQuery(this); 857 wpestate_add_remove_favorite(icon); 858 }); 859 860 jQuery(".share_list, .icon-fav, .compare-action,.property_listing_details_v7_item").on('mouseenter', function () { 861 jQuery(this).tooltip('show'); 862 }) 863 .on('mouseleave', function () { 864 jQuery(this).tooltip('hide'); 865 }); 866 867 868 jQuery('.share_list').on('click', function (event) { 869 event.stopPropagation(); 870 var sharediv = jQuery(this).parent().find('.share_unit'); 871 sharediv.toggle(); 872 jQuery(this).toggleClass('share_on'); 873 }); 874 875 wpestate_grid_list_controls(); 876 wpestate_enable_share_unit(); 877 wpestate_enable_not_logged_favorites(); 878} 879 880 881 882 883 884/* 885* 886* Remove/Add to favorites(property page) when login is not required 887* 888*/ 889 890function wpestate_add_remove_favorite_local_storage_single(icon,post_id){ 891 var current_favorites = window.localStorage.getItem('wpestate_favorites'); 892 post_id=parseInt(post_id); 893 894 895 if(icon.hasClass('isnotfavorite')){ 896 897 if ( current_favorites ) { 898 current_favorites=current_favorites + ',' + post_id; 899 window.localStorage.setItem('wpestate_favorites',current_favorites ); 900 } else { 901 current_favorites=post_id; 902 window.localStorage.setItem('wpestate_favorites', current_favorites); 903 } 904
905 setCookie('wpestate_favorites',current_favorites,10); 906 907 jQuery('#add_favorites').removeClass('isnotfavorite').addClass('isfavorite').attr('title', ajaxcalls_vars.remove_favorite); 908 jQuery('#add_favorites').html('<i class="fas fa-heart"></i>' + ajaxcalls_vars.favorite); 909 910 }else{ 911 912 var prop_ids = jQuery.map(current_favorites.split(','), function(value){ 913 return parseInt(value); 914 }); 915 916 917 const index = prop_ids.indexOf( post_id ); 918 919 if (index > -1) { 920 prop_ids.splice(index, 1); 921 window.localStorage.setItem('wpestate_favorites', prop_ids); 922 setCookie('wpestate_favorites',prop_ids,10); 923 } 924 925 926 jQuery('#add_favorites').removeClass('isfavorite').addClass('isnotfavorite').attr('title', ajaxcalls_vars.add_favorite); 927 jQuery('#add_favorites').html('<i class="far fa-heart"></i>' + ajaxcalls_vars.favorite); 928 929 } 930 931 current_favorites = window.localStorage.getItem('wpestate_favorites'); 932} 933 934 935 936/* 937* 938* Remove/Add to favorites when login is not required 939* 940*/ 941 942 943function wpestate_add_remove_favorite_local_storage(icon,post_id){ 944 var current_favorites = window.localStorage.getItem('wpestate_favorites'); 945 post_id=parseInt(post_id); 946 947 if(icon.hasClass('icon-fav-off')){ 948 949 if ( current_favorites ) { 950 current_favorites=current_favorites+','+post_id; 951 window.localStorage.setItem('wpestate_favorites', current_favorites); 952 } else { 953 current_favorites=post_id; 954 window.localStorage.setItem('wpestate_favorites', current_favorites); 955 } 956 957 setCookie('wpestate_favorites',current_favorites,10); 958 959 icon.removeClass('icon-fav-off').addClass('icon-fav-on'); 960 icon.attr('title', ajaxcalls_vars.remove_fav); 961 962 }else{ 963 964 var prop_ids = jQuery.map(current_favorites.split(','), function(value){ 965 return parseInt(value); 966 }); 967 968 const index = prop_ids.indexOf( post_id ); 969 970 if (index > -1) { 971 prop_ids.splice(index, 1); 972 window.localStorage.setItem('wpestate_favorites', prop_ids); 973 setCookie('wpestate_favorites',prop_ids,10); 974 } 975 976 if (icon.hasClass('remove_fav_dash')) { 977 icon.parents('.property_wrapper_dash').remove(); 978 icon.parents('.listing_wrapper').remove(); 979 } 980 981 icon.removeClass('icon-fav-on').addClass('icon-fav-off'); 982 icon.attr('title', ajaxcalls_vars.add_favorite); 983 } 984 985 current_favorites = window.localStorage.getItem('wpestate_favorites'); 986} 987 988 989 990/* 991* 992* Remove/Add to favorites 993* 994*/ 995 996function wpestate_add_remove_favorite(icon) { 997 "use strict"; 998 var post_id, securitypass, ajaxurl; 999 post_id = icon.attr('data-postid'); 1000 securitypass = jQuery('#security-pass').val(); 1001 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 1002 var nonce = jQuery('#wpestate_ajax_filtering').val(); 1003 var use_favorite_login = ajaxcalls_vars.favorites_login; 1004 1005 if(use_favorite_login == "no"){ 1006 wpestate_add_remove_favorite_local_storage(icon, post_id); 1007 return; 1008 } 1009 1010 if (parseInt(ajaxcalls_vars.userid, 10) === 0) { 1011 wpestate_trigger_login_modal_open(1); 1012 } else { 1013 icon.toggleClass('icon-fav-off'); 1014 icon.toggleClass('icon-fav-on'); 1015 1016 1017 jQuery.ajax({ 1018 type: 'POST', 1019 url: ajaxurl, 1020 dataType: 'json', 1021 data: { 1022 'action': 'wpestate_ajax_add_fav', 1023 'post_id': post_id, 1024 'security': nonce 1025 }, 1026 success: function (data) { 1027 1028 if (data.added) { 1029 icon.removeClass('icon-fav-off').addClass('icon-fav-on'); 1030 // Update Bootstrap tooltip attributes 1031 icon.attr('aria-label', ajaxcalls_vars.remove_fav); 1032 icon.attr('data-bs-original-title', ajaxcalls_vars.remove_fav); 1033 // Also update title for fallback 1034 icon.attr('title', ajaxcalls_vars.remove_fav); 1035 1036 // Refresh the Bootstrap tooltip if it exists 1037 if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip) { 1038 var tooltipInstance = bootstrap.Tooltip.getInstance(icon[0]); 1039 if (tooltipInstance) { 1040 tooltipInstance.setContent({ 1041 '.tooltip-inner': ajaxcalls_vars.remove_fav 1042 }); 1043 } 1044 } 1045 } else { 1046 if (icon.hasClass('remove_fav_dash')) { 1047 icon.parents('.property_wrapper_dash').remove(); 1048 } 1049 icon.removeClass('icon-fav-on').addClass('icon-fav-off'); 1050 // Update Bootstrap tooltip attributes 1051 icon.attr('aria-label', ajaxcalls_vars.add_favorite); 1052 icon.attr('data-bs-original-title', ajaxcalls_vars.add_favorite); 1053 // Also update title for fallback 1054 icon.attr('title', ajaxcalls_vars.add_favorite); 1055 1056 // Refresh the Bootstrap tooltip if it exists 1057 if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip) { 1058 var tooltipInstance = bootstrap.Tooltip.getInstance(icon[0]); 1059 if (tooltipInstance) { 1060 tooltipInstance.setContent({ 1061 '.tooltip-inner': ajaxcalls_vars.add_favorite 1062 }); 1063 } 1064 } 1065 } 1066 }, 1067 error: function (errorThrown) { 1068 // Handle error case 1069 } 1070 }); // end ajax 1071 } // end login use 1072} 1073
1074//////////////////////////////////////////////////////////////////////////////////////////// 1075/// resend listing for approval-jslint checked 1076//////////////////////////////////////////////////////////////////////////////////////////// 1077function wpestate_resend_for_approval(prop_id, selected_div) { 1078 "use strict"; 1079 var ajaxurl, normal_list_no; 1080 ajaxurl = control_vars.admin_url + 'admin-ajax.php'; 1081 var nonce = jQuery('#wpestate_property_actions').val(); 1082 1083 jQuery.ajax({ 1084 type: 'POST', 1085 url: ajaxurl, 1086 data: { 1087 'action': 'wpestate_ajax_resend_for_approval', 1088 'propid': prop_id, 1089 'security': nonce 1090 }, 1091 success: function (data) { 1092 1093 if (data === 'pending') { 1094 selected_div.parent().empty().append('<span class="featured_prop">Sent for approval</span>'); 1095 normal_list_no = parseInt(jQuery('#normal_list_no').text(), 10); 1096 jQuery('#normal_list_no').text(normal_list_no - 1); 1097 } else { 1098 selected_div.removeClass('resend_pending').html(data); 1099 } 1100 }, 1101 error: function (errorThrown) { 1102 1103 } 1104 });//end ajax 1105} 1106 1107//////////////////////////////////////////////////////////////////////////////////////////// 1108/// make property featured-jslint checked 1109//////////////////////////////////////////////////////////////////////////////////////////// 1110function wpestate_make_prop_featured(prop_id, selectedspan) { 1111 "use strict"; 1112 var ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 1113 var nonce = jQuery('#wpestate_property_actions').val(); 1114 1115 jQuery.ajax({ 1116 type: 'POST', 1117 url: ajaxurl, 1118 data: { 1119 'action': 'wpestate_ajax_make_prop_featured', 1120 'propid': prop_id, 1121 'security': nonce 1122 }, 1123 success: function (data) { 1124 if (data.trim() === 'done') { 1125 selectedspan.empty().html('<span class="label label-success">' + ajaxcalls_vars.prop_featured + '</span>'); 1126 var featured_list_no = parseInt(jQuery('#featured_list_no').text(), 10); 1127 jQuery('#featured_list_no').text(featured_list_no - 1); 1128 } else { 1129 selectedspan.empty().removeClass('make_featured').addClass('featured_exp').text(ajaxcalls_vars.no_prop_featured); 1130 } 1131 1132 }, 1133 error: function (errorThrown) { 1134 } 1135 1136 });//end ajax 1137} 1138 1139//////////////////////////////////////////////////////////////////////////////////////////// 1140/// pay package via paypal recuring-jslint checked 1141//////////////////////////////////////////////////////////////////////////////////////////// 1142function wpestate_recuring_pay_pack_via_paypal() { 1143 "use strict"; 1144 var ajaxurl, packName, packId; 1145 ajaxurl = control_vars.admin_url + 'admin-ajax.php'; 1146 1147 packName = jQuery('.package_selected .pack-listing-title').text(); 1148 packId = jQuery('.package_selected .pack-listing-title').attr('data-packid'); 1149 1150 var nonce = jQuery('#wpestate_payments_nonce').val(); 1151 jQuery.ajax({ 1152 type: 'POST', 1153 url: ajaxurl, 1154 data: { 1155 'action': 'wpestate_ajax_paypal_pack_recuring_generation_rest_api', 1156 'packName': packName, 1157 'packId': packId, 1158 'security': nonce 1159 }, 1160 success: function (data) { 1161 // Server returns a PayPal recurring-billing URL; validate before redirecting (XSS-5). 1162 wpestate_safe_redirect(data); 1163 }, 1164 error: function (errorThrown) { 1165 1166 } 1167 });//end ajax 1168} 1169 1170jQuery(".buypackage").click(function () { 1171 "use strict"; 1172 var stripe_pack_id, stripetitle2, stripetitle, stripepay; 1173 1174 1175 jQuery(".pack-listing").removeClass("package_selected"); 1176 jQuery(".pack-listing input").prop('checked', false); 1177 1178 jQuery(this).find('.input_pak_check').prop('checked', true); 1179 jQuery(this).parent().addClass("package_selected"); 1180 1181 stripetitle = jQuery(this).parent().find('.pack-listing-title').attr('data-stripetitle'); 1182 stripetitle2 = jQuery(this).parent().find('.pack-listing-title').attr('data-stripetitle2'); 1183 stripepay = jQuery(this).parent().find('.pack-listing-title').attr('data-stripepay'); 1184 stripe_pack_id = jQuery(this).parent().find('.pack-listing-title').attr('data-packid'); 1185 1186 jQuery('.stripe_buttons').attr("id", stripetitle2); 1187 jQuery('#stripe_script').attr("data-amount", stripepay); 1188 jQuery('#stripe_script').attr("data-description", stripetitle); 1189 1190 jQuery('#pack_id').val(stripe_pack_id); 1191 jQuery('#pack_title').val(stripetitle2); 1192 jQuery('#pay_ammout').val(stripepay); 1193 jQuery('#stripe_form').attr('data-amount', stripepay); 1194 1195 1196 jQuery('.wpestate_stripe_pay_desc').html(control_vars.stripe_pay_for + " " + stripetitle2); 1197 jQuery('#wpestate_stripe_form_button_sumit').html(control_vars.stripe_pay + " " + stripepay / 100 + " " + control_vars.submission_curency); 1198 1199 // enable stripe code 1200 1201 1202}); 1203 1204 1205 1206//////////////////////////////////////////////////////////////////////////////////////////// 1207/// pay package via paypal-jslint checked
1208//////////////////////////////////////////////////////////////////////////////////////////// 1209function wpestate_pay_pack_via_paypal() { 1210 "use strict"; 1211 var ajaxurl, packName, packId; 1212 ajaxurl = control_vars.admin_url + 'admin-ajax.php'; 1213 packName = jQuery('.package_selected .pack-listing-title').text(); 1214 packId = jQuery('.package_selected .pack-listing-title').attr('data-packid'); 1215 var nonce = jQuery('#wpestate_payments_nonce').val(); 1216 jQuery.ajax({ 1217 type: 'POST', 1218 url: ajaxurl, 1219 data: { 1220 'action': 'wpestate_ajax_paypal_pack_generation', 1221 'packName': packName, 1222 'packId': packId, 1223 'security': nonce 1224 }, 1225 success: function (data) { 1226 // Server returns a PayPal one-time-payment URL for the package; validate before redirecting (XSS-5). 1227 wpestate_safe_redirect(data); 1228 }, 1229 error: function (errorThrown) { 1230 1231 } 1232 });//end ajax 1233 1234} 1235//////////////////////////////////////////////////////////////////////////////////////////// 1236/// listing pay -jslint checked 1237//////////////////////////////////////////////////////////////////////////////////////////// 1238function wpestate_listing_pay(prop_id, selected_div, is_featured, is_upgrade) { 1239 "use strict"; 1240 var ajaxurl = control_vars.admin_url + 'admin-ajax.php'; 1241 var nonce = jQuery('#wpestate_payments_nonce').val(); 1242 jQuery.ajax({ 1243 type: 'POST', 1244 url: ajaxurl, 1245 data: { 1246 'action': 'wpestate_ajax_listing_pay', 1247 'propid': prop_id, 1248 'is_featured': is_featured, 1249 'is_upgrade': is_upgrade, 1250 'security': nonce 1251 }, 1252 success: function (data) { 1253 // Server returns a PayPal URL for listing payment/upgrade; validate before redirecting (XSS-5). 1254 wpestate_safe_redirect(data); 1255 }, 1256 error: function (errorThrown) { 1257 } 1258 });//end ajax 1259} 1260 1261//////////////////////////////////////////////////////////////////////////////////////////// 1262/// start filtering -jslint checked 1263//////////////////////////////////////////////////////////////////////////////////////////// 1264 1265/** 1266 * Resolve a single-select dropdown filter to a taxonomy payload array. 1267 * 1268 * Reads the active dropdown button `data-value`, ignores placeholder values, 1269 * then resolves the selected `<li data-value="...">` to `data-term-id` when present. 1270 * Returns a one-item array for AJAX payload compatibility. 1271 * 1272 * @param {string} filterButtonSelector jQuery selector for the dropdown trigger. 1273 * @param {Array<string>} placeholderValues Values that mean "no filter". 1274 * @returns {Array<string>} Selected taxonomy value array (term id preferred). 1275 */ 1276function wpestate_resolve_single_filter_taxonomy_values(filterButtonSelector, placeholderValues) { 1277 "use strict"; 1278 1279 // Step 1: Resolve button and current selected value. 1280 var filterButton = jQuery(filterButtonSelector).first(); 1281 if (filterButton.length === 0) { 1282 return []; 1283 } 1284 1285 var selectedValue = (filterButton.attr('data-value') || '').trim(); 1286 if (selectedValue === '') { 1287 return []; 1288 } 1289 1290 // Step 2: Skip placeholder values that represent "all". 1291 var normalizedSelectedValue = selectedValue.toLowerCase(); 1292 var normalizedPlaceholders = (placeholderValues || []).map(function (value) { 1293 return String(value).toLowerCase(); 1294 }); 1295 if (normalizedPlaceholders.indexOf(normalizedSelectedValue) !== -1) { 1296 return []; 1297 } 1298 1299 // Step 3: Resolve selected option term id from the related dropdown list. 1300 var resolvedValue = selectedValue; 1301 var dropdownId = filterButton.attr('id') || ''; 1302 if (dropdownId !== '') { 1303 var dropdownMenu = jQuery('ul[aria-labelledby="' + dropdownId + '"]').first(); 1304 if (dropdownMenu.length > 0) { 1305 var selectedListItem = dropdownMenu.find('li').filter(function () { 1306 return (jQuery(this).attr('data-value') || '') === selectedValue; 1307 }).first(); 1308 1309 if (selectedListItem.length > 0) {
1310 var termId = wpestate_get_term_id_from_element(selectedListItem); 1311 if (termId !== '') { 1312 resolvedValue = termId; 1313 } 1314 } 1315 } 1316 } 1317 1318 // Step 4: Return the normalized value as one-item array. 1319 return [resolvedValue]; 1320} 1321 1322/** 1323 * Collect taxonomy filters for wpestate_start_filtering payload. 1324 * 1325 * Uses canonical taxonomy names as payload keys and term ids as values 1326 * whenever term metadata exists on dropdown options. 1327 * 1328 * @returns {Object} Taxonomy payload object keyed by taxonomy names. 1329 */ 1330function wpestate_collect_start_filtering_taxonomies() { 1331 "use strict"; 1332 1333 // Step 1: Collect each single-select filter using canonical taxonomy keys. 1334 return { 1335 property_action_category: wpestate_resolve_single_filter_taxonomy_values('#a_filter_action', ['all', 'types', 'all-actions']), 1336 property_category: wpestate_resolve_single_filter_taxonomy_values('#a_filter_categ', ['all', 'categories', 'all-types']), 1337 property_status: wpestate_resolve_single_filter_taxonomy_values('#a_filter_status', ['all', 'property status']), 1338 property_features: wpestate_resolve_single_filter_taxonomy_values('#a_filter_features', ['all', 'property features']), 1339 property_county_state: wpestate_resolve_single_filter_taxonomy_values('#a_filter_county', ['all', 'states']), 1340 property_city: wpestate_resolve_single_filter_taxonomy_values('#a_filter_cities', ['all', 'cities', 'all-cities']), 1341 property_area: wpestate_resolve_single_filter_taxonomy_values('#a_filter_areas', ['all', 'areas', 'all-areas']) 1342 }; 1343} 1344 1345function wpestate_start_filtering(newpage) { 1346 "use strict"; 1347 jQuery('#gmap-loading').show(); 1348 jQuery('#grid_view').addClass('icon_selected'); 1349 jQuery('#list_view').removeClass('icon_selected'); 1350 1351 // Step 1: Collect canonical taxonomy payload (taxonomy keys + array values). 1352 var taxonomyPayload = wpestate_collect_start_filtering_taxonomies(); 1353 1354 // Step 2: Read ordering and page context values. 1355 var order = jQuery('#a_filter_order').attr('data-value'); 1356 var ajaxurl; 1357 var page_id; 1358 ajaxurl = ajaxcalls_vars.wpestate_ajax; 1359 page_id = jQuery('#page_idx').val(); 1360 1361 // Step 3: Read listing card rendering context from wrapper. 1362 var card_version = jQuery('.wpestate_filter_list_properties_wrapper').attr('data-card_version'); 1363 var rownumber = jQuery('.wpestate_filter_list_properties_wrapper').attr('data-rownumber'); 1364 var ishortcode = jQuery('.wpestate_filter_list_properties_wrapper').attr('data-ishortcode'); 1365 var number = jQuery('.wpestate_filter_list_properties_wrapper').attr('data-number'); 1366 var context = jQuery('.wpestate_filter_list_properties_wrapper').attr('data-context'); 1367 1368 1369 1370 // Step 4: Show loading skeletons before the AJAX request. 1371 var align = ''; 1372 if (jQuery('.wpestate_filter_list_properties_wrapper').length > 0) { 1373 1374 wpestate_createSkeletons(jQuery('.wpestate_filter_list_properties_wrapper')); 1375 align = jQuery('.wpestate_filter_list_properties_wrapper').attr('data-align'); 1376 } else { 1377 wpestate_createSkeletons(jQuery('#listing_ajax_container')); 1378 } 1379 var nonce = jQuery('#wpestate_ajax_filtering').val(); 1380 1381 // Step 5: Build the request payload with canonical taxonomy keys. 1382 var ajaxData = { 1383 'action': 'wpestate_ajax_filter_listings', 1384 'property_action_category': taxonomyPayload.property_action_category, 1385 'property_category': taxonomyPayload.property_category, 1386 'property_status': taxonomyPayload.property_status, 1387 'property_features': taxonomyPayload.property_features, 1388 'property_county_state': taxonomyPayload.property_county_state, 1389 'property_city': taxonomyPayload.property_city, 1390 'property_area': taxonomyPayload.property_area, 1391 'order': order, 1392 'newpage': newpage, 1393 'page_id': page_id, 1394 'align': align, 1395 'card_version': card_version, 1396 'rownumber': rownumber, 1397 'ishortcode': ishortcode, 1398 'number': number, 1399 'context': context, 1400 'security': nonce 1401 }; 1402 1403 jQuery.ajax({ 1404 type: 'POST', 1405 url: ajaxurl, 1406 dataType: 'json', 1407 data: ajaxData, 1408 success: function (data) { 1409 1410 jQuery('#listing_loader').hide(); 1411 if (jQuery('.wpestate_filter_list_properties_wrapper').length > 0) { 1412 1413 wpestate_replaceSkeletons(jQuery('.wpestate_filter_list_properties_wrapper'), data.to_show); 1414 } else { 1415 wpestate_replaceSkeletons(jQuery('#listing_ajax_container'), data.to_show); 1416 } 1417 1418 jQuery('.pagination_nojax').hide(); 1419 1420 // map update 1421 var no_results = parseInt(data.no_results); 1422 if (no_results !== 0) { 1423 wpestate_load_on_demand_pins(data.markers, no_results, 0); 1424 } else { 1425 wpestate_show_no_results(); 1426 } 1427 1428 jQuery('.col-md-12.listing_wrapper .property_unit_custom_element.image').each(function () { 1429 jQuery(this).parent().addClass('wrap_custom_image'); 1430 }); 1431 1432 // Re-bind click handlers on the freshly-injected DOM (pagination, 1433 // favorites, etc.). Without this, the new pagination_ajax links 1434 // fall back to their server-rendered href, which during an 1435 // admin-ajax POST resolves to /wp-admin/admin-ajax.php?paged=N. 1436 wpestate_restart_js_after_ajax(); 1437 1438 jQuery('#gmap-loading').hide(); 1439 1440 }, 1441 error: function (errorThrown) { 1442 1443 } 1444 });//end ajax 1445} 1446 1447 1448 1449 1450 1451 1452 1453//////////////////////////////////////////////////////////////////////////////////////////// 1454// on ready -jslint checked 1455// developer listing on tab click !!
1456//////////////////////////////////////////////////////////////////////////////////////////// 1457jQuery(document).ready(function ($) { 1458 "use strict"; 1459 1460 wpestate_add_to_favorites(); 1461 wpestate_js_pagination_ajax(); 1462 wpestate_enable_not_logged_favorites(); 1463 wpestate_load_agency_developer_listings(); 1464 1465 1466 wpestate_agent_submit_email(); 1467 1468 wpestate_theme_slider_show_contact(); 1469 wpestate_enable_schedule_contact(); 1470 1471 1472 1473 1474 1475 1476 /////////////////////////////////////////////////////////////////////////////////////////// 1477 //// stripe cancel 1478 /////////////////////////////////////////////////////////////////////////////////////////// 1479 $('#stripe_cancel').on('click', function (event) { 1480 1481 var stripe_user_id, ajaxurl; 1482 stripe_user_id = $(this).attr('data-stripeid'); 1483 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 1484 $('#stripe_cancel').text(ajaxcalls_vars.saving); 1485 var nonce = jQuery('#wpestate_stripe_cancel_nonce').val(); 1486 1487 $.ajax({ 1488 type: 'POST', 1489 url: ajaxurl, 1490 data: { 1491 'action': 'wpestate_cancel_stripe', 1492 'stripe_customer_id': stripe_user_id, 1493 'security': nonce, 1494 1495 }, 1496 success: function (data) { 1497 $('#stripe_cancel').text(ajaxcalls_vars.stripecancel); 1498 }, 1499 error: function (errorThrown) { 1500 } 1501 }); 1502 }); 1503 1504 1505 //////////////////////////////////////////////////////////////////////////////////////////// 1506 /// resend for approval 1507 /////////////////////////////////////////////////////////////////////////////////////////// 1508 $('.resend_pending').on('click', function (event) { 1509 1510 var prop_id = $(this).attr('data-listingid'); 1511 wpestate_resend_for_approval(prop_id, $(this)); 1512 }); 1513 1514 1515 1516 jQuery('#wpestate_stripe_booking_recurring').on('click', function () { 1517 1518 var modalid = jQuery(this).attr('data-modalid'); 1519 var modal = jQuery('#' + modalid); 1520 1521 modal.appendTo('body'); 1522 1523 modal.show(); 1524 jQuery('#' + modalid + ' .wpestate_stripe_form_1').show(); 1525 1526 wpestate_start_stripe(1, modalid); 1527 }); 1528 1529 /////////////////////////////////////////////////////////////////////////////////////////// 1530 //////// pack upgrade via paypal 1531 /////////////////////////////////////////////////////////////////////////////////////////// 1532 $('#pick_pack').on('click', function (event) { 1533 1534 var pay_paypal; 1535 pay_paypal = '<div class="modal fade" id="paypal_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog"><div class="modal-content"><div class="modal-body listing-submit">' + ajaxcalls_vars.paypal + '</div></div></div></div></div>'; 1536 jQuery('body').append(pay_paypal); 1537 jQuery('#paypal_modal').modal(); 1538 1539 1540 if ($('#pack_recuring').is(':checked')) { 1541 wpestate_recuring_pay_pack_via_paypal(); 1542 } else { 1543 wpestate_pay_pack_via_paypal(); 1544 } 1545 }); 1546 1547 /////////////////////////////////////////////////////////////////////////////////////////// 1548 //////// listing pay via paypal 1549 /////////////////////////////////////////////////////////////////////////////////////////// 1550 $('.listing_submit_normal').on('click', function (event) { 1551 var prop_id, featured_checker, is_featured, is_upgrade, pay_paypal; 1552 pay_paypal = '<div class="modal fade" id="paypal_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog"><div class="modal-content"><div class="modal-body listing-submit">' + ajaxcalls_vars.paypal + '</div></div></div></div></div>'; 1553 jQuery('body').append(pay_paypal); 1554 jQuery('#paypal_modal').modal(); 1555 1556 1557 prop_id = $(this).attr('data-listingid'); 1558 featured_checker = $(this).parent().find('input'); 1559 is_featured = 0; 1560 is_upgrade = 0; 1561 1562 if (featured_checker.prop('checked')) { 1563 is_featured = 1; 1564 } else { 1565 is_featured = 0; 1566 } 1567 1568 wpestate_listing_pay(prop_id, $(this), is_featured, is_upgrade); 1569 }); 1570 1571 jQuery('.woo_pay_submit').on('click', function () { 1572 var pay_paypal, prop_id, book_id, invoice_id, is_featured, is_upgrade, ajaxurl, depozit, is_submit, pack_id; 1573 prop_id = jQuery(this).attr('data-propid'); 1574 depozit = jQuery(this).attr('data-deposit'); 1575 is_featured = jQuery(this).attr('data-is_featured'); 1576 pack_id = jQuery('.package_selected').attr('data-id'); 1577 is_upgrade = 0; 1578 is_submit = 1; 1579 if (jQuery('#open_packages').length > 0) { 1580 is_submit = 0; 1581 } 1582 book_id = ''; 1583 invoice_id = ''; 1584 1585 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 1586 jQuery.ajax({ 1587 type: 'POST', 1588 url: ajaxurl, 1589 data: { 1590 'action': 'wpestate_woo_pay', 1591 'propid': prop_id, 1592 'depozit': depozit, 1593 'is_submit': is_submit, 1594 'is_featured': is_featured, 1595 'pack_id': pack_id, 1596 'book_id': book_id, 1597 'invoiceid': invoice_id, 1598 'security': ajaxcalls_vars.wpestate_woo_pay_nonce 1599 }, 1600 success: function (data) { 1601 if (data !== false) { 1602 window.location.href = ajaxcalls_vars.checkout_url; 1603 } 1604 }, 1605 error: function (errorThrown) {} 1606 });//end ajax 1607 }); 1608 1609 $('.listing_upgrade').on('click', function (event) { 1610 var is_upgrade, is_featured, prop_id; 1611 is_upgrade = 1; 1612 is_featured = 0; 1613 prop_id = $(this).attr('data-listingid'); 1614 wpestate_listing_pay(prop_id, $(this), is_featured, is_upgrade); 1615 }); 1616 1617 1618
1619 /////////////////////////////////////////////////////////////////////////////////////////// 1620 /////// Property page + ajax call on contact 1621 /////////////////////////////////////////////////////////////////////////////////////////// 1622 1623 1624 1625 1626 /////////////////////////////////////////////////////////////////////////////////////////// 1627 //////// property listing listing 1628 //////////////////////////////////////////////////////////////////////////////////////////// 1629 1630 $('.listing_filters_head li').on('click', function (event) { 1631 1632 var pick, value, parent; 1633 pick = $(this).text(); 1634 value = $(this).attr('data-value'); 1635 parent = $(this).parent().parent(); 1636 parent.find('.filter_menu_trigger').text(pick).append('<span class="caret caret_filter"></span>').attr('data-value', value); 1637 parent.find('input:hidden').val(value); 1638 1639 wpestate_start_filtering(1); 1640 1641 1642 }); 1643 1644 1645 1646 1647 /////////////////////////////////////////////////////////////////////////////////////////// 1648 //////// advanced search filtering 1649 //////////////////////////////////////////////////////////////////////////////////////////// 1650 1651 jQuery(document).on('click', '.wpresidence_property_list_half_map_core .wpresidence_wrap_a_filter_order li', function (event) { 1652 1653 var pick, value, parent; 1654 pick = $(this).text(); 1655 value = $(this).attr('data-value'); 1656 parent = $(this).parent().parent(); 1657 parent.find('.filter_menu_trigger').text(pick).append('<span class="caret caret_filter"></span>').attr('data-value', value); 1658 parent.find('input:hidden').val(value); 1659 1660 if(mapfunctions_vars.custom_search==='yes'){ 1661 jQuery('.half-pagination').remove(); 1662 1663 wpestate_custom_search_start_filtering_ajax(1); 1664 }else{ 1665 1666 wpestate_start_filtering_ajax(1); 1667 } 1668 1669 }); 1670 1671 1672 $('.adv_listing_filters_head li').on('click', function (event) { 1673 1674 var pick, value, parent, args, page_id, ajaxurl; 1675 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 1676 pick = $(this).text(); 1677 value = $(this).attr('data-value'); 1678 parent = $(this).parent().parent(); 1679 parent.find('.filter_menu_trigger').text(pick).append('<span class="caret caret_filter"></span>').attr('data-value', value); 1680 args = $('#searcharg').val(); 1681 page_id = $('#page_idx').val(); 1682 //$('#listing_ajax_container').empty(); 1683 //$('#listing_loader').show(); 1684 1685 1686 const listingContainer = jQuery('#listing_ajax_container'); 1687 wpestate_createSkeletons(listingContainer); 1688 1689 1690 var nonce = jQuery('#wpestate_search_nonce').val(); 1691 $.ajax({ 1692 type: 'POST', 1693 url: ajaxurl, 1694 1695 data: { 1696 'action': 'wpestate_advanced_search_filters', 1697 'args': args, 1698 'value': value, 1699 'page_id': page_id, 1700 'security': nonce 1701 }, 1702 success: function (data) { 1703 //$('#listing_loader').hide(); 1704 //$('#listing_ajax_container').append(data); 1705 wpestate_replaceSkeletons(listingContainer, data); 1706 1707 1708 wpestate_restart_js_after_ajax(); 1709 wpestate_add_pagination_orderby(); 1710 }, 1711 error: function (errorThrown) { 1712 } 1713 }); //end ajax 1714 }); 1715 1716 1717 function wpestate_add_pagination_orderby() { 1718 1719 var order = $('#a_filter_order').attr('data-value'); 1720 jQuery('.pagination a').each(function () { 1721 var href = $(this).attr('href'); 1722 href = href + "&order_search=" + order; 1723 $(this).attr('href', href); 1724 }); 1725 } 1726 1727 /////////////////////////////////////////////////////////////////////////////////////////// 1728 //////// Ajax add to favorites on listing 1729 //////////////////////////////////////////////////////////////////////////////////////////// 1730 $('.icon-fav,.remove_fav_dash').on('click', function (event) { 1731 event.stopPropagation(); 1732 var icon = $(this); 1733 wpestate_add_remove_favorite(icon); 1734 }); 1735 1736 1737 1738 1739 // remove from fav listing on user profile 1740 $('.icon-fav-on-remove').on('click', function (event) { 1741 event.stopPropagation(); 1742 $(this).parent().parent().remove(); 1743 1744 }); 1745 1746 1747 1748 1749
1750 /////////////////////////////////////////////////////////////////////////////////////////// 1751 //////// update profile 1752 //////////////////////////////////////////////////////////////////////////////////////////// 1753 $('#register_agent').on('click', function (event) { 1754 var firstname = $('#firstname').val(); 1755 var secondname = $('#secondname').val(); 1756 var useremail = $('#useremail').val(); 1757 var userphone = $('#userphone').val(); 1758 var usermobile = $('#usermobile').val(); 1759 var usertitle = $('#usertitle').val(); 1760 var description = $('#about_me').val(); 1761 var userfacebook = $('#userfacebook').val(); 1762 var usertwitter = $('#usertwitter').val(); 1763 var userlinkedin = $('#userlinkedin').val(); 1764 var userpinterest = $('#userpinterest').val(); 1765 var userinstagram = $('#userinstagram').val(); 1766 var userurl = $('#website').val(); 1767 var agent_username = $('#agent_username').val(); 1768 var agent_password = $('#agent_password').val(); 1769 var agent_repassword = $('#agent_repassword').val(); 1770 var agent_category_submit = $('#agent_category_submit').val(); 1771 var agent_action_submit = $('#agent_action_submit').val(); 1772 var agent_city = $('#agent_city').val(); 1773 var agent_county = $('#agent_county').val(); 1774 var agent_member = $('#agent_member').val(); 1775 var agent_address = $('#agent_address').val(); 1776 1777 var agent_youtube = $('#useryoutube').val(); 1778 var agent_tiktok = $('#usertiktok').val(); 1779 var agent_telegram = $('#usertelegram').val(); 1780 var agent_vimeo = $('#uservimeo').val(); 1781 var agent_private_notes = $('#agent_private_notes').val(); 1782 1783 var agent_area = $('#agent_area').val(); 1784 var is_agent_edit = $('#is_agent_edit').val(); 1785 var user_id = $('#user_id').val(); 1786 var agent_id = $('#agent_id').val(); 1787 var ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 1788 var securityprofile = $('#security-profile').val(); 1789 var upload_picture = $('#upload_picture').val(); 1790 var profile_image_url = $('#profile-image').attr('data-profileurl'); 1791 var profile_image_url_small = $('#profile-image').attr('data-smallprofileurl'); 1792 var acf_fields = wpestate_return_form_acf_fields('.field-group'); 1793 1794 // customparameters 1795 var agent_custom_label = []; 1796 $('.single_parameter_row .agent_custom_label').each(function () { 1797 agent_custom_label.push($(this).val()); 1798 }); 1799 1800 var agent_custom_value = []; 1801 $('.single_parameter_row .agent_custom_value').each(function () { 1802 agent_custom_value.push($(this).val()); 1803 }); 1804 var nonce = jQuery('#wpestate_register_agent_nonce').val(); 1805 1806 window.scrollTo(0, 0); 1807 1808 $('#profile_message').empty().append('<div class="login-alert">' + ajaxcalls_vars.saving + '<div>'); 1809 1810 1811 $.ajax({ 1812 type: 'POST', 1813 url: ajaxurl, 1814 dataType: 'json', 1815 data: { 1816 'action': 'wpestate_ajax_register_agent', 1817 'agent_username': agent_username, 1818 'agent_password': agent_password, 1819 'agent_repassword': agent_repassword, 1820 'firstname': firstname, 1821 'secondname': secondname, 1822 'useremail': useremail, 1823 'userphone': userphone, 1824 'usermobile': usermobile, 1825 'usertitle': usertitle, 1826 'description': description, 1827 'upload_picture': upload_picture, 1828 'security-profile': securityprofile, 1829 'profile_image_url': profile_image_url, 1830 'profile_image_url_small': profile_image_url_small, 1831 'userfacebook': userfacebook, 1832 'usertwitter': usertwitter, 1833 'userlinkedin': userlinkedin, 1834 'userpinterest': userpinterest, 1835 'userinstagram': userinstagram, 1836 'userurl': userurl, 1837 'agent_category_submit': agent_category_submit, 1838 'agent_action_submit': agent_action_submit, 1839 'agent_city': agent_city, 1840 'agent_county': agent_county, 1841 'agent_area': agent_area, 1842 'agentedit': is_agent_edit, 1843 'userid': user_id, 1844 'agentid': agent_id, 1845 'agent_member': agent_member, 1846 'agent_address': agent_address, 1847 'agent_youtube':agent_youtube, 1848 'agent_tiktok':agent_tiktok, 1849 'agent_telegram':agent_telegram, 1850 'agent_vimeo': agent_vimeo, 1851 'agent_private_notes': agent_private_notes, 1852 'acf_fields': JSON.stringify(acf_fields), 1853 'agent_custom_label': agent_custom_label, 1854 'agent_custom_value': agent_custom_value, 1855 'security': nonce 1856 1857 }, 1858 success: function (data) { 1859 $('#profile_message').empty().append('<div class="login-alert">
1859' + data.mesaj + '<div>'); 1860 if (data.added) { 1861 setTimeout(function () { 1862 window.open(ajaxcalls_vars.agent_list, '_self', false); 1863 }, 1500); 1864 } 1865 }, 1866 error: function (errorThrown) { 1867 1868 } 1869 }); 1870 }); 1871 1872 1873 $('#update_profile').on('click', function (event) { 1874 1875 $('#profile_message').find('.login-alert').remove(); 1876 1877 var firstname, secondname, userurl, usermobile, userinstagram, userpinterest, userlinkedin, usertwitter, userfacebook, profile_image_url, profile_image_url_small, firstname, secondname, useremail, userphone, usertitle, description, ajaxurl, securityprofile, upload_picture; 1878 firstname = $('#firstname').val(); 1879 secondname = $('#secondname').val(); 1880 useremail = $('#useremail').val(); 1881 userphone = $('#userphone').val(); 1882 usermobile = $('#usermobile').val(); 1883 usertitle = $('#usertitle').val(); 1884 description = $('#about_me').val(); 1885 userfacebook = $('#userfacebook').val(); 1886 usertwitter = $('#usertwitter').val(); 1887 userlinkedin = $('#userlinkedin').val(); 1888 userpinterest = $('#userpinterest').val(); 1889 userinstagram = $('#userinstagram').val(); 1890 userurl = $('#website').val(); 1891 var hubspot_api = $('#hubspot_api').val(); 1892 var agent_member = $('#agent_member').val(); 1893 var agent_address= $('#agent_address').val(); 1894 1895 var agent_youtube = $('#useryoutube').val(); 1896 var agent_tiktok = $('#usertiktok').val(); 1897 var agent_telegram = $('#usertelegram').val(); 1898 var agent_vimeo = $('#uservimeo').val(); 1899 var agent_private_notes = $('#agent_private_notes').val(); 1900 1901 var agent_category_submit = $('#agent_category_submit').val(); 1902 var agent_action_submit = $('#agent_action_submit').val(); 1903 var agent_city = $('#agent_city').val(); 1904 var agent_county = $('#agent_county').val(); 1905 var agent_area = $('#agent_area').val(); 1906 var nonce = jQuery('#wpestate_update_profile_nonce').val(); 1907 1908 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 1909 securityprofile = $('#security-profile').val(); 1910 upload_picture = $('#upload_picture').val(); 1911 profile_image_url = $('#profile-image').attr('data-profileurl'); 1912 profile_image_url_small = $('#profile-image').attr('data-smallprofileurl'); 1913 1914 var acf_fields = wpestate_return_form_acf_fields('.field-group'); 1915 1916 // customparameters 1917 var agent_custom_label = []; 1918 $('.cliche_row .agent_custom_label').each(function () { 1919 agent_custom_label.push($(this).val()); 1920 }); 1921 1922 var agent_custom_value = []; 1923 $('.cliche_row .agent_custom_value').each(function () { 1924 agent_custom_value.push($(this).val()); 1925 }); 1926 1927 1928 1929 window.scrollTo(0, 0); 1930 $('#profile_message').empty().append('<div class="login-alert">' + ajaxcalls_vars.saving + '<div>'); 1931 $.ajax({ 1932 type: 'POST', 1933 url: ajaxurl, 1934 data: { 1935 'action': 'wpestate_ajax_update_profile', 1936 'firstname': firstname, 1937 'secondname': secondname, 1938 'useremail': useremail, 1939 'userphone': userphone, 1940 'usermobile': usermobile, 1941 'usertitle': usertitle, 1942 'description': description, 1943 'upload_picture': upload_picture, 1944 'security-profile': securityprofile, 1945 'profile_image_url': profile_image_url, 1946 'profile_image_url_small': profile_image_url_small, 1947 'userfacebook': userfacebook, 1948 'usertwitter': usertwitter, 1949 'userlinkedin': userlinkedin, 1950 'userpinterest': userpinterest, 1951 'userinstagram': userinstagram, 1952 'userurl': userurl, 1953 'agent_category_submit': agent_category_submit, 1954 'agent_action_submit': agent_action_submit, 1955 'agent_city': agent_city, 1956 'agent_county': agent_county, 1957 'agent_area': agent_area, 1958 'agent_member': agent_member, 1959 'agent_address':agent_address, 1960 'agent_youtube':agent_youtube, 1961 'agent_tiktok':agent_tiktok, 1962 'agent_telegram':agent_telegram, 1963 'agent_vimeo': agent_vimeo, 1964 'agent_private_notes': agent_private_notes, 1965 'agent_custom_label': agent_custom_label, 1966 'agent_custom_value': agent_custom_value, 1967 'acf_fields': JSON.stringify(acf_fields), 1968 'hubspot_api': hubspot_api, 1969 'security': nonce, 1970 1971 }, 1972 success: function (data) { 1973 1974 $('#profile_message').empty().append('<div class="login-alert">
1974' + data + '<div>'); 1975 window.scrollTo(0, 0); 1976 }, 1977 error: function (errorThrown) { 1978 } 1979 }); 1980 }); 1981 1982 1983 1984 $('#update_profile_agency').on('click', function () { 1985 1986 var hubspot_api, agency_opening_hours, agency_license, agency_long, agency_lat, agency_address, agency_area, agency_county, agency_city, agency_action_submit, agency_action_submit, agency_category_submit, agency_taxes, agency_website, agency_languages, agency_name, userurl, usermobile, userinstagram, userpinterest, userlinkedin, usertwitter, userfacebook, profile_image_url, profile_image_url_small, firstname, secondname, useremail, userphone, usertitle, description, ajaxurl, securityprofile, upload_picture; 1987 agency_name = $('#agency_title').val(); 1988 useremail = $('#useremail').val(); 1989 userphone = $('#userphone').val(); 1990 usermobile = $('#usermobile').val(); 1991 1992 description = $('#about_me').val(); 1993 userfacebook = $('#userfacebook').val(); 1994 usertwitter = $('#usertwitter').val(); 1995 userlinkedin = $('#userlinkedin').val(); 1996 userpinterest = $('#userpinterest').val(); 1997 userinstagram = $('#userinstagram').val(); 1998 1999 var useryoutube = $('#useryoutube').val(); 2000 var usertiktok = $('#usertiktok').val(); 2001 var usertelegram = $('#usertelegram').val(); 2002 var uservimeo = $('#uservimeo').val(); 2003 var agency_private_notes = $('#agency_private_notes').val(); 2004 2005 2006 2007 agency_languages = $('#agency_languages').val(); 2008 agency_website = $('#agency_website').val(); 2009 agency_taxes = $('#agency_taxes').val(); 2010 agency_license = $('#agency_license').val(); 2011 2012 2013 agency_category_submit = $('#agency_category_submit').val(); 2014 agency_action_submit = $('#agency_action_submit').val(); 2015 agency_city = $('#agency_city').val(); 2016 agency_county = $('#agency_county').val(); 2017 agency_area = $('#agency_area').val(); 2018 agency_address = $('#agency_address').val(); 2019 agency_lat = $('#agency_lat').val(); 2020 agency_long = $('#agency_long').val(); 2021 agency_opening_hours = $('#agency_opening_hours ').val(); 2022 hubspot_api = $('#hubspot_api ').val(); 2023 securityprofile = $('#security-profile').val(); 2024 upload_picture = $('#upload_picture').val(); 2025 profile_image_url = $('#profile-image').attr('data-profileurl'); 2026 profile_image_url_small = $('#profile-image').attr('data-smallprofileurl'); 2027 2028 var acf_fields = wpestate_return_form_acf_fields('.field-group'); 2029 2030 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 2031 2032 var nonce = jQuery('#wpestate_update_profile_nonce').val(); 2033 $('#profile_message').empty().append('<div class="login-alert">' + ajaxcalls_vars.saving + '<div>'); 2034 window.scrollTo(0, 0); 2035 $.ajax({ 2036 type: 'POST', 2037 url: ajaxurl, 2038 data: { 2039 'action': 'wpestate_ajax_update_profile_agency', 2040 'agency_name': agency_name, 2041 'useremail': useremail, 2042 'userphone': userphone, 2043 'usermobile': usermobile, 2044 'usertitle': usertitle, 2045 'description': description, 2046 'upload_picture': upload_picture, 2047 'security-profile': securityprofile, 2048 'profile_image_url': profile_image_url, 2049 'profile_image_url_small': profile_image_url_small, 2050 'userfacebook': userfacebook, 2051 'usertwitter': usertwitter, 2052 'userlinkedin': userlinkedin, 2053 'userpinterest': userpinterest, 2054 'userinstagram': userinstagram, 2055 'useryoutube':useryoutube, 2056 'usertiktok':usertiktok, 2057 'usertelegram':usertelegram, 2058 'uservimeo':uservimeo, 2059 'agency_private_notes':agency_private_notes, 2060 'userurl': userurl, 2061 'agency_languages': agency_languages, 2062 'agency_website': agency_website, 2063 'agency_taxes': agency_taxes, 2064 'agency_license': agency_license, 2065 'agency_category_submit': agency_category_submit, 2066 'agency_action_submit': agency_action_submit, 2067 'agency_city': agency_city, 2068 'agency_county': agency_county, 2069 'agency_area': agency_area, 2070 'agency_address': agency_address, 2071 'agency_lat': agency_lat, 2072 'agency_opening_hours': agency_opening_hours, 2073 'agency_long': agency_long, 2074 'hubspot_api': hubspot_api, 2075 'acf_fields': JSON.stringify(acf_fields), 2076 'security': nonce 2077 }, 2078 success: function (data) { 2079 $('#profile_message').empty().append('<div class="login-alert">
2079' + data + '<div>'); 2080 window.scrollTo(0, 0); 2081 }, 2082 error: function (errorThrown) { 2083 console.log(errorThrown); 2084 } 2085 }); 2086 }); 2087 2088 2089 2090// update developer profile 2091 $('#update_profile_developer').on('click', function () { 2092 2093 var hubspot_api, developer_license, developer_long, developer_lat, developer_address, developer_area, developer_county, developer_city, developer_action_submit, developer_action_submit, developer_category_submit, developer_taxes, developer_website, developer_languages, developer_name, userurl, usermobile, userinstagram, userpinterest, userlinkedin, usertwitter, userfacebook, profile_image_url, profile_image_url_small, firstname, secondname, useremail, userphone, usertitle, description, ajaxurl, securityprofile, upload_picture; 2094 developer_name = $('#developer_title').val(); 2095 useremail = $('#useremail').val(); 2096 userphone = $('#userphone').val(); 2097 usermobile = $('#usermobile').val(); 2098 2099 description = $('#about_me').val(); 2100 userfacebook = $('#userfacebook').val(); 2101 usertwitter = $('#usertwitter').val(); 2102 userlinkedin = $('#userlinkedin').val(); 2103 userpinterest = $('#userpinterest').val(); 2104 userinstagram = $('#userinstagram').val(); 2105 2106 2107 var useryoutube = $('#useryoutube').val(); 2108 var usertiktok = $('#usertiktok').val(); 2109 var usertelegram = $('#usertelegram').val(); 2110 var uservimeo = $('#uservimeo').val(); 2111 var developer_private_notes = $('#developer_private_notes').val(); 2112 2113 2114 2115 developer_languages = $('#developer_languages').val(); 2116 developer_website = $('#developer_website').val(); 2117 developer_taxes = $('#developer_taxes').val(); 2118 developer_license = $('#developer_license').val(); 2119 2120 2121 developer_category_submit = $('#developer_category_submit').val(); 2122 developer_action_submit = $('#developer_action_submit').val(); 2123 developer_city = $('#developer_city').val(); 2124 developer_county = $('#developer_county').val(); 2125 developer_area = $('#developer_area').val(); 2126 developer_address = $('#developer_address').val(); 2127 developer_lat = $('#developer_lat').val(); 2128 developer_long = $('#developer_long').val(); 2129 securityprofile = $('#security-profile').val(); 2130 upload_picture = $('#upload_picture').val(); 2131 profile_image_url = $('#profile-image').attr('data-profileurl'); 2132 profile_image_url_small = $('#profile-image').attr('data-smallprofileurl'); 2133 hubspot_api = $('#hubspot_api').val(); 2134 2135 var acf_fields = wpestate_return_form_acf_fields('.field-group'); 2136 2137 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 2138 var nonce = jQuery('#wpestate_update_profile_nonce').val(); 2139 $('#profile_message').empty().append('<div class="login-alert">' + ajaxcalls_vars.saving + '<div>'); 2140 window.scrollTo(0, 0); 2141 $.ajax({ 2142 type: 'POST', 2143 url: ajaxurl, 2144 data: { 2145 'action': 'wpestate_ajax_update_profile_developer', 2146 'developer_name': developer_name, 2147 'useremail': useremail, 2148 'userphone': userphone, 2149 'usermobile': usermobile, 2150 'usertitle': usertitle, 2151 'description': description, 2152 'upload_picture': upload_picture, 2153 'security-profile': securityprofile, 2154 'profile_image_url': profile_image_url, 2155 'profile_image_url_small': profile_image_url_small, 2156 'userfacebook': userfacebook, 2157 'usertwitter': usertwitter, 2158 'userlinkedin': userlinkedin, 2159 'userpinterest': userpinterest, 2160 'userinstagram': userinstagram, 2161 'userurl': userurl, 2162 'developer_languages': developer_languages, 2163 'developer_website': developer_website, 2164 'developer_taxes': developer_taxes, 2165 'developer_license': developer_license, 2166 'developer_category_submit': developer_category_submit, 2167 'developer_action_submit': developer_action_submit, 2168 'developer_city': developer_city, 2169 'developer_county': developer_county, 2170 'developer_area': developer_area, 2171 'developer_address': developer_address, 2172 'developer_lat': developer_lat, 2173 'developer_long': developer_long, 2174 'hubspot_api': hubspot_api, 2175 'useryoutube':useryoutube, 2176 'usertiktok':usertiktok,
2177 'usertelegram':usertelegram, 2178 'uservimeo':uservimeo, 2179 'developer_private_notes':developer_private_notes, 2180 'acf_fields': JSON.stringify(acf_fields), 2181 'security': nonce 2182 }, 2183 success: function (data) { 2184 $('#profile_message').empty().append('<div class="login-alert">' + data + '<div>'); 2185 window.scrollTo(0, 0); 2186 }, 2187 error: function (errorThrown) { 2188 } 2189 }); 2190 }); 2191 2192 //delete profile 2193 2194 $('#delete_profile').on('click', function (event) { 2195 var ajaxurl; 2196 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 2197 var nonce = jQuery('#wpestate_update_profile_nonce').val(); 2198 var result = confirm(ajaxcalls_vars.delete_account); 2199 if (result) { 2200 //Logic to delete the item 2201 2202 $.ajax({ 2203 type: 'POST', 2204 url: ajaxurl, 2205 data: { 2206 'action': 'wpestate_delete_profile', 2207 'security': nonce, 2208 }, 2209 success: function (data) { 2210 window.location = '/'; 2211 }, 2212 error: function (errorThrown) { 2213 2214 } 2215 }); 2216 } 2217 }); 2218 2219 //end delete profile 2220 2221}); // end ready jquery 2222//End ready ******************************************************************** 2223 2224 2225/** 2226 * Handles the loading of agency/developer listings via AJAX. 2227 * This function is triggered when a user clicks on a term bar item. 2228 */ 2229function wpestate_load_agency_developer_listings() { 2230 jQuery('.term_bar_item, .listing_load_more').on('click', function (event) { 2231 2232 2233 // Select relevant DOM elements 2234 var $this = jQuery(this); 2235 var $listingParent = $this.parents('.single_listing_block'); 2236 var listings_per_page= $listingParent.attr('data-listings_per_page'); 2237 var rownumber= $listingParent.attr('data-rownumber'); 2238 2239 var $loadMoreButton = jQuery('.load_more_ajax_cont .listing_load_more', $listingParent); 2240 var $agencyListingsWrapper = jQuery('.agency_listings_wrapper'); 2241 var $listingLoader = jQuery('#listing_loader'); 2242 var $termBarWrapper = jQuery('.term_bar_wrapper'); 2243 var $areadyLoadedItems = jQuery('.listing_wrapper', $listingParent).length; 2244 2245 var $page_with_sidebar = 0; 2246 if(jQuery('#primary_sidebar_wrapper').length > 0){ 2247 $page_with_sidebar = 1; 2248 } 2249 2250 // Display load more button 2251 $loadMoreButton.fadeIn(); 2252 2253 2254 // Perform AJAX request 2255 if(!$this.hasClass('listing_load_more')){ 2256 //$agencyListingsWrapper.empty(); 2257 $areadyLoadedItems=0; 2258 2259 // Update active term styling 2260 jQuery('.term_bar_item').removeClass('active_term'); 2261 $this.addClass('active_term'); 2262 2263 } 2264 2265 2266 2267 2268 var $active_tab = jQuery('.active_term', $listingParent); 2269 var term_name = jQuery($active_tab).attr('data-term_name'); 2270 2271 2272 2273 // Prepare AJAX data 2274 var ajaxData = { 2275 action: 'wpestate_agency_listings', 2276 listings_per_page:listings_per_page, 2277 rownumber:rownumber, 2278 term_name: $this.attr('data-term_name'), 2279 agency_id: $termBarWrapper.attr('data-agency_id'), 2280 agent_id: $termBarWrapper.attr('data-agent_id'), 2281 post_id: $termBarWrapper.attr('data-post_id'), 2282 term_name: term_name, 2283 loaded: $areadyLoadedItems, 2284 is_agency: jQuery('.single-estate_agency').length > 0 ? 1 : 0, 2285 page_with_sidebar: $page_with_sidebar, 2286 security: jQuery('#wpestate_developer_listing_nonce').val() 2287 }; 2288 2289 2290 2291 2292 2293 const listingContainer = jQuery('.agency_listings_wrapper'); 2294 2295 if(!$this.hasClass('listing_load_more')){ 2296 wpestate_createSkeletons(listingContainer); 2297 }else{ 2298 wpestate_createSkeletons(listingContainer,true); 2299 } 2300 2301 // $listingLoader.show(); 2302 2303 jQuery.ajax({ 2304 type: 'POST', 2305 url: ajaxcalls_vars.admin_url + 'admin-ajax.php', 2306 data: ajaxData, 2307 dataType: 'json', 2308 success: function (response) { 2309 $listingLoader.hide(); 2310 if (response.success) { 2311 2312 if(response.data.found_posts > 0){ 2313 if(!$this.hasClass('listing_load_more')){ 2314 //$agencyListingsWrapper.html(response.data.html); 2315 wpestate_replaceSkeletons(listingContainer, response.data.html); 2316 2317 }else{ 2318 2319 //$agencyListingsWrapper.append(response.data.html); 2320 wpestate_replaceSkeletons(listingContainer,response.data.html); 2321 2322 } 2323 2324 wpestate_restart_js_after_ajax(); 2325 }else{ 2326 //$agencyListingsWrapper.append(response.data.html); 2327 wpestate_replaceSkeletons(listingContainer,response.data.html); 2328 if($this.hasClass('listing_load_more')){ 2329 $this.hide(); 2330 } 2331 } 2332 2333 2334 2335 } else { 2336 $agencyListingsWrapper.html('<p>' + response.data.message + '</p>'); 2337 } 2338 }, 2339 error: function (jqXHR, textStatus, errorThrown) { 2340 console.error('AJAX request failed:', textStatus, errorThrown); 2341 $listingLoader.hide(); 2342 $agencyListingsWrapper.html('<p>Error loading listings. Please try again.</p>'); 2343 } 2344 }); 2345 }); 2346} 2347 2348 2349function wpestate_add_to_favorites() { 2350 2351 2352 jQuery('#add_favorites').on('click', function (event) { 2353 2354 var post_id, ajaxurl; 2355 post_id = jQuery('#add_favorites').attr('data-postid'); 2356 var icon = jQuery('#add_favorites'); 2357 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 2358 var nonce = jQuery('#wpestate_ajax_filtering').val(); 2359 var use_favorite_login = ajaxcalls_vars.favorites_login; 2360 if(use_favorite_login=="no"){ 2361 wpestate_add_remove_favorite_local_storage_single(icon,post_id); 2362 return; 2363 } 2364 2365 2366 2367 if (parseInt(ajaxcalls_vars.userid, 10) === 0) { 2368 if (!Modernizr.mq('only all and (max-width: 768px)')) { 2369 jQuery('#modal_login_wrapper').show(); 2370 jQuery('#modal_login_wrapper').find('[autofocus]').focus(); 2371 jQuery('.loginpop').val('1'); 2372 } else { 2373 jQuery('.mobile-trigger-user').trigger('click'); 2374 } 2375 2376 } else { 2377 jQuery('#add_favorites').text(ajaxcalls_vars.saving); 2378 jQuery.ajax({ 2379 type: 'POST', 2380 url: ajaxurl, 2381 dataType: 'json', 2382 data: { 2383 'action': 'wpestate_ajax_add_fav', 2384 'post_id': post_id, 2385 'security': nonce 2386 }, 2387 success: function (data) { 2388 if (data.added) { 2389 jQuery('#add_favorites').removeClass('isnotfavorite').addClass('isfavorite').attr('title', ajaxcalls_vars.remove_favorite); 2390 jQuery('#add_favorites').html('<i class="fas fa-heart"></i>' + ajaxcalls_vars.favorite); 2391 2392 // Refresh the Bootstrap tooltip if it exists 2393 if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip) { 2394 var tooltipInstance = bootstrap.Tooltip.getInstance(icon[0]); 2395 if (tooltipInstance) { 2396 tooltipInstance.setContent({ 2397 '.tooltip-inner': ajaxcalls_vars.remove_fav 2398 }); 2399 } 2400 } 2401 2402 2403 } else { 2404 jQuery('#add_favorites').removeClass('isfavorite').addClass('isnotfavorite').attr('title', ajaxcalls_vars.add_favorite); 2405 jQuery('#add_favorites').html('<i class="far fa-heart"></i>' + ajaxcalls_vars.favorite); 2406 2407 // Refresh the Bootstrap tooltip if it exists 2408 if (typeof bootstrap !== 'undefined' && bootstrap.Tooltip) { 2409 var tooltipInstance = bootstrap.Tooltip.getInstance(icon[0]); 2410 if (tooltipInstance) { 2411 tooltipInstance.setContent({ 2412 '.tooltip-inner': ajaxcalls_vars.remove_fav 2413 }); 2414 } 2415 } 2416 2417 } 2418 }, 2419 error: function (errorThrown) { 2420 } 2421 }); //end ajax 2422 }// end check login 2423 }); 2424} 2425
2426/////////////////////////////////////////////////////////////////////////////////////////// 2427/////// Property page + ajax call on contact 2428/////////////////////////////////////////////////////////////////////////////////////////// 2429function wpestate_theme_slider_show_contact() { 2430 jQuery('.wpestate_theme_slider_contact_agent').on('click', function () { 2431 var acesta = jQuery(this).parent().parent(); 2432 acesta.find('#show_contact').text(ajaxcalls_vars.contact_agent); 2433 acesta.find('.theme_slider_contact_form_wrapper').show('0').toggleClass('theme_slider_contact_form_wrapper_visible'); 2434 jQuery('#estate-carousel').carousel('pause'); 2435 2436 }); 2437 2438 2439 2440 jQuery('.theme_slider_details_modal_close').on('click', function () { 2441 jQuery(this).parent().removeClass('theme_slider_contact_form_wrapper_visible'); 2442 jQuery('#estate-carousel').carousel('cycle'); 2443 }); 2444 2445 jQuery('.theme_slider_contact_form_wrapper').on('click', function (event) { 2446 event.stopPropagation(); 2447 }); 2448 2449 2450} 2451 2452 2453/** 2454 * Enable Schedule Contact Functionality 2455 * 2456 * This function sets up event handlers for the schedule meeting functionality 2457 * and initializes the datepicker for schedule day selection. 2458 * 2459 * @package WpResidence 2460 * @subpackage PropertyDetails 2461 * @since 3.0.3 2462 * 2463 * Dependencies: 2464 * - jQuery 2465 * - jQuery UI Datepicker 2466 * 2467 * Usage: Call this function after DOM is ready and dependencies are loaded. 2468 */ 2469 2470function wpestate_enable_schedule_contact() { 2471 // Toggle schedule wrapper visibility when clicking on schedule meeting button 2472 jQuery('.schedule_meeting').on('click', function (event) { 2473 var parent = jQuery(this).parent().parent(); 2474 var scheduleWrapper = parent.find('.schedule_wrapper'); 2475 2476 scheduleWrapper.slideToggle(400, function() { 2477 scheduleWrapper.css('display', scheduleWrapper.is(':visible') ? 'flex' : 'none'); 2478 }); 2479 }); 2480 2481 2482 2483 // Initialize datepicker for schedule day input with position correction 2484 jQuery(".schedule_day, #schedule_day").datepicker({ 2485 dateFormat: "yy-mm-dd", 2486 beforeShow: function(input, inst) { 2487 // Position correction 2488 setTimeout(function() { 2489 inst.dpDiv.css({ 2490 position: 'absolute', 2491 top: jQuery(input).offset().top + jQuery(input).outerHeight(), 2492 left: jQuery(input).offset().left 2493 }); 2494 }, 0); 2495 } 2496 }).datepicker('widget').wrap('<div class="ll-skin-melon"/>'); 2497} 2498 2499 2500function wpestate_agent_submit_email() { 2501 jQuery('.wpresidence_elementor_form').on('submit', function (event) { 2502 event.preventDefault(); 2503 var form_submit = jQuery('.wpresidence_elementor_form').find('.agent_submit_class_elementor'); 2504 process_form_submit(form_submit); 2505 }); 2506 2507 jQuery('.agent_submit_class').on('click', function (event) { 2508 process_form_submit(jQuery(this)); 2509 }); 2510 2511 jQuery('.message_submit').on('click', function (event) { 2512 process_form_submit(jQuery(this)); 2513 }); 2514} 2515 2516 2517function process_form_submit(form_submit) { 2518 2519 var parent, contact_name, contact_email, contact_phone, contact_coment, agent_id, property_id, nonce, ajaxurl; 2520 parent = form_submit.closest('.wpestate_contact_form_parent'); 2521 2522 var is_private_message='no'; 2523 if(form_submit.hasClass('message_submit')){ 2524 is_private_message='yes'; 2525 } 2526 2527 2528 contact_name = parent.find('#agent_contact_name').val(); 2529 contact_email = parent.find('#agent_user_email').val(); 2530 contact_phone = parent.find('#agent_phone').val(); 2531 contact_intent = parent.find('#agent_contact_intent input[name="contact_intent"]').val() || ''; 2532 contact_coment = parent.find('#agent_comment').val(); 2533 agent_id = parent.find('#agent_id').val(); 2534 property_id = parent.find('#agent_property_id').val(); 2535 2536 nonce = parent.find('#agent_property_ajax_nonce').val(); 2537 ajaxurl = ajaxcalls_vars.admin_url + 'admin-ajax.php'; 2538 2539 var schedule_day = parent.find('.schedule_day').val(); 2540 var schedule_hour = parent.find('.schedule_hour').val(); 2541 var schedule_mode ='in_person'; 2542 2543 2544 2545 if( parent.hasClass('wpestate_schedule_tour_wrapper_content') || 2546 parent.hasClass('wpestate_shedule_tour_wrapper_type2') || 2547 parent.hasClass('wpestate_schedule_tour_wrapper') ){ 2548 2549 schedule_day = parent.find('.shedule_day_option_selected').attr('data-scheudle-day'); 2550 schedule_hour = parent.find('#wpestate_schedule_tour_time').val(); 2551 2552 var schedule_mode_button = parent.find('.shedule_option_selected'); 2553 if( schedule_mode_button.hasClass('schedule_video_chat') ){ 2554 schedule_mode ='video_chat'; 2555 } 2556 } 2557 2558 2559 var is_elementor = 0; 2560 if (form_submit.parents('.wpresidence_elementor_form').length) { 2561 parent = form_submit.parents('.wpresidence_elementor_form'); 2562 contact_name = parent.find('#form-field-name').val(); 2563 contact_email = parent.find('#form-field-email').val(); 2564 contact_coment = parent.find('#form-field-message').val(); 2565 contact_phone = parent.find('input[name="phone"]').val(); 2566 nonce = parent.find('#agent_property_ajax_nonce').val(); 2567 is_elementor = parent.find('#contact_form_elementor').val(); 2568 var wpresidence_form_id = parent.find('#wpresidence_form_id').val(); 2569 var elementor_email_subject = parent.find('#elementor_email_subject').val(); 2570 2571 var temp_details; 2572 temp_details = ''; 2573 var elementor_form = form_submit.parents('.wpresidence_elementor_form'); 2574 var form_items = elementor_form.find('.elementor-field'); 2575 var label_name =''; 2576 var labelElement; 2577 form_items.each(function () { 2578 2579 labelElement=jQuery(this).parent().find('.elementor-field-label'); 2580 2581 if (labelElement.length > 0) { 2582 label_name = labelElement.text(); 2583 label_name = label_name.replace('*', ''); 2584 } else { 2585 // Convert field ID to human-readable name (e.g. inquiry_type â Inquiry Type) 2586 // Some .elementor-field elements (e.g. dropdown buttons) have no name attribute 2587 label_name = jQuery(this).attr('name') || ''; 2588 label_name = label_name.replace(/_/g, ' ').replace(/\b\w/g, function(c){ return c.toUpperCase(); }); 2589 } 2590
2591 // Skip fields with no label and no value to avoid stray ":" in email 2592 var field_val = jQuery(this).val() || ''; 2593 label_name = label_name.trim(); 2594 if (label_name === '' && field_val === '') { 2595 return; 2596 } 2597 2598 temp_details = temp_details + label_name + ": " + field_val + "/n"; 2599 }); 2600 2601 contact_coment = temp_details ; 2602 2603 } 2604 2605 if (parent.find('.wpestate_agree_gdpr').length > 0) { 2606 if (!parent.find('.wpestate_agree_gdpr').is(':checked')) { 2607 parent.find('#alert-agent-contact').empty().append(ajaxcalls_vars.gdpr_terms); 2608 return; 2609 } 2610 } 2611 2612 // Validate required fields â check all inputs/textareas with data-required attribute 2613 // We use data-required instead of HTML5 required to show custom per-field messages 2614 var validationFailed = false; 2615 var firstInvalidField = null; 2616 2617 parent.find('[data-required="true"]').each(function () { 2618 var field = jQuery(this); 2619 var fieldValue = field.val(); 2620 2621 // Check if empty (trim whitespace for text inputs) 2622 if (!fieldValue || fieldValue.trim() === '') { 2623 // Get the custom validation message from data attribute, or fall back to generic 2624 var customMessage = field.data('validation-message') || 'This field is required'; 2625 2626 // Show the error message in the alert area 2627 if (!validationFailed) { 2628 parent.find('#alert-agent-contact').empty().append(customMessage); 2629 firstInvalidField = field; 2630 } 2631 validationFailed = true; 2632 2633 // Highlight the field group with red border error styling 2634 field.closest('.elementor-field-group').addClass('elementor-field-error'); 2635 } else { 2636 // Remove error highlight if field is filled 2637 field.closest('.elementor-field-group').removeClass('elementor-field-error'); 2638 } 2639 }); 2640 2641 // Stop submission if any required field is empty 2642 if (validationFailed) { 2643 // Bind one-time listeners to clear red border when user starts filling a field 2644 parent.find('.elementor-field-error').each(function () { 2645 var fieldGroup = jQuery(this); 2646 2647 // Clear error on text input/textarea focus or typing 2648 fieldGroup.find('input, textarea').one('input focus', function () { 2649 fieldGroup.removeClass('elementor-field-error'); 2650 }); 2651 2652 // Clear error on dropdown selection (hidden input value change) 2653 fieldGroup.find('input[type="hidden"]').one('change', function () { 2654 fieldGroup.removeClass('elementor-field-error'); 2655 }); 2656 }); 2657 return; 2658 } 2659 2660 parent.find('#alert-agent-contact').empty().append(ajaxcalls_vars.sending); 2661 2662 jQuery.ajax({ 2663 type: 'POST', 2664 dataType: 'json', 2665 url: ajaxurl, 2666 data: { 2667 'action': 'wpestate_ajax_agent_contact_form', 2668 'name': contact_name, 2669 'email': contact_email, 2670 'phone': contact_phone, 2671 'contact_intent': contact_intent, 2672 'comment': contact_coment, 2673 'agent_id': agent_id, 2674 'propid': property_id, 2675 'schedule_day': schedule_day, 2676 'schedule_hour': schedule_hour, 2677 'schedule_mode':schedule_mode, 2678 'elementor_wpresidence_form_id': wpresidence_form_id, 2679 'elementor_email_subject': elementor_email_subject, 2680 'is_elementor': is_elementor, 2681 'is_private_message':is_private_message, 2682 'nonce': nonce 2683 }, 2684 success: function (data) { 2685 2686 if (data.sent) { 2687 parent.find('#agent_contact_name').val(''); 2688 parent.find('#agent_user_email').val(''); 2689 parent.find('#agent_phone').val(''); 2690 parent.find('#agent_comment').val(''); 2691 parent.find('#agent_contact_intent input[name="contact_intent"]').val(''); 2692 parent.find('#agent_contact_intent .dropdown-toggle').text(parent.find('#agent_contact_intent').data('placeholder') || ''); 2693 parent.find('.schedule_day').val(''); 2694 parent.find('#schedule_hour').val(''); 2695 parent.find('#alert-agent-contact').addClass(' wpestate-agent-contact-sent ').empty().append(data.response); 2696 2697 2698 if (typeof (form_items) !== 'undefined') { 2699 form_items.each(function () { 2700 jQuery(this).val(''); 2701 }); 2702 } 2703 2704 // Redirect after form submission if a redirect URL is configured 2705 var redirectUrl = parent.find('input[name="redirect_url"]').val(); 2706 if (redirectUrl && redirectUrl.length > 0) { 2707 setTimeout(function() { 2708 window.location.href = redirectUrl; 2709 }, 1000); 2710 } 2711 2712 } else { 2713 parent.find('#alert-agent-contact').empty().append(data.response); 2714 } 2715 2716 }, 2717 error: function (errorThrown) { 2718 2719 } 2720 }); 2721 2722 2723 2724 jQuery.ajax({ 2725 type: 'POST', 2726 // dataType: 'json', 2727 url: ajaxurl, 2728 data: { 2729 'action': 'wpestate_ajax_agent_contact_form_forcrm', 2730 'name': contact_name, 2731 'email': contact_email, 2732 'phone': contact_phone, 2733 'contact_intent': contact_intent, 2734 'comment': contact_coment, 2735 'agent_id': agent_id, 2736 'propid': property_id, 2737 'schedule_day': schedule_day, 2738 'schedule_hour': schedule_hour, 2739 'schedule_mode':schedule_mode, 2740 'nonce': nonce 2741 }, 2742 success: function (data) { 2743 }, 2744 error: function (errorThrown) { 2745 2746 } 2747 }); 2748 2749 2750} 2751 2752 2753/////////////////////////////////////////////////////////////////////////////////////////// 2754/////// Property page + ajax call on contact 2755/////////////////////////////////////////////////////////////////////////////////////////// 2756 2757 2758function wpestate_enable_share_unit(){ 2759 2760 jQuery('.share_list').unbind('click'); 2761 jQuery('.share_list').on( 'click', function(event) { 2762 event.stopPropagation(); 2763 var sharediv=jQuery(this).parent().find('.share_unit');
2764 sharediv.toggle(); 2765 jQuery(this).toggleClass('share_on'); 2766 }); 2767 2768} 2769 2770function setCookie(cname, cvalue, exdays) { 2771 const d = new Date(); 2772 d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); 2773 let expires = "expires="+d.toUTCString(); 2774 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; 2775 } 2776 2777 2778function wpestate_enable_not_logged_favorites(){ 2779 2780 var use_favorite_login = ajaxcalls_vars.favorites_login; 2781 2782 if(use_favorite_login=="yes"){ 2783 return; 2784 } 2785 2786 var current_favorites = window.localStorage.getItem('wpestate_favorites'); 2787 setCookie('wpestate_favorites',current_favorites,10); 2788 var prop_ids=''; 2789 2790 if( current_favorites!==null ){ 2791 prop_ids = jQuery.map(current_favorites.split(','), function(value){ 2792 return parseInt(value); 2793 }); 2794 } 2795 2796 jQuery('.icon-fav').each(function(){ 2797 var icon=jQuery(this); 2798 var property_id=icon.attr('data-postid'); 2799 property_id=parseInt(property_id); 2800 var index = prop_ids.indexOf( property_id ); 2801 2802 if (index > -1) { 2803 icon.removeClass('icon-fav-off').addClass('icon-fav-on'); 2804 icon.attr('title', ajaxcalls_vars.remove_fav); 2805 2806 }else{ 2807 icon.removeClass('icon-fav-on').addClass('icon-fav-off'); 2808 icon.attr('title', ajaxcalls_vars.add_favorite); 2809 2810 } 2811 }) 2812 2813 2814 if(jQuery('#add_favorites').length>0){ 2815 var property_id=jQuery('#add_favorites').attr('data-postid'); 2816 property_id=parseInt(property_id); 2817 var index = prop_ids.indexOf( property_id ); 2818 2819 if (index > -1) { 2820 jQuery('#add_favorites').removeClass('isnotfavorite').addClass('isfavorite').attr('title', ajaxcalls_vars.remove_favorite); 2821 jQuery('#add_favorites').html('<i class="fas fa-heart"></i>' + ajaxcalls_vars.favorite); 2822 2823 } 2824 } 2825 2826} 2827 2828 2829 2830/** 2831 * Returns ACF fields from a given container. 2832 * 2833 * This function collects input, textarea, and select elements within the specified container 2834 * and returns an Array containing their values, formatted according to ACF field naming conventions. 2835 * 2836 * @param {string} container - The CSS selector for the container to search within. 2837 * @returns {Array} acf_fields - An Array containing ACF field names and their corresponding values. 2838 */ 2839function wpestate_return_form_acf_fields( container = '') { 2840 2841 var acf_fields = {}; 2842 2843 if ( !jQuery(container).length ) { 2844 return acf_fields; 2845 } 2846 2847 jQuery(container).find('input, textarea, select').each(function() { 2848 var $field = jQuery(this); 2849 var fieldName = $field.attr('name'); 2850 2851 if (!fieldName || !fieldName.startsWith('acf_fields[')) { 2852 return; 2853 } 2854 2855 // Extract field name from acf_fields[field_name] format 2856 var matches = fieldName.match(/acf_fields\[([^\]]+)\]/); 2857 if (!matches) { 2858 return; 2859 } 2860 2861 var cleanFieldName = matches[1]; 2862 2863 if ($field.is(':checkbox')) { 2864 // Handle checkboxes 2865 if ($field.attr('name').includes('[]')) { 2866 // Multiple checkboxes (checkbox field type) 2867 if (!acf_fields[cleanFieldName]) { 2868 acf_fields[cleanFieldName] = []; 2869 } 2870 if ($field.is(':checked')) { 2871 acf_fields[cleanFieldName].push($field.val()); 2872 } 2873 } else { 2874 // Single checkbox (true/false field type) 2875 acf_fields[cleanFieldName] = $field.is(':checked') ? $field.val() : ''; 2876 } 2877 } else if ($field.is(':radio')) { 2878 // Handle radio buttons 2879 if ($field.is(':checked')) { 2880 acf_fields[cleanFieldName] = $field.val(); 2881 } 2882 } else { 2883 // Handle other input types 2884 acf_fields[cleanFieldName] = $field.val(); 2885 } 2886 }); 2887 return acf_fields; 2888} 2889 2890 2891/** 2892 * Bootstrap dropdown click handler for Elementor contact form fields. 2893 * Uses the same <li role="presentation" data-value="..."> pattern as search form dropdowns. 2894 * When a dropdown <li> is clicked, updates the sibling hidden input value 2895 * and changes the dropdown button text to reflect the selection. 2896 */ 2897jQuery(document).on('click', '.wpresidence_elementor_form .wpresidence-dropdown-field .filter_menu li', function(e) { 2898 e.preventDefault(); 2899 2900 var selectedValue = jQuery(this).data('value'); 2901 var selectedText = jQuery(this).text(); 2902
2903 // Find the dropdown wrapper that contains this <li> 2904 var dropdownWrapper = jQuery(this).closest('.wpresidence-dropdown-field'); 2905 2906 // If "all" is selected, clear the hidden input value 2907 if (selectedValue === 'all') { 2908 dropdownWrapper.find('input[type="hidden"].elementor-field').val('').trigger('change'); 2909 } else { 2910 dropdownWrapper.find('input[type="hidden"].elementor-field').val(selectedValue).trigger('change'); 2911 } 2912 2913 // Update the dropdown button text to show the current selection 2914 dropdownWrapper.find('.dropdown-toggle').text(selectedText); 2915}); 2916 2917 2918/** 2919 * Bootstrap dropdown click handler for contact intent fields. 2920 * Updates the hidden input value and button text when user selects an option. 2921 */ 2922jQuery(document).on('click', '.contact_intent_dropdown_wrapper .filter_menu li', function(e) { 2923 e.preventDefault(); 2924 2925 var selectedValue = jQuery(this).data('value'); 2926 var selectedText = jQuery(this).text(); 2927 var wrapper = jQuery(this).closest('.contact_intent_dropdown_wrapper'); 2928 2929 // Update hidden input value and button label 2930 wrapper.find('input[name="contact_intent"]').val(selectedValue).trigger('change'); 2931 wrapper.find('.dropdown-toggle').text(selectedText); 2932});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.