diff --git a/Extension_ImageService_Api.php b/Extension_ImageService_Api.php index 3bb7a323c..acf3021f7 100644 --- a/Extension_ImageService_Api.php +++ b/Extension_ImageService_Api.php @@ -15,16 +15,6 @@ * @since 2.2.0 */ class Extension_ImageService_Api { - /** - * API Base URL. - * - * @since 2.2.0 - * @access private - * - * @var string - */ - private $base_url = 'https://api2.w3-edge.com'; - /** * W3TC Pro license key. * @@ -137,7 +127,7 @@ public function convert( $filepath, array $options = array() ) { 'optimize' => $options['optimize'], ); - if ( ( defined( 'W3TC_PRO' ) && W3TC_PRO ) || ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE ) ) { + if ( Util_Environment::is_pro_constant( $config ) ) { $post_fields['pro_c'] = 1; } @@ -153,7 +143,7 @@ public function convert( $filepath, array $options = array() ) { // Send request. $response = wp_remote_request( - $this->get_base_url() . $this->endpoints['convert']['uri'], + Util_Environment::get_api_base_url() . $this->endpoints['convert']['uri'], array( 'method' => $this->endpoints['convert']['method'], 'sslverify' => false, @@ -254,7 +244,7 @@ public function convert( $filepath, array $options = array() ) { */ public function get_status( $job_id, $signature ) { $response = wp_remote_request( - $this->get_base_url() . $this->endpoints['status']['uri'] . '/' . $job_id . '/' . $signature, + Util_Environment::get_api_base_url() . $this->endpoints['status']['uri'] . '/' . $job_id . '/' . $signature, array( 'method' => $this->endpoints['status']['method'], 'sslverify' => false, @@ -295,7 +285,7 @@ public function get_status( $job_id, $signature ) { */ public function download( $job_id, $signature ) { $response = wp_remote_request( - $this->get_base_url() . $this->endpoints['download']['uri'] . '/' . $job_id . '/' . $signature, + Util_Environment::get_api_base_url() . $this->endpoints['download']['uri'] . '/' . $job_id . '/' . $signature, array( 'method' => $this->endpoints['download']['method'], 'sslverify' => false, @@ -356,7 +346,7 @@ public function get_usage( bool $refresh = false ): array { $response = wp_remote_request( esc_url( - $this->get_base_url() . $this->endpoints['usage']['uri'] . + Util_Environment::get_api_base_url() . $this->endpoints['usage']['uri'] . '/' . rawurlencode( $this->license_key ) . '/' . urlencode( $this->item_name ) . // phpcs:ignore '/' . rawurlencode( $this->home_url ) @@ -392,19 +382,6 @@ public function get_usage( bool $refresh = false ): array { } } - /** - * Get base URL. - * - * @since 2.2.0 - * @access private - * - * @returns string - */ - private function get_base_url() { - return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ? - esc_url( W3TC_API2_URL, 'https', '' ) : $this->base_url; - } - /** * Update usage transient data. * diff --git a/Generic_Plugin_Admin.php b/Generic_Plugin_Admin.php index 79b8cebcc..950f43e6c 100644 --- a/Generic_Plugin_Admin.php +++ b/Generic_Plugin_Admin.php @@ -385,6 +385,24 @@ public function admin_enqueue_scripts() { wp_enqueue_script( 'w3tc-feature-counter' ); + // Conditional loading for the exit survey on the plugins page. + $current_screen = get_current_screen(); + if ( isset( $current_screen->id ) && 'plugins' === $current_screen->id ) { + wp_enqueue_style( 'w3tc-exit-survey', plugins_url( 'pub/css/exit-survey.css', W3TC_FILE ), array(), W3TC_VERSION, false ); + wp_register_script( 'w3tc-exit-survey', plugins_url( 'pub/js/exit-survey.js', W3TC_FILE ), array(), W3TC_VERSION, false ); + wp_localize_script( + 'w3tc-exit-survey', + 'w3tcData', + array( + 'nonce' => wp_create_nonce( 'w3tc' ), + ) + ); + wp_enqueue_script( 'w3tc-exit-survey' ); + + wp_enqueue_style( 'w3tc-lightbox' ); + wp_enqueue_script( 'w3tc-lightbox' ); + } + // Messages. if ( ! is_null( $this->w3tc_message ) && isset( $this->w3tc_message['actions'] ) && is_array( $this->w3tc_message['actions'] ) ) { foreach ( $this->w3tc_message['actions'] as $action ) { @@ -421,8 +439,14 @@ public function admin_head() { global $wp_version; global $wpdb; + // Attempt to get the 'page' parameter from the request. $page = Util_Request::get_string( 'page', null ); + // If 'page' is null or an empty string, fallback to current screen ID. + if ( empty( $page ) ) { + $page = get_current_screen()->id ?? null; + } + if ( ( ! is_multisite() || is_super_admin() ) && false !== strpos( $page, 'w3tc' ) && 'w3tc_setup_guide' !== $page && ! get_site_option( 'w3tc_setupguide_completed' ) ) { $state_master = Dispatcher::config_state_master(); @@ -445,8 +469,7 @@ public function admin_head() { } } - if ( $this->_config->get_boolean( 'common.track_usage' ) && $this->is_w3tc_page ) { - + if ( $this->_config->get_boolean( 'common.track_usage' ) && ( $this->is_w3tc_page || 'plugins' === $page ) ) { $current_user = wp_get_current_user(); $page = Util_Request::get_string( 'page' ); if ( 'w3tc_extensions' === $page ) { @@ -492,7 +515,7 @@ function w3tc_ga(){dataLayer.push(arguments);} 'w3tc_install_date': '', 'w3tc_pro': '_config ) ? 1 : 0; ?>', 'w3tc_has_key': '_config->get_string( 'plugin.license_key' ) ? 1 : 0; ?>', - 'w3tc_pro_c': '', + 'w3tc_pro_c': '', 'w3tc_enterprise_c': '', 'w3tc_plugin_type': '_config->get_string( 'plugin.type' ) ); ?>', } diff --git a/Generic_Plugin_Survey.php b/Generic_Plugin_Survey.php new file mode 100644 index 000000000..f59458fb8 --- /dev/null +++ b/Generic_Plugin_Survey.php @@ -0,0 +1,177 @@ +_config = Dispatcher::config(); + + if ( Util_Environment::is_w3tc_pro( $this->_config ) ) { + $this->license_key = $this->_config->get_string( 'plugin.license_key' ); + $this->item_name = W3TC_PURCHASE_PRODUCT_NAME; + } + + $this->home_url = network_home_url(); + } + + /** + * Runs plugin + * + * @since X.X.X + * + * @return void + */ + public function run() { + add_action( 'w3tc_ajax_exit_survey_render', array( $this, 'w3tc_ajax_exit_survey_render' ) ); + add_action( 'w3tc_ajax_exit_survey_submit', array( $this, 'w3tc_ajax_exit_survey_submit' ) ); + } + + /** + * Renders the exit survey lightbox content + * + * @since X.X.X + * + * @return void + */ + public function w3tc_ajax_exit_survey_render() { + if ( ! \user_can( \get_current_user_id(), 'manage_options' ) ) { + return; + } + + // Verify nonce. + if ( ! wp_verify_nonce( Util_Request::get_string( '_wpnonce' ), 'w3tc' ) ) { + wp_send_json_error( array( 'message' => 'Invalid nonce.' ) ); + } + + include W3TC_INC_DIR . '/lightbox/exit_survey.php'; + } + + /** + * Processes the exit survey submission and sends it to the API. + * + * @since X.X.X + * + * @return void + */ + public function w3tc_ajax_exit_survey_submit() { + if ( ! \user_can( \get_current_user_id(), 'manage_options' ) ) { + return; + } + + // Verify nonce. + if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( Util_Request::get_string( '_wpnonce' ), 'w3tc' ) ) { + wp_send_json_error( array( 'message' => 'Invalid nonce.' ) ); + } + + // Collect survey data. + $uninstall_reason = sanitize_text_field( Util_Request::get_string( 'reason' ) ); + $other_reason = sanitize_text_field( Util_Request::get_string( 'other' ) ); + $remove_data = sanitize_text_field( Util_Request::get_string( 'remove' ) ); + + // Prepare the data to send to the API. + $data = array( + 'type' => 'exit', + 'license_key' => $this->license_key, + 'home_url' => $this->home_url, + 'item_name' => $this->item_name, + 'reason' => $uninstall_reason, + ); + + // Add 'other' to $data only if the uninstall reason is "other" and $other_reason is non-blank. + if ( 'other' === $uninstall_reason && ! empty( $other_reason ) ) { + $data['other'] = $other_reason; + } + + if ( Util_Environment::is_pro_constant( $this->_config ) ) { + $data['pro_c'] = 1; + } + + // Send the data to your API server using wp_remote_post. + $response = wp_remote_post( + Util_Environment::get_api_base_url() . '/surveys', + array( + 'method' => 'POST', + 'headers' => array( + 'Content-Type' => 'application/json', + ), + 'body' => wp_json_encode( $data ), + ) + ); + + // Check the API response. + if ( is_wp_error( $response ) ) { + wp_send_json_error( array( 'message' => 'Failed to submit data to the API.' ) ); + } + + // Handle API response. + $response_body = wp_remote_retrieve_body( $response ); + $api_response = json_decode( $response_body ); + + if ( $api_response && 201 === wp_remote_retrieve_response_code( $response ) ) { + if ( 'yes' === $remove_data ) { + update_option( 'w3tc_remove_data', true ); + } + + wp_send_json_success( array( 'message' => 'Thank you for your feedback!' ) ); + } else { + wp_send_json_error( array( 'message' => 'API error: ' . $api_response->message ) ); + } + } +} diff --git a/Licensing_Plugin_Admin.php b/Licensing_Plugin_Admin.php index 5271c766e..268fe4505 100644 --- a/Licensing_Plugin_Admin.php +++ b/Licensing_Plugin_Admin.php @@ -157,7 +157,7 @@ function admin_notices() { $state = Dispatcher::config_state(); $status = $state->get_string( 'license.status' ); - if ( defined( 'W3TC_PRO' ) ) { + if ( Util_Environment::is_pro_constant( $this->_config ) ) { } elseif ( 'no_key' === $status ) { } elseif ( $this->_status_is( $status, 'inactive.expired' ) ) { $message = wp_kses( @@ -254,7 +254,7 @@ function w3tc_notes( $notes ) { $terms = ''; $state_master = Dispatcher::config_state_master(); - if ( defined( 'W3TC_PRO' ) ) { + if ( Util_Environment::is_pro_constant( $this->_config ) ) { $terms = 'accept'; } elseif ( ! Util_Environment::is_w3tc_pro( $this->_config ) ) { $terms = $state_master->get_string( 'license.community_terms' ); diff --git a/PageSpeed_Api.php b/PageSpeed_Api.php index 32d228bbb..9c09f93af 100644 --- a/PageSpeed_Api.php +++ b/PageSpeed_Api.php @@ -31,13 +31,6 @@ class PageSpeed_Api { */ public $client; - /** - * W3TC API server base URL. Overwritten by W3TC_API2_URL constant. - * - * @var string - */ - private $w3tc_api_base_url = 'https://api2.w3-edge.com'; - /** * Retry Attemps. Overwritten by W3TC_PAGESPEED_MAX_ATTEMPTS constant. * @@ -249,7 +242,7 @@ public function refresh_token( $site_id, $w3tc_pagespeed_key ) { return; } - $request = $this->get_w3tc_api_url( 'google/refresh-token' ) . '/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); + $request = Util_Environment::get_api_base_url() . '/google/refresh-token/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); $response = wp_remote_get( $request, @@ -334,21 +327,6 @@ public function get_pagespeed_url() { return defined( 'W3TC_PAGESPEED_API_URL' ) && W3TC_PAGESPEED_API_URL ? W3TC_PAGESPEED_API_URL : $this->pagespeed_api_base_url; } - /** - * Get W3TC API server URL target. - * - * @since 2.3.0 - * - * @param string $target API target URI. - * - * @return string - */ - public function get_w3tc_api_url( $target ) { - return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ? - trailingslashit( W3TC_API2_URL ) . $target : - trailingslashit( $this->w3tc_api_base_url ) . $target; - } - /** * PageSpeed authorize admin notice. * @@ -401,7 +379,7 @@ public function reset() { return; } - $request = $this->get_w3tc_api_url( 'google/revoke-token' ) . '/' . rawurlencode( $access_token ) . '/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); + $request = Util_Environment::get_api_base_url() . '/google/revoke-token/' . rawurlencode( $access_token ) . '/' . rawurlencode( $site_id ) . '/' . rawurlencode( $w3tc_pagespeed_key ); $response = wp_remote_get( $request, diff --git a/Root_AdminActivation.php b/Root_AdminActivation.php index 8ba10a6c8..160d9104d 100644 --- a/Root_AdminActivation.php +++ b/Root_AdminActivation.php @@ -140,5 +140,10 @@ public static function deactivate() { // Delete cron events. require_once __DIR__ . '/Extension_ImageService_Cron.php'; Extension_ImageService_Cron::delete_cron(); + + // Check if data cleanup is required. + if ( get_option( 'w3tc_remove_data' ) ) { + Root_Environment::delete_plugin_data(); + } } } diff --git a/Root_Environment.php b/Root_Environment.php index 39619bc2e..61a05f1e0 100644 --- a/Root_Environment.php +++ b/Root_Environment.php @@ -203,4 +203,47 @@ public function get_other_instructions( $config ) { } return $instructions_descriptors; } + + /** + * Deletes all W3 Total Cache data from the database. + * + * phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery + * phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching + * phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log + * + * @since X.X.X + * + * @return void + */ + public static function delete_plugin_data() { + global $wpdb; + + // Define prefixes for options and transients. + $prefixes = array( + 'w3tc_', // General options prefix. + 'w3tcps_', // Additional options prefix. + '_transient_w3tc_', // Transient prefix. + '_transient_timeout_w3tc_', // Transient timeout prefix. + ); + + // Delete options and transients with defined prefixes. + foreach ( $prefixes as $prefix ) { + $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", + $prefix . '%' + ) + ); + } + + // Remove plugin-created directories. + $directories = array( + defined( 'W3TC_CACHE_DIR' ) ? W3TC_CACHE_DIR : WP_CONTENT_DIR . '/cache', + defined( 'W3TC_CONFIG_DIR' ) ? W3TC_CONFIG_DIR : WP_CONTENT_DIR . '/w3tc-config', + ); + + foreach ( $directories as $dir ) { + Util_File::rmdir( $dir ); + } + } } diff --git a/Root_Loader.php b/Root_Loader.php index 08e089fe3..914c7359d 100644 --- a/Root_Loader.php +++ b/Root_Loader.php @@ -79,6 +79,7 @@ public function __construct() { if ( is_admin() ) { $plugins[] = new Generic_Plugin_Admin(); $plugins[] = new Generic_Plugin_AdminNotices(); + $plugins[] = new Generic_Plugin_Survey(); $plugins[] = new BrowserCache_Plugin_Admin(); $plugins[] = new DbCache_Plugin_Admin(); $plugins[] = new UserExperience_Plugin_Admin(); diff --git a/SetupGuide_Plugin_Admin.php b/SetupGuide_Plugin_Admin.php index 8e6cd36ce..1c59aa909 100644 --- a/SetupGuide_Plugin_Admin.php +++ b/SetupGuide_Plugin_Admin.php @@ -894,7 +894,8 @@ public function config_imageservice() { * @return bool */ private function maybe_ask_tos() { - if ( defined( 'W3TC_PRO' ) ) { + $config = new Config(); + if ( Util_Environment::is_pro_constant( $config ) ) { return false; } diff --git a/Util_Environment.php b/Util_Environment.php index e1b792de5..e849465b0 100644 --- a/Util_Environment.php +++ b/Util_Environment.php @@ -1396,6 +1396,21 @@ public static function is_w3tc_pro_dev() { return defined( 'W3TC_PRO_DEV_MODE' ) && W3TC_PRO_DEV_MODE; } + /** + * Pro constants? + * + * @since X.X.X + * + * @static + * + * @param Config $config Config. + * + * @return bool + */ + public static function is_pro_constant( $config = null ) { + return ( defined( 'W3TC_PRO' ) && W3TC_PRO ) || ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE ); + } + /** * Quotes regular expression string. * @@ -1834,4 +1849,17 @@ protected static function get_cron_spawn() { return $result; } + + /** + * Gets the BoldGrid API URL + * + * This URL can be overridden by defining W3TC_API2_URL + * + * @since X.X.X + * + * @return string The API URL to use for requests. + */ + public static function get_api_base_url() { + return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ? esc_url( W3TC_API2_URL, array( 'https' ), '' ) : 'https://api2.w3-edge.com'; + } } diff --git a/inc/lightbox/exit_survey.php b/inc/lightbox/exit_survey.php new file mode 100644 index 000000000..c413993bc --- /dev/null +++ b/inc/lightbox/exit_survey.php @@ -0,0 +1,72 @@ + +
+
+ +
+

+

+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+ + +
+ +

+

+ +
+ +
+ +
+ +
+ + +
+ + +
+
+
+
diff --git a/inc/options/general.php b/inc/options/general.php index 469ccebb5..34bdc1d97 100644 --- a/inc/options/general.php +++ b/inc/options/general.php @@ -1284,7 +1284,7 @@ class="w3tc-ignore-change" type="text" - +

diff --git a/pub/css/exit-survey.css b/pub/css/exit-survey.css new file mode 100644 index 000000000..fcd60ddc6 --- /dev/null +++ b/pub/css/exit-survey.css @@ -0,0 +1,18 @@ +#w3tc-exit-survey-modal { + padding: 15px; +} +.w3tc-modal-content { + margin-top: -15px; +} +.w3tc-exit-survey-actions { + margin-top: 15px; +} +#w3tc-exit-survey-skip { + float: right; + text-decoration: none; + margin: 6px 0; +} +#w3tc_exit_survey_uninstall_reason_other { + width: 100%; + margin-top: 5px; +} \ No newline at end of file diff --git a/pub/css/lightbox.css b/pub/css/lightbox.css index 8fcf2c90d..7bbf3404f 100644 --- a/pub/css/lightbox.css +++ b/pub/css/lightbox.css @@ -102,6 +102,33 @@ th.minify-files-add, td.minify-files-add { color: #999; } +.lightbox-spinner { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10000; +} + +.lightbox-spinner .dashicons-update { + font-size: 35px; + color: #000000; + display: inline-block; + width: 35px; + height: 35px; + border-radius: 50%; + animation: rotate-spinner 1s linear infinite; +} + +@keyframes rotate-spinner { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + /** ################### ## Overlays diff --git a/pub/js/exit-survey.js b/pub/js/exit-survey.js new file mode 100644 index 000000000..aefd0c11a --- /dev/null +++ b/pub/js/exit-survey.js @@ -0,0 +1,149 @@ +/** + * File: exit-survey.js + * + * JavaScript for the exit survey modal. + * + * @since X.X.X + * + * @global w3tcData Localized array variable. + */ + +/** + * Display the exit servey modal on plugin deactivation. + * + * @since X.X.X + */ +function w3tc_exit_survey_render() { + W3tc_Lightbox.open({ + id: 'w3tc-overlay', + height: 'auto', + maxWidth: 600, + url: ajaxurl + + '?action=w3tc_ajax&_wpnonce=' + w3tcData.nonce + '&w3tc_action=exit_survey_render' + + (w3tc_ga_cid ? '&client_id=' + encodeURIComponent(w3tc_ga_cid) : ''), + callback: function(lightbox) { + // Retrieve the original deactivation URL. + var deactivateUrl = jQuery('#deactivate-w3-total-cache').attr('href'); + + // Cancel button action + jQuery('#w3tc-exit-survey-skip', lightbox.container).on( 'click', function() { + // Show spinner and disable interactions. + lightbox.show_spinner(); + + if (window.w3tc_ga) { + w3tc_ga( + 'event', + 'button', + { + eventCategory: 'click', + eventLabel: 'exit_survey_skip' + } + ); + } + + // Close the lightbox. + lightbox.close(); + // Proceed with plugin deactivation. + window.location.href = deactivateUrl; + }); + + // Handle form submission. + jQuery('#w3tc-exit-survey-form', lightbox.container).on('submit', function(event) { + event.preventDefault(); + + // Show spinner and disable interactions. + lightbox.show_spinner(); + + if (window.w3tc_ga) { + w3tc_ga( + 'event', + 'button', + { + eventCategory: 'click', + eventLabel: 'exit_survey_submit' + } + ); + } + + // Collect form data. + var reason = jQuery('input[name="reason"]:checked', lightbox.container).val(); + var other = jQuery('input[name="other"]', lightbox.container).val(); + var remove = jQuery('input[name="remove"]:checked', lightbox.container).val(); + + // Build the params object. + var params = { + action: 'w3tc_ajax', + _wpnonce: w3tcData.nonce, + w3tc_action: 'exit_survey_submit', + reason: reason, + other: other, + remove: remove + }; + + // Send the survey data to the API server. + jQuery.post( ajaxurl, params, function(response) { + if(response.success) { + lightbox.close(); + window.location.href = deactivateUrl; + } else { + if (window.w3tc_ga) { + w3tc_ga( + 'event', + 'w3tc_error', + { + eventCategory: 'exit_survey', + eventLabel: 'api_error' + } + ); + } + lightbox.close(); + window.location.href = deactivateUrl; + } + }); + }); + + lightbox.resize(); + } + }); +} + +// On document ready. +jQuery(function() { + /** + * Trigger display of exit survey on plugin deactivation link click. + * + * @since X.X.X + */ + jQuery('#deactivate-w3-total-cache').on( 'click', function(e) { + e.preventDefault(); + + if (window.w3tc_ga) { + w3tc_ga( + 'event', + 'button', + { + eventCategory: 'click', + eventLabel: 'exit_survey_open' + } + ); + } + + w3tc_exit_survey_render(); + return false; + }); + + // Listen for changes on the radio buttons. + jQuery(document).on('change', 'input[name="reason"]', function() { + // Enable Submit & Deactivate button once an option is selected. + if (jQuery('input[name="reason"]:checked').length > 0) { + jQuery('#w3tc-exit-survey-submit').prop('disabled', false); + } + + // If the "Other" option is selected, show the text box. + if (jQuery(this).val() === 'other') { + jQuery('#w3tc_exit_survey_uninstall_reason_other').show(); + } else { + jQuery('#w3tc_exit_survey_uninstall_reason_other').hide(); + } + }); +}); diff --git a/pub/js/lightbox.js b/pub/js/lightbox.js index 297579796..eb75ae57d 100644 --- a/pub/js/lightbox.js +++ b/pub/js/lightbox.js @@ -6,7 +6,7 @@ var W3tc_Lightbox = { create: function() { var me = this; - this.container = jQuery('
').css({ + this.container = jQuery('
').css({ top: 0, left: 0, width: 0, @@ -205,7 +205,19 @@ var W3tc_Lightbox = { this.container.find('.lightbox-content').addClass('lightbox-loader'); else this.container.find('.lightbox-content').removeClass('lightbox-loader'); - } + }, + + show_spinner: function() { + this.container.find('.lightbox-spinner').show(); // Show the spinner + this.container.find('.lightbox-content').css('opacity', '0.5'); // Gray out the modal + this.container.find('input, button, a').prop('disabled', true); // Disable other interactions + }, + + hide_spinner: function() { + this.container.find('.lightbox-spinner').hide(); // Hide the spinner + this.container.find('.lightbox-content').css('opacity', '1'); // Restore the modal opacity + this.container.find('input, button, a').prop('disabled', false); // Enable interactions + } }; var W3tc_Overlay = { @@ -226,7 +238,7 @@ var W3tc_Overlay = { opacity: 0.6 }); - jQuery('#w3tc').append(this.container); + jQuery('body').append(this.container); this.window.resize(function() { me.resize();