PageSourceSearch

https://tradingtacticasinversoras.es/wp-content/plugins/i-recommend-this/assets/js/irecommendthis.js?ver=4.0.1

js tradingtacticasinversoras.es collected 2026-10-05 23:20:00 UTC 9,302 bytes, 297 lines download raw bytes

1/**
2 * I Recommend This Plugin Script
3 *
4 * This script handles the AJAX-based "recommend" functionality in WordPress.
5 * It listens for clicks on elements with the .irecommendthis class and sends
6 * an AJAX request to update the recommendation count.
7 *
8 * @package IRecommendThis
9 * @version 4.0.0
10 */
11
12jQuery(
13	function ( $ ) {
14		'use strict';
15
16		// IRecommendThis main object - Using object literal pattern for organization.
17		const IRecommendThis = {
18			/**
19			 * Initialize the recommendation system.
20			 */
21			init: function () {
22				// Get configuration settings.
23				this.settings = this.getSettings();
24
25				// Initialize event listeners.
26				this.bindEvents();
27			},
28
29			/**
30			 * Get settings from the localized variables.
31			 *
32			 * WordPress passes plugin settings via wp_localize_script() which
33			 * creates the 'irecommendthis' global object with all our settings.
34			 */
35			getSettings: function () {
36				// Use only the new variable name.
37				let settings = ( typeof irecommendthis !== 'undefined' ) ? irecommendthis : null;
38
39				if ( ! settings ) {
40					console.error( 'AJAX settings not found - plugin may not be properly initialized.' );
41					return {
42						ajaxurl:       ajaxurl || '',
43						nonce:         '',
44						options:       '{}',
45						removal_delay: 250
46					};
47				}
48
49				// Parse options from JSON string to object.
50				try {
51					settings.parsedOptions = JSON.parse( settings.options );
52				} catch ( e ) {
53					console.error( 'Error parsing options JSON:', e );
54					settings.parsedOptions = {};
55				}
56
57				return settings;
58			},
59
60			/**
61			 * Bind event listeners for recommendation buttons.
62			 *
63			 * Uses event delegation to capture clicks on any current or future
64			 * recommendation buttons added to the page.
65			 */
66			bindEvents: function () {
67				// Use event delegation for all recommendation buttons.
68				$( document ).on( 'click', '.irecommendthis', this.handleRecommendClick.bind( this ) );
69			},
70
71			/**
72			 * Handle recommendation button clicks.
73			 *
74			 * This function processes user interactions with the recommendation buttons,
75			 * determines the post ID, and manages the button state.
76			 *
77			 * @param {Object} event The click event object.
78			 * @return {boolean} Returns false to prevent default action.
79			 */
80			handleRecommendClick: function ( event ) {
81				event.preventDefault();
82
83				const $link = $( event.currentTarget );
84
85				// Prevent multiple processing if this button is already in process.
86				if ( $link.hasClass( 'processing' ) ) {
87					return false;
88				}
89
90				// Get post ID from the button.
91				const postId = this.getPostId( $link );
92				if ( ! postId ) {
93					console.error( 'Could not determine post ID for recommendation.' );
94					return false;
95				}
96
97				// Get state information - whether this is a like or unlike action.
98				const unrecommend = $link.hasClass( 'active' );
99				const suffix      = $link.find( '.irecommendthis-suffix' ).text();
100
101				// Process the recommendation via AJAX.
102				this.processRecommendation( postId, unrecommend, suffix, $link );
103
104				return false;
105			},
106
107			/**
108			 * Extract the post ID from a recommendation link.
109			 *
110			 * Tries multiple methods to determine the post ID:
111			 * 1. From data-post-id attribute (preferred)
112			 * 2. From ID attribute
113			 * 3. From class names
114			 *
115			 * @param {Object} $el jQuery element object.
116			 * @return {string|null} The post ID or null if not found.
117			 */
118			getPostId: function ( $el ) {
119				// Try data attribute first (best practice).
120				let postId = $el.data( 'post-id' );
121
122				// Fall back to ID attribute.
123				if ( ! postId && $el.attr( 'id' ) ) {
124					postId = $el.attr( 'id' ).replace( 'irecommendthis-', '' );
125				}
126
127				// Last resort: check class names.
128				if ( ! postId && $el.attr( 'class' ) ) {
129					// Find class names that match our pattern.
130					$.each(
131						$el.attr( 'class' ).split( ' ' ),
132						function ( _, className ) {
133							if ( className.indexOf( 'irecommendthis-post-' ) === 0 ) {
134								postId = className.replace( 'irecommendthis-post-', '' );
135								// Break the each loop.
136								return false;
137							}
138						}
139					);
140				}
141
142				return postId;
143			},
144
145			/**
146			 * Process a recommendation through AJAX.
147			 *
148			 * Sends the request to the server to update the recommendation count
149			 * and handles the response.
150			 *
151			 * @param {string} postId      The post ID to recommend/unrecommend.
152			 * @param {boolean} unrecommend Whether this is an unrecommend action.
153			 * @param {string} suffix      The text suffix for the count.
154			 * @param {Object} $link       The jQuery button element that was clicked.
155			 */
156			processRecommendation: function ( postId, unrecommend, suffix, $link ) {
157				// Add a 'processing' class to prevent duplicate clicks.
158				$link.addClass( 'processing' );
159
160				// Get all buttons for this post for later updating (there might be multiple on the page).
161				const allButtons = this.getAllButtonsForPost( postId );
162
163				// Make a single AJAX request with simpler approach.
164				$.ajax(
165					{
166						url: this.settings.ajaxurl,
167						type: 'POST',
168						data: {
169							action: 'irecommendthis',
170							recommend_id: postId,
171							suffix: suffix,
172							unrecommend: unrecommend,
173							nonce: this.settings.nonce
174						},
175						success: function ( data ) {
176							// Handle the response.
177							IRecommendThis.handleSuccess( data, postId, unrecommend, allButtons );
178						},
179						error: function ( xhr, status, error ) {
180							IRecommendThis.handleError( xhr, status, error, $link );
181						},
182						complete: function () {
183							// Clean up processing state with a slight delay for visual feedback.
184							setTimeout(
185								function () {
186									allButtons.removeClass( 'processing' );
187								},
188								IRecommendThis.settings.removal_delay || 250
189							);
190						}
191					}
192				);
193			},
194
195			/**
196			 * Get all recommendation buttons for a specific post.
197			 *
198			 * Finds all buttons on the page that refer to the same post ID,
199			 * so they can all be updated simultaneously.
200			 *
201			 * @param {string} postId The post ID to find buttons for.
202			 * @return {Object} jQuery collection of matching buttons.
203			 */
204			getAllButtonsForPost: function ( postId ) {
205				// Create selector for all possible buttons matching this post ID.
206				return $( '.irecommendthis[data-post-id="' + postId + '"], #irecommendthis-' + postId + ', .irecommendthis-post-' + postId );
207			},
208
209			/**
210			 * Handle successful AJAX response.
211			 *
212			 * Updates all buttons for the post with new count and state.
213			 *
214			 * @param {string|Object} data       The response from the server.
215			 * @param {string} postId            The post ID that was acted upon.
216			 * @param {boolean} unrecommend      Whether this was an unrecommend action.
217			 * @param {Object} $buttons          jQuery collection of buttons to update.
218			 */
219			handleSuccess: function ( data, postId, unrecommend, $buttons ) {
220				// Check if the server responded with an error.
221				if ( typeof data === 'object' && data.success === false ) {
222					console.error( 'Error:', data.data ? data.data.message : 'Unknown error.' );
223					return;
224				}
225
226				const options = this.settings.parsedOptions;
227
228				// Get text states from data attributes or settings.
229				const defaultLikeText   = options.link_title_new || 'Recommend this';
230				const defaultUnlikeText = options.link_title_active || 'Unrecommend this';
231
232				// Update each matching button.
233				$buttons.each(
234					function () {
235						const $button = $( this );
236
237						// Get text state from data attributes (if available).
238						const likeText   = $button.data( 'like' ) || defaultLikeText;
239						const unlikeText = $button.data( 'unlike' ) || defaultUnlikeText;
240
241						// Replace the HTML content with the response data.
242						$button.html( data );
243
244						// Toggle the 'active' state.
245						$button.toggleClass( 'active' );
246
247						// Update both title and aria-label for accessibility.
248						const newState = $button.hasClass( 'active' ) ? unlikeText : likeText;
249						$button.attr( 'title', newState );
250						$button.attr( 'aria-label', newState );
251
252						// Check the numeric count, if present.
253						const $count = $button.find( '.irecommendthis-count' );
254						if ( $count.length ) {
255							const countText = $count.text().trim();
256							const count     = parseInt( countText, 10 );
257
258							if ( ! isNaN( count ) ) {
259								// Hide count if zero and user wants to hide zero counts.
260								if ( count === 0 && parseInt( options.hide_zero, 10 ) === 1 ) {
261									$count.hide();
262								} else {
263									$count.show();
264								}
265							}
266						}
267					}
268				);
269			},
270
271			/**
272			 * Handle AJAX errors.
273			 *
274			 * Logs error information and removes processing state.
275			 *
276			 * @param {Object} xhr    The XHR object.
277			 * @param {string} status The status text.
278			 * @param {string} error  The error message.
279			 * @param {Object} $link  The jQuery button element.
280			 */
281			handleError: function ( xhr, status, error, $link ) {
282				console.error( 'AJAX Error:', status, error );
283				if ( xhr.responseJSON && xhr.responseJSON.data ) {
284					console.error( 'Error details:', xhr.responseJSON.data );
285				}
286				$link.removeClass( 'processing' );
287			}
288		};
289
290		// Initialize when DOM is ready.
291		$(
292			function () {
293				IRecommendThis.init();
294			}
295		);
296	}
297);

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.