function opt_in(nonce) { clear_breeze().then(function () { jQuery.ajax({ url: local_data.ajax_url, // WordPress AJAX handler URL type: 'POST', data: { action: 'opt_in_handler', nonce: nonce, }, success: function (response) { // Handle the response from the server location.reload(); }, error: function (xhr, status, error) { console.error('Error:', error); alert('An error occurred while processing your request. Please try again later.'); }, }); }); }; function opt_out(nonce) { clear_breeze().then(function () { jQuery.ajax({ url: local_data.ajax_url, // WordPress AJAX handler URL type: 'POST', data: { action: 'opt_out_handler', nonce: nonce, }, success: function (response) { // Handle the response from the server location.reload(); }, error: function (xhr, status, error) { // Handle any errors that occurred during the request console.error('Error:', error); alert('An error occurred while processing your request. Please try again later.'); }, }); }); } function clear_breeze() { let breeze_key; // make sure we have a cache key set in local_data: if (typeof local_data !== 'undefined' && local_data.hasOwnProperty('breeze_key') && local_data.breeze_key) { breeze_key = local_data.breeze_key; } else { console.error('No breeze key found in local_data.'); return Promise.resolve(); } return jQuery.ajax({ url: '/wp-json/breeze/v1/clear-all-cache', type: 'POST', data: { key: breeze_key, }, success: function (response) { console.log(response); }, }); } function open_msg_form(event) { let clicked = jQuery(event.target); if (!clicked.hasClass('contact')) { clicked = clicked.parents('.contact'); } let uid = clicked.attr('uid'); jQuery.colorbox({ href: '#contact_form', inline: true, }); jQuery('#contact_form input[name=uid]').val(uid); } jQuery(document).on('click', '.contact', open_msg_form); jQuery(document).on('click', '#send_message_button', send_message); function send_message(event) { event.preventDefault(); let ajax_url = local_data['ajax_msg_url']; let nonce = local_data['nonce']; let to_uid = jQuery('#contact_form input[name=uid]').val(); let message_subject = jQuery('#contact_form input[name=message_subject]').val(); let message_body = jQuery('#contact_form textarea[name=message_body]').val(); if (message_subject == '' || message_body == '') { alert('Please enter a subject and message.'); return; } let data = { action: 'send_message', to_uid: to_uid, message_subject: message_subject, message_body: message_body, nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { // Handle the response from the server jQuery.colorbox.close(); jQuery('#contact_form input[name=message_subject]').val(''); jQuery('#contact_form textarea[name=message_body]').val(''); jQuery('#contact_form input[name=uid]').val(''); }, }); } // contact interaction functions jQuery(document).on('click', '.contacts-header', function (event) { jQuery('.contact-requests-container').toggle(); clear_contact_request_alert_count(); }); jQuery(document).on('click', '.request_contact', request_contact); function request_contact(event) { event.preventDefault(); let confirm_trigger = jQuery('.confirm_first_request_trigger'); let show_confirm = confirm_trigger.length > 0; if (show_confirm) { if ( confirm( 'Requesting the contact info will also share your email address with the user. Are you sure you want to proceed?' ) ) { confirm_trigger.remove(); } else { return; } } let ajax_url = local_data['ajax_url']; let nonce = local_data['nonce']; let clicked = jQuery(event.target); if (!clicked.hasClass('request_contact')) { clicked = clicked.parents('.request_contact'); } let request_uid = clicked.attr('uid'); let data = { action: 'request_contact', request_uid: request_uid, nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { if (response['message'] != undefined) { alert(response['message']); } else { handle_response(jQuery(), response); alert('Your request has been sent.'); } }, }); } jQuery(document).on('click', '.approve_contact', approve_contact); function approve_contact(event) { event.preventDefault(); let ajax_url = local_data['ajax_url']; let nonce = local_data['nonce']; let clicked = jQuery(event.target); if (!clicked.hasClass('approve_contact')) { clicked = clicked.parents('.approve_contact'); } let request_uid = clicked.attr('uid'); let data = { action: 'approve_contact', request_uid: request_uid, nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { let blocked = clicked.parents('.blocked_sect').length > 0; handle_response(clicked, response); // If clicked is in the blocked section, change alert text if (blocked) { alert('You have unblocked the contact.'); } else { alert('You have approved the request.'); } maintain_blocked_sect(); }, }); } function maintain_blocked_sect() { let blocked_requests = jQuery('.blocked_sect').find('.contact-request'); if (blocked_requests.length > 0) { jQuery('.blocked_sect').show(); } else { jQuery('.blocked_sect').hide(); } } jQuery(document).on('click', '.cancel_request', cancel_request); function cancel_request(event) { event.preventDefault(); if (!confirm('Are you sure you want to cancel this request?')) { return; } let ajax_url = local_data['ajax_url']; let nonce = local_data['nonce']; let clicked = jQuery(event.target); if (!clicked.hasClass('cancel_request')) { clicked = clicked.parents('.cancel_request'); } let request_uid = clicked.attr('uid'); let data = { action: 'cancel_request', request_uid: request_uid, nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { if (response['message'] != undefined) { alert(response['message']); handle_response(clicked, response); } else { clicked.parents('.contact-request').remove(); alert('The request has been cancelled.'); } }, }); } jQuery(document).on('click', '.ignore_contact', ignore_contact); function ignore_contact(event) { event.preventDefault(); let ajax_url = local_data['ajax_url']; let nonce = local_data['nonce']; let clicked = jQuery(event.target); if (!clicked.hasClass('ignore_contact')) { clicked = clicked.parents('.ignore_contact'); } let request_uid = clicked.attr('uid'); let data = { action: 'ignore_contact', request_uid: request_uid, nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { jQuery('.ignored_sect').show(); handle_response(clicked, response); alert('You have ignored the request.'); }, }); } jQuery(document).on('click', '.block_contact', block_contact); function block_contact(event) { event.preventDefault(); let ajax_url = local_data['ajax_url']; let nonce = local_data['nonce']; let clicked = jQuery(event.target); if (!clicked.hasClass('block_contact')) { clicked = clicked.parents('.block_contact'); } let request_uid = clicked.attr('uid'); let data = { action: 'block_contact', request_uid: request_uid, nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { jQuery('.blocked_sect').show(); handle_response(clicked, response); alert('You have blocked the contact.'); }, }); } jQuery(document).on('click', '.download_vcard', download_vcard); function download_vcard(event) { event.preventDefault(); let ajax_url = local_data['ajax_url']; let nonce = local_data['nonce']; let clicked = jQuery(event.target); if (!clicked.hasClass('download_vcard')) { clicked = clicked.parents('.download_vcard'); } let request_uid = clicked.attr('uid'); let data = { action: 'download_vcard', request_uid: request_uid, nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { // make a blob out of the response const blob = new Blob([response], { type: 'text/vcard' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; // the filename you want a.download = 'name.vcf'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); alert('your file has downloaded!'); // or you know, something with better UX... }, }); } function handle_response(clicked, response) { clicked.parents('.contact-request').remove(); target = response['target']; new_user = response['html']; target_ob = jQuery('#' + target); target_ob.append(jQuery(new_user)); sort_contents(target_ob); // Page maintenance show_hide_ignored_sect(); // update_request_links(); remove_used_request_buttons(); } function clear_contact_request_alert_count() { let ajax_url = local_data['ajax_url']; let nonce = local_data['nonce']; let data = { action: 'clear_contact_request_alert_count', nonce: nonce, }; jQuery.ajax({ url: ajax_url, // WordPress AJAX handler URL type: 'POST', data: data, success: function (response) { jQuery('.contact-request-alert').remove(); }, }); } // utility functions function sort_contents(wrapper_ob) { // the elements of have attributes 'sort_key_1', 'sort_key_2', etc. // they also have an attribute 'sort_id' which should be unique in a section. // sort them by these attributes let contents = wrapper_ob.children(); contents.sort(function (a, b) { let a_key = a.getAttribute('sort_key_1'); let b_key = b.getAttribute('sort_key_1'); if (a_key < b_key) { return -1; } if (a_key > b_key) { return 1; } a_key = a.getAttribute('sort_key_2'); b_key = b.getAttribute('sort_key_2'); if (a_key < b_key) { return -1; } if (a_key > b_key) { return 1; } return 0; }); // refill the wrapper with the sorted contents let seen_sort_ids = []; wrapper_ob.empty(); contents.each(function () { let sort_id = this.getAttribute('sort_id'); if (seen_sort_ids.includes(sort_id)) { return; } seen_sort_ids.push(sort_id); wrapper_ob.append(this); }); } // Page maintenance functions function show_hide_ignored_sect() { let ignored_requests = jQuery('.ignored_sect').find('.contact-request'); if (ignored_requests.length > 0) { jQuery('.ignored_sect').show(); } else { jQuery('.ignored_sect').hide(); } } function update_request_links() { let pending_requests = jQuery('[status=pending_request]'); pending_requests.each(function () { let uid = jQuery(this).attr('sort_id'); let request_link = jQuery('.request_contact[uid=' + uid + ']'); request_link.addClass('pending'); request_link.find('.default_text').text('Contact has been requested.'); }); } function remove_used_request_buttons() { let pending_requests = jQuery('[status=pending_request]'); let incoming_requests = jQuery('[status=incoming_request]'); let approved_requests = jQuery('[status=approved_request]'); // merge all the requests into one jQuery object all_requests = pending_requests.add(incoming_requests).add(approved_requests); console.log(all_requests); all_requests.each(function () { let uid = jQuery(this).attr('sort_id'); let request_link = jQuery('.request_contact[uid=' + uid + ']'); console.log(request_link); request_link.remove(); }); // remove the request buttons for the current user let current_user_request_link = jQuery('.request_contact[uid=' + local_data.current_user_id + ']'); if (current_user_request_link.length > 0) { current_user_request_link.remove(); } } jQuery(function () { show_hide_ignored_sect(); // update_request_links(); remove_used_request_buttons(); }); // -----------------Chat----------------- // jQuery(document).on('click', '.colorbox_chat_link', function (event) { // event.preventDefault(); // let chat_url = jQuery(this).attr('url'); // let with_user = jQuery(this).attr('uid'); // let nonce = jQuery(this).attr('nonce'); // jQuery.colorbox({ // href: chat_url, // iframe: true, // // trying to improve the box sizing on mobile devices // width: window.innerWidth * 0.9, // maxWidth: '600px', // height: window.innerHeight * 0.9, // maxHeight: window.innerHeight * 0.9, // // colorbox doesn't seem to get the 90% right on mobile chrome. // // width: '90%', // // innerWidth: '95%', // // maxWidth: '600px', // // height: '90%', // onCleanup: function () { // // set the timestamp that the chat was last viewed (set_chat_timestamp) // let timestamp = Math.floor(Date.now() / 1000); // jQuery.post(local_data['ajax_url'], { // action: 'set_chat_timestamp', // user_id: with_user, // timestamp: timestamp, // nonce: nonce, // }); // show_unseen_counts(); // }, // }); // }); // jQuery(document).on('click', '.manual_modal_chat_link_TRAD', function (event) { // event.preventDefault(); // let chat_url = jQuery(this).attr('url'); // let with_user = jQuery(this).attr('uid'); // let nonce = jQuery(this).attr('nonce'); // // Display a vanilla JS modal with an iframe chat // let modal = document.createElement('div'); // modal.style.position = 'fixed'; // modal.style.top = '0'; // modal.style.left = '0'; // modal.style.width = window.innerWidth * 0.9; // modal.style.height = window.innerHeight * 0.9; // modal.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; // modal.style.zIndex = '1000'; // // Create an iframe for the chat // let iframe = document.createElement('iframe'); // iframe.className = 'chat_modal'; // iframe.src = chat_url; // iframe.style.width = '100%'; // iframe.style.height = '100%'; // iframe.style.border = 'none'; // // Add a close button to the modal // let close_button = document.createElement('button'); // close_button.textContent = 'Close'; // close_button.style.position = 'absolute'; // close_button.style.top = '10px'; // close_button.style.right = '10px'; // close_button.style.backgroundColor = 'white'; // close_button.style.border = 'none'; // // Add the iframe to the modal // modal.appendChild(iframe); // // Add the modal to the document body // document.body.appendChild(modal); // // Add the close button to the modal // modal.appendChild(close_button); // // Add the modal to the document body // document.body.appendChild(modal); // // Add a click event listener to the close button // close_button.addEventListener('click', function () { // document.body.removeChild(modal); // }); // }); jQuery(document).on('click', '.manual_modal_chat_link', function (event) { event.preventDefault(); let chat_url = jQuery(this).attr('url'); let chat_hash = jQuery(this).attr('data-chat-hash'); let with_user = jQuery(this).attr('uid'); let nonce = jQuery(this).attr('nonce'); openChatDialog(chat_url, chat_hash, with_user, nonce); }); /**** * Open a chat dialog in a HTML5 dialog element. * This is a replacement for the colorbox chat link in the effort to fix in-app issues on certain devices. */ function openChatDialog(chatUrl, chatHash, withUser, nonce) { const dialog = document.createElement('dialog'); dialog.className = 'chat_modal'; // Keeping the colorbox_chat_link class for now to make sure the original styles are applied const iframe = document.createElement('iframe'); iframe.src = chatUrl; iframe.style.width = window.innerWidth * 0.9 + 'px'; iframe.style.maxWidth = '600px'; iframe.style.height = window.innerHeight * 0.9 + 'px'; iframe.style.border = 'none'; iframe.style.paddingTop = '0px'; iframe.style.margin = '0px'; const close_button = document.createElement('button'); const x_icon = document.createElement('i'); x_icon.className = 'fa-solid fa-x'; x_icon.style.padding = '0px'; x_icon.style.margin = '0px'; x_icon.style.fontSize = '12px'; close_button.appendChild(x_icon); close_button.style.position = 'absolute'; close_button.style.top = '5px'; close_button.style.right = '5px'; close_button.style.background = 'gray'; close_button.style.border = 'none'; const dialog_content = document.createElement('div'); dialog_content.appendChild(iframe); dialog_content.appendChild(close_button); dialog.appendChild(dialog_content); document.body.appendChild(dialog); dialog.showModal(); // Handle cleanup when dialog closes function cleanup() { onModalCleanup(withUser, chatUrl, chatHash, nonce); dialog.remove(); } dialog.addEventListener('close', cleanup); // Use the variable directly instead of querySelector close_button.addEventListener('click', () => { dialog.close(); }); } function onModalCleanup(withUser, chatUrl, chatHash, nonce) { // Set the timestamp that the chat was last viewed let timestamp = Math.floor(Date.now() / 1000); // Get current timestamp in seconds for WP // Make the AJAX request using fetch fetch(local_data['ajax_url'], { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ action: 'set_chat_timestamp', user_id: withUser, timestamp: timestamp, nonce: nonce, }), }) .then(response => response.json()) .then(data => { // Manually update the chat channel last seen timestamp in local_data. // By doing this we can avoid an extra request to WordPress. if (local_data.chan_ts_pairs) { for (let i = 0; i < local_data.chan_ts_pairs.length; i++) { let pair = local_data.chan_ts_pairs[i]; if (pair.channel === chatHash) { // Update the last seen timestamp for this chat channel pair.timestamp = timestamp + 2; // Add a small buffer (2 seconds) to the timestamp to account for network delays updating WP break; } } } // Update unseen counts after setting the timestamp do_chat_count_updates(); }) .catch(error => { console.error('Error setting chat timestamp:', error); }); } function align_colorbox_bottom() { if (window.Capacitor && window.Capacitor.platform === 'android') { // Android app (but not android chrome) does better without this fix, // so skip it. return; } // this resizes the colorbox and puts it at the bottom of the screen // specifically for mobile browser keyboard resize events, but also helps desktop window resizing. let colorbox = document.getElementById("colorbox"); jQuery.colorbox.resize({height: window.visualViewport.height * 0.9}); colorbox.scrollIntoView({ block: "end" }); } function fetch_user_alert() { if (jQuery('.contact_alert_container').length > 0) { jQuery.ajax({ url: local_data['ajax_url'], type: 'POST', data: { action: 'fetch_user_alert_count', nonce: local_data['nonce'], }, success: function (response) { if (response['data'] !== undefined) { jQuery('.contact_alert_container').html(response['data']); } else { jQuery('.contact_alert_container').html(''); } }, }); } } function show_unseen_counts() { return fetch_new_chat_counts_in_local_data().then(function () { update_unseen_counts(); // jQuery('.colorbox_chat_link').each(function () { jQuery('.manual_modal_chat_link').each(function () { // Remove any existing count spans first jQuery(this).find('.new_chat_count').remove(); let unseen_count = jQuery(this).attr('unseen'); if (unseen_count > 0) { jQuery(this).append(" " + unseen_count + ' '); } }); }); } function show_unseen_counts_on_load() { // jQuery('.colorbox_chat_link').each(function () { jQuery('.manual_modal_chat_link').each(function () { // Remove any existing count spans first jQuery(this).find('.new_chat_count').remove(); let unseen_count = jQuery(this).attr('unseen'); if (unseen_count > 0) { jQuery(this).append(" " + unseen_count + ' '); } }); } function update_unseen_counts() { let unseen_counts = local_data['new_chat_counts']; // jQuery('.colorbox_chat_link').each(function () { jQuery('.manual_modal_chat_link').each(function () { let uid = jQuery(this).attr('uid'); if (unseen_counts[uid] !== undefined) { let unseen_count = unseen_counts[uid]; jQuery(this).attr('unseen', unseen_count); } else { jQuery(this).attr('unseen', 0); } }); } function fetch_new_chat_counts_in_local_data() { return jQuery.ajax({ url: local_data['ajax_url'], type: 'POST', data: { action: 'fetch_new_chat_counts', nonce: local_data['nonce'], }, success: function (response) { new_chat_counts = response['data']; local_data['new_chat_counts'] = new_chat_counts; }, }); } function fetch_new_chat_localdata_from_wp() { return jQuery.ajax({ url: local_data['ajax_url'], type: 'POST', data: { action: 'fetch_updated_chat_localdata', nonce: local_data['nonce'], }, success: function (response) { // Check if response is HTML instead of JSON (indicates server error) if (typeof response === 'string' && response.includes('')) { console.error('fetch_new_chat_localdata_from_wp()::Received HTML instead of JSON - server error'); return Promise.reject('Server returned HTML instead of JSON'); } // Update local_data with the new data from WordPress if (!response || !response.data) { console.error('fetch_new_chat_localdata_from_wp()::No data received from WordPress'); return Promise.reject('No data received'); } const data = response.data; if (!data) { console.error('fetch_new_chat_localdata_from_wp()::No data field in response'); return Promise.reject('No data field in response'); } Object.assign(local_data, response.data); // After fetching new chat data, update all the chat counts // This will use the updated local_data update_chat_counts_from_direct_response(); }, error: function(xhr, status, error) { console.error('Error fetching updated chat local data:', error); return Promise.reject(error); } }); } // NEW: Direct chat server communication for count updates function fetch_chat_counts_direct() { // Use the pre-built channel-timestamp pairs from PHP if (!local_data.chan_ts_pairs || local_data.chan_ts_pairs.length === 0) { // Return a promise of type application/json that resolves immediately and calls the update function on blank return Promise.resolve().then(() => { update_chat_counts_from_direct_response({}); }); } // Direct request to chat server using pre-built data const chat_server_url = local_data.qna_url; return jQuery.ajax({ url: chat_server_url, type: 'POST', headers: { 'Content-Type': 'application/json', }, data: JSON.stringify({ chan_ts_pairs: local_data.chan_ts_pairs }), timeout: 10000, success: function (response) { // Update local data with new counts local_data['new_chat_counts'] = response; // Convert chat hashes back to UIDs and update display update_chat_counts_from_direct_response(response); }, error: function(xhr, status, error) { console.warn('Direct chat server request failed, falling back to WordPress:', error); // Fallback to WordPress if direct request fails return fetch_new_chat_counts_in_local_data(); } }); } function update_chat_counts_from_direct_response(chat_counts) { // Convert chat hash counts to UID-based counts using the mapping from PHP const uid_counts = {}; if (local_data.chat_hash_to_uid_map && chat_counts) { Object.keys(chat_counts).forEach(channel => { const uid = local_data.chat_hash_to_uid_map[channel]; if (uid) { uid_counts[uid] = chat_counts[channel]; } }); } // Update individual chat link counts jQuery('.manual_modal_chat_link').each(function () { const uid = jQuery(this).attr('uid'); // Remove existing count spans jQuery(this).find('.new_chat_count').remove(); const unseen_count = uid_counts[uid] || 0; jQuery(this).attr('unseen', unseen_count); if (unseen_count > 0) { jQuery(this).append(" " + unseen_count + ' '); } }); // Update total count in header let total_chat_count = 0; Object.values(chat_counts || {}).forEach(count => { total_chat_count += parseInt(count) || 0; }); // Filter out blocked users from the total count if (local_data.blocked && Array.isArray(local_data.blocked)) { let blocked_count = 0; Object.keys(uid_counts).forEach(uid => { if (local_data.blocked.includes(uid)) { blocked_count += parseInt(uid_counts[uid]) || 0; } }); // Subtract blocked count from total total_chat_count -= blocked_count; } // Add in contact request counts if (local_data.contact_request_count) { total_chat_count += parseInt(local_data.contact_request_count) || 0; } let alert_containers = jQuery('.contact_alert_container'); if (total_chat_count > 0) { const alert_html = "
" + total_chat_count + "
"; alert_containers.each(function () { // Clear any existing content before updating jQuery(this).empty(); jQuery(this).html(alert_html); }); } else { alert_containers.each(function () { jQuery(this).empty(); }); } } function do_chat_count_updates() { if (local_data.qna_url) { // Use the direct chat server polling method // This will bypass WordPress and use the chat server directly return fetch_chat_counts_direct().catch(function(error) { console.warn('Direct chat polling failed:', error); // Could fall back to WordPress polling here if needed throw error; // Re-throw to maintain promise chain }); } else { // Fallback to WordPress if chat server URL not configured console.warn('Chat server URL not configured, using WordPress fallback'); return show_unseen_counts() || Promise.resolve(); // Return promise from show_unseen_counts or resolved promise } } function do_chat_localdata_updates() { fetch_new_chat_localdata_from_wp().then(function() { do_chat_count_updates(); }).catch(function(error) { console.error('Error fetching new contacts:', error); }); } // OPTIMIZED: New polling strategy to reduce server load // Use on('load') to ensure that all shortcodes have been processed before starting polling jQuery(window).on('load', function () { // skip ajax requests and polling intervals when the user is not logged in. // they can create a lot of requests (server crash) and these requests are // unnecessary when the user is not logged in (a user can // only use the messaging / networking feature when they are logged in). const is_logged_in = ( !!local_data.current_user_id && local_data.current_user_id !== '0' // this is what wordpress returns for no user. ); if (is_logged_in) { clear_contact_request_alert_count(); show_unseen_counts_on_load(); // OPTIMIZED POLLING STRATEGY: // 1. Direct chat count updates every 10 seconds (bypass WordPress) // 2. New contact / chat channel discovery every minute (heavy WordPress call) const CHAT_COUNT_INTERVAL = 10000; // 10 seconds - direct to chat server const NEW_CONTACTS_INTERVAL = 60000; // 1 minute - full contact refresh // Fast polling: Direct chat count updates (bypasses WordPress) // Run this right away and then every CHAT_COUNT_INTERVAL do_chat_count_updates().then(function() { // Initial count update successful, now set up the interval setInterval(function() { do_chat_count_updates(); }, CHAT_COUNT_INTERVAL); }).catch(function(error) { console.error('Error during initial chat count update:', error); }); // Slow polling: Check for new contacts (heavy WordPress call) setInterval(function() { do_chat_localdata_updates(); }, NEW_CONTACTS_INTERVAL); } });