PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
← All changes | assets/js/options.js +186 -274 1.10 → trunk View file →
@@ -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);