1jQuery(document).ready(function($) { 2 'use strict'; 3 4 // Handle reaction clicks 5 $(document).on('click', '.gmpri-reaction-item', function(e) { 6 e.preventDefault(); 7 8 var $this = $(this); 9 var $wrapper = $this.closest('.gmpri-reactions-wrapper'); 10 var postId = $wrapper.data('post-id'); 11 var reactionType = $this.data('type'); 12 13 if (!postId || !reactionType) { 14 return; 15 } 16 17 // Disable buttons during request 18 $wrapper.find('.gmpri-reaction-item').css('pointer-events', 'none'); 19 20 $.ajax({ 21 url: gmpriAjax.ajaxUrl, 22 type: 'POST', 23 data: { 24 action: 'gmpri_add_reaction', 25 nonce: gmpriAjax.nonce, 26 post_id: postId, 27 reaction_type: reactionType 28 }, 29 success: function(response) { 30 if (response.success) { 31 // Update counts 32 var data = response.data; 33 34 // Update like count 35 $wrapper.find('.gmpri-like-btn .gmpri-reaction-count').text(data.likes); 36 37 // Update dislike count 38 $wrapper.find('.gmpri-dislike-btn .gmpri-reaction-count').text(data.dislikes); 39 40 // Update active states 41 $wrapper.find('.gmpri-reaction-item').removeClass('active'); 42 43 if (data.user_reaction) { 44 $wrapper.find('.gmpri-' + data.user_reaction + '-btn').addClass('active'); 45 } 46 } 47 }, 48 error: function(xhr, status, error) { 49 console.error('Reaction error:', error); 50 }, 51 complete: function() { 52 // Re-enable buttons 53 $wrapper.find('.gmpri-reaction-item').css('pointer-events', 'auto'); 54 } 55 }); 56 }); 57 58 // Handle bookmark toggle - FIXED: Get post_id properly 59 $(document).on('click', '.gmpri-bookmark-item', function(e) { 60 e.preventDefault(); 61 62 var $this = $(this); 63 var postId = $this.data('post-id'); 64 65 // If no post-id on bookmark item itself, try to get from parent wrapper 66 if (!postId) { 67 var $wrapper = $this.closest('.gmpri-reactions-wrapper'); 68 postId = $wrapper.data('post-id'); 69 } 70 71 if (!postId) { 72 console.error('No post ID found for bookmark'); 73 return; 74 } 75 76 $this.css('pointer-events', 'none'); 77 78 // SVG icons 79 var bookmarkIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>'; 80 var bookmarkFilledIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>'; 81 82 $.ajax({ 83 url: gmpriAjax.ajaxUrl, 84 type: 'POST', 85 data: { 86 action: 'gmpri_toggle_bookmark', 87 nonce: gmpriAjax.nonce, 88 post_id: postId 89 }, 90 success: function(response) { 91 if (response.success) { 92 if (response.data.is_bookmarked) { 93 $this.addClass('bookmarked'); 94 $this.find('.gmpri-reaction-icon').html(bookmarkFilledIcon); 95 } else { 96 $this.removeClass('bookmarked'); 97 $this.find('.gmpri-reaction-icon').html(bookmarkIcon); 98 } 99 } 100 }, 101 error: function(xhr, status, error) { 102 console.error('Bookmark error:', error); 103 }, 104 complete: function() { 105 $this.css('pointer-events', 'auto'); 106 } 107 }); 108 }); 109 110 // Handle share button click - FIXED: Get URL from data attributes, not window.location 111 $(document).on('click', '.gmpri-share-trigger', function(e) { 112 e.preventDefault(); 113 e.stopPropagation(); 114 115 var $this = $(this); 116 var postUrl, postTitle; 117 118 // Try to get from parent wrapper (for [gm_reactions] shortcode) 119 var $reactionsWrapper = $this.closest('.gmpri-reactions-wrapper'); 120 if ($reactionsWrapper.length) { 121 postUrl = $reactionsWrapper.data('post-url'); 122 postTitle = $reactionsWrapper.data('post-title'); 123 } 124 125 // Try to get from share button wrapper (for [gm_share_button] shortcode) 126 if (!postUrl) { 127 var $shareWrapper = $this.closest('.gmpri-share-button-wrapper'); 128 if ($shareWrapper.length) { 129 postUrl = $shareWrapper.data('post-url'); 130 postTitle = $shareWrapper.data('post-title'); 131 } 132 } 133 134 // Fallback to current page if no data attributes found (shouldn't happen) 135 if (!postUrl) { 136 postUrl = window.location.href; 137 postTitle = document.title; 138 } 139 140 // Check if Web Share API is available 141 if (navigator.share) { 142 navigator.share({ 143 title: postTitle, 144 url: postUrl 145 }).then(function() { 146 // Share successful - remove any active states 147 $this.blur(); 148 }).catch(function(error) {
149 console.log('Share cancelled or error:', error); 150 $this.blur(); 151 }); 152 } else { 153 // Fallback: Copy to clipboard 154 var tempInput = $('<input>'); 155 $('body').append(tempInput); 156 tempInput.val(postUrl).select(); 157 158 try { 159 document.execCommand('copy'); 160 161 // Show temporary success message 162 var $btn = $this; 163 var originalHtml = $btn.html(); 164 165 if ($btn.hasClass('gmpri-share-item')) { 166 // Icon only button 167 $btn.attr('title', 'Link copied!'); 168 setTimeout(function() { 169 $btn.attr('title', 'Share'); 170 }, 2000); 171 } else { 172 // Button with text 173 $btn.find('span:last').text('Copied!'); 174 setTimeout(function() { 175 $btn.html(originalHtml); 176 }, 2000); 177 } 178 } catch (err) { 179 console.error('Copy failed:', err); 180 // Final fallback: Open share dialog 181 var shareUrl = 'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(postUrl); 182 window.open(shareUrl, '_blank', 'width=600,height=400'); 183 } 184 185 tempInput.remove(); 186 $this.blur(); 187 } 188 }); 189});
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.