PageSourceSearch

https://www.dneph.com/wp-content/plugins/dneph-pressganey-reviews/assets/js/script.js?ver=1790291962

js dneph.com collected 2026-09-24 23:48:05 UTC 13,626 bytes, 324 lines download raw bytes

1/**
2 * PressGaney Reviews Plugin JavaScript
3 * Handles AJAX requests, UI interactions, and dynamic content loading
4 */
5
6(function($) {
7    'use strict';
8
9    // Main plugin object
10    var PressGaneyReviews = {
11        
12        // Initialize the plugin
13        init: function() {
14            this.bindEvents();
15            this.initializeReviews();
16        },
17
18        // Bind event listeners
19        bindEvents: function() {
20            $(document).on('click', '.pressganey-load-more-button', this.handleLoadMore);
21            $(document).on('click', '.pressganey-copy-shortcode', this.copyToClipboard);
22            $(document).on('click', '#force-sync', this.handleForceSync);
23        },
24
25        // Initialize reviews containers (no longer needed for AJAX, but kept for future use)
26        initializeReviews: function() {
27            // Reviews are now loaded server-side, so no initialization needed
28            // This function is kept for backward compatibility and future enhancements
29        },
30
31        // Reviews are now loaded server-side, so this function is no longer needed
32        // Kept for backward compatibility
33        loadReviews: function(container, entityType, entityId, displayType) {
34            // Reviews are now rendered server-side in the template
35            console.log('Reviews loaded server-side for entity:', entityId);
36        },
37
38        // Generate basic display HTML (no longer used - reviews rendered server-side)
39        generateBasicDisplay: function(entity) {
40            console.log('generateBasicDisplay called - reviews now rendered server-side');
41            return '';
42        },
43
44        // Generate reviews display HTML (no longer used - reviews rendered server-side)
45        generateReviewsDisplay: function(entity) {
46            console.log('generateReviewsDisplay called - reviews now rendered server-side');
47            return '';
48        },
49
50        // Generate star rating HTML
51        generateStars: function(rating) {
52            var fullStars = Math.floor(rating);
53            var hasHalfStar = rating % 1 >= 0.5;
54            var emptyStars = 5 - fullStars - (hasHalfStar ? 1 : 0);
55            
56            var stars = '★'.repeat(fullStars);
57            if (hasHalfStar) stars += '☆';
58            stars += '☆'.repeat(emptyStars);
59            
60            return stars;
61        },
62
63        // Handle load more button click (updated for server-side data)
64        handleLoadMore: function(e) {
65            e.preventDefault();
66            
67            var button = $(this);
68            var container = button.closest('.pressganey-reviews-container');
69            var reviewsList = container.find('.pressganey-reviews-list');
70            var currentIndex = parseInt(button.data('current-index')) || 6;
71            var totalReviews = parseInt(button.data('total-reviews')) || 0;
72            
73            // Get all reviews from the button's data attribute (now stored there)
74            var allReviews = [];
75            try {
76                var encodedData = button.data('reviews-data') || '';
77                if (encodedData) {
78                    // Decode base64 data
79                    var decodedString = decodeURIComponent(escape(atob(encodedData)));
80                    allReviews = JSON.parse(decodedString);
81                }
82            } catch (e) {
83                console.error('Error parsing reviews data:', e);
84                console.error('Encoded data:', encodedData);
85                return;
86            }
87            
88            button.prop('disabled', true).text('Loading...');
89            
90            // Calculate how many reviews to show next
91            var nextBatch = allReviews.slice(currentIndex, currentIndex + 6);
92            var newIndex = currentIndex + nextBatch.length;
93            
94            if (nextBatch.length > 0) {
95                var startIndex = reviewsList.children().length;
96                
97                // Add each review in the next batch
98                for (var i = 0; i < nextBatch.length; i++) {
99                    var review = nextBatch[i];
100                    var reviewRating = review.overallRating ? review.overallRating.value : 0;
101                    var reviewDate = new Date(review.mentionTime).toLocaleDateString('en-US', {
102                        year: 'numeric',
103                        month: 'short',
104                        day: 'numeric'
105                    });
106					
107					var commentText = (review.comment && typeof review.comment === 'object')
108						? review.comment.comment
109						: review.comment;
110
111					commentText = commentText || '';
112                    
113                    var reviewHtml = '<li class="pressganey-review-item pressganey-slide-in" style="animation-delay: ' + ((startIndex + i
113) * 0.1) + 's">' +
114                                   '<div class="pressganey-review-header">' +
115                                   '<div class="pressganey-review-stars" data-rating="' + reviewRating + '">' + 
116                                   PressGaneyReviews.generateStars(reviewRating) + '</div>' +
117                                   '<div class="pressganey-review-date">' + reviewDate + '</div>' +
118                                   '</div>' +
119                                   '<p class="pressganey-review-comment">' + PressGaneyReviews.escapeHtml(commentText) + '</p>' +
120                                   '</li>';
121                    
122                    reviewsList.append(reviewHtml);
123                }
124                
125                // Update button data
126                button.data('current-index', newIndex);
127                
128                // Hide button if no more reviews to show
129                if (newIndex >= totalReviews) {
130                    button.parent().fadeOut();
131                }
132            }
133            
134            button.prop('disabled', false).text('Load More Reviews');
135        },
136
137        // Bind load more functionality
138        bindLoadMore: function(container, entityType, entityId, displayType, scrollKey) {
139            // The load more functionality is now handled by the document-level event listener
140            // No additional binding needed since we're using event delegation
141        },
142
143        // Copy shortcode to clipboard
144        copyToClipboard: function(e) {
145            e.preventDefault();
146            
147            var shortcode = $(this).siblings('input').val();
148            if (shortcode) {
149                if (navigator.clipboard && window.isSecureContext) {
150                    navigator.clipboard.writeText(shortcode).then(function() {
151                        PressGaneyReviews.showNotification('Shortcode copied to clipboard!', 'success');
152                    }).catch(function() {
153                        PressGaneyReviews.fallbackCopyTextToClipboard(shortcode);
154                    });
155                } else {
156                    PressGaneyReviews.fallbackCopyTextToClipboard(shortcode);
157                }
158            }
159        },
160
161        // Fallback copy method for older browsers
162        fallbackCopyTextToClipboard: function(text) {
163            var textArea = document.createElement('textarea');
164            textArea.value = text;
165            textArea.style.top = '0';
166            textArea.style.left = '0';
167            textArea.style.position = 'fixed';
168            document.body.appendChild(textArea);
169            textArea.focus();
170            textArea.select();
171            
172            try {
173                document.execCommand('copy');
174                this.showNotification('Shortcode copied to clipboard!', 'success');
175            } catch (err) {
176                this.showNotification('Failed to copy shortcode', 'error');
177            }
178            
179            document.body.removeChild(textArea);
180        },
181
182        // Show notification
183        showNotification: function(message, type) {
184            var notification = $('<div class="pressganey-notification pressganey-notification-' + type + '">' + message + '</div>');
185            
186            $('body').append(notification);
187            
188            setTimeout(function() {
189                notification.addClass('pressganey-notification-show');
190            }, 100);
191            
192            setTimeout(function() {
193                notification.removeClass('pressganey-notification-show');
194                setTimeout(function() {
195                    notification.remove();
196                }, 300);
197            }, 3000);
198        },
199
200        // Handle force sync button click
201        handleForceSync: function(e) {
202            e.preventDefault();
203            
204            var button = $(this);
205            var syncText = button.find('.sync-text');
206            var syncLoading = button.find('.sync-loading');
207            var syncResult = $('#sync-result');
208            
209            // Show loading state
210            button.prop('disabled', true);
211            syncText.hide();
212            syncLoading.show();
213            syncResult.hide();
214            
215            $.ajax({
216                url: pressganey_ajax.ajax_url,
217                type: 'POST',
218                data: {
219                    action: 'pressganey_force_sync',
220                    nonce: pressganey_ajax.nonce
221                },
222                success: function(response) {
223                    if (response.success) {
224                        var html = '<div class="notice notice-success"><p>' + response.data.message + '</p></div>';
225                        
226                        // Add debug information if available
227                        if (response.data.debug && response.data.debug.length > 0) {
228                            html += '<div class="sync-debug">';
229                            html += '<h4>Debug Information:</h4>';
230                            html += '<div style="background: #f0f0f0; padding: 10px; border-radius: 4px; max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px; white-space: pre-wrap;">';
231                            
232                            for (var i = 0; i < response.data.debug.length; i++) {
233                                html += response.data.debug[i] + '\n';
234                            }
235                            
236                            html += '</div>';
237                            html += '</div>';
238                        }
239                        
240                        syncResult.html(html).show();
241                        PressGaneyReviews.showNotification('Sync completed successfully!', 'success');
242                    } else {
243                        var errorData = typeof response.data === 'object' ? response.data : { message: response.data };
244                        var html = '<div class="notice notice-error"><p>' + errorData.message + '</p></div>';
245                        
246                        // Add debug information if available
247                        if (errorData.debug && errorData.debug.length > 0) {
248                            html += '<div class="sync-debug">';
249                            html += '<h4>Debug Information:</h4>';
250                            html += '<div style="background: #f0f0f0; padding: 10px; border-radius: 4px; max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px; white-space: pre-wrap;">';
251                            
252                            for (var i = 0; i < errorData.debug.length; i++) {
253                                html += errorData.debug[i] + '\n';
254                            }
255                            
256                            html += '</div>';
257                            html += '</div>';
258                        }
259                        
260                        syncResult.html(html).show();
261                        PressGaneyReviews.showNotification('Sync failed!', 'error');
262                    }
263                },
264                error: function(xhr, status, error) {
265                    syncResult.html('<div class="notice notice-error"><p>Sync failed: ' + error + '</p></div>').show();
266                    PressGaneyReviews.showNotification('Sync failed!', 'error');
267                },
268                complete: function() {
269                    // Reset button state
270                    button.prop('disabled', false);
271                    syncText.show();
272                    syncLoading.hide();
273                }
274            });
275        },
276
277        // Escape HTML to prevent XSS
278        escapeHtml: function(text) {
279            var map = {
280                '&': '&amp;',
281                '<': '&lt;',
282                '>': '&gt;',
283                '"': '&quot;',
284                "'": '&#039;'
285            };
286            return text.replace(/[&<>"']/g, function(m) { return map[m]; });
287        }
288    };
289
290    // Initialize when document is ready
291    $(document).ready(function() {
292        PressGaneyReviews.init();
293    });
294
295    // Add notification styles
296    $('<style>')
297        .prop('type', 'text/css')
298        .html(`
299            .pressganey-notification {
300                position: fixed;
301                top: 20px;
302                right: 20px;
303                padding: 12px 20px;
304                border-radius: 6px;
305                color: white;
306                font-weight: 500;
307                z-index: 9999;
308                transform: translateX(100%);
309                transition: transform 0.3s ease;
310                max-width: 300px;
311            }
312            .pressganey-notification-success {
313                background: #28a745;
314            }
315            .pressganey-notification-error {
316                background: #dc3545;
317            }
318            .pressganey-notification-show {
319                transform: translateX(0);
320            }
321        `)
322        .appendTo('head');
323
324})(jQuery); 

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.