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.