PageSourceSearch

https://xn--80aaiayg0ak.xn--p1acf/wp-content/plugins/quotes-llama/includes/js/quotes-llama.js?m=1782571684

js xn--80aaiayg0ak.xn--p1acf collected 2026-10-04 13:33:59 UTC 54,851 bytes, 2,162 lines download raw bytes

1/**
2 * Quotes Llama JS
3 *
4 * Description. Javascript functions.
5 *
6 * @Link        http://wordpress.org/plugins/quotes-llama/
7 * @package     quotes-llama
8 * @since       1.0.0
9 * Version:     1.3.6
10 * License:     GPLv3
11 * License URI: https://www.gnu.org/licenses/gpl-3.0.html
12 */
13
14/**
15 * Url for admin-ajax.php.
16 *
17 * @since 1.0.0
18 * @var string
19 */
20var quotes_llama_ajaxurl = quotesllamaOption.ajaxurl;
21
22/**
23 * Page - Last localid in author list.
24 *
25 * @since 1.0.0
26 * @var integer
27 */
28var quotes_llama_cid = 0;
29
30/**
31 * Page - Current localid in author list.
32 *
33 * @since 1.0.0
34 * @var integer
35 */
36var quotes_llama_lastid = jQuery( '.quotes-llama-page-link' ).last().attr( 'localid' );
37
38/**
39 * Page - Background color.
40 *
41 * @since 1.0.0
42 * @var string
43 */
44var quotes_llama_foregroundcolor = quotesllamaOption.ForegroundColor;
45
46/**
47 * Page - Foreground color.
48 *
49 * @since 1.0.0
50 * @var string
51 */
52var quotes_llama_backgroundcolor = quotesllamaOption.BackgroundColor;
53
54/**
55 * Character limit before showing read more link.
56 *
57 * @since 1.0.0
58 * @var integer
59 */
60var quotes_llama_quotelimit = quotesllamaOption.Limit;
61
62/**
63 * Whether to display the countdown timer.
64 *
65 * @since 1.0.0
66 * @var integer
67 */
68var quotes_llama_show_timer = quotesllamaOption.GalleryShowTimer;
69
70/**
71 * Gallery interval... how long it displays.
72 *
73 * @since 1.0.0
74 * @var integer
75 */
76var quotes_llama_galleryinterval = quotesllamaOption.GalleryInterval;
77
78/**
79 * Gallery minimum time for display.
80 *
81 * @since 1.0.0
82 * @var integer
83 */
84var quotes_llama_galleryminimum = quotesllamaOption.GalleryMinimum;
85
86/**
87 * Quote limit Ellipses.
88 *
89 * @since 1.0.0
90 * @var string
91 */
92var quotes_llama_ellipses = quotesllamaOption.Ellipses;
93
94/**
95 * Sidebar position... Left or right.
96 *
97 * @since 1.0.0
98 * @var string
99 */
100var quotes_llama_sidebarpos = quotesllamaOption.Sidebarpos;
101
102/**
103 * Text displayed for read more link in limited quotes.
104 *
105 * @since 1.0.0
106 * @var string
107 */
108var quotes_llama_moretext = quotesllamaOption.MoreText;
109
110/**
111 * Text displayed for read less link in limited quotes.
112 *
113 * @since 1.0.0
114 * @var string
115 */
116var quotes_llama_lesstext = quotesllamaOption.LessText;
117
118/**
119 * Display quote source on a new line.
120 *
121 * @since 1.0.0
122 * @var string
123 */
124var quotes_llama_sourcenewline = quotesllamaOption.SourceNewLine;
125
126/**
127 * Display icons in quotes and sources.
128 *
129 * @since 1.0.0
130 * @var integer
131 */
132var quotes_llama_showicons = quotesllamaOption.ShowIcons;
133
134/**
135 * URL to uploads.
136 *
137 * @since 1.3.1
138 * @var string
139 */
140var quotes_llama_this_url = quotesllamaOption.ThisURL;
141
142/**
143 * Align image.
144 *
145 * @since 1.3.3
146 * @var bool
147 */
148var quotes_llama_borderradius = quotesllamaOption.BorderRadius;
149
150/**
151 * Align quote text... left, center, right.
152 *
153 * @since 1.3.3
154 * @var string
155 */
156var quotes_llama_alignquote = quotesllamaOption.AlignQuote;
157
158/**
159 * Center image above quote.
160 *
161 * @since 1.3.3
162 * @var bool
163 */
164var quotes_llama_imageattop = quotesllamaOption.ImageAtTop;
165
166/**
167 * Transition Speed.
168 *
169 * @since 1.3.4
170 * @var int
171 */
172var quotes_llama_transitionspeed = parseInt( quotesllamaOption.TransitionSpeed );
173
174/**
175 * All quotes from mysql.
176 *
177 * @since 3.1.0
178 * @var string
179 */
180var quotes_llama_quotes = quotesllamaOption.AllQuotes;
181
182/**
183 * Old Id of Auto quote for clearInterval.
184 *
185 * @since 3.1.6
186 * @var int
187 */
188var quotes_llama_old_auto_uid = 0;
189
190/**
191 * Old Id of Widget quote for clearInterval.
192 *
193 * @since 3.1.6
194 * @var int
195 */
196var quotes_llama_old_widget_uid = 0;
197
198// ***** Begin Admin *****
199
200/*
201 * Admin - Load media library and select a single image to get the thumbnail url.
202 *
203 * @since 1.0.0
204 *
205 * @param string selector        - Element to load image url into from selection in library.
206 * @param string button_selector - Element of button clicked to open the media library.
207 */
208function quotes_llama_media_gallery( selector, button_selector )  {
209	let clicked_button;
210	clicked_button = false;
211
212	jQuery(
213		selector
214	).each(
215		function (
216			i,
217			input
218		) {
219			let button;
220			button = jQuery( input ).next( button_selector );
221			button.click(
222				function (
223					event
224				) {
225					event.preventDefault();
226					let selected_img;
227					selected_img;
228					clicked_button = jQuery( this );
229
230					// Check for media manager instance.
231					if ( wp.media.frames.quotes_llama_frame ) {
232						wp.media.frames.quotes_llama_frame.open();
233						return;
234					}
235
236					// Configuration of the media manager new instance.
237					wp.media.frames.quotes_llama_frame = wp.media(
238						{
239							title: 'Select image',
240							multiple: false,
241							library: {
242								type: 'image'
243							},
244							button: {
245								text: 'Get Thumbnail URL'
246							}
247						}
248					);
249
250					let quotes_llama_media_gallery_set_image;
251					quotes_llama_media_gallery_set_image = function () {
252
253						// The image selected and media manager closing.
254						let selection;
255						selection = wp.media.frames.quotes_llama_frame.state().get( 'selection' );
256
257						// No selection.
258						if ( ! selection ) {
259							return;
260						}
261
262						// Iterate through selected elements.
263						selection.each(
264							function (	attachment ) {
265								// Get thumbnail url. View the object dump to get an idea of sizes available. var_dump(attachment.attributes);.
266								let url;
267								url = attachment.attributes.sizes.thumbnail.url;
268								clicked_button.prev( selector ).val( url );
269							}
270						);
271					};
272
273					// Closing event for media manger.
274					wp.media.frames.quotes_llama_frame.on( 'close', quotes_llama_media_gallery_set_image );
275
276					// Image selection event.
277					wp.media.frames.quotes_llama_frame.on( 'select', quotes_llama_media_gallery_set_image );
278
279					// Showing media manager.
280					wp.media.frames.quotes_llama_frame.open();
281				}
282			);
283		}
284	);
285};
286
287jQuery( // Admin - Select image from media library button click.
288	document
289).on(
290	'click',
291	'.quotes-llama-media-button',
292	function () {
293		quotes_llama_media_gallery( '#quotes_llama_imgurl', '.quotes-llama-media-button' );
294	}
295);
296
297// Admin - Run media gallery once so it is aware on first click in media library.
298quotes_llama_media_gallery( '#quotes_llama_imgurl', '.quotes-llama-media-button' );
299
300/*
301 * Manage tab - Category, click on category name to populate textbox for renaming or deleting.
302 *
303 * @since 2.0.5
304 */
305jQuery( '.ql-manage-cat' ).each(
306	function () {
307		jQuery( this ).on(
308			'click',
309			function () {
310
311				// Remove existing highlight.
312				jQuery( '.ql-manage-cat' ).css( 'text-decoration', 'none' );
313
314				let cat;
315				cat = jQuery( this ).html();
316
317				// Set textbox text.
318				jQuery(	'#ql-bulk-category' ).val( cat );
319
320				// Set old category, hidden.
321				jQuery( '#ql-bulk-category-old' ).val( cat );
322
323				// Highlight the button we selected.
324				jQuery(	this ).css( 'text-decoration', 'underline' );
325			}
326		)
327	}
328);
329
330/*
331 * Confirm some bulk change to the table data.
332 *
333 * @since 1.3.4
334 *
335 * @returns bool - true or false.
336 */
337function quotes_llama_change_table_confirm() {
338	return confirm( "Are you sure you want to take this action?\n This action cannot be undone!" );
339}
340
341/*
342 * Add a new category checkbox to the category list.
343 *
344 * @since 2.0.1
345 */
346jQuery(
347	document
348).on(
349	'click',
350	'#ql-new-cat-btn',
351	function () {
352		let container = jQuery( '.ql-category' );
353		let newCat    = jQuery( '#ql-new-category' ).val();
354
355		// Check we have something, add it and clear input field.
356		if ( newCat ) {
357			let category = '<label><input checked type="checkbox" name="ql_category[]" value="' + newCat + '"> ' + newCat + '</label><br>';
358			jQuery( category ).prependTo( container );
359			jQuery( '#ql-new-category' ).val( '' );
360		}
361	}
362);
363
364// ***** End Admin *****
365// ***** Begin Auto *****
366
367// Auto, Setup our auto divs if any one class is loaded. If has any elements, then it exists.
368if ( jQuery( '.quotes-llama-auto' )[0] ) {
369	let quotes_llama_auto;
370
371	quotes_llama_auto = jQuery( '.quotes-llama-auto' );
372	jQuery.each(
373		quotes_llama_auto,
374		function (
375			i,
376			list
377		) {
378			let quotes_llama_elements;
379			let quotes_llama_list_class;
380			let quotes_llama_auto_category;
381
382			quotes_llama_elements      = jQuery( list ).children( 'div' );
383			quotes_llama_list_class    = { data: [] };
384			quotes_llama_auto_category = quotes_llama_elements.attr( 'gcategory' );
385			quotes_llama_auto_nonce    = quotes_llama_elements.attr( 'gnonce' );
386
387			jQuery.each(
388				quotes_llama_elements,
389				function (
390					i,
391					element
392				) {
393					let quotes_llama_this_class;
394					quotes_llama_this_class         = jQuery( element ).attr( 'class' );
395					quotes_llama_list_class.data[i] = quotes_llama_this_class;
396				}
397			);
398
399			quotes_llama_quote( 'auto', true, quotes_llama_list_class.data, 0, quotes_llama_auto_category, quotes_llama_auto_nonce );
400		}
401	);
402}
403
404/*
405 * Auto, Re-enable quote auto-refresh.
406 */
407jQuery(
408	document
409).on(
410	'click',
411	'.quotes-llama-auto-reenable',
412	function () {
413
414		// If click id is Restart then enable gallery.
415		if ( jQuery( this ).children( 'span' ).attr( 'id' ) == 'quotes-llama-restart' ) {
416
417			let uid;
418			let rcategory;
419
420			// Get unique class name for this elements parent to load into.
421			uid = jQuery( this ).parent().attr( 'class' );
422
423			// Get category.
424			rcategory = jQuery( this ).parent().attr( 'gcategory' );
425			rnonce    = jQuery( this ).parent().attr( 'gnonce' );
426
427			// Get quote.
428			quotes_llama_quote( 'auto', true, uid, 0, rcategory, rnonce );
429
430			// Remove timer html.
431			jQuery( '.' + uid + '-reenable' ).html( '' );
432
433			// Set id of quote div to loop so on next click it will stop, not change the quote.
434			jQuery( '.' + uid + '-quotebox' ).attr( 'id', 'loop' );
435
436			// Set category.
437			jQuery( '.' + uid + '-quotebox' ).attr( 'gcategory', rcategory );
438		}
439	}
440);
441
442// ***** End auto *****
443// ***** Begin Gallery *****
444
445// Gallery, Setup our gallery divs if any one class is loaded. If has any elements, then it exists.
446if ( jQuery( '.quotes-llama-gallery' )[0] ) {
447	let quotes_llama_gallery;
448
449	quotes_llama_gallery = jQuery( '.quotes-llama-gallery' );
450
451	jQuery.each(
452		quotes_llama_gallery,
453		function (
454			i,
455			list
456		) {
457			let quotes_llama_elements;
458			let quotes_llama_list_class;
459			let quotes_llama_gallery_category;
460			let quotes_llama_gallery_nonce;
461
462			quotes_llama_elements         = jQuery( list ).children( 'div' );
463			quotes_llama_list_class       = { data: [] };
464			quotes_llama_gallery_category = quotes_llama_elements.attr( 'gcategory' );
465			quotes_llama_gallery_nonce    = quotes_llama_elements.attr( 'gnonce' );
466
467			jQuery.each(
468				quotes_llama_elements,
469				function (
470					i,
471					element
472				) {
473					let quotes_llama_this_class;
474					quotes_llama_this_class         = jQuery( element ).attr( 'class' );
475					quotes_llama_list_class.data[i] = quotes_llama_this_class;
476				}
477			);
478
479			quotes_llama_quote( 'gallery', true, quotes_llama_list_class.data, 0, quotes_llama_gallery_category, quotes_llama_gallery_nonce );
480		}
481	);
482}
483
484/*
485 * Gallery, Re-enable quote slideshow.
486 */
487jQuery(
488	document
489).on(
490	'click',
491	'.quotes-llama-gallery-reenable',
492	function () {
493
494		// If click id is Restart then enable gallery. Get unique class name for this elements parent to load into.
495		if ( jQuery( this ).children( 'span' ).attr( 'id' ) == 'quotes-llama-restart' ) {
496
497			let uid;
498			let lcategory;
499
500			uid = jQuery( this ).parent().parent().attr( 'class' );
501
502			lcategory = jQuery( this ).parent().parent().attr( 'gcategory' );
503			lnonce    = jQuery( this ).parent().parent().attr( 'gnonce' );
504
505			quotes_llama_quote( 'gallery', true, uid, 0, lcategory, lnonce );
506
507			// Remove timer html.
508			jQuery( '.' + uid + '-reenable' ).html( '' );
509
510			// Set id of quote div to loop so on next click it will stop, not change the quote.
511			jQuery( '.' + uid + '-quotebox' ).attr( 'id', 'loop' );
512
513			// Set category.
514			jQuery( '.' + uid + '-quotebox' ).attr( 'gcategory', lcategory );
515		}
516	}
517);
518
519/*
520 * Gallery, Manually click for next quote.
521 *
522 * @since 1.0.0
523 *
524 * @param string uid    - Unique class name.
525 * @param string tuid   - Quote timer id.
526 * @param string suid   - Seconds timer id.
527 * @param string mode   - Gallery or auto.
528 * @param string cat    - Category.
529 * @param string nonce  - nonce.
530 */
531function quotes_llama_manualnext( uid, tuid, suid, mode, cat, nonce ) {
532	let qid;
533
534	// Get ID of quote div for loop or manual.
535	qid = jQuery(
536		'.' + uid + '-quotebox'
537	).attr(
538		'id'
539	);
540
541	// If loop then this is first click.
542	if ( qid == 'loop' ) {
543
544		// Stop quote timer.
545		quotes_llama_stoptimer( tuid );
546
547		// Stop time timer.
548		quotes_llama_stoptimer( suid );
549
550		// Set re-enable link for starting timer again.
551		jQuery(
552			'.' + uid + '-countdown'
553		).html(
554			'<span class="' + uid + '-reenable dashicons dashicons-controls-forward" id="quotes-llama-restart" title="Restart"></span>'
555		);
556
557		// Set id of quote div to manual so on next click it will change the quote.
558		jQuery( '.' + uid + '-quotebox' ).attr( 'id', 'manual' );
559	} else {
560
561		// Loop already disabled so just get next quote.
562		quotes_llama_quote( mode, false, uid, 0, cat, nonce );
563	}
564}
565
566/*
567 *	Gallery, get random position and move next quote there.
568 *
569 * @since 1.0.0
570 *
571 *	@param string quotebox  - Unique class.
572 *	@param string container - Unique class parent.
573 */
574function quotes_llama_move( quotebox, container ) {
575	let new_top;
576	let new_left;
577	let parent_width;
578	let parent_height;
579	let quote_height;
580	let quote_from_top;
581	let container_width;
582
583	parent_height   = jQuery( '.' + container + '-quotes-llama-gallery' ).height() * .2;
584	parent_width    = jQuery( '.' + container + '-quotes-llama-gallery' ).width() * .4;
585	new_left        = Math.floor( quotes_llama_random_number( 0, parent_width ) );
586	new_top         = Math.floor( quotes_llama_random_number( 0, parent_height ) );
587	container_width = jQuery( '.' + container ).outerWidth();
588
589	// Top minimum in px.
590	if ( 26 > new_top ) {
591		new_top = 26;
592	}
593
594	// Set quotebox width.
595	jQuery( '.' + quotebox ).width( container_width - new_left - 15 );
596
597	// Move container div to new postion.
598	jQuery(
599		'.' + quotebox
600	).animate(
601		{
602			opacity: '0.1',
603			top: new_top,
604			left: new_left
605		},
606		quotes_llama_transitionspeed,
607		function () {
608
609			// Height of quote.
610			quote_height = jQuery( '.' + quotebox ).outerHeight();
611
612			// Pixels down from top.
613			quote_from_top = parseInt( jQuery( '.' + quotebox ).css( 'top' ), 20 );
614
615			// Resize container height to fit quote.
616			jQuery( '.' + container + '-quotes-llama-gallery' ).height( quote_height + quote_from_top );
617			jQuery( '.' + container + '-quotes-llama-gallery-rotate' ).height( quote_height + quote_from_top );
618		}
619	);
620}
621
622// ***** End Gallery *****
623// ***** Begin Widget *****
624
625// Widget, Setup widget instances for auto-refresh if any one class is loaded.
626if ( jQuery( '.quotes-llama-widget-gallery' )[0] ) {
627	let quotes_llama_this_widget;
628	quotes_llama_this_widget = jQuery( '.quotes-llama-widget-gallery' );
629	jQuery.each(
630		quotes_llama_this_widget,
631		function (
632			i,
633			list
634		) {
635			let quotes_llama_widget_uid;
636			quotes_llama_widget_uid   = jQuery( list ).attr( 'id' );
637			quotes_llama_widget_cat   = jQuery( list ).attr( 'category' );
638			quotes_llama_widget_nonce = jQuery( list ).attr( 'nonce' );
639			quotes_llama_widget_quote( quotes_llama_widget_uid, 0, quotes_llama_widget_cat, quotes_llama_widget_nonce );
640		}
641	);
642}
643
644/*
645 *	Widget, Next quote click.
646 */
647jQuery(
648	document
649).on(
650	'click',
651	'.quotes-llama-widget-next',
652	function () {
653		let author;
654		let source;
655		let category;
656		let img;
657		let div_instance;
658		let nonce;
659
660		author       = jQuery( this ).attr( 'author' );
661		source       = jQuery( this ).attr( 'source' );
662		category     = jQuery( this ).attr( 'category' );
663		img          = jQuery( this ).attr( 'img' );
664		div_instance = jQuery( this ).attr( 'divid' );
665		nonce        = jQuery( this ).attr( 'nonce' );
666
667		jQuery.post(
668			quotes_llama_ajaxurl,
669			{
670				action: 'widget_instance',
671				author: author,
672				source: source,
673				category: category,
674				img: img,
675				div_instance: div_instance,
676				nonce: nonce,
677			},
678			function ( response ) {
679				// Success, fadeout next link.
680				jQuery( '.quotes-llama-' + div_instance + '-next' ).fadeOut( 500 );
681
682				// Set response data to div. Strip return code 0 from ajax callback.
683				jQuery(
684					'#' + div_instance
685				).fadeOut(
686					quotes_llama_transitionspeed,
687					function () {
688						jQuery(
689							'#' + div_instance
690						).html(
691							response.substr( response.length - 1, 1 ) === '0' ? response.substr( 0, response.length - 1 ) : response
692						);
693
694						// Reformat quote if having character limit.
695						if ( quotes_llama_quotelimit > 0 ) {
696							quotes_llama_limit_format( '.quotes-llama-' + div_instance + '-next-more', div_instance + '-next' );
697							quotes_llama_limit_more( '.quotes-llama-' + div_instance + '-next-morelink' );
698
699							// Hide the extra text as element is created after styles.
700							jQuery(
701								'.quotes-llama-' + div_instance + '-next-morelink'
702							).prev().css(
703								'display',
704								'none'
705							);
706						}
707
708						// Make images round rather than rectangle, if settings allow.
709						if ( quotes_llama_borderradius ) {
710							jQuery( '.quotes-llama-widget-random img' ).css( 'border-radius', '50%' );
711						}
712
713						// Make images display above the quote, if settings allow.
714						if ( quotes_llama_imageattop ) {
715							jQuery( '.quotes-llama-widget-random img' ).css( quotes_llama_css_image_at_top() );
716						}
717
718						// Align quote and format icons.
719						jQuery( '.quotes-llama-widget-random' ).css( quotes_llama_css_align_quote() );
720						jQuery( '.quotes-llama-icons img' ).css( quotes_llama_css_icons_reformat() );
721
722						// Fadein quote.
723						jQuery( '#' + div_instance ).fadeIn( quotes_llama_transitionspeed );
724
725						// Fadein next link.
726						jQuery( '.quotes-llama-' + div_instance + '-next' ).fadeIn( 1000 );
727					}
728				);
729			}
730		);
731	}
732);
733
734/*
735 * Widget, auto-refresh random quote.
736 *
737 * @since 1.0.0
738 *
739 * @param array uid    - Our elements id.
740 * @param integer tuid - Timer for the id.
741 * @param string cat   - Category.
742 * @param string nonce - nonce.
743 */
744function quotes_llama_widget_quote( uid, tuid, cat, nonce ) {
745	let show_author;
746	let show_source;
747	let show_image;
748	show_author    = jQuery( '#' + uid ).attr( 'wauthor' );
749	show_source    = jQuery( '#' + uid ).attr( 'wsource' );
750	show_image     = jQuery( '#' + uid ).attr( 'wimage' );
751	let quote_data = [];
752	let quote_use  = [];
753	let cat_use    = [];
754	let cat_cats;
755	let cat_kits;
756	let quote_keys;
757	let quote_rand;
758
759	// If by category.
760	if ( cat ) {
761		jQuery.each(
762			quotes_llama_quotes,
763			function ( i, q ) {
764
765				// Split quote categories into array.
766				cat_cats = q.category.split( ',' );
767
768				// Split search categories.
769				cat_kits = cat.split( ',' );
770
771				// Cat found so using quote.
772				jQuery.each(
773					cat_kits,
774					function ( k, c ) {
775						if ( jQuery.inArray( c, cat_cats ) > -1 ) {
776							quote_use.push( q );
777							return;
778						}
779					}
780				);
781			}
782		);
783	} else {
784		quote_use = quotes_llama_quotes.slice();
785	}
786
787	// Quote keys.
788	quote_keys = Object.keys( quote_use );
789
790	// Random quote key.
791	quote_rand = quote_keys.length * Math.random();
792
793	// Random quote array.
794	quote_data = quote_use[quote_keys[ quote_rand << 0]];
795
796	// Fade out widget.
797	jQuery( '#' + uid ).stop( true, true ).fadeOut(
798		quotes_llama_transitionspeed,
799		function () {
800			let rand_quote;
801			let author_icon;
802			let source_icon;
803			let rand_title;
804			let rand_first;
805			let rand_last;
806			let rand_source;
807			let rand_img;
808			let rand_author_icon;
809			let rand_source_icon;
810			let rand_category;
811			let rand_comma;
812			let delayTime;
813			let rand_length;
814
815			rand_quote       = quotes_llama_stripslashes( quotes_llama_nl2br( quote_data.quote, false ) );
816			author_icon      = '';
817			source_icon      = '';
818			rand_title       = quotes_llama_stripslashes( quote_data.title_name ) + ' ';
819			rand_first       = quotes_llama_stripslashes( quote_data.first_name ) + ' ';
820			rand_last        = quotes_llama_stripslashes( quote_data.last_name );
821			rand_source      = quotes_llama_stripslashes( quote_data.source );
822			rand_img         = quotes_llama_stripslashes( quote_data.img_url );
823			rand_author_icon = quotes_llama_stripslashes( quote_data.author_icon );
824			rand_source_icon = quotes_llama_stripslashes( quote_data.source_icon );
825			rand_category    = quotes_llama_stripslashes( quote_data.category );
826			rand_comma       = '';
827
828			// If title is null.
829			if ( null === rand_title ) {
830				rand_title = '';
831			}
832
833			// If displaying icons in author.
834			author_icon = show_icons( rand_author_icon );
835
836			// If showing author, populate fields.
837			if ( rand_title && ( false == show_author ) ) {
838				rand_title = '';
839			}
840
841			if ( rand_first && ( false == show_author ) ) {
842				rand_first = '';
843			}
844
845			if ( rand_last && ( false == show_author ) ) {
846				rand_last = '';
847			}
848
849			// If showing both author and source, populate rand_comma.
850			if ( ( rand_first || rand_last && ( false != show_author ) ) && ( rand_source && ( false != show_source ) ) ) {
851
852				// If the options are set to put source on a new line populate a line break instead.
853				if ( quotes_llama_sourcenewline == 'br' ) {
854					rand_comma = '<br>';
855				} else {
856					rand_comma = ', ';
857				}
858			}
859
860			// If showing source, populate rand_source.
861			if ( rand_source && ( false != show_source ) ) {
862
863				// If displaying icons in source.
864				source_icon = show_icons( rand_source_icon );
865				rand_source = '<span class="quotes-llama-widget-source">' + rand_source + '</span>';
866			} else {
867				rand_source = '';
868			}
869
870			// If showing image, populate rand_img.
871			if ( rand_img && ( false != show_image  ) ) {
872				rand_img = '<img src="' + rand_img +
873				'" title="' + rand_title + rand_first + rand_last +
874				'">';
875			} else {
876				rand_img = '';
877			}
878
879			// Length of quote with author and source.
880			rand_length = rand_quote.length + rand_first.length + rand_last.length + rand_source.length;
881
882			// Delay from length rounded. If less than minimum set in options then set to minimum.
883			delayTime = parseInt( rand_length / quotes_llama_galleryinterval );
884
885			if ( delayTime < quotes_llama_galleryminimum ) {
886				delayTime = quotes_llama_galleryminimum;
887			}
888
889			// Set new timer interval.
890			jQuery(
891				'.quotes-llama-' + uid + '-countdown'
892			).quotes_llama_countdown(
893				delayTime,
894				'widget',
895				uid
896			);
897
898			// Stop timer, just to be sure.
899			quotes_llama_stoptimer( tuid );
900
901			// Schedule the next quote.
902			tuid = setInterval(
903				function () {
904					quotes_llama_stoptimer( tuid );
905					quotes_llama_widget_quote( uid, tuid, cat, nonce );
906				},
907				delayTime * 1000
908			);
909
910			// Render the widget to the display.
911			jQuery(
912				'#' + uid
913			).html(
914				'<div class="quotes-llama-widget-quote">' +
915				'<span class="quotes-llama-' + uid + '-countdown quotes-llama-widget-countdown"></span> ' +
916				rand_img + '<span class="quotes-llama-' + uid + '-more">' + rand_quote + '</span>' +
917				'<span class="quotes-llama-widget-author">' +
918				author_icon.trim() + rand_title + rand_first + rand_last + rand_comma +
919				'<span class="quotes-llama-widget-source">' + source_icon + rand_source + '</span>' +
920				'</span></div>'
921			);
922
923			// Reformat quote if having character limit.
924			if ( quotes_llama_quotelimit > 0 ) {
925				quotes_llama_limit_format( '.quotes-llama-' + uid + '-more', uid );
926				quotes_llama_limit_more( '.quotes-llama-' + uid + '-morelink' );
927
928				// Hide the extra text as element is created after styles.
929				jQuery(
930					'.quotes-llama-' + uid + '-morelink'
931				).prev().css(
932					'display',
933					'none'
934				);
935			}
936
937			// Make images round rather than rectangle, if settings allow.
938			if ( quotes_llama_borderradius ) {
939				jQuery( '.quotes-llama-widget-gallery img, .quotes-llama-widget-random img' ).css( 'border-radius', '50%' );
940			}
941
942			// Make images display above the quote, if settings allow.
943			if ( quotes_llama_imageattop ) {
944				jQuery( '.quotes-llama-widget-gallery img, .quotes-llama-widget-random img' ).css( quotes_llama_css_image_at_top() );
945			}
946
947			// Align quote and format icons.
948			jQuery( '.quotes-llama-widget-gallery, .quotes-llama-widget-random' ).css( quotes_llama_css_align_quote() );
949			jQuery( '.quotes-llama-icons img' ).css( quotes_llama_css_icons_reformat() );
950
951			// Fade in quotebox.
952			jQuery( '#' + uid ).fadeIn( quotes_llama_transitionspeed );
953		}
954	);
955}
956
957// ***** End Widget *****
958// ***** Begin Page *****
959
960/*
961 *	Page, Load quotes from selected author.
962 */
963jQuery( document ).on(
964	'click',
965	'.quotes-llama-page-link',
966	function () {
967		let title;
968		let first;
969		let last;
970		let nonce;
971		let localid;
972
973		title   = jQuery( this ).attr( 'title-name' );
974		first   = jQuery( this ).attr( 'first' );
975		last    = jQuery( this ).attr( 'last' );
976		nonce   = jQuery( this ).attr( 'nonce' );
977		localid = jQuery( this ).attr( 'localid' );
978
979		// Update status to loading.
980		jQuery(
981			'.quotes-llama-page-status'
982		).html(
983			'<center>Loading ' + title + ' ' + first + ' ' + last + '</center>'
984		);
985
986		jQuery.post(
987			quotes_llama_ajaxurl,
988			{
989				action: 'select_author',
990				author: 1,
991				title: title,
992				first: first,
993				last: last,
994				nonce: nonce
995			},
996			function ( quotes ) {
997
998				jQuery( '.quotes-llama-page-quote' ).fadeOut(
999					quotes_llama_transitionspeed,
1000					function () {
1001						jQuery( '.quotes-llama-page-quote' ).html( quotes );
1002
1003						// reformat quote if having character limit.
1004						if ( quotes_llama_quotelimit > 0 ) {
1005							quotes_llama_limit_format( '.quotes-llama-page-quote-more', 'page' );
1006							quotes_llama_limit_more( '.quotes-llama-page-morelink' );
1007						}
1008
1009						// Make images round rather than rectangle, if settings allow.
1010						if ( quotes_llama_borderradius ) {
1011							jQuery( '.quotes-llama-page-quote img' ).css( 'border-radius', '50%' );
1012						}
1013
1014						// Make images display above the quote, if settings allow.
1015						if ( quotes_llama_imageattop ) {
1016							jQuery( '.quotes-llama-page-quote img' ).css( quotes_llama_css_image_at_top() );
1017						}
1018
1019						// Align quote and format icons.
1020						jQuery( '.quotes-llama-page-quote' ).css( quotes_llama_css_align_quote() );
1021						jQuery( '.quotes-llama-icons img' ).css( quotes_llama_css_icons_reformat() );
1022						jQuery( '.quotes-llama-page-quote' ).fadeIn( quotes_llama_transitionspeed );
1023						jQuery(
1024							'.quotes-llama-page-status'
1025						).html(
1026							''
1027						);
1028					}
1029				);
1030			}
1031		);
1032
1033		// Update local authors ID for next/prev.
1034		quotes_llama_cid = localid;
1035
1036		// Move to top where quotes are loaded.
1037		jQuery(
1038			'html,body'
1039		).animate(
1040			{
1041				scrollTop: jQuery(
1042					'.quotes-llama-page-container'
1043				).offset().top - 40
1044			},
1045			1000
1046		);
1047	}
1048);
1049
1050/*
1051 * Page, Click next author button.
1052 */
1053jQuery(
1054	document
1055).on(
1056	'click',
1057	'.quotes-llama-page-next',
1058	function () {
1059
1060		// Increment local id for next element.
1061		++quotes_llama_cid;
1062
1063		// If at last in list, load last.
1064		if ( quotes_llama_cid >= quotes_llama_lastid ) {
1065			quotes_llama_cid = quotes_llama_lastid
1066		};
1067
1068		// Click next element.
1069		jQuery( '.quotes-llama-page-link' ).eq( quotes_llama_cid ).click();
1070		jQuery( '.quotes-llama-current' ).html( quotes_llama_cid );
1071	}
1072);
1073
1074/*
1075 * Page, Quote search.
1076 * Funtion also called after replacing innerHTML on print -
1077 * so that the search box will still work.
1078 */
1079jQuery(
1080	'div.quotes-llama-page-quotes-form'
1081).submit(
1082	function () {
1083		let quotesearch;
1084		let quotecolumn;
1085		let nonce;
1086
1087		// Get search value.
1088		quotesearch = jQuery( '.quotes-llama-page-quotesearch' ).val();
1089
1090		// Get search column.
1091		quotecolumn = jQuery( '.sc' ).val();
1092
1093		// Get nonce.
1094		nonce = jQuery( '.quotes-llama-page-token' ).val();
1095
1096		// Page mode.
1097		if ( quotesearch ) {
1098			jQuery(
1099				'.quotes-llama-page-status'
1100			).html(
1101				'<div>Searching... ' +
1102					quotesearch +
1103				'</div>'
1104			);
1105
1106			jQuery.post(
1107				quotes_llama_ajaxurl,
1108				{
1109					action: 'select_search_page',
1110					search_for_quote: 1,
1111					term: quotesearch,
1112					sc: quotecolumn,
1113					ql_token: nonce
1114				},
1115				function ( quotes ) {
1116					jQuery( '.quotes-llama-page-quote' ).fadeOut(
1117						quotes_llama_transitionspeed,
1118						function () {
1119							jQuery( '.quotes-llama-page-quote' ).html( quotes );
1120
1121							// Reformat quote if having character limit.
1122							if ( quotes_llama_quotelimit > 0 ) {
1123								quotes_llama_limit_format( '.quotes-llama-page-quote-more', 'page' );
1124								quotes_llama_limit_more( '.quotes-llama-page-morelink' );
1125							}
1126
1127							// Make images round rather than rectangle, if settings allow.
1128							if ( quotes_llama_borderradius ) {
1129								jQuery( '.quotes-llama-page-quote img' ).css( 'border-radius', '50%' );
1130							}
1131
1132							// Make images display above the quote, if settings allow.
1133							if ( quotes_llama_imageattop ) {
1134								jQuery( '.quotes-llama-page-quotebox img' ).css( quotes_llama_css_image_at_top() );
1135							}
1136
1137							// Align quote and format icons.
1138							jQuery( '.quotes-llama-page-author' ).css( quotes_llama_css_align_quote() );
1139							jQuery( '.quotes-llama-page-quotebox' ).css( quotes_llama_css_align_quote() );
1140							jQuery( '.quotes-llama-icons img' ).css( quotes_llama_css_icons_reformat() );
1141
1142							// Fade in quote.
1143							jQuery( '.quotes-llama-page-quote' ).fadeIn( quotes_llama_transitionspeed );
1144
1145							// Clear status.
1146							jQuery( '.quotes-llama-page-status' ).html( '' );
1147						}
1148					);
1149				}
1150			);
1151
1152			// Move to top where quotes are loaded.
1153			jQuery(
1154				'html, body'
1155			).animate(
1156				{
1157					scrollTop: jQuery(
1158						'.quotes-llama-page-sidebarleft'
1159					).offset().top - 30
1160				},
1161				1000
1162			);
1163		}
1164	}
1165);
1166
1167/*
1168 * Page, Prints an authors list of quotes.
1169 *
1170 * @since 1.0.0
1171 */
1172function quotes_llama_printdiv( s ) {
1173
1174	// Hide the return and print buttons from div to print.
1175	jQuery(
1176		'.quotes-llama-page-author-back'
1177	).hide();
1178
1179	// Fix image size - contributed by: Salvatore.
1180	jQuery(
1181		'.quotes-llama-page-more > img.emoji'
1182	).css(
1183		{
1184			'width'  : '15px',
1185			'height' : '15px'
1186		}
1187	);
1188
1189	jQuery(
1190		'.quotes-llama-page-more > img:not( [class] )'
1191	).css(
1192		{
1193			'width' : '150px',
1194			'height' : '150px'
1195		}
1196	);
1197
1198	// Copy the div content that we want to print into a var.
1199	let printContents;
1200	printContents = document.getElementById( 'quotes-llama-printquote' ).innerHTML;
1201
1202	// Show the return and print buttons for next author.
1203	jQuery( '.quotes-llama-page-author-back' ).show();
1204
1205	// Create print window.
1206	let mywindow;
1207	mywindow = window.open(
1208		'',
1209		'quotes-llama-window',
1210		'height=400',
1211		'width=600'
1212	);
1213
1214	// outterHMTL.
1215	mywindow.document.write( '<html><head><title>quotes</title></head><body>' );
1216
1217	// innerHTML.
1218	mywindow.document.write( printContents );
1219	mywindow.document.write( '</body></html>' );
1220
1221	// For IE >= 10.
1222	mywindow.document.close();
1223
1224	// IE >= 10.
1225	mywindow.focus();
1226
1227	// Execute print dialog.
1228	mywindow.print();
1229
1230	// Close window.
1231	mywindow.close();
1232}
1233
1234/*
1235 *	Page, Click print icon.
1236 */
1237jQuery( document ).on(
1238	'click',
1239	'.quotes-llama-print',
1240	function () {
1241		quotes_llama_printdiv();
1242	}
1243);
1244
1245/*
1246 * Page, Click previous author button.
1247 */
1248jQuery(
1249	document
1250).on(
1251	'click',
1252	'.quotes-llama-page-previous',
1253	function () {
1254
1255		// Decrement local id for previous element.
1256		--quotes_llama_cid;
1257
1258		// If at start of list load first.
1259		if ( quotes_llama_cid < 0 ) {
1260			quotes_llama_cid = 0
1261		};
1262
1263		// Click previous element.
1264		jQuery( '.quotes-llama-page-link' ).eq( quotes_llama_cid ).click();
1265		jQuery( '.quotes-llama-current' ).html( quotes_llama_cid );
1266	}
1267);
1268
1269// ***** End Page *****
1270// ***** Begin Search *****
1271
1272/*
1273 * Search, Quote search using search bar short-code.
1274 *
1275 * @since 2.2.3
1276 */
1277jQuery(
1278	'div.quotes-llama-search-quotes-form'
1279).submit(
1280	function () {
1281		var quotesearch;
1282		var quotecolumn;
1283		var quotetarget;
1284		var nonce;
1285
1286		// Get target class.
1287		quotetarget = jQuery( '.quotes-llama-search-quotesearch' ).attr( 'target' );
1288
1289		// Get search value.
1290		quotesearch = jQuery( '.quotes-llama-search-quotesearch' ).val();
1291
1292		// Get search column.
1293		quotecolumn = jQuery( '.sc' ).val();
1294
1295		// Get nonce.
1296		nonce = jQuery( '.quotes-llama-search-token' ).val();
1297
1298		if ( quotesearch ) {
1299
1300			// Check if output div exists as could be custom target.
1301			if ( jQuery( '.' + quotetarget ).length > 0 ) {
1302
1303				jQuery(
1304					'.quotes-llama-search-status'
1305				).html(
1306					'<div>Searching... ' +
1307						quotesearch +
1308					'</div>'
1309				);
1310
1311				jQuery.post(
1312					quotes_llama_ajaxurl,
1313					{
1314						action: 'select_search',
1315						search_form: 1,
1316						target: quotetarget,
1317						term: quotesearch,
1318						sc: quotecolumn,
1319						ql_token: nonce
1320					},
1321					function ( quote ) {
1322						jQuery( '.' + quotetarget ).fadeOut(
1323							quotes_llama_transitionspeed,
1324							function () {
1325								jQuery( '.' + quotetarget ).html( quote );
1326
1327								// Format image.
1328								jQuery( '.' + quotetarget + ' img' ).css(
1329									{
1330										'border-radius': '5px',
1331										'max-width': '150px',
1332										'max-height': '150px',
1333										'box-shadow': '5px 10px 12px 0px rgba(0,0,0,0.75)',
1334										'float': 'left',
1335										'object-fit': 'cover',
1336										'margin-right': '15px',
1337										'margin-bottom': '15px'
1338									}
1339								);
1340
1341								// Reformat quote if having character limit.
1342								if ( quotes_llama_quotelimit > 0 ) {
1343									quotes_llama_limit_format( '.' + quotetarget + '-quote-more', quotetarget, true );
1344									quotes_llama_limit_more( '.' + quotetarget + '-morelink' );
1345								}
1346
1347								// Hide the extra text as element is created after styles.
1348								jQuery(
1349									'.' + quotetarget + '-morelink'
1350								).prev().css(
1351									'display',
1352									'none'
1353								);
1354
1355								// Make images round rather than rectangle, if settings allow.
1356								if ( quotes_llama_borderradius ) {
1357									jQuery( '.' + quotetarget + ' img' ).css( 'border-radius', '50%' );
1358								}
1359
1360								// Make images display above the quote, if settings allow.
1361								if ( quotes_llama_imageattop ) {
1362									jQuery( '.' + quotetarget + '-quotebox img' ).css( quotes_llama_css_image_at_top() );
1363								}
1364
1365								// Align quote and format icons.
1366								jQuery( '.' + quotetarget + '-author' ).css( quotes_llama_css_align_quote() );
1367								jQuery( '.' + quotetarget + '-quotebox' ).css( quotes_llama_css_align_quote() );
1368								jQuery( '.quotes-llama-icons img' ).css( quotes_llama_css_icons_reformat() );
1369
1370								// Format source.
1371								jQuery( '.' + quotetarget + '-source' ).css(
1372									{
1373										'display': 'block',
1374										'text-align': 'right',
1375										'font-size': 'small',
1376										'font-style': 'italic'
1377									}
1378								);
1379
1380								// Format hr tag.
1381								jQuery( '.' + quotetarget + ' hr' ).css(
1382									{
1383										'clear': 'left'
1384									}
1385								);
1386
1387								// Format quotebox.
1388								jQuery( '.' + quotetarget + '-quotebox' ).css(
1389									{
1390										'padding': '5px'
1391									}
1392								);
1393
1394								// Fade in quote.
1395								jQuery( '.' + quotetarget ).fadeIn( quotes_llama_transitionspeed );
1396
1397								// Clear status.
1398								jQuery( '.quotes-llama-search-status' ).html( '' );
1399							}
1400						);
1401					}
1402				);
1403			} else {
1404
1405				// if no output class.
1406				jQuery(
1407					'.quotes-llama-search-status'
1408				).html(
1409					'<div style="font-size:small; color:red;"><li>Output class (' + quotetarget + ') not found.</li></div>'
1410				);
1411			}
1412		}
1413	}
1414);
1415
1416// ***** End Search *****
1417// ***** Begin Gallery-Auto-Widget *****
1418
1419/*
1420 * Gallery, Auto and Widget, Display countdown timer.
1421 *
1422 * @since 1.0.0
1423 *
1424 * @param int duration - Duration of countdown to display.
1425 * @param string mode - Either gallery or widget.
1426 * @param string uid - If gallery then unique element, if widget then timer id.
1427 *
1428 * Return int - (only if mode is gallery) ID of timer instance.
1429 */
1430jQuery.fn.quotes_llama_countdown = function ( duration, mode, uid ) {
1431
1432	// Must be enabled in options.
1433	if ( quotes_llama_show_timer ) {
1434		let gallery_timer;
1435		let widget_timer;
1436		let auto_timer;
1437
1438		gallery_timer = {};
1439		widget_timer  = {};
1440		auto_timer    = {};
1441
1442		if ( mode == 'gallery' ) {
1443
1444			// Clear the timer.
1445			quotes_llama_stoptimer( gallery_timer[uid] );
1446
1447			// Set the timer interval.
1448			gallery_timer[uid] = setInterval(
1449				function () {
1450
1451					// If seconds remain.
1452					if ( --duration > 0 ) {
1453
1454						// Update the timer display.
1455						jQuery( '.' + uid + '-countdown' ).html( '<small>' + duration + 's</small>' );
1456					}
1457				},
1458				1000
1459			); // Run every second.
1460
1461			// Clear the display.
1462			jQuery( '.' + uid + '-countdown' ).html( '' );
1463
1464			// Return id of timer instance.
1465			return gallery_timer[uid];
1466		}
1467
1468		if ( mode == 'auto' ) {
1469
1470			// Clear the timer with old uid.
1471			quotes_llama_stoptimer( auto_timer[quotes_llama_old_auto_uid] );
1472			quotes_llama_old_auto_uid = uid;
1473
1474			// Set the timer interval.
1475			auto_timer[uid] = setInterval(
1476				function () {
1477
1478					// If seconds remain.
1479					if ( --duration > 0 ) {
1480
1481						// Update the timer display.
1482						jQuery( '.' + uid + '-countdown' ).html( '<small>' + duration + 's</small>' );
1483					}
1484				},
1485				1000
1486			); // Run every second.
1487
1488			// Clear the display.
1489			jQuery( '.' + uid + '-countdown' ).html( '' );
1490
1491			// Return id of timer instance.
1492			return auto_timer[uid];
1493		}
1494
1495		if ( mode == 'widget' ) {
1496
1497			// Clear the timer.
1498			quotes_llama_stoptimer( widget_timer[quotes_llama_old_widget_uid] );
1499			quotes_llama_old_widget_uid = uid;
1500
1501			widget_timer[uid] = setInterval(
1502				function () {
1503					if ( --duration > 0 ) {
1504						jQuery(	'.quotes-llama-' + uid + '-countdown' ).html( '<small>' + duration + 's</small>' );
1505					}
1506				},
1507				1000
1508			);
1509		}
1510	}
1511};
1512
1513/*
1514 * Stop Countdown timer.
1515 *
1516 * @since 1.0.0
1517 *
1518 * @param string i - Name of timer to stop.
1519 */
1520function quotes_llama_stoptimer( i ) {
1521	clearInterval( i );
1522	i = false;
1523}
1524
1525/*
1526 *	Formats quote to the character limit specified in options.
1527 *
1528 * @since 1.0.0
1529 *
1530 *	@param string s      - full class name for quote to format.
1531 *	@param string m      - Class tag... if s is 'quotes-llama-auto-refresh-more' then m should be 'auto-refresh'.
1532 *	@param bool   search - If from search bar.
1533 */
1534function quotes_llama_limit_format( s, m, search = 0 ) {
1535	jQuery( s ).each(
1536		function () {
1537
1538			// If we are limiting the quote length in the options. To get a number from a string, prepend it with (+).
1539			if ( +quotes_llama_quotelimit > 0 ) {
1540				let content;
1541
1542				content = jQuery(
1543					this
1544				).html().trim();
1545
1546				// If quote length is greater than limit in options.
1547				if ( content.length > quotes_llama_quotelimit ) {
1548					let al;
1549					let eow;
1550					let stl;
1551					let ls;
1552					let rs;
1553					let html;
1554					let iend;
1555
1556					iend = 0;
1557
1558					// If first character is < then image, so get that length for exclusion.
1559					if ( content.charAt( 0 ) == '<' ) {
1560						iend = content.indexOf( '>' );
1561					}
1562
1563					// Everything after the limit.
1564					al = content.substr( +quotes_llama_quotelimit + iend );
1565
1566					// Make sure string ends in a word so asset doesn't become ass... get first space.
1567					eow = al.indexOf( ' ' );
1568
1569					// If limit is on last word of quote then just leave it at entire quote.
1570					if ( eow < 0 ) {
1571
1572						// In .each return true is equivelant to continue in a for loop, return false is exit.
1573						return;
1574					}
1575
1576					// Add length to next space to the limit.
1577					stl = +quotes_llama_quotelimit + iend + eow;
1578
1579					// The limited string.
1580					ls = content.substr( 0, stl );
1581
1582					// The remaining string.
1583					rs = content.substr( +quotes_llama_quotelimit + iend + eow );
1584
1585					// Create html for search bar or page.
1586					if ( search ) {
1587						html = ls + '<span class="quotes-llama-widget-moreellipses"> ' +
1588						quotes_llama_ellipses + '</span><span class="' + m + '-morecontent"><span>' +
1589						rs + '</span>&nbsp;<a href="" class="' + m + '-morelink">' + quotes_llama_moretext + '</a></span>';
1590					} else {
1591						// Page.
1592						html = ls + '<span class="quotes-llama-widget-moreellipses"> ' +
1593						quotes_llama_ellipses + '</span><span class="quotes-llama-' + m + '-morecontent"><span>' +
1594						rs + '</span>&nbsp;<a href="" class="quotes-llama-' + m + '-morelink">' + quotes_llama_moretext + '</a></span>';
1595					}
1596
1597					// Set quote html.
1598					jQuery( this ).html( html );
1599				}
1600			}
1601		}
1602	);
1603}
1604
1605/*
1606 * More or less class links for limited length quotes.
1607 *
1608 * @since 1.0.0
1609 *
1610 * @param string s - elements morelink class name.
1611 */
1612function quotes_llama_limit_more( s ) {
1613
1614	// Toggle more or less link on limited quotes.
1615	jQuery(
1616		s
1617	).click(
1618		function () {
1619
1620			if ( jQuery( this ).hasClass( 'quotes-llama-less' ) ) {
1621				jQuery( this ).removeClass( 'quotes-llama-less' );
1622				jQuery( this ).html( quotes_llama_moretext );
1623			} else {
1624				jQuery( this ).addClass( 'quotes-llama-less' );
1625				jQuery( this ).html( quotes_llama_lesstext );
1626			}
1627
1628			// Toggle visiblity of extra text and ellipses.
1629			jQuery( this ).parent().prev().toggle();
1630			jQuery( this ).prev().toggle();
1631
1632			return false;
1633		}
1634	);
1635}
1636
1637/*
1638 * Gallery and Auto, Render a random quote.
1639 *
1640 * @since 1.0.0
1641 *
1642 * @param string mode   - If 'gallery' then moves div to new random position.
1643 * @param bool loop     - If 'loop' will rotate quote.
1644 * @param string uid    - Unique element name.
1645 * @param int tuid      - Elements timer id.
1646 * @param string cat    - Category.
1647 * @param string nonce  - nonce.
1648 */
1649function quotes_llama_quote( mode, loop, uid, tuid, cat, nonce ) {
1650	let quote_data = [];
1651	let quote_use  = [];
1652	let cat_use    = [];
1653	let cat_cats;
1654	let cat_kits;
1655	let quote_keys;
1656	let quote_rand;
1657
1658	// If by category.
1659	if ( cat ) {
1660		jQuery.each(
1661			quotes_llama_quotes,
1662			function ( i, q ) {
1663
1664				// Split quote categories into array.
1665				cat_cats = q.category.split( ',' );
1666
1667				// Split search categories.
1668				cat_kits = cat.split( ',' );
1669
1670				// Cat found so using quote.
1671				jQuery.each(
1672					cat_kits,
1673					function ( k, c ) {
1674						if ( jQuery.inArray( c, cat_cats ) > -1 ) {
1675							quote_use.push( q );
1676							return;
1677						}
1678					}
1679				);
1680			}
1681		);
1682	} else {
1683		quote_use = quotes_llama_quotes.slice();
1684	}
1685
1686	// Quote keys.
1687	quote_keys = Object.keys( quote_use );
1688
1689	// Random quote key.
1690	quote_rand = quote_keys.length * Math.random();
1691
1692	// Random quote array.
1693	quote_data = quote_use[quote_keys[ quote_rand << 0]];
1694
1695	// Check that we have quote data.
1696	if ( quote_data.quote ) {
1697		let show_author;
1698		let show_source;
1699		let show_image;
1700		let gcategory;
1701
1702		// Are we going to display the Author.
1703		show_author = jQuery( '.' + uid ).attr( 'gauthor' );
1704
1705		// Are we going to display the source.
1706		show_source = jQuery( '.' + uid ).attr( 'gsource' );
1707
1708		// Are we going to display the image.
1709		show_image = jQuery( '.' + uid ).attr( 'gimage' );
1710
1711		// Category name.
1712		gcategory = jQuery( '.' + uid ).attr( 'gcategory' );
1713
1714		jQuery(
1715			'.' + uid + '-quotebox'
1716		).stop(
1717			true,
1718			true
1719		).fadeTo(
1720			quotes_llama_transitionspeed,
1721			0,
1722			function () {
1723				let rand_quote;
1724				let author_icon;
1725				let source_icon;
1726				let rand_title;
1727				let rand_first;
1728				let rand_last;
1729				let rand_source;
1730				let rand_img;
1731				let rand_author_icon;
1732				let rand_source_icon;
1733				let rand_comma;
1734				let suid;
1735
1736				rand_quote       = quotes_llama_stripslashes( quotes_llama_nl2br( quote_data.quote, false ) );
1737				author_icon      = '';
1738				source_icon      = '';
1739				rand_title       = quotes_llama_stripslashes( quote_data.title_name ) + ' '; // Add space so it will be trimmed if title not included.
1740				rand_first       = quotes_llama_stripslashes( quote_data.first_name ) + ' ';
1741				rand_last        = quotes_llama_stripslashes( quote_data.last_name );
1742				rand_source      = quotes_llama_stripslashes( quote_data.source );
1743				rand_img         = quotes_llama_stripslashes( quote_data.img_url );
1744				rand_author_icon = quotes_llama_stripslashes( quote_data.author_icon );
1745				rand_source_icon = quotes_llama_stripslashes( quote_data.source_icon );
1746				rand_comma       = '';
1747				suid             = 0;
1748
1749				// If title is null.
1750				if ( null === rand_title ) {
1751					rand_title = '';
1752				}
1753
1754				// If displaying authors.
1755				if ( (rand_first || rand_last) && show_author ) {
1756
1757					// If displaying icons in author.
1758					author_icon = show_icons( rand_author_icon );
1759				}
1760
1761				// If not showing author, empty strings.
1762				if ( rand_title && ( false == show_author ) ) {
1763					rand_title = '';
1764				}
1765
1766				if ( rand_first && ( false == show_author ) ) {
1767					rand_first = '';
1768				}
1769
1770				if ( rand_last && ( false == show_author ) ) {
1771					rand_last = '';
1772				}
1773
1774				// If showing both author and source, will we use a comma or break.
1775				if ( ( rand_first || rand_last && ( false != show_author ) ) && ( rand_source && ( false != show_source ) ) ) {
1776
1777					// If the options are set to put source on a new line populate a line break instead of comma.
1778					if ( quotes_llama_sourcenewline == 'br' ) {
1779						rand_comma = '<br>';
1780					} else {
1781						rand_comma = ', ';
1782					}
1783				}
1784
1785				// If showing source, populate rand_source.
1786				if ( rand_source && ( false != show_source ) ) {
1787
1788					// If using comma to separate author/source, omit source icon.
1789					if ( '<br>' === rand_comma ) {
1790						source_icon = show_icons( rand_source_icon );
1791					}
1792						rand_source = '<span class="quotes-llama-' + mode + '-source">' + rand_source + '</span>';
1793				} else {
1794					rand_source = '';
1795				}
1796
1797				// If showing author with no first or last name, omit title, icon and separator.
1798				if ( ' ' === rand_first && ! rand_last ) {
1799					rand_title  = '';
1800					author_icon = '';
1801					rand_comma  = '';
1802					source_icon = show_icons( rand_source_icon );
1803					rand_source = '<span class="quotes-llama-' + mode + '-source">' + rand_source + '</span>';
1804				}
1805
1806				// Trim completed name.
1807				let fin_name  = rand_title + rand_first + rand_last;
1808				let rand_name = fin_name.trim();
1809
1810				// If showing image, populate rand_img.
1811				if ( rand_img && ( false != show_image  ) ) {
1812					rand_img = '<img src="' + rand_img +
1813					'" title="' + rand_name +
1814					'">';
1815				} else {
1816					rand_img = '';
1817				}
1818
1819				// If to loop quotes.
1820				if ( loop ) {
1821					let rand_length;
1822					let delayTime;
1823
1824					// Length of quote with author and source.
1825					rand_length = rand_quote.length + rand_title.length + rand_name.length + rand_source.length;
1826
1827					// Delay from length rounded.
1828					delayTime = parseInt( rand_length / quotes_llama_galleryinterval );
1829
1830					if ( delayTime < quotes_llama_galleryminimum ) {
1831						delayTime = quotes_llama_galleryminimum;
1832					}
1833
1834					// Create new seconds timer if gallery.
1835					if ( mode == 'gallery' ) {
1836						suid = jQuery( '.' + uid + '-countdown' ).quotes_llama_countdown( delayTime, 'gallery', uid );
1837					}
1838
1839					// Create new seconds timer if auto.
1840					if ( mode == 'auto' ) {
1841						suid = jQuery( '.' + uid + '-countdown' ).quotes_llama_countdown( delayTime, 'auto', uid );
1842					}
1843
1844					// Stop time just in case.
1845					quotes_llama_stoptimer( tuid );
1846
1847					// Set quote timer to fire a new quote in so many seconds from now.
1848					tuid = setInterval(
1849						function () {
1850							quotes_llama_stoptimer( tuid );
1851							quotes_llama_quote(
1852								mode,
1853								true,
1854								uid,
1855								tuid,
1856								gcategory,
1857								nonce
1858							);
1859						},
1860						delayTime * 1000
1861					);
1862				}
1863
1864				// Mode being gallery or auto... Render to the div.
1865				jQuery( '.' + uid + '-quotebox' ).html(
1866					"<div class='quotes-llama-" + mode + "-quote quotes-llama-click' data-uid='" + uid + "' data-tuid='" + tuid + "' data-suid='" + suid + "' data-mode='" + mode + "' data-gc
1866ategory='" + gcategory + "' data-nonce='" + nonce + "'>" +
1867						rand_img +
1868						"<div class='quotes-llama-" + mode + "-quote quotes-llama-" + uid + "-more'>" +
1869							rand_quote +
1870							" <span class='quotes-llama-" + mode + "-author'>" +
1871								author_icon.trim() + rand_name + rand_comma +
1872								"<span class='quotes-llama-" + mode + "-source'>" + source_icon + rand_source + "</span>" +
1873							"</span>" +
1874						"</div>" +
1875					"</div>"
1876				);
1877
1878				// Reformat quote if having character limit.
1879				if ( quotes_llama_quotelimit > 0 ) {
1880					quotes_llama_limit_format(
1881						'.quotes-llama-' + uid + '-more',
1882						uid
1883					);
1884
1885					quotes_llama_limit_more(
1886						'.quotes-llama-' + uid + '-morelink'
1887					);
1888
1889					// Hide the extra text as element is created after styles.
1890					jQuery(
1891						'.quotes-llama-' + uid + '-morelink'
1892					).prev().css(
1893						'display',
1894						'none'
1895					);
1896				}
1897
1898				// Make images round rather than rectangle, if settings allow.
1899				if ( quotes_llama_borderradius ) {
1900					jQuery( '.quotes-llama-gallery img, .quotes-llama-auto img' ).css( 'border-radius', '50%' );
1901				}
1902
1903				// Make images display above the quote, if settings allow.
1904				if ( quotes_llama_imageattop ) {
1905					jQuery( '.quotes-llama-gallery img, .quotes-llama-auto img' ).css( quotes_llama_css_image_at_top() );
1906				}
1907
1908				// Align quote and format icons.
1909				jQuery( '.quotes-llama-gallery, .quotes-llama-auto-quote' ).css( quotes_llama_css_align_quote() );
1910				jQuery( '.quotes-llama-icons img' ).css( quotes_llama_css_icons_reformat() );
1911
1912				// Move to new random location if gallery mode.
1913				if ( mode == 'gallery' ) {
1914					quotes_llama_move( uid + '-quotebox', uid );
1915				}
1916
1917				// Fade in quotebox.
1918				jQuery( '.' + uid + '-quotebox' ).fadeTo( quotes_llama_transitionspeed, 1 );
1919			}
1920		);
1921	}
1922}
1923
1924// Listener for above function.
1925document.addEventListener(
1926	"click",
1927	function ( e ) {
1928		const elem = e.target.closest( ".quotes-llama-click" );
1929		if ( ! elem ) {
1930			return;
1931		}
1932
1933		quotes_llama_manualnext(
1934			elem.dataset.uid,
1935			parseInt( elem.dataset.tuid ),
1936			parseInt( elem.dataset.suid ),
1937			elem.dataset.mode,
1938			elem.dataset.gcategory,
1939			elem.dataset.nonce
1940		);
1941	}
1942);
1943
1944// ***** End Gallery-Auto-Widget *****
1945// ***** Begin Formats *****
1946
1947/*
1948 * Display icons in quotes.
1949 *
1950 * @since 1.3.1
1951 *
1952 * @param string icon - Dash-Icon name or image url.
1953 *
1954 * @returns string - html span element with icon, or no span at all.
1955 */
1956function show_icons( icon ) {
1957
1958	// If displaying icons in source.
1959	if ( quotes_llama_showicons ) {
1960		let png  = icon.includes( '.png' ); // If .png.
1961		let jpg  = icon.includes( '.jpg' ); // If .jpg.
1962		let jpeg = icon.includes( '.jpeg' ); // If .jpeg.
1963		let gif  = icon.includes( '.gif' ); // If .gif.
1964		let svg  = icon.includes( '.svg' ); // If .svg.
1965
1966		if ( png || jpg || jpeg || gif || svg ) {
1967			icon = '<span class="quotes-llama-icons"><img src="' + quotes_llama_this_url + icon + '"></span>';
1968		} else {
1969			icon = '<span class="dashicons dashicons-' + icon + '"></span>';
1970		}
1971
1972		return icon;
1973	}
1974
1975	return '';
1976}
1977
1978/*
1979 * Image css centered at top.
1980 *
1981 * @since 2.1.0
1982 */
1983function quotes_llama_css_image_at_top() {
1984	return {
1985		'float' : 'none',
1986		'display' : 'block',
1987		'margin-right' : 'auto',
1988		'margin-left' : 'auto',
1989		'width' : '50%',
1990		'max-height' : '150px'
1991	};
1992}
1993
1994/*
1995 * Align quote text.
1996 *
1997 * @since 2.1.0
1998 */
1999function quotes_llama_css_align_quote() {
2000	let align;
2001	align = quotes_llama_alignquote;
2002	return {'text-align' : align};
2003}
2004
2005/*
2006 * Icons css reformatted.
2007 *
2008 * @since 2.1.0
2009 */
2010function quotes_llama_css_icons_reformat() {
2011	return {
2012		'all' : 'unset',
2013		'display' : 'inline-block',
2014		'width' : '16px',
2015		'height' : '16px',
2016		'vertical-align' : 'middle',
2017		'margin-right' : '8px',
2018		'margin-bottom' : '1px',
2019		'text-align' : 'right',
2020		'float' : 'none'
2021	};
2022}
2023
2024/*
2025 * Equivalent to stripslashes() in php.
2026 *
2027 * @since 1.0.0
2028 *
2029 * @param string str - string to filter.
2030 *
2031 * returns string - string with backslashes stripped.
2032 */
2033function quotes_llama_stripslashes( str ) {
2034	return (
2035		str + ''
2036	).replace(
2037		/\\(.?)/g,
2038		function ( s, n1 ) {
2039			switch ( n1 ) {
2040				case '\\':
2041					return '\\';
2042				case '0':
2043					return '\u0000';
2044				case '':
2045					return '';
2046				default:
2047					return n1;
2048			}
2049		}
2050	);
2051}
2052
2053/*
2054 * Equivalent to var_dump() in php.
2055 *
2056 * @since 1.0.0
2057 *
2058 * @param string object       - String or object to dump.
2059 * @param bool doreturn       - Whether to return or alert. 1 alerts.
2060 *
2061 * @returns string - string with backslashes stripped.
2062 */
2063function quotes_llama_var_dump( object, doreturn ) {
2064	let returning;
2065	let elem;
2066
2067	returning = '';
2068
2069	for ( var element in object ) {
2070		elem = object[element];
2071
2072		if ( typeof elem == 'object' ) {
2073			elem = var_dump( object[element], true );
2074		}
2075
2076		returning += element + ': ' + elem + '\n';
2077	}
2078
2079	if ( returning == '' ) {
2080		returning = 'Empty object';
2081	}
2082
2083	if ( doreturn === true ) {
2084		return returning;
2085	}
2086
2087	alert( returning );
2088}
2089
2090// Generate random number.
2091function quotes_llama_random_number( min, max ) {
2092	return Math.random() * ( max - min );
2093}
2094
2095/*
2096 * nl2br Change \n into <br>.
2097 *
2098 * @param string str    - String to filter.
2099 * @param bool is_xhtml - true or false.
2100 *
2101 * @returns string - Filtered string.
2102 */
2103function quotes_llama_nl2br( str, is_xhtml ) {
2104	let breakTag;
2105
2106	if ( typeof str === 'undefined' || str === null ) {
2107		return '';
2108	}
2109
2110	breakTag = ( is_xhtml || typeof is_xhtml === 'undefined' ) ? '<br />' : '<br>';
2111	return ( str + '' ).replace( /([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2' );
2112}
2113
2114// Format any initial quotes if character limit.
2115if ( quotes_llama_quotelimit > 0 ) {
2116	quotes_llama_limit_format( '.quotes-llama-widget-more', 'widget' );
2117	quotes_llama_limit_more( '.quotes-llama-widget-morelink' );
2118	quotes_llama_limit_format( '.quotes-llama-widget-next-more', 'widget-next' );
2119	quotes_llama_limit_more( '.quotes-llama-widget-next-morelink' );
2120	quotes_llama_limit_format( '.quotes-llama-widget-static-more', 'widget-static' );
2121	quotes_llama_limit_more( '.quotes-llama-widget-static-morelink' );
2122}
2123
2124// Page - Sidebar position left or right.
2125jQuery( '.quotes-llama-page-sidebarleft' ).css( 'float', quotes_llama_sidebarpos );
2126
2127// Apply background color to index sidebar seperators. (background in options).
2128jQuery( '.quotes-llama-page-title, .quotes-llama-page-letter' ).css( 'background', quotes_llama_backgroundcolor );
2129
2130// Apply font color to index sidebar seperators. (foreground in options).
2131jQuery( '.quotes-llama-page-title, .quotes-llama-page-letter a' ).css( 'color', quotes_llama_foregroundcolor );
2132
2133// Make any remaining images round rather than rectangle, if settings allow.
2134if ( quotes_llama_borderradius ) {
2135	jQuery( '.quotes-llama-url-list img, .quotes-llama-widget-random img, .quotes-llama-count-quote img, .quotes-llama-id img, .quotes-llama-all-quote img' ).css( 'border-radius', '50%' );
2136}
2137
2138// Make remaining images display above the quote, if settings allow. Otherwise float image left.
2139if ( quotes_llama_imageattop ) {
2140	jQuery( '.quotes-llama-url-list img, .quotes-llama-widget-random img, .quotes-llama-count-quote img, .quotes-llama-id img, .quotes-llama-all-quote img' ).css( quotes_llama_css_image_at_top() );
2141}
2142
2143// Align remaining quotes and format icons.
2144jQuery( '.quotes-llama-widget-random, .quotes-llama-url-author, .quotes-llama-url-quote' ).css( quotes_llama_css_align_quote() );
2145jQuery( '.quotes-llama-icons img' ).css( quotes_llama_css_icons_reformat() );
2146
2147// Fadeout any messages.
2148jQuery( window ).on(
2149	'load',
2150	function () {
2151		if ( jQuery( '.qlmsg' ) [0] ) {
2152			setTimeout(
2153				function () {
2154					jQuery(
2155						'.qlmsg'
2156					).fadeOut( 1000 );
2157				},
2158				5000
2159			);
2160		}
2161	}
2162);

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.