PageSourceSearch

https://city-skills.com/wp-content/plugins/engageai-buddyboss/assets/js/frontend.js?ver=1.0.0

js city-skills.com collected 2026-10-08 23:51:45 UTC 19,737 bytes, 579 lines download raw bytes

1// EngageAI Frontend JavaScript
2
3(function($) {
4    'use strict';
5    
6    // Main frontend object
7    const EngageAI_Frontend = {
8        init: function() {
9            this.bindEvents();
10            this.initComponents();
11            this.loadStoredData();
12        },
13        
14        bindEvents: function() {
15            // Activity feed interactions
16            $(document).on('click', '.engageai-welcome-message', this.trackWelcomeInteraction);
17            $(document).on('click', '.engageai-discussion-prompt', this.trackDiscussionInteraction);
18            $(document).on('click', '.engageai-motivational-content', this.trackMotivationalInteraction);
19            
20            // Comment form enhancements
21            $(document).on('focus', '.ac-reply-content', this.enhanceCommentForm);
22            $(document).on('submit', '.ac-form', this.trackCommentSubmission);
23            
24            // Engagement tracking
25            $(document).on('click', '.activity-item .activity-content a', this.trackLinkClick);
26            $(document).on('click', '.acomment-reply', this.trackReplyClick);
27            
28            // Gamification interactions
29            $(document).on('click', '.engageai-points-earned', this.showPointsDetails);
30            $(document).on('click', '.engageai-badge-earned', this.showBadgeDetails);
31            
32            // Infinite scroll for activity feed
33            $(window).on('scroll', this.handleInfiniteScroll);
34            
35            // Real-time notifications
36            this.initNotifications();
37        },
38        
39        initComponents: function() {
40            this.initLazyLoading();
41            this.initAnimations();
42            this.initTooltips();
43            this.initAccessibility();
44        },
45        
46        // Track welcome message interactions
47        trackWelcomeInteraction: function(e) {
48            const $message = $(this);
49            const groupId = $message.data('group-id');
50            const messageId = $message.data('message-id');
51            
52            EngageAI_Frontend.trackEvent('welcome_message_clicked', {
53                group_id: groupId,
54                message_id: messageId
55            });
56        },
57        
58        // Track discussion prompt interactions
59        trackDiscussionInteraction: function(e) {
60            const $prompt = $(this);
61            const promptId = $prompt.data('prompt-id');
62            const groupId = $prompt.data('group-id');
63            
64            EngageAI_Frontend.trackEvent('discussion_prompt_clicked', {
65                prompt_id: promptId,
66                group_id: groupId
67            });
68            
69            // Focus on comment form if it exists
70            const $commentForm = $('.ac-reply-content');
71            if ($commentForm.length) {
72                setTimeout(function() {
73                    $commentForm.focus();
74                }, 300);
75            }
76        },
77        
78        // Track motivational content interactions
79        trackMotivationalInteraction: function(e) {
80            const $content = $(this);
81            const contentId = $content.data('content-id');
82            
83            EngageAI_Frontend.trackEvent('motivational_content_clicked', {
84                content_id: contentId
85            });
86        },
87        
88        // Enhance comment form with suggestions
89        enhanceCommentForm: function(e) {
90            const $form = $(this).closest('.ac-form');
91            const $activityItem = $form.closest('.activity-item');
92            
93            if ($activityItem.hasClass('engageai-automated')) {
94                EngageAI_Frontend.addCommentSuggestions($form);
95            }
96        },
97        
98        // Add comment suggestions
99        addCommentSuggestions: function($form) {
100            if ($form.find('.engageai-suggestions').length > 0) {
101                return; // Already added
102            }
103            
104            const suggestions = [
105                'Thanks for sharing this!',
106                'This is really helpful.',
107                'I have a similar experience...',
108                'Great point!',
109                'I\'d love to hear more about this.'
110            ];
111            
112            const $suggestionsContainer = $('<div class="engageai-suggestions">');
113            const $suggestionsTitle = $('<div class="suggestions-title">Quick responses:</div>');
114            const $suggestionsList = $('<div class="suggestions-list">');
115            
116            suggestions.forEach(function(suggestion) {
117                const $suggestion = $('<button type="button" class="suggestion-btn">' + suggestion + '</button>');
118                $suggestion.on('click', function() {
119                    const $textarea = $form.find('textarea');
120                    const currentText = $textarea.val();
121                    const newText = currentText ? currentText + ' ' + suggestion : suggestion;
122                    $textarea.val(newText).focus();
123                });
124                $suggestionsList.append($suggestion);
125            });
126            
127            $suggestionsContainer.append($suggestionsTitle, $suggestionsList);
128            $form.find('textarea').after($suggestionsContainer);
129        },
130        
131        // Track comment submissions
132        trackCommentSubmission: function(e) {
133            const $form = $(this);
134            const $activityItem = $form.closest('.activity-item');
135            
136            if ($activityItem.hasClass('engageai-automated')) {
137                const automationType = $activityItem.data('automation-type');
138                
139                EngageAI_Frontend.trackEvent('comment_on_automated_content', {
140                    automation_type: automationType,
141                    activity_id: $activityItem.data('activity-id')
142                });
143            }
144        },
145        
146        // Track link clicks
147        trackLinkClick: function(e) {
148            const $link = $(this);
149            const $activityItem = $link.closest('.activity-item');
150            
151            if ($activityItem.hasClass('engageai-automated')) {
152                EngageAI_Frontend.trackEvent('link_clicked_in_automated_content', {
153                    url: $link.attr('href'),
154                    automation_type: $activityItem.data('automation-type')
155                });
156            }
157        },
158        
159        // Track reply clicks
160        trackReplyClick: function(e) {
161            const $button = $(this);
162            const $activityItem = $button.closest('.activity-item');
163            
164            if ($activityItem.hasClass('engageai-automated')) {
165                EngageAI_Frontend.trackEvent('reply_to_automated_content', {
166                    automation_type: $activityItem.data('automation-type')
167                });
168            }
169        },
170        
171        // Show points details
172        showPointsDetails: function(e) {
173            e.preventDefault();
174            
175            const $points = $(this);
176            const points = $points.data('points');
177            const reason = $points.data('reason');
178            
179            EngageAI_Frontend.showTooltip($points, `+${points} points for ${reason}`);
180        },
181        
182        // Show badge details
183        showBadgeDetails: function(e) {
184            e.preventDefault();
185            
186            const $badge = $(this);
187            const badgeName = $badge.data('badge-name');
188            const description = $badge.data('description');
189            
190            EngageAI_Frontend.showTooltip($badge, `${badgeName}: ${description}`);
191        },
192        
193        // Handle infinite scroll
194        handleInfiniteScroll: function() {
195            if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100) {
196                EngageAI_Frontend.loadMoreActivities();
197            }
198        },
199        
200        // Load more activities
201        loadMoreActivities: function() {
202            if (this.loadingMore) return;
203            
204            this.loadingMore = true;
205            
206            // Implementation would depend on BuddyBoss's activity loading system
207            // This is a placeholder for the infinite scroll functionality
208            
209            setTimeout(() => {
210                this.loadingMore = false;
211            }, 1000);
212        },
213        
214        // Initialize lazy loading for images
215        initLazyLoading: function() {
216            if ('IntersectionObserver' in window) {
217                const imageObserver = new IntersectionObserver((entries, observer) => {
218                    entries.forEach(entry => {
219                        if (entry.isIntersecting) {
220                            const img = entry.target;
221                            img.src = img.dataset.src;
222                            img.classList.remove('lazy');
223                            imageObserver.unobserve(img);
224                        }
225                    });
226                });
227                
228                document.querySelectorAll('img[data-src]').forEach(img => {
229                    imageObserver.observe(img);
230                });
231            }
232        },
233        
234        // Initialize animations
235        initAnimations: function() {
236            // Animate elements when they come into view
237            if ('IntersectionObserver' in window) {
238                const animationObserver = new IntersectionObserver((entries) => {
239                    entries.forEach(entry => {
240                        if (entry.isIntersecting) {
241                            entry.target.classList.add('animate-in');
242                        }
243                    });
244                }, {
245                    threshold: 0.1
246                });
247                
248                document.querySelectorAll('.engageai-welcome-message, .engageai-discussion-prompt, .engageai-motivational-content').forEach(el => {
249                    animationObserver.observe(el);
250                });
251            }
252        },
253        
254        // Initialize tooltips
255        initTooltips: function() {
256            $('[data-tooltip]').each(function() {
257                const $element = $(this);
258                const tooltipText = $element.data('tooltip');
259                
260                $element.on('mouseenter', function() {
261                    EngageAI_Frontend.showTooltip($element, tooltipText);
262                });
263                
264                $element.on('mouseleave', function() {
265                    EngageAI_Frontend.hideTooltip();
266                });
267            });
268        },
269        
270        // Initialize accessibility features
271        initAccessibility: function() {
272            // Add ARIA labels to automated content
273            $('.engageai-automated').each(function() {
274                const $item = $(this);
275                const automationType = $item.data('automation-type');
276                
277                $item.attr('aria-label', `Automated ${automationType} content`);
278            });
279            
280            // Add keyboard navigation
281            $(document).on('keydown', '.engageai-automated', function(e) {
282                if (e.key === 'Enter' || e.key === ' ') {
283                    e.preventDefault();
284                    $(this).trigger('click');
285                }
286            });
287        },
288        
289        // Initialize real-time notifications
290        initNotifications: function() {
291            if ('Notification' in window) {
292                // Request permission for notifications
293                if (Notification.permission === 'default') {
294                    Notification.requestPermission();
295                }
296            }
297            
298            // Set up event source for real-time updates (if available)
299            this.setupEventSource();
300        },
301        
302        // Setup event source for real-time updates
303        setupEventSource: function() {
304            // This would connect to a server-sent events endpoint
305            // for real-time notifications about new automated content
306            // Implementation depends on server setup
307        },
308        
309        // Show tooltip
310        showTooltip: function($element, text) {
311            this.hideTooltip();
312            
313            const $tooltip = $('<div class="engageai-tooltip">
313' + text + '</div>');
314            $('body').append($tooltip);
315            
316            const elementOffset = $element.offset();
317            const elementHeight = $element.outerHeight();
318            
319            $tooltip.css({
320                top: elementOffset.top + elementHeight + 10,
321                left: elementOffset.left + ($element.outerWidth() / 2) - ($tooltip.outerWidth() / 2)
322            }).fadeIn(200);
323            
324            this.currentTooltip = $tooltip;
325        },
326        
327        // Hide tooltip
328        hideTooltip: function() {
329            if (this.currentTooltip) {
330                this.currentTooltip.fadeOut(200, function() {
331                    $(this).remove();
332                });
333                this.currentTooltip = null;
334            }
335        },
336        
337        // Track events
338        trackEvent: function(eventType, data) {
339            if (typeof gtag !== 'undefined') {
340                gtag('event', eventType, {
341                    custom_parameter: data
342                });
343            }
344            
345            // Send to backend for internal analytics
346            $.ajax({
347                url: engageai_frontend.ajax_url,
348                type: 'POST',
349                data: {
350                    action: 'engageai_track_event',
351                    event_type: eventType,
352                    event_data: data,
353                    nonce: engageai_frontend.nonce
354                }
355            });
356        },
357        
358        // Load stored data
359        loadStoredData: function() {
360            // Load user preferences and engagement history
361            const preferences = localStorage.getItem('engageai_preferences');
362            if (preferences) {
363                this.preferences = JSON.parse(preferences);
364            }
365        },
366        
367        // Save user preferences
368        savePreferences: function() {
369            localStorage.setItem('engageai_preferences', JSON.stringify(this.preferences));
370        },
371        
372        // Show notification
373        showNotification: function(title, message, type = 'info') {
374            if ('Notification' in window && Notification.permission === 'granted') {
375                new Notification(title, {
376                    body: message,
377                    icon: engageai_frontend.plugin_url + 'assets/images/icon.png'
378                });
379            } else {
380                // Fallback to in-page notification
381                this.showInPageNotification(title, message, type);
382            }
383        },
384        
385        // Show in-page notification
386        showInPageNotification: function(title, message, type) {
387            const $notification = $(`
388                <div class="engageai-notification ${type}">
389                    <div class="notification-header">
390                        <strong>${title}</strong>
391                        <button class="notification-close">&times;</button>
392                    </div>
393                    <div class="notification-body">${message}</div>
394                </div>
395            `);
396            
397            $('body').append($notification);
398            
399            $notification.slideDown(300);
400            
401            // Auto-hide after 5 seconds
402            setTimeout(() => {
403                $notification.slideUp(300, function() {
404                    $(this).remove();
405                });
406            }, 5000);
407            
408            // Manual close
409            $notification.find('.notification-close').on('click', function() {
410                $notification.slideUp(300, function() {
411                    $(this).remove();
412                });
413            });
414        },
415        
416        // Utilities
417        utils: {
418            // Debounce function
419            debounce: function(func, wait, immediate) {
420                let timeout;
421                return function executedFunction() {
422                    const context = this;
423                    const args = arguments;
424                    const later = function() {
425                        timeout = null;
426                        if (!immediate) func.apply(context, args);
427                    };
428                    const callNow = immediate && !timeout;
429                    clearTimeout(timeout);
430                    timeout = setTimeout(later, wait);
431                    if (callNow) func.apply(context, args);
432                };
433            },
434            
435            // Format time ago
436            timeAgo: function(date) {
437                const now = new Date();
438                const diff = now - new Date(date);
439                const seconds = Math.floor(diff / 1000);
440                const minutes = Math.floor(seconds / 60);
441                const hours = Math.floor(minutes / 60);
442                const days = Math.floor(hours / 24);
443                
444                if (days > 0) return `${days}d ago`;
445                if (hours > 0) return `${hours}h ago`;
446                if (minutes > 0) return `${minutes}m ago`;
447                return 'Just now';
448            }
449        },
450        
451        // Initialize properties
452        loadingMore: false,
453        currentTooltip: null,
454        preferences: {}
455    };
456    
457    // Initialize when document is ready
458    $(document).ready(function() {
459        EngageAI_Frontend.init();
460    });
461    
462    // Make EngageAI_Frontend globally available
463    window.EngageAI_Frontend = EngageAI_Frontend;
464    
465})(jQuery);
466
467// CSS for tooltips and notifications
468const engageaiStyles = `
469<style>
470.engageai-tooltip {
471    position: absolute;
472    background: rgba(0,0,0,0.9);
473    color: white;
474    padding: 8px 12px;
475    border-radius: 4px;
476    font-size: 12px;
477    white-space: nowrap;
478    z-index: 10000;
479    display: none;
480}
481
482.engageai-notification {
483    position: fixed;
484    top: 20px;
485    right: 20px;
486    background: white;
487    border-radius: 8px;
488    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
489    max-width: 300px;
490    z-index: 9999;
491    display: none;
492}
493
494.engageai-notification.info { border-left: 4px solid #2271b1; }
495.engageai-notification.success { border-left: 4px solid #46b450; }
496.engageai-notification.warning { border-left: 4px solid #ffb900; }
497.engageai-notification.error { border-left: 4px solid #dc3232; }
498
499.notification-header {
500    padding: 12px 16px 8px;
501    display: flex;
502    justify-content: space-between;
503    align-items: center;
504    border-bottom: 1px solid #eee;
505}
506
507.notification-close {
508    background: none;
509    border: none;
510    font-size: 18px;
511    cursor: pointer;
512    color: #666;
513}
514
515.notification-body {
516    padding: 8px 16px 12px;
517    font-size: 14px;
518    color: #666;
519}
520
521.engageai-suggestions {
522    margin-top: 10px;
523    padding: 10px;
524    background: #f9f9f9;
525    border-radius: 4px;
526}
527
528.suggestions-title {
529    font-size: 12px;
530    color: #666;
531    margin-bottom: 8px;
532}
533
534.suggestions-list {
535    display: flex;
536    flex-wrap: wrap;
537    gap: 5px;
538}
539
540.suggestion-btn {
541    background: #e7f3ff;
542    border: 1px solid #cee4fd;
543    color: #0073aa;
544    padding: 4px 8px;
545    border-radius: 12px;
546    font-size: 11px;
547    cursor: pointer;
548    transition: background-color 0.2s;
549}
550
551.suggestion-btn:hover {
552    background: #cee4fd;
553}
554
555.animate-in {
556    animation: slideInUp 0.5s ease-out;
557}
558
559@keyframes slideInUp {
560    from {
561        opacity: 0;
562        transform: translateY(20px);
563    }
564    to {
565        opacity: 1;
566        transform: translateY(0);
567    }
568}
569</style>
570`;
571
572// Inject styles
573if (document.head) {
574    document.head.insertAdjacentHTML('beforeend', engageaiStyles);
575} else {
576    document.addEventListener('DOMContentLoaded', function() {
577        document.head.insertAdjacentHTML('beforeend', engageaiStyles);
578    });
579}

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.