PageSourceSearch

https://www.califidparrotandexotic.com/wp-content/plugins/socialfeeds-pro/assets/js/frontend.js?ver=1.0.8

js califidparrotandexotic.com collected 2026-10-02 00:47:29 UTC 10,595 bytes, 303 lines download raw bytes

1jQuery(document).ready(function ($) {
2
3	// ===== INSTAGRAM PREMIUM LIGHTBOX (Matches Preview) =====
4	function init_insta_Modal() {
5		if (window._socialfeeds_modal_inited) return;
6		window._socialfeeds_modal_inited = true;
7
8		$(document).on('click', '.socialfeeds-open-modal-media', function (e) {
9			let $feedContainer = $(this).closest('.socialfeeds-instagram-feed, .socialfeeds-facebook-feed');
10			let isFacebook = $feedContainer.hasClass('socialfeeds-facebook-feed');
11			let playMode = $feedContainer.attr('data-play-mode') || 'newtab';
12
13			// Only intercept if play mode is lightbox
14			if (playMode !== 'lightbox') return;
15
16			e.preventDefault();
17
18			let mediaUrl = $(this).attr('data-media') || $(this).find('img').attr('src') || '';
19			let type = $(this).attr('data-type') || 'IMAGE';
20			let permalink = $(this).attr('data-permalink') || '#';
21
22			if (!mediaUrl) return;
23
24			let media_content = '';
25			if (type === 'VIDEO') {
26				media_content = `
27					<video src="${mediaUrl}" controls autoplay 
28						style="max-width: 90vw; max-height: 80vh; border-radius: 12px; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); border: 2px solid rgba(255,255,255,0.1);">
29						Your browser does not support the video tag.
30					</video>`;
31			} else {
32				media_content = `
33					<img src="${mediaUrl}" 
34						style="max-width: 90vw; max-height: 80vh; border-radius: 12px; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); object-fit: contain; border: 2px solid rgba(255,255,255,0.1);">`;
35			}
36
37			const $lightbox = $(`
38				<div class="socialfeeds-premium-lightbox" style="position: fixed; inset: 0; z-index: 999999; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(8px); background: rgba(0, 0, 0, 0.85); opacity: 0; transition: opacity 0.3s ease;">
39					<button class="close-btn" style="position: absolute; top: 30px; right: 30px; width: 44px; height: 44px; background: rgba(255,255,255,0.1); border: none; border-radius: 50%; color: white; font-size: 24px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s;">&times;</button>
40					<div class="lightbox-content-wrap" style="transform: scale(0.9); transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);">
41						${media_content}
42						${permalink && permalink !== '#' ? `<div style="text-align: center; margin-top: 15px;"><a href="${permalink}" target="_blank" style="color: white; text-decoration: none; background: rgba(255,255,255,0.1); padding: 8px 16px; border-radius: 20px; font-size: 13px; font-weight: 500;">View on ${isFacebook ? 'Facebook' : 'Instagram'}</a></div>` : ''}
43					</div>
44				</div>
45			`);
46
47			$('body').append($lightbox);
48
49			// Animate In
50			setTimeout(() => {
51				$lightbox.css('opacity', '1');
52				$lightbox.find('.lightbox-content-wrap').css('transform', 'scale(1)');
53			}, 10);
54
55			const close_lightbox = () => {
56				$lightbox.css('opacity', '0');
57				$lightbox.find('.lightbox-content-wrap').css('transform', 'scale(0.9)');
58				setTimeout(() => $lightbox.remove(), 300);
59			};
60
61			$lightbox.on('click', function (evt) {
62				if (evt.target === this || $(evt.target).hasClass('close-btn')) {
63					close_lightbox();
64				}
65			});
66
67			$(document).on('keydown.sf_lightbox_frontend', function (evt) {
68				if (evt.key === 'Escape') {
69					close_lightbox();
70					$(document).off('keydown.sf_lightbox_frontend');
71				}
72			});
73		});
74	}
75
76	$('.socialfeeds-load-more-btn').on('click', function (e) {
77		e.preventDefault();
78
79		let $btn = $(this);
80		
81		let feedType = $btn.data('feed-type');
82
83		// ===== INSTAGRAM LOAD MORE =====
84		if (feedType === 'instagram') {
85			let nextUrl = $btn.attr('data-next-url');
86			let loaded = parseInt($btn.data('loaded'), 10) || 0;
87			let $feed = $btn.closest('.socialfeeds-instagram-feed');
88			let $itemsContainer = $feed.find('.socialfeeds-instagram-inner');
89
90			if (!nextUrl) {
91				$btn.hide();
92				return;
93			}
94
95			let original_text = $btn.text();
96			$btn.prop('disabled', true).addClass('socialfeeds-loading');
97
98			$.ajax({
99				url: socialfeeds_ajax.ajax_url,
100				type: 'POST',
101				dataType: 'json',
102				data: {
103					action: 'socialfeeds_load_more_instagram',
104					next_url: nextUrl,
105					load_count: parseInt($btn.data('load-count')) || 12,
106					show_reels: $btn.data('show-reels'),
107	    			show_feed_posts: $btn.data('show-feed-posts'),
108					layout: $btn.data('layout'),
109					padding: $btn.data('padding'),
110					cols: $btn.data('cols'),
111					aspect_ratio: $btn.data('aspect-ratio'),
112					caption_enabled: $btn.data('caption-enabled'),
113					likes_enabled: $btn.data('likes-enabled'),
114					comments_enabled: $btn.data('comments-enabled'),
115					views_enabled: $btn.data('views-enabled'),
116					hover_state: $btn.data('hover-state'),
117					alignment: $btn.data('alignment') || 'left',
118					play_mode: $btn.data('play-mode'),
119					show_play_icon: $btn.data('show-play-icon'),
120					nonce: socialfeeds_ajax.nonce
121				},
122				success: function (response) {
123
124					if (!response.success || !response.data) {
125						$btn.text('No More Posts').hide();
126						return;
127					}
128
129					if (response.data.html) {
130						$itemsContainer.append(response.data.html);
131						// If carousel, trigger resize to update dots/nav
132						if ($itemsContainer.hasClass('layout-carousel')) {
133							$(window).trigger('resize');
134						}
135					}
136
137					let new_loaded = loaded + response.data.count;
138					$btn.data('loaded', new_loaded).attr('data-loaded', new_loaded);
139
140					if (response.data.next) {
141						$btn.attr('data-next-url', response.data.next);
142						$btn.prop('disabled', false)
143							.removeClass('socialfeeds-loading')
144							.text(original_text);
145					} else {
146						$btn.text('No More Posts').hide();
147					}
148				},
149				error: function () {
150					console.error('SocialFeeds Instagram AJAX Error');
151					$btn.prop('disabled', false)
152						.removeClass('socialfeeds-loading')
153						.text('Error loading posts');
154				}
155			});
156		}
157		// ===== FACEBOOK LOAD MORE =====
158		else if (feedType === 'facebook') {
159			let original_text = $btn.text();
160			let $feed = $btn.closest('.socialfeeds-facebook-feed');
161			let $itemsContainer = $feed.find('.socialfeeds-facebook-inner');
162			let feedId = $btn.data('feed-id');
163			let loadCount = parseInt($btn.data('load-count')) || 9;
164			// Use Facebook cursor-based pagination — numeric offset causes duplicate posts
165			let afterCursor = $btn.attr('data-after-cursor') || '';
166
167			if (!afterCursor) {
168				$btn.text('No More Posts').hide();
169				return;
170			}
171
172			// Collect IDs of posts already on the page so the server can filter duplicates
173			let existingIds = [];
174			$itemsContainer.find('.socialfeeds-facebook-item[data-post-id]').each(function () {
175				let pid = $(this).attr('data-post-id');
176				if (pid) existingIds.push(pid);
177			});
178
179			$btn.prop('disabled', true).text('Loading...');
180
181			$.ajax({
182				url: socialfeeds_ajax.ajax_url,
183				type: 'POST',
184				dataType: 'json',
185				data: {
186					action: 'socialfeeds_load_more_facebook',
187					feed_id: feedId,
188					load_count: loadCount,
189					after_cursor: afterCursor,
190					existing_ids: existingIds,
191					nonce: socialfeeds_ajax.nonce
192				},
193				success: function (response) {
194					if (!response.success || !response.data || !response.data.html) {
195						$btn.text('No More Posts').hide();
196						return;
197					}
198
199					$itemsContainer.append(response.data.html);
200
201					// If carousel, trigger resize
202					if ($itemsContainer.hasClass('layout-carousel')) {
203						$(window).trigger('resize');
204					}
205
206					// Store the next cursor so the following click fetches the correct page
207					let nextCursor = response.data.next_cursor || '';
208					$btn.attr('data-after-cursor', nextCursor);
209
210					if (response.data.has_more && nextCursor) {
211						$btn.prop('disabled', false).text(original_text);
212					} else {
213						$btn.text('No More Posts').hide();
214					}
215				},
216				error: function () {
217					$btn.prop('disabled', false).text('Error loading posts');
218				}
219			});
220		}
221	});
222
223	init_insta_Modal();
224
225	// ===== INSTAGRAM CAROUSEL =====
226	function init_insta_Carousel() {
227		$('.socialfeeds-instagram-inner.layout-carousel, .socialfeeds-facebook-inner.layout-carousel').each(function () {
228			let $carousel = $(this);
229			let $feedWrapper = $carousel.closest('.socialfeeds-instagram-feed');
230
231			// Prevent double init
232			if ($feedWrapper.find('.socialfeeds-carousel-stage').length) return;
233
234			$carousel.wrap('<div class="socialfeeds-carousel-stage" style="position:relative; width:100%;"></div>');
235			let $stage = $carousel.parent();
236
237			let $nav = $('<div class="socialfeeds-carousel-nav">' +
238				'<button class="socialfeeds-carousel-btn prev" aria-label="Previous" type="button"><span class="dashicons dashicons-arrow-left-alt2"></span></button>' +
239				'<button class="socialfeeds-carousel-btn next" aria-label="Next" type="button"><span class="dashicons dashicons-arrow-right-alt2"></span></button>' +
240				'</div>');
241
242			$stage.append($nav);
243
244			let $dots = $('<div class="socialfeeds-carousel-dots"></div>');
245			$stage.after($dots);
246
247			function updateDots() {
248				$dots.empty();
249				let scrollW = $carousel[0].scrollWidth;
250				let clientW = $carousel[0].clientWidth;
251				if (clientW >= scrollW) {
252					$dots.hide();
253					$nav.hide();
254					return;
255				}
256
257				$dots.show();
258				$nav.show();
259
260				let pageCount = Math.ceil(scrollW / clientW);
261				for (let i = 0; i < pageCount; i++) {
262					let $d = $('<span class="socialfeeds-dot"></span>');
263					if (i === 0) $d.addClass('active');
264					$d.data('page', i);
265					$dots.append($d);
266				}
267			}
268
269			setTimeout(updateDots, 300);
270			$(window).on('resize', updateDots);
271
272			// Scroll Events
273			$nav.find('.prev').on('click', function (e) {
274				e.preventDefault();
275				$carousel.animate({ scrollLeft: $carousel.scrollLeft() - $carousel.width() }, 300, update_active_dot);
276			});
277
278			$nav.find('.next').on('click', function (e) {
279				e.preventDefault();
280				$carousel.animate({ scrollLeft: $carousel.scrollLeft() + $carousel.width() }, 300, update_active_dot);
281			});
282
283			$dots.on('click', '.socialfeeds-dot', function () {
284				let page = $(this).data('page');
285				$carousel.animate({ scrollLeft: page * $carousel.width() }, 400, update_active_dot);
286			});
287
288			function update_active_dot() {
289				let scroll_left = $carousel.scrollLeft();
290				let clientW = $carousel[0].clientWidth;
291				let page = Math.round(scroll_left / (clientW || 1));
292				$dots.find('.socialfeeds-dot').removeClass('active').eq(page).addClass('active');
293			}
294
295			$carousel.on('scroll', function () {
296				clearTimeout($carousel.data('scrollTimer'));
297				$carousel.data('scrollTimer', setTimeout(update_active_dot, 100));
298			});
299		});
300	}
301
302	init_insta_Carousel();
303});

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.