PageSourceSearch

https://enhancesportsphysio.com.au/wp-content/plugins/trx_addons/a…/igenerator/igenerator.js?reload=1320095414

js enhancesportsphysio.com.au collected 2026-10-08 23:54:37 UTC 35,316 bytes, 817 lines download raw bytes

1/**
2 * Shortcode IGenerator - Generate images with AI
3 *
4 * @package ThemeREX Addons
5 * @since v2.20.2
6 */
7
8/* global jQuery, TRX_ADDONS_STORAGE */
9
10
11jQuery( document ).ready( function() {
12
13	"use strict";
14
15	var $window   = jQuery( window ),
16		$document = jQuery( document ),
17		$body     = jQuery( 'body' );
18
19	// OnLoad event for images - remove 'loading' class from the wrapper 'sc_igenerator_image_inner'
20	window.trx_addons_ai_helper_igenerator_load_image = function( $tag ) {
21		$tag.parents( '.sc_igenerator_image_inner' ).removeClass( 'sc_igenerator_image_loading' );
22	};
23
24	// OnError event for images - reload image if error occurs after 5 seconds
25	window.trx_addons_ai_helper_igenerator_reload_image = function( $tag ) {
26		if ( ( $tag.data( 'total-reloads' ) || 0 ) < 20 && $tag.attr( 'src' ) !== '' && trx_addons_is_external_url( $tag.attr( 'src' ) ) ) {
27			$tag
28				.data( 'total-reloads', ( $tag.data( 'total-reloads' ) || 0 ) + 1 )
29				.parents( '.sc_igenerator_image_inner' ).addClass( 'sc_igenerator_image_loading' );
30			var src = $tag.attr( 'src' );
31			setTimeout( function() {
32				$tag.attr( 'src', '' );
33				$tag.attr( 'src', src );
34			}, 5000 );
35		// } else {
36		// 	trx_addons_ai_helper_igenerator_load_image( $tag );
37		}
38	};
39
40	$document.on( 'action.init_hidden_elements', function(e, container) {
41
42		if ( container === undefined ) {
43			container = $body;
44		}
45
46		var animation_out = trx_addons_apply_filters( 'trx_addons_filter_sc_igenerator_animation_out', 'fadeOutDownSmall animated normal' ),
47			animation_in = trx_addons_apply_filters( 'trx_addons_filter_sc_igenerator_animation_in', 'fadeInUpSmall animated normal' );
48
49		// Init IGenerator
50		container.find( '.sc_igenerator:not(.sc_igenerator_inited)' ).each( function() {
51
52			var $sc = jQuery( this ).addClass( 'sc_igenerator_inited' ),
53				$form = $sc.find( '.sc_igenerator_form' ),
54				$prompt = $sc.find( '.sc_igenerator_form_field_prompt_text' ),
55				$negative_prompt = $sc.find( '.sc_igenerator_form_field_negative_prompt_text' ),
56				$upload_image = $sc.find( '.sc_igenerator_form_field_upload_image_field' ),
57				$button = $sc.hasClass( 'sc_igenerator_default' ) ? $sc.find( '.sc_igenerator_form_field_prompt_button' ) : $sc.find( '.sc_igenerator_form_field_generate_button' ),
58				$settings = $sc.find( '.sc_igenerator_form_settings' ),
59				$settings_button = $sc.find( '.sc_igenerator_form_settings_button' ),
60				settings_light = $sc.hasClass( 'sc_igenerator_default' ) && ! $settings.hasClass( 'sc_igenerator_form_settings_full' ),
61				$model = $sc.hasClass( 'sc_igenerator_default' ) ? $settings.find( '[name="sc_igenerator_form_settings_field_model"]' ) : $sc.find( '[name="sc_igenerator_form_field_model"]'),
62				$style = $sc.hasClass( 'sc_igenerator_default' ) ? $settings.find( '[name="sc_igenerator_form_settings_field_style"]' ) : $sc.find( '[name="sc_igenerator_form_field_style"]'),
63				$style_openai = $sc.hasClass( 'sc_igenerator_default' ) ? $settings.find( '[name="sc_igenerator_form_settings_field_style_openai"]' ) : $sc.find( '[name="sc_igenerator_form_field_style_openai"]'),
64				$size = $sc.hasClass( 'sc_igenerator_default' ) ? $settings.find( '[name="sc_igenerator_form_settings_field_size"]' ) : $sc.find( '[name="sc_igenerator_form_field_size"]'),
65				$width = $sc.hasClass( 'sc_igenerator_default' ) ? $settings.find( '[name="sc_igenerator_form_settings_field_width"]' ) : $sc.find( '[name="sc_igenerator_form_field_width"]'),
66				$height = $sc.hasClass( 'sc_igenerator_default' ) ? $settings.find( '[name="sc_igenerator_form_settings_field_height"]' ) : $sc.find( '[name="sc_igenerator_form_field_height"]'),
67				$preview = $sc.find( '.sc_igenerator_images' ),
68				$actions = $sc.find( '.sc_igenerator_form_actions' ),
69				$actions_slider = $sc.find( '.sc_igenerator_form_actions_slider:not(.sc_igenerator_form_actions_slider_inited)' ).addClass('sc_igenerator_form_actions_slider_inited'),
70				$upscaler = $sc.find( '[name="sc_igenerator_form_field_upscaler"]'),
71				fetch_img = '';
72
73			var need_resize = trx_addons_apply_filters( 'sc_igenerator_filter_need_resize', $sc.parents( '.sc_switcher' ).length > 0 ),
74				resize_delay = trx_addons_apply_filters( 'sc_igenerator_filter_resize_delay', animation_in || animation_out ? 400 : 0 );
75	
76			// Show/hide settings popup
77			$settings_button.on( 'click', function(e) {
78				e.preventDefault();
79				$settings.toggleClass( 'sc_igenerator_form_settings_show' );
80				return false;
81			} );
82			// Hide popup on click outside
83			$document.on( 'click', function(e) {
84				if ( $settings.hasClass( 'sc_igenerator_form_settings_show' ) && ! jQuery( e.target ).closest( '.sc_igenerator_form_settings' ).length ) {
85					$settings.removeClass( 'sc_igenerator_form_settings_show' );
86				}
87			} );
88			// Hide popup on a model selected by click (not by arrow keys) if settings are in the light mode (single field with model selector only)
89			if ( settings_light && $sc.hasClass( 'sc_igenerator_default' ) ) {
90				$model.on( 'click', function(e) {
91					setTimeout( function() {
92						$settings.removeClass( 'sc_igenerator_form_settings_show' );
93					}, 200 );
94				} );
95			}
96
97			$model.on( 'change', function() {
98				check_fields_visibility();
99			} );
100
101			$prompt.on( 'change keyup', function() {
102				check_fields_visibility();
103			} );
104
105			$upload_image.on( 'change', function() {
106				check_fields_visibility();
107			} );
108
109			$upscaler.on( 'change', function() {
110				check_fields_visibility();
111			} );
112
113			$size.on( 'change', function( e, from_check ) {
114				if ( ! from_check ) {
115					check_fields_visibility();
116				}
117			} );
118
119			// Inc/Dec the 'width' and 'height' fields on click on the arrows
120			if ( ! settings_light ) {
121				$sc
122					.find( '.sc_igenerator_form_settings_field_numeric_wrap_button_inc,.sc_igenerator_form_settings_field_numeric_wrap_button_dec,.sc_igenerator_form_field_numeric_wrap_button_inc,.sc_igenerator_form_field_numeric_wrap_button_dec' )
123						.on( 'click', function(e) {
124							e.preventDefault();
125							var $self = jQuery( this ),
126								$field = $self.parents( '.sc_igenerator_form_settings_field_numeric_wrap,.sc_igenerator_form_field_numeric_wrap' ).eq(0),
127								$input = $field.find( 'input' ),
128								val = Number( $input.val() || 0 ),
129								step = Number( $input.attr( 'step' ) || 1 ),
130								min = Number( $input.attr( 'min' ) || 0 ),
131								max = Number( $input.attr( 'max' ) || 1024 );
132							if ( $self.hasClass( 'sc_igenerator_form_settings_field_numeric_wrap_button_inc' ) || $self.hasClass( 'sc_igenerator_form_field_numeric_wrap_button_inc' ) ) {
133								val = Math.min( max, val + step );
134							} else {
135								val = Math.max( min, val - step );
136							}
137							// Round the value to 1 decimal place if the step is less than 1 to avoid endless digitals (7.699999999999999 instead of 7.7)
138							if ( step < 1 ) {
139								val = Math.round( val * 10 ) / 10;
140							}
141							$input.val( val ).trigger( 'change' );
142							return false;
143						} );
144			}
145
146			// Change the prompt text on click on the tag
147			$sc.on( 'click', '.sc_igenerator_form_field_tags_item,.sc_igenerator_message_translation', function(e) {
148				e.preventDefault();
149				var $self = jQuery( this ),
150					$prompt_field = $self.data( 'tag-type' ) == 'negative_prompt' ? $negative_prompt : $prompt;
151				if ( ! $prompt_field.attr( 'disabled' ) ) {
152					$prompt_field.val( $self.data( 'tag-prompt' ) ).trigger( 'change' ).get(0).focus();
153				}
154				return false;
155			} );
156
157			// Display file name in the decorated upload field text on change the file
158			$upload_image.on( 'change', function(e) {
159				var $self = jQuery( this ),
160					file = $self.val().replace( /\\/g, '/' ).replace( /.*\//, '' );
161				$self.parent()
162					.toggleClass( 'filled', true )
163					.find( '.sc_igenerator_form_field_upload_image_text' )
164						.removeClass( 'theme_form_field_placeholder' )
165						.text( file );
166			} );
167
168			// Close a message popup on click on the close button
169			$sc.on( 'click', '.sc_igenerator_message_close', function(e) {
170				e.preventDefault();
171				$form.find( '.sc_igenerator_message' ).slideUp();
172				return false;
173			} );
174
175			// Trigger the button on Enter key
176			$prompt.on( 'keydown', function(e) {
177				if ( e.keyCode == 13 ) {
178					e.preventDefault();
179					$button.trigger( 'click' );
180					return false;
181				}
182			} );
183
184			// Layout-specific actions: 'Default'
185			if ( $sc.hasClass( 'sc_igenerator_default' ) ) {
186				// Set padding for the prompt field to avoid overlapping the button
187				if ( $button.css( 'position' ) == 'absolute' ) {
188					var set_prompt_padding = ( function() {
189						$prompt.css( 'padding-right', ( Math.ceil( $button.outerWidth() ) + 10 ) + 'px' );
190					} )();
191					$window.on( 'resize', set_prompt_padding );
192				}
193			}
194
195			// Layout-specific actions: 'Extended'
196			if ( $sc.hasClass( 'sc_igenerator_extended' ) ) {
197
198				// Switch actions on click on the action button
199				$actions.on( 'click', 'a[data-action]', function(e) {
200					e.preventDefault();
201					var $self = jQuery( this ),
202						$item = $self.parent();
203					if ( ! $item.hasClass( 'sc_igenerator_form_actions_item_active' ) ) {
204						$item.siblings( '.sc_igenerator_form_actions_item_active' ).removeClass( 'sc_igenerator_form_actions_item_active' );
205						$item.addClass( 'sc_igenerator_form_actions_item_active' );
206						trx_addons_ai_helper_igenerator_move_slider_to_active_item();
207						check_fields_visibility();
208					}
209					return false;
210				} );
211
212				// Move slider to active item
213				window.trx_addons_ai_helper_igenerator_move_slider_to_active_item = function() {
214					var $active = $actions.find( '.sc_igenerator_form_actions_item_active a' );
215					if ( $active.length ) {
216						$actions_slider.css( {
217							left: $active.offset().left - $actions.offset().left,
218							width: $active.outerWidth()
219						} );
220					}
221				};
222				trx_addons_ai_helper_igenerator_move_slider_to_active_item();
223	
224				// Move slider to active item on resize
225				$document.on( 'action.resize_trx_addons', trx_addons_debounce( trx_addons_ai_helper_igenerator_move_slider_to_active_item, 200 ) );
226			}
227
228			function check_fields_visibility() {
229
230				var action = $sc.hasClass( 'sc_igenerator_extended' ) ? $actions.find( '.sc_igenerator_form_actions_item_active a' ).data( 'action' ) : 'generation';
231				var model = ( $model.length
232								? ( $model.is('input[type="radio"]') ? $model.filter( ':checked' ).val() : $model.val() )
233								: $form.data( 'igenerator-default-model' )
234							)
235							|| '';
236
237				// Enable/disable the button on change the prompt text
238				var disabled = false;
239				if ( action == 'generation' ) {
240					disabled = $prompt.attr( 'disabled' ) == 'disabled' || $prompt.val() == '';
241				} else if ( action == 'variations' || action == 'upscale' ) {
242					disabled = $upload_image.attr( 'disabled' ) == 'disabled' || $upload_image.val() == '';
243				}
244				$button.toggleClass( 'sc_igenerator_form_field_prompt_button_disabled sc_igenerator_form_field_disabled', disabled );
245
246				// Show/hide fields
247				$form.find( '.sc_igenerator_form_field,.sc_igenerator_form_settings_field' ).each( function() {
248					var $self = jQuery( this ),
249						visible = ! $sc.hasClass( 'sc_igenerator_extended' ) || ( '' + $self.data( 'actions' ) ).indexOf( action ) >= 0;
250
251					if ( $self.data( 'models' ) ) {
252						var parts = $self.data( 'models' ).split( ',' ),
253							allow = false;
254						for ( var i = 0; i < parts.length; i++ ) {
255							if ( model.indexOf( parts[i] ) >= 0 ) {
256								allow = true;
257								break;
258							}
259						}
260						visible &&= allow;
261					}
262
263					// If the field is 'model' in the layout 'extended' - disable the button 'settings' for the 'openai' model
264					if ( ! settings_light && $sc.hasClass( 'sc_igenerator_extended' ) && $self.attr( 'class' ).indexOf( 'field_model' ) > 0 ) {
265						$self.find( '.sc_igenerator_form_settings_button' ).toggleClass( 'trx_addons_hidden', model.indexOf( 'openai/' ) >= 0 || model.indexOf( 'x-ai/' ) >= 0 );
266					}
267
268					// If the field is 'style' - show it only for the 'stability-ai' model
269					if ( ! settings_light && $self.attr( 'class' ).indexOf( 'field_style' ) > 0 && $self.attr( 'class' ).indexOf( 'field_style_' ) < 0 ) {
270						visible &&= model.indexOf( 'stability-ai/' ) >= 0;
271					}
272
273					// If the field is 'style_openai' - show it only for the 'openai' model 'DALL-E-3'
274					if ( ! settings_light && $self.attr( 'class' ).indexOf( 'field_style_openai' ) > 0 ) {
275						visible &&= model.indexOf( 'openai/dall-e-3' ) >= 0;
276					}
277
278					// If the field is 'lora_model' - show it only for the 'stable-diffusion' models
279					if ( ! settings_light && $self.attr( 'class' ).indexOf( 'field_lora_model' ) > 0 ) {
280						visible &&= model.indexOf( 'stable-diffusion/' ) >= 0 && model != 'stable-diffusion/default';
281					}
282
283					// If the field is 'size' - show it for the not 'x-ai' models
284					if ( ! settings_light && $self.attr( 'class' ).indexOf( 'field_size' ) > 0 ) {
285						visible &&= model.indexOf( 'x-ai/' ) < 0;
286					}
287
288					// If the field is 'size'
289					if ( ! settings_light && $self.attr( 'class' ).indexOf( 'field_size' ) > 0 ) {
290						// Hide unavailable sizes for the selected model
291						$size.find( 'option' ).each( function() {
292							var $option = jQuery( this ),
293								val = $option.val(),
294								text = $option.text();
295							$option.toggleClass( 'trx_addons_hidden',
296								( model.indexOf( 'openai/' ) >
296= 0 && ( ! TRX_ADDONS_STORAGE['ai_helper_sc_igenerator_openai_sizes'] || ! TRX_ADDONS_STORAGE['ai_helper_sc_igenerator_openai_sizes'][ val ] ) )
297								|| ( model.indexOf( 'stable-diffusion/' ) >= 0 && text.indexOf( 'only' ) > 0 && text.indexOf( 'SD only' ) < 0 )
298								|| ( model.indexOf( 'stability-ai/' ) >= 0 && text.indexOf( 'only' ) > 0 && text.indexOf( 'Stability AI only' ) < 0 )
299							);
300							if ( $option.is( ':selected' ) && $option.hasClass( 'trx_addons_hidden' ) ) {
301								$size.val( '256x256' ).trigger( 'change', true );
302							}
303						} );
304						var upscaler_model = $upscaler.length ? ( $upscaler.val() || '' ) : '';
305						// Hide subfields 'width' and 'height' if the size is not 'custom'
306						$self.find( '.sc_igenerator_form_field_dimensions_wrap' ).toggleClass( 'trx_addons_hidden', action == 'upscale' ? upscaler_model.indexOf( 'stability-ai/' ) < 0 : $size.val() != 'custom' );
307						// Show/hide the 'size' field
308						$self.find( '.sc_igenerator_form_field_size_wrap' ).toggleClass( 'trx_addons_hidden', action == 'upscale' );
309						// Show/hide the 'scale' field
310						$self.find( '.sc_igenerator_form_field_scale_wrap' ).toggleClass( 'trx_addons_hidden', action != 'upscale' || upscaler_model.indexOf( 'stable-diffusion/' ) < 0 );
311					}
312
313					// If the field is 'width' or 'height' in the layout 'default' (popup with settings) - show it only for the 'custom' size
314					if ( ! settings_light && $sc.hasClass( 'sc_igenerator_default' ) && ( $self.attr( 'class' ).indexOf( 'field_width' ) > 0 || $self.attr( 'class' ).indexOf( 'field_height' ) > 0 ) ) {
315						visible &&= $size.val() == 'custom';
316					}
317
318					// If the field is 'negative_prompt' - show it for the not 'openai' models
319					if ( $self.attr( 'class' ).indexOf( 'field_negative_prompt' ) > 0 ) {
320						visible &&= model.indexOf( 'openai/' ) < 0;
321					}
322
323					$self.toggleClass( 'trx_addons_hidden', ! visible );
324				} );
325
326				if ( need_resize ) {
327					$document.trigger( 'action.resize_trx_addons' );
328				}
329			}
330
331			check_fields_visibility();
332
333			// Send request via AJAX to generate images
334			//-----------------------------------------
335			$button.on( 'click', function(e) {
336				e.preventDefault();
337
338				// if ( TRX_ADDONS_STORAGE['pagebuilder_preview_mode'] ) {
339				// 	alert( TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_disabled'] );
340				// 	return false;
341				// }
342
343				var action_type = $sc.hasClass( 'sc_igenerator_default' )
344									? ( $upload_image.length && $upload_image.val() ? 'variations' : 'generation' )
345									: $actions.find( '.sc_igenerator_form_actions_item_active a' ).data( 'action' ),
346					prompt = $prompt.val(),
347					negative_prompt = $negative_prompt.length ? $negative_prompt.val() : '',
348					model = action_type == 'upscale'
349								? $upscaler.val()
350								: ( ( settings_light ? $model.filter(':checked').val() : $model.val() ) || $form.data( 'igenerator-default-model' ) ),
351					settings = $form.data( 'igenerator-settings' );
352
353				if ( ( action_type != 'upscale' && ! prompt ) || ! check_limits() ) {
354					return false;
355				}
356
357				$form.addClass( 'sc_igenerator_form_loading' );
358
359				// Send request via AJAX
360				var data = {
361					nonce: TRX_ADDONS_STORAGE['ajax_nonce'],
362					action: 'trx_addons_ai_helper_igenerator',
363					action_type: action_type,
364					settings: settings,
365					prompt: prompt,
366					negative_prompt: model.indexOf( 'openai/' ) >= 0 ? '' : negative_prompt,
367					model: model,
368					count: ( trx_addons_get_cookie( 'trx_addons_ai_helper_igenerator_count' ) || 0 ) * 1 + 1
369				};
370				if ( ! settings_light ) {
371					data.size = $size.val();
372					if ( data.size == 'custom' || action_type == 'upscale' ) {
373						data.width = $width.val();
374						data.height = $height.val();
375					}
376					data.style = model.indexOf( 'stability-ai/' ) >= 0
377									? $style.val()
378									: ( model.indexOf( 'openai/dall-e-3' ) >= 0
379										? $style_openai.val()
380										: ''
381										);
382					if ( model.indexOf( 'stable-diffusion/' ) >= 0 && model != 'stable-diffusion/default' ) {
383						data.lora_model = $sc.find( '[name="sc_igenerator_form_field_lora_model"]' ).val();
384					}
385				}
386				if ( $sc.hasClass( 'sc_igenerator_extended' ) ) {
387					if ( action_type == 'upscale' ) {
388						data.scale = $form.find('input[name="sc_igenerator_form_field_scale"]').val() || 2;
389					}
390					if ( data.model.indexOf( 'stable-diffusion/' ) >= 0 ) {
391						data.guidance_scale = $sc.find( '[name="sc_igenerator_form_settings_field_guidance_scale"]' ).val();
392						data.inference_steps = $sc.find( '[name="sc_igenerator_form_settings_field_inference_steps"]' ).val();
393						data.seed = $sc.find( '[name="sc_igenerator_form_settings_field_seed"]' ).val();
394					} else if ( data.model.indexOf( 'stability-ai/' ) >= 0 ) {
395						if ( $sc.find( '[name="sc_igenerator_form_settings_field_strength"]' ).length ) {	// v2 (Beta)
396							data.strength = $sc.find( '[name="sc_igenerator_form_settings_field_strength"]' ).val();
397						} else {																			// v1 (Legacy)
398							data.cfg_scale = $sc.find( '[name="sc_igenerator_form_settings_field_cfg_scale"]' ).val();
399							data.diffusion_steps = $sc.find( '[name="sc_igenerator_form_settings_field_diffusion_steps"]' ).val();
400						}
401						data.seed = $sc.find( '[name="sc_igenerator_form_settings_field_seed"]' ).val();
402					}
403				}
404				// If upload image is present - convert data to FormData object and send via method ajax()
405				if ( $upload_image.length && $upload_image.val() && ['variations', 'upscale'].indexOf( data.action_type ) >= 0 ) {
406					var formData = new FormData();
407					for ( var key in data ) {
408						formData.append( key, data[key] );
409					}
410					formData.append( 'upload_image', $upload_image.get(0).files[0], $upload_image.get(0).files[0].name );
411					jQuery.ajax( {
412						url: TRX_ADDONS_STORAGE['ajax_url'],
413						type: "POST",
414						data: formData,
415						processData: false,		// Don't process fields to the string
416						contentType: false,		// Prevent content type header
417						success: getImages
418					} );
419				// Else send data via method post()
420				} else {
421					jQuery.post( TRX_ADDONS_STORAGE['ajax_url'], data, getImages );
422				}
423
424				// Callback to get images from server
425				function getImages( response ) {
426					// Prepare response
427					var rez = trx_addons_parse_ajax_response( response, TRX_ADDONS_STORAGE['msg_ai_helper_error'] );
428
429					$form.removeClass( 'sc_igenerator_form_loading' );
430
431					// Show images
432					if ( ! rez.error && rez.data ) {
433						var i = 0;
434						// If need to fetch images after timeout
435						if ( rez.data.fetch_id ) {
436							for ( i = 0; i < rez.data.fetch_number; i++ ) {
437								rez.data.images.push( {
438									url: rez.data.fetch_img
439								} );
440							}
441							if ( ! fetch_img ) {
442								fetch_img = rez.data.fetch_img;
443							}
444							var time = rez.data.fetch_time ? rez.data.fetch_time : 8000;
445							setTimeout( function() {
446								fetch_images( rez.data );
447							}, time );
448						}
449						if ( rez.data.images.length > 0 ) {
450							if ( ! rez.data.demo ) {
451								update_limits_counter( rez.data.images.length );
452								update_requests_counter();
453							}
454							var $images = $preview.find( '.sc_igenerator_image' );
455							if ( animation_in || animation_out ) {
456								$preview.css( {
457									'height': $images.length ? $preview.height() + 'px' : '36vh'
458								} );
459							}
460							if ( ! $images.length ) {
461								$preview.show();
462							} else if ( animation_out ) {
463								$images.removeClass( animation_in ).addClass( animation_out );
464							}
465							setTimeout( function() {
466								var currentDate = new Date();
467								var timestamp = currentDate.getTime();
468								var icon = $form.data( 'igenerator-download-icon' ) || 'trx_addons_icon-download';
469								var html = '<div class="sc_igenerator_columns_wrap sc_item_columns '
470												+ TRX_ADDONS_STORAGE['columns_wrap_class']
471												+ ' columns_padding_bottom'
472												+ ( rez.data.columns >
472= rez.data.number ? ' ' + TRX_ADDONS_STORAGE['columns_in_single_row_class'] : '' )
473												+ '">';
474								for ( var i = 0; i < rez.data.images.length; i++ ) {
475									html += '<div class="sc_igenerator_image ' + trx_addons_get_column_class( 1, rez.data.columns, rez.data.columns_tablet, rez.data.columns_mobile )
476												+ ( rez.data.fetch_id ? ' sc_igenerator_image_fetch' : '' )
477												+ ( animation_in ? ' ' + animation_in : '' )
478											+ '">'
479												+ '<div class="sc_igenerator_image_inner">'
480													+ '<span class="sc_igenerator_image_wrap">'
481														+ '<img src="' + rez.data.images[i].url + '" alt=""' + ( rez.data.fetch_id ? ' id="fetch-' + rez.data.fetch_id + '"' : '' )
482															+ ' width="1000" height="1000"'	// Set the size for images to show 'loading' indicator
483														+ '>'
484														+ '<span class="sc_igenerator_image_wait_available">'
485															+ '<span class="sc_igenerator_image_wait_icon"></span>'
486															+ '<span class="sc_igenerator_image_wait_msg">' + TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_wait_available'] + '</span>'
487														+ '</span>'
488													+ '</span>'
489													+ ( rez.data.fetch_id
490														? '<span class="sc_igenerator_image_fetch_info">'
491																+ '<span class="sc_igenerator_image_fetch_msg">' + rez.data.fetch_msg + '</span>'
492																+ '<span class="sc_igenerator_image_fetch_progress">'
493																	+ '<span class="sc_igenerator_image_fetch_progressbar"></span>'
494																+ '</span>'
495															+ '</span>'
496														: ''
497														)
498													+ ( ! rez.data.demo && rez.data.show_download
499														? '<a href="' + get_download_link( rez.data.images[i].url ) + '"'
500															+ ' download="' + prompt.replace( /[\s]+/g, '-' ).toLowerCase() + '"'
501															+ ' data-expired="' + ( ( rez.data.fetch_id ? 0 : timestamp ) + rez.data.show_download * 1000 ) + '"'
502															+ ' data-elementor-open-lightbox="no"'
503															//+ ' target="_blank"'
504															+ ' class="sc_igenerator_image_link sc_button sc_button_default sc_button_size_small sc_button_with_icon sc_button_icon_left"'
505															+ ' data-elementor-open-lightbox="no"'
506															+ '>'
507																+ ( icon && ! trx_addons_is_off( icon ) ? '<span class="sc_button_icon"><span class="' + icon + '"></span></span>' : '' )
508																+ '<span class="sc_button_text"><span class="sc_button_title">' + TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_download'] + '</span></span>'
509															+ '</a>'
510														: ''
511														)
512												+ '</div>'
513											+ '</div>';
514								}
515								html += '</div>';
516								$preview.html( html );
517								$preview
518									.find('.sc_igenerator_image_inner img')
519									.on( 'load', function() {
520										trx_addons_ai_helper_igenerator_load_image(jQuery(this));
521									} )
522									.on( 'error', function() {
523										trx_addons_ai_helper_igenerator_reload_image(jQuery(this));
524									} );
525								$preview
526									.find('.sc_igenerator_image_wait_available' )
527									.on( 'click', function(e) {
528										// Stop bubbling to avoid opening the image in the popup until the image is not available
529										e.stopPropagation();
530										return false;
531									} );
532
533								setTimeout( function() {
534									$preview.css( 'height', 'auto' );
535									$sc.addClass( 'sc_igenerator_images_show' );
536									prepare_images_for_popup();
537									if ( need_resize ) {
538//										setTimeout( function() {
539											trx_addons_when_images_loaded( $preview, function() {
540												$document.trigger( 'action.resize_trx_addons' );
541											} );
542//										}, resize_delay );
543									}
544								}, animation_in ? 700 : 0 );
545								// Check if download links are expired
546								$preview.find( '.sc_igenerator_image_link' ).on( 'click', function( e ) {
547									var currentDate = new Date();
548									var timestamp = currentDate.getTime();
549									var $link = jQuery( this );
550									if ( $link.attr( 'data-expired' ) && parseInt( $link.attr( 'data-expired' ), 10 ) < timestamp ) {
551										e.preventDefault();
552										if ( typeof trx_addons_msgbox_warning == 'function' ) {
553											trx_addons_msgbox_warning(
554												TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_download_expired'],
555												TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_download_error'],
556												'attention',
557												0,
558												[ TRX_ADDONS_STORAGE['msg_caption_ok'] ]
559											);
560										} else {
561											//alert( TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_download_expired'].replace( /<br>/g, "\n" ) );
562											show_message( TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_download_expired'], 'error' );
563										}
564										return false;
565									}
566								} );
567							}, $images.length && animation_out ? 700 : 0 );
568						}
569						if ( rez.data.message ) {
570							show_message( rez.data.message, rez.data.message_type );
571						}
572					} else {
573						if ( typeof trx_addons_msgbox_warning == 'function' ) {
574							trx_addons_msgbox_warning(
575								rez.error,
576								TRX_ADDONS_STORAGE['msg_ai_helper_igenerator_download_error'],
577								'attention',
578								0,
579								[ TRX_ADDONS_STORAGE['msg_caption_ok'] ]
580							);
581						} else {
582							//alert( rez.error );
583							show_message( rez.error, 'error' );
584						}
585					}
586				}
587			} );
588
589			// Fetch images
590			function fetch_images(data) {
591				jQuery.post( TRX_ADDONS_STORAGE['ajax_url'], {
592					nonce: TRX_ADDONS_STORAGE['ajax_nonce'],
593					action: 'trx_addons_ai_helper_fetch_images',
594					fetch_id: data.fetch_id,
595					fetch_url: data.fetch_url,
596					fetch_model: data.fetch_model
597				}, function( response ) {
598					var rez = trx_addons_parse_ajax_response( response, TRX_ADDONS_STORAGE['msg_ai_helper_error'] );
599					if ( ! rez.error ) {
600						if ( rez.data && rez.data.images && rez.data.images.length > 0 ) {
601							var images = rez.data.images,
602								$fetch = $preview.find( 'img#fetch-' + data.fetch_id );
603							// Fade out fetch placeholders
604							if ( animation_out ) {
605								for ( var i = 0; i < images.length; i++ ) {
606									$fetch.eq( i ).parents( '.sc_igenerator_image_fetch' )
607										.removeClass( animation_in )
608										.addClass( animation_out );
609								}
610							}
611							// Replace fetch placeholders with real images
612							setTimeout( function() {
613								var $download_link;
614								var currentDate = new Date();
615								var timestamp = currentDate.getTime();
616								for ( var i = 0; i < images.length; i++ ) {
617									$fetch.eq( i ).attr( 'src', images[i].url );
618									$download_link = $fetch.eq( i ).parents( '.sc_igenerator_image' ).find( '.sc_igenerator_image_link' );
619									$download_link.attr( 'href', get_download_link( images[i].url ) );
620									$download_link.attr( 'data-expired', parseInt( $download_link.attr( 'data-expired' ), 10 ) + timestamp );
621								}
622								if ( need_resize ) {
623									trx_addons_when_images_loaded( $preview, function() {
624										$document.trigger( 'action.resize_trx_addons' );
625									} );
626								}
627							}, animation_out ? 300 : 0 );
628							// Fade in real images
629							setTimeout( function() {
630								for ( var i = 0; i < images.length; i++ ) {
631									$fetch.eq( i )
632										.parents( '.sc_igenerator_image_fetch' )
633											.removeClass( 'sc_igenerator_image_fetch' )
634											.find( '.sc_igenerator_image_fetch_info')
635												.remove();
636									if ( animation_in ) {
637										trx_addons_when_images_loaded( $fetch.eq( i ).parents( '.sc_igenerator_image' ), function( $img ) {
638											$img
639												.removeClass( animation_out )
640												.addClass( animation_in );
641										} );
642									}
643								}
644								prepare_images_for_popup();
645								if ( need_resize ) {
646									setTimeout( function() {
647										trx_addons_when_images_loaded( $preview, function() {
648											$document.trigger( 'action.resize_trx_addons' );
649										} );
650									}, resize_delay );
651							}
652							}, animation_out ? 800 : 0 );
653						} else {
654							setTimeout( function() {
655								fetch_images( data );
656							}, data.fetch_time ? data.fetch_time : 8000 );
657						}
658					} else {
659						$preview.empty();
660						//alert( rez.error );
661						show_message( rez.error, 'error' );
662					}
663				} );
664			}
665
666			// Show message
667			function show_message( msg, type ) {
668				if ( msg.indexOf( '<p>' ) == -1 ) {
669					msg = '<p>' + msg + '</p>';
670				}
671				$form
672					.find( '.sc_igenerator_message_inner' )
673						.html( msg )
674						.parent()
675							.toggleClass( 'sc_igenerator_message_type_error', type == 'error' )
676							.toggleClass( 'sc_igenerator_message_type_info', type == 'info' )
677							.toggleClass( 'sc_igenerator_message_type_success', type == 'success' )
678							.addClass( 'sc_igenerator_message_show' )
679							.slideDown( function() {
680								if ( need_resize ) {
681									$document.trigger( 'action.resize_trx_addons' );
682								}
683							} );
684			}
685
686			// Check limits for generation images
687			function check_limits() {
688				// Block the button if the limits are exceeded only if the demo images are not selected in the shortcode params
689				if ( ! $form.data( 'igenerator-demo-images' ) ) {
690					var total, used, number;
691					// Check limits for the image generation
692					var $limit_total = $form.find( '.sc_igenerator_limits_total_value' ),
693						$limit_used  = $form.find( '.sc_igenerator_limits_used_value' );
694					if ( $limit_total.length && $limit_used.length ) {
695						total = parseInt( $limit_total.text(), 10 );
696						used  = parseInt( $limit_used.text(), 10 );
697						number = parseInt( $form.data( 'igenerator-number' ), 10 );
698						if ( ! isNaN( total ) && ! isNaN( used ) && ! isNaN( number ) ) {
699							if ( used >= total ) {
700								disable_fields();
701								return false;
702							}
703						}
704					}
705					// Check limits for the generation requests
706					var $requests_total = $form.find( '.sc_igenerator_limits_total_requests' ),
707						$requests_used  = $form.find( '.sc_igenerator_limits_used_requests' );
708					if ( $requests_total.length && $requests_used.length ) {
709						total = parseInt( $requests_total.text(), 10 );
710						//used  = parseInt( $requests_used.text(), 10 );
711						used = ( trx_addons_get_cookie( 'trx_addons_ai_helper_igenerator_count' ) || 0 ) * 1;
712						if ( ! isNaN( total ) && ! isNaN( used ) ) {
713							if ( used >= total ) {
714								disable_fields();
715								return false;
716							}
717						}
718					}
719				}
720				return true;
721			}
722
723			// Disable fields if limits are exceeded
724			function disable_fields() {
725				$button.toggleClass( 'sc_igenerator_form_field_prompt_button_disabled sc_igenerator_form_field_disabled', true );
726				$prompt.attr( 'disabled', 'disabled' );
727				$negative_prompt.attr( 'disabled', 'disabled' );
728				$upload_image.attr( 'disabled', 'disabled' );
729				if ( $sc.hasClass( 'sc_igenerator_extended' ) ) {
730					$model.attr( 'disabled', 'disabled' );
731					$size.attr( 'disabled', 'disabled' );
732					$width.attr( 'disabled', 'disabled' );
733					$height.attr( 'disabled', 'disabled' );
734				}
735				show_message( $form.data( 'igenerator-limit-exceed' ), 'error' );
736			}
737
738			// Update a counter of generated images inside a limits text
739			function update_limits_counter( number ) {
740				var total, used;
741				// Update a counter of the generated images
742				var $limit_total = $form.find( '.sc_igenerator_limits_total_value' ),
743					$limit_used  = $form.find( '.sc_igenerator_limits_used_value' );
744				if ( $limit_total.length && $limit_used.length ) {
745					total = parseInt( $limit_total.text(), 10 );
746					used  = parseInt( $limit_used.text(), 10 );
747					if ( ! isNaN( total ) && ! isNaN( used ) && ! isNaN( number ) ) {
748						if ( used < total ) {
749							used = Math.min( used + number, total );
750							$limit_used.text( used );
751						}
752					}
753				}
754				// Update a counter of the generation requests
755				var $requests_total = $form.find( '.sc_igenerator_limits_total_requests' ),
756					$requests_used  = $form.find( '.sc_igenerator_limits_used_requests' );
757				if ( $requests_total.length && $requests_used.length ) {
758					total = parseInt( $requests_total.text(), 10 );
759					// used  = parseInt( $requests_used.text(), 10 );
760					used = ( trx_addons_get_cookie( 'trx_addons_ai_helper_igenerator_count' ) || 0 ) * 1;
761					if ( ! isNaN( total ) && ! isNaN( used ) ) {
762						if ( used < total ) {
763							used = Math.min( used + 1, total );
764							$requests_used.text( used );
765						}
766					}
767				}
768			}
769
770			// Update a counter of the generation requests
771			function update_requests_counter() {
772				// Save a number of requests to the client storage
773				var count = trx_addons_get_cookie( 'trx_addons_ai_helper_igenerator_count' ) || 0,
774					limit = 60 * 60 * 1000 * 1,	// 1 hour
775					expired = limit - ( new Date().getTime() % limit );
776
777				trx_addons_set_cookie( 'trx_addons_ai_helper_igenerator_count', ++count, expired );
778			}
779
780			// Return an URL to download the image
781			function get_download_link( url ) {
782				return trx_addons_add_to_url( TRX_ADDONS_STORAGE['site_url'], {
783					'action': 'trx_addons_ai_helper_igenerator_download',
784					'image': trx_addons_get_file_name( url )
785				} );
786			}
787
788			// Wrap the image into the link to open it in the popup
789			function prepare_images_for_popup() {
790				var popup = $form.data( 'igenerator-popup' );
791				if ( popup ) {
792					var found = false;
793					$preview.find( '.sc_igenerator_image:not(.sc_igenerator_image_fetch) img' ).each( function() {
794						var $img = jQuery( this ),
795							$wrap = $img.parent(),
796							$link = $wrap.parent();
797						if ( $link.is( 'a' ) ) {
798							$link.attr( {
799								'href': $img.attr( 'src' ),
800								'data-elementor-open-lightbox': 'no'
801							} );
802						} else {
803							$wrap.wrap( '<a class="sc_igenerator_image_wrap_link" href="' + $img.attr( 'src' ) + '" rel="' + ( TRX_ADDONS_STORAGE['popup_engine'] == 'pretty' ? 'prettyPhoto[slideshow]' : 'magnific' ) + '" data-elementor-open-lightbox="no"></a>' );
804						}
805						found = true;
806					} );
807					if ( found ) {
808						$document.trigger( 'action.init_hidden_elements', [ $preview ] );
809					}
810				}
811			}
812
813		} );
814
815	} );
816
817} );

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.