| @@ -10,9 +10,9 @@ | ||
| 10 | 10 | $( '#imagify-settings #api_key' ).on( 'blur.imagify', function() { |
| 11 | 11 | var obj = $( this ), |
| 12 | 12 | value = obj.val(); |
| 13 | 13 | |
| 14 | - if ( $.trim( value ) === '' ) { | |
| 14 | + if ( String( value ).trim() === '' ) { | |
| 15 | 15 | return false; |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | if ( $( '#check_api_key' ).val() === value ) { |
| @@ -45,9 +45,12 @@ | ||
| 45 | 45 | } ).then( function() { |
| 46 | 46 | location.reload(); |
| 47 | 47 | } ); |
| 48 | 48 | } |
| 49 | - | |
| 49 | + } ) | |
| 50 | + .always( function() { | |
| 51 | + // Always release the lock, even when the request was aborted or failed, | |
| 52 | + // so a following blur can trigger a fresh check instead of staying stuck. | |
| 50 | 53 | busy = false; |
| 51 | 54 | } ); |
| 52 | 55 | } ); |
| 53 | 56 | |
| @@ -137,9 +140,9 @@ | ||
| 137 | 140 | |
| 138 | 141 | /** |
| 139 | 142 | * Fade CDN URL field. |
| 140 | 143 | */ |
| 141 | - $( '[name="imagify_settings[display_webp_method]"]' ).on( 'change.imagify init.imagify', function( e ) { | |
| 144 | + $( '[name="imagify_settings[display_nextgen_method]"]' ).on( 'change.imagify init.imagify', function( e ) { | |
| 142 | 145 | if ( 'picture' === e.target.value ) { |
| 143 | 146 | $( e.target ).closest( '.imagify-radio-group' ).next( '.imagify-options-line' ).removeClass( 'imagify-faded' ); |
| 144 | 147 | } else { |
| 145 | 148 | $( e.target ).closest( '.imagify-radio-group' ).next( '.imagify-options-line' ).addClass( 'imagify-faded' ); |
| @@ -145,8 +148,53 @@ | ||
| 145 | 148 | $( e.target ).closest( '.imagify-radio-group' ).next( '.imagify-options-line' ).addClass( 'imagify-faded' ); |
| 146 | 149 | } |
| 147 | 150 | } ).filter( ':checked' ).trigger( 'init.imagify' ); |
| 148 | 151 | |
| 152 | + /** | |
| 153 | + * Reset Internal State button. | |
| 154 | + */ | |
| 155 | + $( '#imagify-reset-internal-state' ).on( 'click.imagify', function() { | |
| 156 | + var $button = $( this ), | |
| 157 | + nonce = $button.data( 'nonce' ), | |
| 158 | + $feedback = $( '#imagify-reset-internal-state-feedback' ); | |
| 159 | + | |
| 160 | + swal( { | |
| 161 | + title: imagifyOptions.resetInternalState.confirm, | |
| 162 | + type: 'warning', | |
| 163 | + customClass: 'imagify-sweet-alert', | |
| 164 | + padding: 0, | |
| 165 | + showCancelButton: true, | |
| 166 | + cancelButtonText: imagifySwal.labels.cancelButtonText, | |
| 167 | + reverseButtons: true | |
| 168 | + } ).then( | |
| 169 | + function() { | |
| 170 | + $button.prop( 'disabled', true ); | |
| 171 | + $feedback.text( '' ).removeClass( 'imagify-success imagify-error' ); | |
| 172 | + | |
| 173 | + $.post( ajaxurl, { | |
| 174 | + 'action': imagifyOptions.resetInternalState.action, | |
| 175 | + '_wpnonce': nonce | |
| 176 | + } ) | |
| 177 | + .done( function( response ) { | |
| 178 | + if ( response && response.success ) { | |
| 179 | + $feedback.text( imagifyOptions.resetInternalState.success ).addClass( 'imagify-success' ); | |
| 180 | + } else { | |
| 181 | + $feedback.text( imagifyOptions.resetInternalState.error ).addClass( 'imagify-error' ); | |
| 182 | + } | |
| 183 | + } ) | |
| 184 | + .fail( function() { | |
| 185 | + $feedback.text( imagifyOptions.resetInternalState.error ).addClass( 'imagify-error' ); | |
| 186 | + } ) | |
| 187 | + .always( function() { | |
| 188 | + $button.prop( 'disabled', false ); | |
| 189 | + } ); | |
| 190 | + }, | |
| 191 | + function() { | |
| 192 | + // User cancelled — do nothing. | |
| 193 | + } | |
| 194 | + ); | |
| 195 | + } ); | |
| 196 | + | |
| 149 | 197 | } )(jQuery, document, window); |
| 150 | 198 | |
| 151 | 199 | |
| 152 | 200 | // Display Imagify User data ======================================================================= |
| @@ -422,39 +470,8 @@ | ||
| 422 | 470 | |
| 423 | 471 | w.imagify.optionsBulk = { |
| 424 | 472 | // Properties ============================================================================== |
| 425 | 473 | /** |
| 426 | - * When media IDs have been fetched for a context (or tried, with error), the context is removed from this list. | |
| 427 | - * | |
| 428 | - * @var {array} fetchQueue An array of contexts. | |
| 429 | - */ | |
| 430 | - fetchQueue: [], | |
| 431 | - /** | |
| 432 | - * Contexts in queue. | |
| 433 | - * | |
| 434 | - * @var {array} queue An array of objects: { | |
| 435 | - * @type {string} context The context, like 'wp'. | |
| 436 | - * @type {string} optimizeURL The URL to ping to optimize a file. | |
| 437 | - * @type {array} mediaIDs A list of media IDs. | |
| 438 | - * } | |
| 439 | - */ | |
| 440 | - queue: [], | |
| 441 | - /** | |
| 442 | - * List of medias being processed. | |
| 443 | - * | |
| 444 | - * @var {array} processingQueue An array of objects: { | |
| 445 | - * @type {string} context The context, like 'wp'. | |
| 446 | - * @type {int} mediaID The media ID. | |
| 447 | - * } | |
| 448 | - */ | |
| 449 | - processingQueue: [], | |
| 450 | - /** | |
| 451 | - * Stores the first error ID or message that is occurring when fetching media IDs. | |
| 452 | - * | |
| 453 | - * @var {string|bool} error False if no error. | |
| 454 | - */ | |
| 455 | - fetchError: false, | |
| 456 | - /** | |
| 457 | 474 | * The current error ID or message. |
| 458 | 475 | * |
| 459 | 476 | * @var {string|bool} error False if no error. |
| 460 | 477 | */ |
| @@ -469,22 +486,10 @@ | ||
| 469 | 486 | * Set to true to stop the whole thing. |
| 470 | 487 | * |
| 471 | 488 | * @var {bool} processIsStopped |
| 472 | 489 | */ |
| 473 | - processIsStopped: true, | |
| 490 | + processIsStopped: false, | |
| 474 | 491 | /** |
| 475 | - * Total number of processed media. | |
| 476 | - * | |
| 477 | - * @var {int} | |
| 478 | - */ | |
| 479 | - processedMedia: 0, | |
| 480 | - /** | |
| 481 | - * Total number of media to process. | |
| 482 | - * | |
| 483 | - * @var {int} | |
| 484 | - */ | |
| 485 | - totalMedia: 0, | |
| 486 | - /** | |
| 487 | 492 | * The button. |
| 488 | 493 | * |
| 489 | 494 | * @var {jQuery} |
| 490 | 495 | */ |
| @@ -513,8 +518,12 @@ | ||
| 513 | 518 | /* |
| 514 | 519 | * Init. |
| 515 | 520 | */ |
| 516 | 521 | init: function () { |
| 522 | + var progress; | |
| 523 | + this.$missingWebpElement = $('.generate-missing-webp'); | |
| 524 | + this.$missingWebpMessage = $('.generate-missing-webp p'); | |
| 525 | + | |
| 517 | 526 | this.$button = $( '#imagify-generate-webp-versions' ); |
| 518 | 527 | this.$progressWrap = this.$button.siblings( '.imagify-progress' ); |
| 519 | 528 | this.$progressBar = this.$progressWrap.find( '.bar' ); |
| 520 | 529 | this.$progressText = this.$progressBar.find( '.percent' ); |
| @@ -524,9 +533,9 @@ | ||
| 524 | 533 | .on( 'change.imagify init.imagify', { imagifyOptionsBulk: this }, this.toggleButton ) |
| 525 | 534 | .trigger( 'init.imagify' ); |
| 526 | 535 | |
| 527 | 536 | // Launch optimization. |
| 528 | - this.$button.on( 'click.imagify', { imagifyOptionsBulk: this }, this.maybeLaunchAllProcesses ); | |
| 537 | + this.$button.on( 'click.imagify', { imagifyOptionsBulk: this }, this.maybeLaunchMissingWebpProcess ); | |
| 529 | 538 | |
| 530 | 539 | // Imagifybeat for optimization queue. |
| 531 | 540 | $( d ) |
| 532 | 541 | .on( 'imagifybeat-send', { imagifyOptionsBulk: this }, this.addQueueImagifybeat ) |
| @@ -533,8 +542,30 @@ | ||
| 533 | 542 | .on( 'imagifybeat-tick', { imagifyOptionsBulk: this }, this.processQueueImagifybeat ) |
| 534 | 543 | // Imagifybeat for requirements. |
| 535 | 544 | .on( 'imagifybeat-send', this.addRequirementsImagifybeat ) |
| 536 | 545 | .on( 'imagifybeat-tick', { imagifyOptionsBulk: this }, this.processRequirementsImagifybeat ); |
| 546 | + | |
| 547 | + if ( false !== imagifyOptions.bulk.progress_next_gen.total && false !== imagifyOptions.bulk.progress_next_gen.remaining ) { | |
| 548 | + // Reset properties. | |
| 549 | + w.imagify.optionsBulk.error = false; | |
| 550 | + w.imagify.optionsBulk.working = true; | |
| 551 | + w.imagify.optionsBulk.processIsStopped = false; | |
| 552 | + | |
| 553 | + // Disable the button. | |
| 554 | + this.$button.prop( 'disabled', true ).find( '.dashicons' ).addClass( 'rotate' ); | |
| 555 | + | |
| 556 | + // Fasten Imagifybeat: 1 tick every 15 seconds, and disable suspend. | |
| 557 | + w.imagify.beat.interval( 15 ); | |
| 558 | + w.imagify.beat.disableSuspend(); | |
| 559 | + | |
| 560 | + this.$missingWebpMessage.hide().attr('aria-hidden', 'true'); | |
| 561 | + | |
| 562 | + progress = this.getProgress( imagifyOptions.bulk.progress_next_gen.total, imagifyOptions.bulk.progress_next_gen.remaining ); | |
| 563 | + this.$progressBar.css( 'width', progress.percent + '%' ); | |
| 564 | + this.$progressText.text( progress.processed + '/' + progress.total ); | |
| 565 | + | |
| 566 | + this.$progressWrap.slideDown().attr( 'aria-hidden', 'false' ).removeClass( 'hidden' ); | |
| 567 | + } | |
| 537 | 568 | }, |
| 538 | 569 | |
| 539 | 570 | // Event callbacks ========================================================================= |
| 540 | 571 | |
| @@ -551,13 +582,13 @@ | ||
| 551 | 582 | } |
| 552 | 583 | }, |
| 553 | 584 | |
| 554 | 585 | /* |
| 555 | - * Build the queue and launch all processes. | |
| 586 | + * Maybe launch the missing WebP generation process. | |
| 556 | 587 | * |
| 557 | 588 | * @param {object} e Event object. |
| 558 | 589 | */ |
| 559 | - maybeLaunchAllProcesses: function ( e ) { | |
| 590 | + maybeLaunchMissingWebpProcess: function ( e ) { | |
| 560 | 591 | if ( ! e.data.imagifyOptionsBulk || e.data.imagifyOptionsBulk.working ) { |
| 561 | 592 | return; |
| 562 | 593 | } |
| 563 | 594 | |
| @@ -565,41 +596,23 @@ | ||
| 565 | 596 | return; |
| 566 | 597 | } |
| 567 | 598 | |
| 568 | 599 | // Reset properties. |
| 569 | - e.data.imagifyOptionsBulk.fetchQueue = imagifyOptions.bulk.contexts.slice(); | |
| 570 | - e.data.imagifyOptionsBulk.queue = []; | |
| 571 | - e.data.imagifyOptionsBulk.processingQueue = []; | |
| 572 | - e.data.imagifyOptionsBulk.fetchError = false; | |
| 573 | 600 | e.data.imagifyOptionsBulk.error = false; |
| 574 | 601 | e.data.imagifyOptionsBulk.working = true; |
| 575 | 602 | e.data.imagifyOptionsBulk.processIsStopped = false; |
| 576 | - e.data.imagifyOptionsBulk.processedMedia = 0; | |
| 577 | - e.data.imagifyOptionsBulk.totalMedia = 0; | |
| 578 | 603 | |
| 579 | 604 | // Disable the button. |
| 580 | 605 | e.data.imagifyOptionsBulk.$button.prop( 'disabled', true ).find( '.dashicons' ).addClass( 'rotate' ); |
| 581 | 606 | |
| 582 | - // Add a message to be displayed when the user wants to quit the page. | |
| 583 | - $( w ).on( 'beforeunload.imagify', e.data.imagifyOptionsBulk.getConfirmMessage ); | |
| 584 | - | |
| 585 | 607 | // Fasten Imagifybeat: 1 tick every 15 seconds, and disable suspend. |
| 586 | 608 | w.imagify.beat.interval( 15 ); |
| 587 | 609 | w.imagify.beat.disableSuspend(); |
| 588 | 610 | |
| 589 | - // Fetch IDs of media to optimize. | |
| 590 | - e.data.imagifyOptionsBulk.fetchIDs(); | |
| 611 | + // Launch missing WebP generation process | |
| 612 | + e.data.imagifyOptionsBulk.launchProcess(); | |
| 591 | 613 | }, |
| 592 | 614 | |
| 593 | - /* | |
| 594 | - * Get the message displayed to the user when (s)he leaves the page. | |
| 595 | - * | |
| 596 | - * @return {string} | |
| 597 | - */ | |
| 598 | - getConfirmMessage: function () { | |
| 599 | - return imagifyOptions.bulk.labels.processing; | |
| 600 | - }, | |
| 601 | - | |
| 602 | 615 | // Imagifybeat ============================================================================= |
| 603 | 616 | |
| 604 | 617 | /** |
| 605 | 618 | * Add a Imagifybeat ID on "imagifybeat-send" event to sync the optimization queue. |
| @@ -607,14 +620,32 @@ | ||
| 607 | 620 | * @param {object} e Event object. |
| 608 | 621 | * @param {object} data Object containing all Imagifybeat IDs. |
| 609 | 622 | */ |
| 610 | 623 | addQueueImagifybeat: function ( e, data ) { |
| 611 | - if ( e.data.imagifyOptionsBulk && e.data.imagifyOptionsBulk.processingQueue.length ) { | |
| 612 | - data[ imagifyOptions.bulk.imagifybeatIDs.queue ] = e.data.imagifyOptionsBulk.processingQueue; | |
| 613 | - } | |
| 624 | + data[ imagifyOptions.bulk.imagifybeatIDs.progress ] = imagifyOptions.bulk.contexts; | |
| 614 | 625 | }, |
| 615 | 626 | |
| 616 | 627 | /** |
| 628 | + * Compute a display-safe progress state. | |
| 629 | + * | |
| 630 | + * `total` is a snapshot taken when the run started, while `remaining` is recounted on | |
| 631 | + * every Imagifybeat tick. Anything that grows the workload mid-run pushes `remaining` | |
| 632 | + * above `total`: uploading new media while the run is in progress, or switching the | |
| 633 | + * Next-Gen format so that every media is suddenly missing one. `total - remaining` then | |
| 634 | + * rendered as a negative count, and a snapshot of 0 divided by zero on top of that. | |
| 635 | + * | |
| 636 | + * Track the largest workload seen instead, so the count never goes negative and the | |
| 637 | + * denominator reflects what is actually left to do. | |
| 638 | + * | |
| 639 | + * @param {number} total Number of media to process when the run started. | |
| 640 | + * @param {number} remaining Number of media still waiting to be processed. | |
| 641 | + * @return {object} Object with `processed`, `total` and `percent` keys. | |
| 642 | + */ | |
| 643 | + getProgress: function ( total, remaining ) { | |
| 644 | + return w.imagify.getProgress( total, remaining ); | |
| 645 | + }, | |
| 646 | + | |
| 647 | + /** | |
| 617 | 648 | * Listen for the custom event "imagifybeat-tick" on $(document). |
| 618 | 649 | * It allows to update various data periodically. |
| 619 | 650 | * |
| 620 | 651 | * @param {object} e Event object. |
| @@ -620,13 +651,29 @@ | ||
| 620 | 651 | * @param {object} e Event object. |
| 621 | 652 | * @param {object} data Object containing all Imagifybeat IDs. |
| 622 | 653 | */ |
| 623 | 654 | processQueueImagifybeat: function ( e, data ) { |
| 624 | - if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.imagifybeatIDs.queue ] !== 'undefined' ) { | |
| 625 | - $.each( data[ imagifyOptions.bulk.imagifybeatIDs.queue ], function ( i, mediaData ) { | |
| 626 | - e.data.imagifyOptionsBulk.mediaProcessed( mediaData ); | |
| 627 | - } ); | |
| 655 | + var images_status, progress; | |
| 656 | + | |
| 657 | + if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.imagifybeatIDs.progress ] === 'undefined' ) { | |
| 658 | + return; | |
| 628 | 659 | } |
| 660 | + | |
| 661 | + if ( e.data.imagifyOptionsBulk.processIsStopped ) { | |
| 662 | + e.data.imagifyOptionsBulk.processFinished(); | |
| 663 | + return; | |
| 664 | + } | |
| 665 | + | |
| 666 | + images_status = data[ imagifyOptions.bulk.imagifybeatIDs.progress ]; | |
| 667 | + | |
| 668 | + if ( images_status.remaining === 0 ) { | |
| 669 | + e.data.imagifyOptionsBulk.processFinished(); | |
| 670 | + return; | |
| 671 | + } | |
| 672 | + | |
| 673 | + progress = e.data.imagifyOptionsBulk.getProgress( images_status.total, images_status.remaining ); | |
| 674 | + e.data.imagifyOptionsBulk.$progressBar.css( 'width', progress.percent + '%' ); | |
| 675 | + e.data.imagifyOptionsBulk.$progressText.text( progress.processed + '/' + progress.total ); | |
| 629 | 676 | }, |
| 630 | 677 | |
| 631 | 678 | /** |
| 632 | 679 | * Add a Imagifybeat ID for requirements on "imagifybeat-send" event. |
| @@ -662,46 +709,20 @@ | ||
| 662 | 709 | |
| 663 | 710 | // Optimization ============================================================================ |
| 664 | 711 | |
| 665 | 712 | /* |
| 666 | - * Fetch IDs of media to optimize. | |
| 713 | + * launch the missing WebP generation process. | |
| 667 | 714 | */ |
| 668 | - fetchIDs: function () { | |
| 669 | - var _this, context; | |
| 715 | + launchProcess: function () { | |
| 716 | + var _this; | |
| 670 | 717 | |
| 671 | 718 | if ( this.processIsStopped ) { |
| 672 | 719 | return; |
| 673 | 720 | } |
| 674 | 721 | |
| 675 | - if ( ! this.fetchQueue.length ) { | |
| 676 | - // No more IDs to fetch. | |
| 677 | - if ( this.queue.length ) { | |
| 678 | - // We have files to process. | |
| 679 | - // Reset and display the progress bar. | |
| 680 | - this.$progressBar.removeAttr( 'style' ); | |
| 681 | - this.$progressText.text( '0' + ( this.totalMedia ? '/' + this.totalMedia : '' ) ); | |
| 682 | - this.$progressWrap.slideDown().attr( 'aria-hidden', 'false' ); | |
| 722 | + _this = this; | |
| 683 | 723 | |
| 684 | - this.processQueue(); | |
| 685 | - return; | |
| 686 | - } | |
| 687 | - | |
| 688 | - if ( ! this.fetchError ) { | |
| 689 | - // No files to process. | |
| 690 | - this.fetchError = 'no-images'; | |
| 691 | - } | |
| 692 | - | |
| 693 | - // Error, or no files to process. | |
| 694 | - this.stopProcess( this.fetchError ); | |
| 695 | - this.fetchError = false; | |
| 696 | - return; | |
| 697 | - } | |
| 698 | - | |
| 699 | - // Fetch IDs for the next context. | |
| 700 | - _this = this; | |
| 701 | - context = this.fetchQueue.shift(); | |
| 702 | - | |
| 703 | - $.get( this.getAjaxUrl( 'getMediaIds', context ) ) | |
| 724 | + $.get( this.getAjaxUrl( 'MissingNextGen', imagifyOptions.bulk.contexts ) ) | |
| 704 | 725 | .done( function( response ) { |
| 705 | 726 | var errorMessage; |
| 706 | 727 | |
| 707 | 728 | if ( _this.processIsStopped ) { |
| @@ -715,172 +736,39 @@ | ||
| 715 | 736 | } |
| 716 | 737 | |
| 717 | 738 | if ( ! response.success ) { |
| 718 | 739 | // Error. |
| 719 | - if ( ! _this.fetchError ) { | |
| 720 | - _this.fetchError = errorMessage; | |
| 740 | + if ( ! _this.error ) { | |
| 741 | + _this.stopProcess( errorMessage ); | |
| 721 | 742 | } |
| 722 | 743 | return; |
| 723 | 744 | } |
| 724 | 745 | |
| 725 | - if ( ! $.isArray( response.data ) ) { | |
| 726 | - // Error: should be an array. | |
| 727 | - if ( ! _this.fetchError ) { | |
| 728 | - _this.fetchError = errorMessage; | |
| 729 | - } | |
| 746 | + if ( 0 === response.data.total ) { | |
| 747 | + // No media to process. | |
| 748 | + _this.stopProcess( 'no-images' ); | |
| 749 | + | |
| 730 | 750 | return; |
| 731 | 751 | } |
| 732 | 752 | |
| 733 | - if ( ! response.data.length ) { | |
| 734 | - // No media to process. | |
| 735 | - return; | |
| 736 | - } | |
| 753 | + _this.$missingWebpMessage.hide().attr('aria-hidden', 'true'); | |
| 737 | 754 | |
| 738 | - // Success. | |
| 739 | - _this.totalMedia += response.data.length; | |
| 740 | - _this.queue.push( { | |
| 741 | - context: context, | |
| 742 | - optimizeURL: _this.getAjaxUrl( 'bulkProcess', context ), | |
| 743 | - mediaIDs: response.data | |
| 744 | - } ); | |
| 755 | + // Reset and display the progress bar. | |
| 756 | + _this.$progressText.text( '0' + ( response.data.total ? '/' + response.data.total : '' ) ); | |
| 757 | + _this.$progressWrap.slideDown().attr( 'aria-hidden', 'false' ).removeClass( 'hidden' ); | |
| 745 | 758 | } ) |
| 746 | 759 | .fail( function() { |
| 747 | 760 | // Error. |
| 748 | - if ( ! _this.fetchError ) { | |
| 749 | - _this.fetchError = 'get-unoptimized-images'; | |
| 761 | + if ( ! _this.error ) { | |
| 762 | + _this.stopProcess( 'get-unoptimized-images' ); | |
| 750 | 763 | } |
| 751 | - } ) | |
| 752 | - .always( function() { | |
| 753 | - // Fetch IDs for the next context. | |
| 754 | - _this.fetchIDs(); | |
| 755 | 764 | } ); |
| 756 | 765 | }, |
| 757 | 766 | |
| 758 | 767 | /* |
| 759 | - * Fill the processing queue until the buffer size is reached. | |
| 760 | - */ | |
| 761 | - processQueue: function () { | |
| 762 | - var _this = this; | |
| 763 | - | |
| 764 | - if ( this.processIsStopped ) { | |
| 765 | - return; | |
| 766 | - } | |
| 767 | - | |
| 768 | - if ( ! this.queue.length && ! this.processingQueue.length ) { | |
| 769 | - return; | |
| 770 | - } | |
| 771 | - | |
| 772 | - // Optimize the files. | |
| 773 | - $.each( this.queue, function ( i, item ) { | |
| 774 | - if ( _this.processingQueue.length >= imagifyOptions.bulk.bufferSize ) { | |
| 775 | - return false; | |
| 776 | - } | |
| 777 | - | |
| 778 | - $.each( item.mediaIDs, function () { | |
| 779 | - _this.processMedia( { | |
| 780 | - context: item.context, | |
| 781 | - mediaID: item.mediaIDs.shift(), | |
| 782 | - optimizeURL: item.optimizeURL | |
| 783 | - } ); | |
| 784 | - | |
| 785 | - if ( ! item.mediaIDs.length ) { | |
| 786 | - _this.queue.shift(); | |
| 787 | - } | |
| 788 | - | |
| 789 | - if ( _this.processingQueue.length >= imagifyOptions.bulk.bufferSize ) { | |
| 790 | - return false; | |
| 791 | - } | |
| 792 | - } ); | |
| 793 | - } ); | |
| 794 | - }, | |
| 795 | - | |
| 796 | - /* | |
| 797 | - * Process the next media. | |
| 798 | - * | |
| 799 | - * @param {object} item { | |
| 800 | - * @type {string} context The context, like 'wp'. | |
| 801 | - * @type {int} mediaID The media ID. | |
| 802 | - * @type {string} optimizeURL The URL to ping to optimize the media. | |
| 803 | - * } | |
| 804 | - */ | |
| 805 | - processMedia: function ( item ) { | |
| 806 | - var _this = this, | |
| 807 | - defaultResponse = { | |
| 808 | - context: item.context, | |
| 809 | - mediaID: item.mediaID | |
| 810 | - }; | |
| 811 | - | |
| 812 | - this.processingQueue.push( { | |
| 813 | - context: item.context, | |
| 814 | - mediaID: item.mediaID | |
| 815 | - } ); | |
| 816 | - | |
| 817 | - $.post( { | |
| 818 | - url: item.optimizeURL, | |
| 819 | - data: { | |
| 820 | - media_id: item.mediaID, | |
| 821 | - context: item.context | |
| 822 | - }, | |
| 823 | - dataType: 'json' | |
| 824 | - } ) | |
| 825 | - .done( function( response ) { | |
| 826 | - if ( response.success ) { | |
| 827 | - // Processing. | |
| 828 | - return; | |
| 829 | - } | |
| 830 | - | |
| 831 | - // Error. | |
| 832 | - _this.mediaProcessed( defaultResponse ); | |
| 833 | - } ) | |
| 834 | - .fail( function() { | |
| 835 | - // Error. | |
| 836 | - _this.mediaProcessed( defaultResponse ); | |
| 837 | - } ); | |
| 838 | - }, | |
| 839 | - | |
| 840 | - /** | |
| 841 | - * After a media has been processed. | |
| 842 | - * | |
| 843 | - * @param {object} response { | |
| 844 | - * The response: | |
| 845 | - * | |
| 846 | - * @type {int} mediaID The media ID. | |
| 847 | - * @type {string} context The context. | |
| 848 | - * } | |
| 849 | - */ | |
| 850 | - mediaProcessed: function( response ) { | |
| 851 | - var _this = this; | |
| 852 | - | |
| 853 | - if ( this.processIsStopped ) { | |
| 854 | - return; | |
| 855 | - } | |
| 856 | - | |
| 857 | - // Remove this media from the "being processed" list. | |
| 858 | - $.each( this.processingQueue, function( i, mediaData ) { | |
| 859 | - if ( response.context === mediaData.context && response.mediaID === mediaData.mediaID ) { | |
| 860 | - _this.processingQueue.splice( i, 1 ); | |
| 861 | - return false; | |
| 862 | - } | |
| 863 | - } ); | |
| 864 | - | |
| 865 | - ++this.processedMedia; | |
| 866 | - | |
| 867 | - // Update the progress bar. | |
| 868 | - response.progress = Math.floor( this.processedMedia / this.totalMedia * 100 ); | |
| 869 | - this.$progressBar.css( 'width', response.progress + '%' ); | |
| 870 | - this.$progressText.text( this.processedMedia + '/' + this.totalMedia ); | |
| 871 | - | |
| 872 | - if ( this.queue.length || this.processingQueue.length ) { | |
| 873 | - this.processQueue(); | |
| 874 | - } else if ( this.totalMedia === this.processedMedia ) { | |
| 875 | - this.queueEmpty(); | |
| 876 | - } | |
| 877 | - }, | |
| 878 | - | |
| 879 | - /* | |
| 880 | 768 | * End. |
| 881 | 769 | */ |
| 882 | - queueEmpty: function () { | |
| 770 | + processFinished: function () { | |
| 883 | 771 | var errorArgs = {}; |
| 884 | 772 | |
| 885 | 773 | // Maybe display an error. |
| 886 | 774 | if ( false !== this.error ) { |
| @@ -898,9 +786,9 @@ | ||
| 898 | 786 | customClass: 'imagify-swal-has-subtitle imagify-swal-error-header', |
| 899 | 787 | showConfirmButton: false |
| 900 | 788 | }; |
| 901 | 789 | } |
| 902 | - else if ( 'get-unoptimized-images' === this.error || 'consumed-all-data' === this.error ) { | |
| 790 | + else if ( 'get-unoptimized-images' === this.error ) { | |
| 903 | 791 | errorArgs = { |
| 904 | 792 | title: imagifyOptions.bulk.labels.getUnoptimizedImagesErrorTitle, |
| 905 | 793 | html: imagifyOptions.bulk.labels.getUnoptimizedImagesErrorText, |
| 906 | 794 | type: 'info' |
| @@ -933,31 +821,20 @@ | ||
| 933 | 821 | this.error = false; |
| 934 | 822 | } |
| 935 | 823 | |
| 936 | 824 | // Reset. |
| 937 | - this.fetchQueue = []; | |
| 938 | - this.queue = []; | |
| 939 | - this.processingQueue = []; | |
| 940 | - this.fetchError = false; | |
| 941 | 825 | this.working = false; |
| 942 | 826 | this.processIsStopped = false; |
| 943 | - this.processedMedia = 0; | |
| 944 | - this.totalMedia = 0; | |
| 945 | 827 | |
| 946 | 828 | // Reset Imagifybeat interval and enable suspend. |
| 947 | 829 | w.imagify.beat.resetInterval(); |
| 948 | 830 | w.imagify.beat.enableSuspend(); |
| 949 | 831 | |
| 950 | - // Unlink the message displayed when the user wants to quit the page. | |
| 951 | - $( w ).off( 'beforeunload.imagify', this.getConfirmMessage ); | |
| 952 | - | |
| 953 | 832 | // Reset the progress bar. |
| 954 | - this.$progressWrap.slideUp().attr( 'aria-hidden', 'true' ); | |
| 955 | - this.$progressBar.removeAttr( 'style' ); | |
| 833 | + this.$progressWrap.slideUp().attr( 'aria-hidden', 'true' ).addClass( 'hidden' ); | |
| 956 | 834 | this.$progressText.text( '0' ); |
| 957 | - | |
| 958 | - // Enable the button. | |
| 959 | - this.$button.prop( 'disabled', false ).find( '.dashicons' ).removeClass( 'rotate' ); | |
| 835 | + this.$missingWebpElement.hide().attr('aria-hidden', 'true'); | |
| 836 | + this.$button.find( '.dashicons' ).removeClass( 'rotate' ); | |
| 960 | 837 | }, |
| 961 | 838 | |
| 962 | 839 | // Tools =================================================================================== |
| 963 | 840 | |
| @@ -1070,18 +947,17 @@ | ||
| 1070 | 947 | /* |
| 1071 | 948 | * Get the URL used for ajax requests. |
| 1072 | 949 | * |
| 1073 | 950 | * @param {string} action An ajax action, or part of it. |
| 1074 | - * @param {string} context The context. | |
| 951 | + * @param {array} context The contexts. | |
| 1075 | 952 | * @return {string} |
| 1076 | 953 | */ |
| 1077 | - getAjaxUrl: function ( action, context ) { | |
| 954 | + getAjaxUrl: function ( action, contexts ) { | |
| 1078 | 955 | var url; |
| 1079 | 956 | |
| 1080 | 957 | url = ajaxurl + w.imagify.concat + '_wpnonce=' + imagifyOptions.bulk.ajaxNonce; |
| 1081 | 958 | url += '&action=' + imagifyOptions.bulk.ajaxActions[ action ]; |
| 1082 | - url += '&context=' + context; | |
| 1083 | - url += '&imagify_action=generate_webp'; | |
| 959 | + url += '&context=' + contexts.join('_'); | |
| 1084 | 960 | |
| 1085 | 961 | return url; |
| 1086 | 962 | }, |
| 1087 | 963 | |
| @@ -1094,9 +970,9 @@ | ||
| 1094 | 970 | this.processIsStopped = true; |
| 1095 | 971 | |
| 1096 | 972 | this.error = errorId; |
| 1097 | 973 | |
| 1098 | - this.queueEmpty(); | |
| 974 | + this.processFinished(); | |
| 1099 | 975 | } |
| 1100 | 976 | }; |
| 1101 | 977 | |
| 1102 | 978 | w.imagify.optionsBulk.init(); |
| @@ -1180,4 +1056,40 @@ | ||
| 1180 | 1056 | } |
| 1181 | 1057 | } ); |
| 1182 | 1058 | |
| 1183 | 1059 | } )(window, document, jQuery); |
| 1060 | + | |
| 1061 | +// Imagify Analytics opt-in toggle ================================================================ | |
| 1062 | +(function($) { | |
| 1063 | + | |
| 1064 | + var $checkbox = $( '#imagify-analytics-enabled' ); | |
| 1065 | + | |
| 1066 | + if ( ! $checkbox.length ) { | |
| 1067 | + return; | |
| 1068 | + } | |
| 1069 | + | |
| 1070 | + $checkbox.on( 'change.imagify-analytics', function() { | |
| 1071 | + var nonce = $( this ).data( 'nonce' ); | |
| 1072 | + | |
| 1073 | + $.post( ajaxurl, { | |
| 1074 | + action: 'imagify_toggle_tracking_optin', | |
| 1075 | + value: $( this ).prop( 'checked' ) ? 1 : 0, | |
| 1076 | + nonce: nonce | |
| 1077 | + } ); | |
| 1078 | + } ); | |
| 1079 | + | |
| 1080 | + $( document ).on( 'click.imagify-analytics', '#imagify-analytics-enable-from-modal', function() { | |
| 1081 | + $( '.imagify-modal.modal-is-open .close-btn' ).trigger( 'click.imagify' ); | |
| 1082 | + $checkbox.prop( 'checked', true ).trigger( 'change.imagify-analytics' ); | |
| 1083 | + } ); | |
| 1084 | + | |
| 1085 | +})(jQuery); | |
| 1086 | + | |
| 1087 | +// Imagify Analytics opt-in notice: toggle the data preview ======================================= | |
| 1088 | +(function($) { | |
| 1089 | + | |
| 1090 | + $( document ).on( 'click.imagify-analytics', '.imagify-analytics-preview-toggle', function( e ) { | |
| 1091 | + e.preventDefault(); | |
| 1092 | + $( this ).closest( 'p' ).next( '.imagify-analytics-data-container' ).slideToggle(); | |
| 1093 | + } ); | |
| 1094 | + | |
| 1095 | +})(jQuery); | |