PageSourceSearch

https://innovationbcc.org/wp-content/plugins/trx_addons/addons/ai-helper/shortcodes/vgenerator/vgenerator.js

js innovationbcc.org collected 2026-10-06 05:55:07 UTC 24,301 bytes, 611 lines download raw bytes

1/**
2 * Shortcode VGenerator - Generate videos 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 videos - remove 'loading' class from the wrapper 'sc_vgenerator_video_inner'
20	window.trx_addons_ai_helper_vgenerator_loadeddata_video = function( $tag ) {
21		$tag.parents( '.sc_vgenerator_video_inner' ).removeClass( 'sc_vgenerator_video_loading' );
22	};
23
24    // OnError event for videos - reload video if error occurs after 5 seconds
25	window.trx_addons_ai_helper_vgenerator_reload_video = 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_vgenerator_video_inner' ).addClass( 'sc_vgenerator_video_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_vgenerator_loadeddata_video( $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_vgenerator_animation_out', 'fadeOutDownSmall animated normal' ),
47			animation_in = trx_addons_apply_filters( 'trx_addons_filter_sc_vgenerator_animation_in', 'fadeInUpSmall animated normal' );
48
49        // Init vgenerator
50		container.find( '.sc_vgenerator:not(.sc_vgenerator_inited)' ).each( function() {
51
52            var $sc = jQuery( this ).addClass( 'sc_vgenerator_inited' ),
53                $form = $sc.find( '.sc_vgenerator_form' ),
54                $prompt = $sc.find( '.sc_vgenerator_form_field_prompt_text' ),
55                $button = $sc.find( '.sc_vgenerator_form_field_prompt_button' ),
56				$upload_keyframes = $sc.find( '.sc_vgenerator_form_field_upload_keyframe_field' ),
57				$keyframes_frame0 = $upload_keyframes.filter( '.sc_vgenerator_form_field_upload_start_keyframe_field' ),
58				$keyframes_frame1 = $upload_keyframes.filter( '.sc_vgenerator_form_field_upload_end_keyframe_field' ),
59                $settings = $sc.find( '.sc_vgenerator_form_settings' ),
60                $settings_button = $sc.find( '.sc_vgenerator_form_settings_button' ),
61                $model = $settings.find( '[name="sc_vgenerator_form_settings_field_model"]' ),
62                $settings_aspect_ratio = $settings.find( '[name="sc_vgenerator_form_settings_field_aspect_ratio"]' ),
63                $settings_resolution = $settings.find( '[name="sc_vgenerator_form_settings_field_resolution"]' ),
64                $settings_duration = $settings.find( '[name="sc_vgenerator_form_settings_field_duration"]' ),
65                $preview = $sc.find( '.sc_vgenerator_videos' );
66
67            var need_resize = trx_addons_apply_filters( 'sc_vgenerator_filter_need_resize', $sc.parents( '.sc_switcher' ).length > 0 ),
68				resize_delay = trx_addons_apply_filters( 'sc_vgenerator_filter_resize_delay', animation_in || animation_out ? 400 : 0 );
69
70            // Show/hide settings popup
71			$settings_button.on( 'click', function(e) {
72				e.preventDefault();
73				$settings.toggleClass( 'sc_vgenerator_form_settings_show' );
74				return false;
75			} );
76			// Hide popup on click outside
77			$document.on( 'click', function(e) {
78				if ( $settings.hasClass( 'sc_vgenerator_form_settings_show' ) && ! jQuery( e.target ).closest( '.sc_vgenerator_form_settings' ).length ) {
79					$settings.removeClass( 'sc_vgenerator_form_settings_show' );
80				}
81			} );
82
83			$model.on( 'change', function() {
84				check_fields_visibility();
85			} );
86
87			$prompt.on( 'change keyup', function() {
88				check_fields_visibility();
89			} );
90
91			$upload_keyframes.on( 'change keyup', function() {
92				check_fields_visibility();
93			} );
94
95            // Change the prompt text on click on the tag
96			$sc.on( 'click', '.sc_vgenerator_form_field_tags_item,.sc_vgenerator_message_translation', function(e) {
97				e.preventDefault();
98				var $self = jQuery( this );
99				if ( ! $prompt.attr( 'disabled' ) ) {
100					$prompt.val( $self.data( 'tag-prompt' ) ).trigger( 'change' ).get(0).focus();
101				}
102				return false;
103			} );
104
105			// Display file name in the decorated upload field text on change the file
106			$upload_keyframes.on( 'change', function(e) {
107				var $self = jQuery( this ),
108					file = $self.val() ? $self.val().replace( /\\/g, '/' ).replace( /.*\//, '' ) : $self.data( 'text-placeholder' ) || '';
109				$self.parent()
110					.toggleClass( 'filled', true )
111					.find( '.sc_vgenerator_form_field_upload_keyframe_text' )
112						.removeClass( 'theme_form_field_placeholder' )
113						.text( file );
114			} );
115
116            // Close a message popup on click on the close button
117			$sc.on( 'click', '.sc_vgenerator_message_close', function(e) {
118				e.preventDefault();
119				$form.find( '.sc_vgenerator_message' ).slideUp();
120				return false;
121			} );
122
123            // Trigger the button on Enter key
124			$prompt.on( 'keydown', function(e) {
125				if ( e.keyCode == 13 ) {
126					e.preventDefault();
127					$button.trigger( 'click' );
128					return false;
129				}
130			} );
131
132			// Set padding for the prompt field to avoid overlapping the button
133			if ( $button.css( 'position' ) == 'absolute' ) {
134				var set_prompt_padding = ( function() {
135					$prompt.css( 'padding-right', ( Math.ceil( $button.outerWidth() ) + 10 ) + 'px' );
136				} )();
137				$window.on( 'resize', set_prompt_padding );
138			}
139
140            // Check fields visibility
141			function check_fields_visibility() {
142
143				var model = ( $model.is('input[type="radio"]') ? $model.filter( ':checked' ).val() : $model.val() ) || '';
144
145				// Enable/disable the button on change the prompt text
146				var disabled = $prompt.attr( 'disabled' ) == 'disabled' || $prompt.val() == '';
147				$button.toggleClass( 'sc_vgenerator_form_field_prompt_button_disabled', disabled );
148
149				$form.find( '.sc_vgenerator_form_field,.sc_vgenerator_form_settings_field' ).each( function () {
150					var $self = jQuery( this );
151
152					if ( $self.hasClass( 'sc_vgenerator_form_settings_field_resolution' ) || $self.hasClass( 'sc_vgenerator_form_settings_field_duration' ) ) {
153						$self.toggleClass( 'trx_addons_hidden', model == 'lumalabs-ai/ray-1-6' );
154					}
155
156					if ( $self.hasClass( 'sc_vgenerator_form_field_upload_start_keyframe' ) || $self.hasClass( 'sc_vgenerator_form_field_upload_end_keyframe' ) || $self.hasClass( 'sc_vgenerator_form_field_upload_keyframe_wrap' ) ) {
157						$self.toggleClass( 'trx_addons_hidden', model == 'lumalabs-ai/ray-2' );
158					}
159				} );
160
161				if ( need_resize ) {
162					$document.trigger( 'action.resize_trx_addons' );
163				}
164			}
165
166			check_fields_visibility();
167
168            // Send request via AJAX to generate video
169			//-----------------------------------------
170			$button.on( 'click', function(e) {
171				e.preventDefault();
172
173                // if ( TRX_ADDONS_STORAGE['pagebuilder_preview_mode'] ) {
174				// 	alert( TRX_ADDONS_STORAGE['msg_ai_helper_vgenerator_disabled'] );
175				// 	return false;
176				// }
177
178                var action_type = 'generation',
179					prompt = $prompt.val(),
180					settings = $form.data( 'vgenerator-settings' ),
181					default_model = $form.data( 'vgenerator-default-model' );
182
183                if ( ! prompt || ! check_limits() ) {
184                    return false;
185                }
186
187                $form.addClass( 'sc_vgenerator_form_loading' );
188
189                // Send request via AJAX
190				var data = {
191					nonce: TRX_ADDONS_STORAGE['ajax_nonce'],
192					action: 'trx_addons_ai_helper_vgenerator',
193					action_type: action_type,
194					settings: settings,
195					prompt: prompt,
196					model: ( $model.length && $model.val() ) ? $model.val() : default_model,
197					count: ( trx_addons_get_cookie( 'trx_addons_ai_helper_vgenerator_count' ) || 0 ) * 1 + 1
198				};
199
200				if ( $settings_aspect_ratio.length && $settings_aspect_ratio.val() ) {
201					data.aspect_ratio = $settings_aspect_ratio.val();
202				}
203
204				if ( $settings_resolution.length && $settings_resolution.val() ) {
205					data.resolution = $settings_resolution.val();
206				}
207
208				if ( $settings_duration.length && $settings_duration.val() ) {
209					data.duration = $settings_duration.val();
210				}
211
212				// If upload image is present - convert data to FormData object and send via method ajax()
213				if ( $upload_keyframes.length && ( $keyframes_frame0.val() || $keyframes_frame1.val() ) ) {
214					var formData = new FormData();
215					for ( var key in data ) {
216						formData.append( key, data[key] );
217					}
218
219					if ( $keyframes_frame0.length && $keyframes_frame0.val() ) {
220						formData.append( 'keyframes_frame0', $keyframes_frame0.get(0).files[0], $keyframes_frame0.get(0).files[0].name );
221					}
222
223					if ( $keyframes_frame1.length && $keyframes_frame1.val() ) {
224						formData.append( 'keyframes_frame1', $keyframes_frame1.get(0).files[0], $keyframes_frame1.get(0).files[0].name );
225					}
226					jQuery.ajax( {
227						url: TRX_ADDONS_STORAGE['ajax_url'],
228						type: "POST",
229						data: formData,
230						processData: false,		// Don't process fields to the string
231						contentType: false,		// Prevent content type header
232						success: getVideos
233					} );
234				// Else send data via method post()
235				} else {
236					jQuery.post( TRX_ADDONS_STORAGE['ajax_url'], data, getVideos );
237				}
238
239                // Callback to get video from server
240				function getVideos( response ) {
241                    // Prepare response
242					var rez = {};
243					if ( response == '' || response == 0 ) {
244						rez = { error: TRX_ADDONS_STORAGE['msg_ai_helper_error'] };
245					} else if ( typeof response == 'string' ) {
246						try {
247							rez = JSON.parse( response );
248						} catch (e) {
249							rez = { error: TRX_ADDONS_STORAGE['msg_ai_helper_error'] };
250							console.log( response );
251						}
252					} else {
253						rez = response;
254					}
255
256                    $form.removeClass( 'sc_vgenerator_form_loading' );
257
258                    // Show videos
259					if ( ! rez.error && rez.data ) {
260						var i = 0;
261						// If need to fetch videos after timeout
262						if ( rez.data.fetch_id ) {
263							for ( i = 0; i < rez.data.fetch_number; i++ ) {
264								rez.data.video.push( {
265									url_preview: rez.data.fetch_img,
266								} );
267							}
268							var time = rez.data.fetch_time ? rez.data.fetch_time : 8000;
269							setTimeout( function() {
270								fetch_data( rez.data );
271							}, time );
272						}
273                        if ( rez.data.video.length > 0 ) {
274							if ( ! rez.data.demo ) {
275								update_limits_counter( rez.data.video.length );
276								update_requests_counter();
277							}
278							var $videos = $preview.find( '.sc_vgenerator_video' );
279							if ( animation_in || animation_out ) {
280								$preview.css( {
281									'height': $videos.length ? $preview.height() + 'px' : ( $preview.width() * 9 / 16 ) + 'px'
282								} );
283							}
284							if ( ! $videos.length ) {
285								$preview.show();
286							} else if ( animation_out ) {
287								$videos.removeClass( animation_in ).addClass( animation_out );
288							}
289							setTimeout( function() {
290								var currentDate = new Date();
291								var timestamp = currentDate.getTime();
292								var icon = $form.data( 'vgenerator-download-icon' ) || 'trx_addons_icon-download';
293								var html = '<div class="sc_vgenerator_columns_wrap">';
294								for ( var i = 0; i < rez.data.video.length; i++ ) {
295									html += '<div class="sc_vgenerator_video sc_vgenerator_videos_item ' 
296												+ ( rez.data.fetch_id ? ' sc_vgenerator_video_fetch' : '' )
297												+ ( animation_in ? ' ' + animation_in : '' )
298											+ '">'
299												+ '<div class="sc_vgenerator_video_inner">'
300													+ '<div class="sc_vgenerator_video_wrap">'
301														+ '<video'
302															+ ' poster="' + rez.data.video[i].url_preview + '"'
303															+ ( rez.data.video[i].url ? ' src="' + rez.data.video[i].url + '"' : '' )
304															+ ( rez.data.fetch_id ? ' id="fetch-' + rez.data.fetch_id + '"' : '' )
305														+ '></video>'
306														+ '<span class="sc_vgenerator_video_wait_available">'
307															+ '<span class="sc_vgenerator_video_wait_icon"></span>'
308															+ '<span class="sc_vgenerator_video_wait_msg">' + TRX_ADDONS_STORAGE['msg_ai_helper_wait_available'] + '</span>'
309														+ '</span>'
310													+ '</div>'
311													+ ( rez.data.fetch_id
312														? '<span class="sc_vgenerator_video_fetch_info">'
313																+ '<span class="sc_vgenerator_video_fetch_msg">' + rez.data.fetch_msg + '</span>'
314																+ '<span class="sc_vgenerator_video_fetch_progress">'
315																	+ '<span class="sc_vgenerator_video_fetch_progressbar"></span>'
316																+ '</span>'
317															+ '</span>'
318														: ''
319														)
320													+ ( ! rez.data.demo && rez.data.show_download
321														? '<a href="' + get_download_link( rez.data.video[i].url ? rez.data.video[i].url : rez.data.video[i].url_preview ) + '"'
322															+ ' download="' + prompt.replace( /[\s]+/g, '-' ).toLowerCase() + '"'
323															+ ' data-expired="' + ( ( rez.data.fetch_id ? 0 : timestamp ) + rez.data.show_download * 1000 ) + '"'
324															+ ' data-elementor-open-lightbox="no"'
325															//+ ' target="_blank"'
326															+ ' class="sc_vgenerator_video_link sc_button sc_button_default sc_button_size_small sc_button_with_icon sc_button_icon_left"'
327															+ ' data-elementor-open-lightbox="no"'
328															+ '>'
329																+ ( icon && ! trx_addons_is_off( icon ) ? '<span class="sc_button_icon"><span class="' + icon + '"></span></span>' : '' )
330																+ '<span class="sc_button_text"><span class="sc_button_title">' + TRX_ADDONS_STORAGE['msg_ai_helper_download'] + '</span></span>'
331															+ '</a>'
332														: ''
333														)
334												+ '</div>'
335											+ '</div>';
336								}
337								html += '</div>';
338								$preview.html( html );
339								$preview
340									.find( '.sc_vgenerator_video_inner video' )
341									.on( 'loadeddata', function() {
342										trx_addons_ai_helper_vgenerator_loadeddata_video(jQuery(this));
343									} )
344									.on( 'error', function() {
345										trx_addons_ai_helper_vgenerator_reload_video(jQuery(this));
346									} );
347								$preview
348									.find('.sc_vgenerator_video_wait_available' )
349									.on( 'click', function(e) {
350										// Stop bubbling to avoid opening the video in the popup until the video is not available
351										e.stopPropagation();
352										return false;
353									} );
354
355								setTimeout( function() {
356									$preview.css( 'height', 'auto' );
357									$sc.addClass( 'sc_vgenerator_video_show' );
358									if ( ! rez.data.fetch_id ) {
359										$document.trigger( 'action.init_hidden_elements', [ $preview ] );
360									}
361									if ( need_resize ) {
362//										setTimeout( function() {
363                                            // trx_addons_when_images_loaded( $preview, function() {
364												$document.trigger( 'action.resize_trx_addons' );
365											// } );
366//										}, resize_delay );
367									}
368								}, animation_in ? 700 : 0 );
369								// Check if download links are expired
370								$preview.find( '.sc_vgenerator_video_link' ).on( 'click', function( e ) {
371									var currentDate = new Date();
372									var timestamp = currentDate.getTime();
373									var $link = jQuery( this );
374									if ( $link.attr( 'data-expired' ) && parseInt( $link.attr( 'data-expired' ), 10 ) < timestamp ) {
375										e.preventDefault();
376										if ( typeof trx_addons_msgbox_warning == 'function' ) {
377											trx_addons_msgbox_warning(
378												TRX_ADDONS_STORAGE['msg_ai_helper_download_expired'],
379												TRX_ADDONS_STORAGE['msg_ai_helper_download_error'],
380												'attention',
381												0,
382												[ TRX_ADDONS_STORAGE['msg_caption_ok'] ]
383											);
384										} else {
385											//alert( TRX_ADDONS_STORAGE['msg_ai_helper_download_expired'].replace( /<br>/g, "\n" ) );
386											show_message( TRX_ADDONS_STORAGE['msg_ai_helper_download_expired'], 'error' );
387										}
388										return false;
389									}
390								} );
391							}, $videos.length && animation_out ? 700 : 0 );
392						}
393						if ( rez.data.message ) {
394							show_message( rez.data.message, rez.data.message_type );
395						}
396                    } else {
397						$preview.empty();
398						//alert( rez.error );
399						show_message( rez.error, 'error' );
400					}
401                };
402            } );
403
404            // Fetch data from the server
405			function fetch_data(data) {
406				jQuery.post( TRX_ADDONS_STORAGE['ajax_url'], {
407					nonce: TRX_ADDONS_STORAGE['ajax_nonce'],
408					action: 'trx_addons_ai_helper_fetch_video',
409					fetch_id: data.fetch_id,
410					fetch_model: data.fetch_model,
411				}, function( response ) {
412					// Prepare response
413					var rez = {};
414					if ( response == '' || response == 0 ) {
415						rez = { error: TRX_ADDONS_STORAGE['msg_ai_helper_error'] };
416					} else if ( typeof response == 'string' ) {
417						try {
418							rez = JSON.parse( response );
419						} catch (e) {
420							rez = { error: TRX_ADDONS_STORAGE['msg_ai_helper_error'] };
421							console.log( response );
422						}
423					} else {
424						rez = response;
425					}
426
427					if ( ! rez.error ) {
428						if ( rez.data && rez.data.video && rez.data.video.length > 0 ) {
429							var video = rez.data.video,
430								$fetch = $preview.find( '#fetch-' + data.fetch_id );
431							// Fade out fetch placeholders
432							if ( animation_out ) {
433								for ( var i = 0; i < video.length; i++ ) {
434									$fetch.eq( i ).parents( '.sc_vgenerator_video_fetch' )
435										.removeClass( animation_in )
436										.addClass( animation_out );
437								}
438							}
439							// Replace fetch placeholders with real video
440							setTimeout( function() {
441								var $download_link;
442								var currentDate = new Date();
443								var timestamp = currentDate.getTime();
444								for ( var i = 0; i < video.length; i++ ) {
445									$fetch.eq( i ).attr( {
446										src: video[i].url,
447										poster: video[i].url_preview,
448										controls: true,
449									} );
450									$download_link = $fetch.eq( i ).parents( '.sc_vgenerator_video' ).find( '.sc_vgenerator_video_link' );
451									$download_link.attr( 'href', get_download_link( video[i].url ) );
452									$download_link.attr( 'data-expired', parseInt( $download_link.attr( 'data-expired' ), 10 ) + timestamp );
453								}
454								if ( need_resize ) {
455									// trx_addons_when_images_loaded( $preview, function() {
456										$document.trigger( 'action.resize_trx_addons' );
457									// } );
458								}
459							}, animation_out ? 300 : 0 );
460							// Fade in real video
461							setTimeout( function() {
462								for ( var i = 0; i < video.length; i++ ) {
463									$fetch.eq( i )
464										.parents( '.sc_vgenerator_video_fetch' )
465											.removeClass( 'sc_vgenerator_video_fetch' )
466											.find( '.sc_vgenerator_video_fetch_info')
467												.remove();
468									if ( animation_in ) {
469										$fetch.eq( i ).parents( '.sc_vgenerator_video' )
470														.removeClass( animation_out )
471														.addClass( animation_in );
472									}
473								}
474								$document.trigger( 'action.init_hidden_elements', [ $preview ] );
475								if ( need_resize ) {
476									setTimeout( function() {
477										// trx_addons_when_images_loaded( $preview, function() {
478											$document.trigger( 'action.resize_trx_addons' );
479										// } );
480									}, resize_delay );
481								}
482							}, animation_out ? 800 : 0 );
483						} else {
484							setTimeout( function() {
485								fetch_data( data );
486							}, data.fetch_time ? data.fetch_time : 8000 );
487						}
488					} else {
489						$preview.empty();
490						//alert( rez.error );
491						show_message( rez.error, 'error' );
492					}
493				} );
494			}
495
496            // Show message
497			function show_message( msg, type ) {
498				if ( msg.indexOf( '<p>' ) == -1 ) {
499					msg = '<p>' + msg + '</p>';
500				}
501				$form
502					.find( '.sc_vgenerator_message_inner' )
503						.html( msg )
504						.parent()
505							.toggleClass( 'sc_vgenerator_message_type_error', type == 'error' )
506							.toggleClass( 'sc_vgenerator_message_type_info', type == 'info' )
507							.toggleClass( 'sc_vgenerator_message_type_success', type == 'success' )
508							.addClass( 'sc_vgenerator_message_show' )
509							.slideDown( function() {
510								if ( need_resize ) {
511									$document.trigger( 'action.resize_trx_addons' );
512								}
513							} );
514			}
515
516			// Check limits for generation video
517			function check_limits() {
518				// Block the button if the limits are exceeded only if the demo video are not selected in the shortcode params
519				if ( ! $form.data( 'vgenerator-demo-video' ) ) {
520					var total, used, number;
521					// Check limits for the video generation
522					var $limit_total = $form.find( '.sc_vgenerator_limits_total_value' ),
523						$limit_used  = $form.find( '.sc_vgenerator_limits_used_value' );
524					if ( $limit_total.length && $limit_used.length ) {
525						total = parseInt( $limit_total.text(), 10 );
526						used  = parseInt( $limit_used.text(), 10 );
527						number = 1;
528						if ( ! isNaN( total ) && ! isNaN( used ) && ! isNaN( number ) ) {
529							if ( used >= total ) {
530								disable_fields();
531								return false;
532							}
533						}
534					}
535					// Check limits for the generation requests
536					var $requests_total = $form.find( '.sc_vgenerator_limits_total_requests' ),
537						$requests_used  = $form.find( '.sc_vgenerator_limits_used_requests' );
538					if ( $requests_total.length && $requests_used.length ) {
539						total = parseInt( $requests_total.text(), 10 );
540						//used  = parseInt( $requests_used.text(), 10 );
541						used = ( trx_addons_get_cookie( 'trx_addons_ai_helper_vgenerator_count' ) || 0 ) * 1;
542						if ( ! isNaN( total ) && ! isNaN( used ) ) {
543							if ( used >= total ) {
544								disable_fields();
545								return false;
546							}
547						}
548					}
549				}
550				return true;
551			}
552
553			// Disable fields if limits are exceeded
554			function disable_fields() {
555				$button.toggleClass( 'sc_vgenerator_form_field_disabled', true );
556				$prompt.attr( 'disabled', 'disabled' );
557				show_message( $form.data( 'vgenerator-limit-exceed' ), 'error' );
558			}
559
560			// Update a counter of generated video inside a limits text
561			function update_limits_counter( number ) {
562				var total, used;
563				// Update a counter of the generated video
564				var $limit_total = $form.find( '.sc_vgenerator_limits_total_value' ),
565					$limit_used  = $form.find( '.sc_vgenerator_limits_used_value' );
566				if ( $limit_total.length && $limit_used.length ) {
567					total = parseInt( $limit_total.text(), 10 );
568					used  = parseInt( $limit_used.text(), 10 );
569					if ( ! isNaN( total ) && ! isNaN( used ) && ! isNaN( number ) ) {
570						if ( used < total ) {
571							used = Math.min( used + number, total );
572							$limit_used.text( used );
573						}
574					}
575				}
576				// Update a counter of the generation requests
577				var $requests_total = $form.find( '.sc_vgenerator_limits_total_requests' ),
578					$requests_used  = $form.find( '.sc_vgenerator_limits_used_requests' );
579				if ( $requests_total.length && $requests_used.length ) {
580					total = parseInt( $requests_total.text(), 10 );
581					// used  = parseInt( $requests_used.text(), 10 );
582					used = ( trx_addons_get_cookie( 'trx_addons_ai_helper_vgenerator_count' ) || 0 ) * 1;
583					if ( ! isNaN( total ) && ! isNaN( used ) ) {
584						if ( used < total ) {
585							used = Math.min( used + 1, total );
586							$requests_used.text( used );
587						}
588					}
589				}
590			}
591
592			// Update a counter of the generation requests
593			function update_requests_counter() {
594				// Save a number of requests to the client storage
595				var count = trx_addons_get_cookie( 'trx_addons_ai_helper_vgenerator_count' ) || 0,
596					limit = 60 * 60 * 1000 * 1,	// 1 hour
597					expired = limit - ( new Date().getTime() % limit );
598
599				trx_addons_set_cookie( 'trx_addons_ai_helper_vgenerator_count', ++count, expired );
600			}
601
602			// Return an URL to download the video
603			function get_download_link( url ) {
604				return trx_addons_add_to_url( TRX_ADDONS_STORAGE['site_url'], {
605					'action': 'trx_addons_ai_helper_vgenerator_download',
606					'video': trx_addons_get_file_name( url )
607				} );
608			}
609        } );
610    } );
611} );

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.