function w3tc_popup(url, name, width, height) {
  if (width === undefined) {
    width = 800;
  }
  if (height === undefined) {
    height = 600;
  }

  return window.open(
    url,
    name,
    "width=" +
      width +
      ",height=" +
      height +
      ",status=no,toolbar=no,menubar=no,scrollbars=yes",
  );
}

function w3tc_input_enable(input, enabled) {
  jQuery(input).each(function () {
    var me = jQuery(this);
    if (enabled) {
      me.removeAttr("disabled");
    } else {
      me.attr("disabled", "disabled");
    }

    if (enabled) {
      me.next("[type=hidden]").remove();
    } else {
      var t = me.attr("type");
      if ((t != "radio" && t != "checkbox") || me.is(":checked")) {
        me.after(
          jQuery("<input />")
            .attr({
              type: "hidden",
              name: me.attr("name"),
            })
            .val(me.val()),
        );
      }
    }
  });
}

function w3tc_minify_js_file_clear() {
  if (!jQuery("#js_files :visible").length) {
    jQuery("#js_files_empty").show();
  } else {
    jQuery("#js_files_empty").hide();
  }
}

function w3tc_minify_css_file_clear() {
  if (!jQuery("#css_files :visible").length) {
    jQuery("#css_files_empty").show();
  } else {
    jQuery("#css_files_empty").hide();
  }
}

function w3tc_minify_js_file_add(theme, template, location, file) {
  var append = jQuery(
    '<li><table><tr><th>&nbsp;</th><th>File URI:</th><th>Template:</th><th colspan="3">Embed Location:</th></tr><tr><td>' +
      (jQuery("#js_files li").length + 1) +
      '.</td><td><input class="js_enabled" type="text" name="js_files[' +
      theme +
      "][" +
      template +
      "][" +
      location +
      '][]" value="" size="70" \/></td><td><select class="js_file_template js_enabled"></select></td><td><select class="js_file_location js_enabled"><option value="include">Embed in &lt;head&gt;</option><option value="include-body">Embed after &lt;body&gt;</option><option value="include-footer">Embed before &lt;/body&gt;</option></select></td><td><input class="js_file_delete js_enabled button" type="button" value="Delete" /> <input class="js_file_verify js_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>',
  );
  append.find("input:text").val(file);
  var select = append.find(".js_file_template");
  for (var i in minify_templates[theme]) {
    select.append(jQuery("<option />").val(i).html(minify_templates[theme][i]));
  }
  select.val(template);
  jQuery(append).find(".js_file_location").val(location);
  jQuery("#js_files").append(append).find("li:last input:first").focus();
  w3tc_minify_js_file_clear();
}

function w3tc_minify_css_file_add(theme, template, file) {
  var append = jQuery(
    '<li><table><tr><th>&nbsp;</th><th>File URI:</th><th colspan="2">Template:</th></tr><tr><td>' +
      (jQuery("#css_files li").length + 1) +
      '.</td><td><input class="css_enabled" type="text" name="css_files[' +
      theme +
      "][" +
      template +
      '][include][]" value="" size="70" \/></td><td><select class="css_file_template css_enabled"></select></td><td><input class="css_file_delete css_enabled button" type="button" value="Delete" /></td><td><input class="css_file_verify css_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>',
  );
  append.find("input:text").val(file);
  var select = append.find(".css_file_template");
  for (var i in minify_templates[theme]) {
    select.append(jQuery("<option />").val(i).html(minify_templates[theme][i]));
  }
  select.val(template);
  jQuery("#css_files").append(append).find("li:last input:first").focus();
  w3tc_minify_css_file_clear();
}

function w3tc_minify_js_theme(theme) {
  jQuery("#js_themes").val(theme);
  jQuery("#js_files :text").each(function () {
    var input = jQuery(this);
    if (input.attr("name").indexOf("js_files[" + theme + "]") != 0) {
      input.parents("li").hide();
    } else {
      input.parents("li").show();
    }
  });
  w3tc_minify_js_file_clear();
}

function w3tc_minify_css_theme(theme) {
  jQuery("#css_themes").val(theme);
  jQuery("#css_files :text").each(function () {
    var input = jQuery(this);
    if (input.attr("name").indexOf("css_files[" + theme + "]") != 0) {
      input.parents("li").hide();
    } else {
      input.parents("li").show();
    }
  });
  w3tc_minify_css_file_clear();
}

function w3tc_cdn_get_cnames() {
  var cnames = [];

  jQuery("#cdn_cnames input[type=text]").each(function () {
    var cname = jQuery(this).val();

    if (cname) {
      var match = /^\*\.(.*)$/.exec(cname);

      if (match) {
        cnames = [];
        for (var i = 1; i <= 10; i++) {
          cnames.push("cdn" + i + "." + match[1]);
        }
        return false;
      }

      cnames.push(cname);
    }
  });

  return cnames;
}

function w3tc_cdn_cnames_assign() {
  var li = jQuery("#cdn_cnames li"),
    size = li.length;

  if (size > 1) {
    li.eq(0).find(".cdn_cname_delete").show();
  } else {
    li.eq(0).find(".cdn_cname_delete").hide();
  }

  jQuery(li).each(function (index) {
    var label = "";

    if (size > 1) {
      switch (index) {
        case 0:
          label = "(reserved for CSS)";
          break;

        case 1:
          label = "(reserved for JS in <head>)";
          break;

        case 2:
          label = "(reserved for JS after <body>)";
          break;

        case 3:
          label = "(reserved for JS before </body>)";
          break;
      }
    }

    jQuery(this).find("span").text(label);
  });
}

function w3tc_toggle(name, check) {
  if (check === undefined) {
    check = true;
  }

  var id = "#" + name,
    cls = "." + name;

  jQuery(cls).on("click", function () {
    var checked = check;

    jQuery(cls).each(function () {
      var _checked = jQuery(this).is(":checked");

      if ((check && !_checked) || (!check && _checked)) {
        checked = !check;

        return false;
      }
    });

    if (checked) {
      jQuery(id).attr("checked", "checked");
    } else {
      jQuery(id).removeAttr("checked");
    }
  });

  jQuery(id).on("click", function () {
    var checked = jQuery(this).is(":checked");
    jQuery(cls).each(function () {
      if (checked) {
        jQuery(this).attr("checked", "checked");
      } else {
        jQuery(this).removeAttr("checked");
      }
    });
  });
}

function w3tc_toggle2(name, dependent_ids) {
  var id = "#" + name,
    dependants = "",
    n;
  for (n = 0; n < dependent_ids.length; n++)
    dependants += (n > 0 ? "," : "") + "#" + dependent_ids[n];

  jQuery(dependants).on("click", function () {
    var total_checked = true;

    jQuery(dependants).each(function () {
      var current_checked = jQuery(this).is(":checked");

      if (!current_checked) total_checked = false;
    });

    if (total_checked) {
      jQuery(id).attr("checked", "checked");
    } else {
      jQuery(id).removeAttr("checked");
    }
  });

  jQuery(id).on("click", function () {
    var checked = jQuery(this).is(":checked");
    jQuery(dependants).each(function () {
      if (checked) {
        jQuery(this).attr("checked", "checked");
      } else {
        jQuery(this).removeAttr("checked");
      }
    });
  });
}

function w3tc_beforeupload_bind() {
  jQuery(window).bind("beforeunload", w3tc_beforeunload);
}

function w3tc_beforeupload_unbind() {
  jQuery(window).off("beforeunload", w3tc_beforeunload);
}

function w3tc_beforeunload() {
  return "Navigate away from this page without saving your changes?";
}

function w3tc_starts_with(s, starts_with) {
  s = s.replace(/\n/g, "");
  s = s.replace(/\s/g, "");
  return s.substr(0, starts_with.length) == starts_with;
}

function w3tc_security_headers() {
  var directive_description = {
    browsercache_security_hsts_directive: {
      maxage:
        'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using <acronym title="HyperText Transfer Protocol over SSL">HTTPS</acronym>. This only affects the site\'s main domain.',
      maxagepre:
        'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using <acronym title="HyperText Transfer Protocol over SSL">HTTPS</acronym> with a request to be included in Chrome\'s HSTS preload list - a list of sites that are hardcoded into Chrome as being <acronym title="HyperText Transfer Protocol over SSL">https</acronym> only. This only affects the site\'s main domain.',
      maxageinc:
        'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using <acronym title="HyperText Transfer Protocol over SSL">HTTPS</acronym>. This affects the site\'s subdomains as well.',
      maxageincpre:
        'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using <acronym title="HyperText Transfer Protocol over SSL">HTTPS</acronym> with a request to be included in Chrome\'s HSTS preload list - a list of sites that are hardcoded into Chrome as being <acronym title="HyperText Transfer Protocol over SSL">https</acronym> only. This affects the site\'s subdomains as well.',
    },
    browsercache_security_xfo_directive: {
      same: "The page can only be displayed in a frame on the same origin as the page itself.",
      deny: "The page cannot be displayed in a frame, regardless of the site attempting to do so.",
      allow: "The page can only be displayed in a frame on the specified URL.",
    },
    browsercache_security_xss_directive: {
      0: "Disables XSS filtering.",
      1: "Enables XSS filtering (usually default in browsers). If a cross-site scripting attack is detected, the browser will sanitize the page (remove the unsafe parts).",
      block:
        "Enables <acronym title='Cross-Site Scripting'>XSS</acronym> filtering. Rather than sanitizing the page, the browser will prevent rendering of the page if an attack is detected.",
    },
    browsercache_security_pkp_extra: {
      maxage:
        'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using one of the defined keys. This only affects the site\'s main domain.',
      maxageinc:
        'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using one of the defined keys. This affects the site\'s subdomains as well.',
    },
    browsercache_security_pkp_report_only: {
      0: 'This instructs the browser to enforce the <acronym title="HTTP Public Key Pinning">HPKP</acronym> policy.',
      1: 'This sets up <acronym title="HTTP Public Key Pinning">HPKP</acronym> without enforcement allowing you to use pinning to test its impact without the risk of a failed connection caused by your site being unreachable or <acronym title="HTTP Public Key Pinning">HPKP</acronym> being misconfigured.',
    },
  };

  jQuery(
    "#browsercache_security_hsts_directive,#browsercache_security_xfo_directive,#browsercache_security_xss_directive,#browsercache_security_pkp_extra,#browsercache_security_pkp_report_only",
  ).on("change", function () {
    jQuery("#" + jQuery(this).attr("id") + "_description").html(
      "<i>" +
        directive_description[jQuery(this).attr("id")][jQuery(this).val()] +
        "</i>",
    );
    if (jQuery(this).attr("id") == "browsercache_security_xfo_directive") {
      if (jQuery(this).val() == "allow") {
        jQuery("#browsercache_security_xfo_allow").show();
      } else {
        jQuery("#browsercache_security_xfo_allow").hide();
      }
    }
  });

  if (jQuery("#browsercache_security_xfo_allow").length) {
    if (jQuery("#browsercache_security_xfo_directive").val() == "allow") {
      jQuery("#browsercache_security_xfo_allow").show();
    } else {
      jQuery("#browsercache_security_xfo_allow").hide();
    }
  }
}

function w3tc_csp_reference() {
  W3tc_Lightbox.open({
    id: "w3tc-overlay",
    close: "",
    width: 890,
    height: 460,
    url:
      ajaxurl +
      "?action=w3tc_ajax&_wpnonce=" +
      w3tcGetAjaxNonce("browsercache_quick_reference") +
      "&w3tc_action=browsercache_quick_reference",
    callback: function (lightbox) {
      lightbox.resize();
    },
  });
  jQuery("div#overlay,.lightbox-content").on("click", function () {
    W3tc_Lightbox.close();
  });
}

/**
 * Bunny CDN check.
 *
 * Prevent enabling Bunny CDN ("bunnycdn" engine) for both CDN and CDNFSD.
 *
 * @since 2.6.0
 *
 * @returns null
 */
function cdn_bunnycdn_check() {
  // Prevents JS error for non W3TC pages.
  if (typeof w3tcData === "undefined") {
    return;
  }

  var $cdn_enabled = jQuery("#cdn__enabled"),
    $cdn_engine = jQuery("#cdn__engine"),
    $cdnfsd_enabled = jQuery("#cdnfsd__enabled"),
    $cdnfsd_engine = jQuery("#cdnfsd__engine"),
    cdn_enabled = $cdn_enabled.is(":checked"),
    cdn_engine = $cdn_engine.find(":selected").val(),
    cdnfsd_enabled = $cdnfsd_enabled.is(":checked"),
    cdnfsd_engine = $cdnfsd_engine.find(":selected").val(),
    $cdn_inside = jQuery("#cdn .inside");

  if (
    cdn_enabled &&
    cdnfsd_enabled &&
    "bunnycdn" === cdn_engine &&
    cdnfsd_engine === cdn_engine
  ) {
    // Reset to what was last saved.
    $cdn_enabled.prop("checked", w3tcData.cdnEnabled);
    $cdn_engine.val(w3tcData.cdnEngine).change();
    $cdnfsd_enabled.prop("checked", w3tcData.cdnfsdEnabled);
    $cdnfsd_engine.val(w3tcData.cdnfsdEngine).change();

    // Display a warning.
    jQuery("<div/>", {
      class: "notice notice-warning",
      id: "w3tc-bunnycdn-warning",
      text: w3tcData.bunnyCdnWarning,
    }).prependTo($cdn_inside);
  } else {
    // Remove the warning.
    jQuery("#w3tc-bunnycdn-warning").remove();
  }
}

/**
 * Cloudfront CDN check.
 *
 * When CDN is enabled as "cf" or "cf2", then display a notice about possible charges.
 *
 * @returns null
 */
function cdn_cf_check() {
  // Prevents JS error for non W3TC pages.
  if (typeof w3tcData === "undefined") {
    return;
  }

  var cdnEnabled = jQuery("#cdn__enabled").is(":checked"),
    cdnEngine = jQuery("#cdn__engine").find(":selected").val(),
    cdnFlushManually = jQuery('[name="cdn__flush_manually"]').is(":checked");

  // Remove any cf admin notices.
  jQuery(".w3tc-cf-notice").remove();

  // General page.
  if (
    !w3tcData.cdnFlushManually &&
    cdnEnabled &&
    ("cf" === cdnEngine || "cf2" === cdnEngine)
  ) {
    // Print cf admin notice.
    jQuery("#cdn .inside").prepend(
      '<div class="notice notice-warning inline w3tc-cf-notice"><p>' +
        w3tcData.cfWarning +
        "</p></div>",
    );
  }

  // CDN page.
  if (
    !cdnFlushManually &&
    w3tcData.cdnEnabled &&
    ("cf" === w3tcData.cdnEngine || "cf2" === w3tcData.cdnEngine)
  ) {
    // Show warning on the CDN page for flush manually.
    jQuery("#cdn-flushmanually-warning").show();
  } else {
    // Hide warning on the CDN page for flush manually.
    jQuery("#cdn-flushmanually-warning").hide();
  }
}

function set_sticky_bar_positions() {
  jQuery("#w3tc > #w3tc-options-menu").css(
    "top",
    Math.floor(
      (jQuery(window).width() > 600 && jQuery("#wpadminbar").length
        ? jQuery("#wpadminbar").outerHeight()
        : 0) + jQuery("#w3tc-top-nav-bar").outerHeight(),
    ),
  );
  jQuery(".w3tc_form_bar").css(
    "top",
    Math.floor(
      (jQuery(window).width() > 600 && jQuery("#wpadminbar").length
        ? jQuery("#wpadminbar").outerHeight()
        : 0) +
        jQuery("#w3tc-top-nav-bar").outerHeight() +
        (jQuery("#w3tc > #w3tc-options-menu").length
          ? jQuery("#w3tc > #w3tc-options-menu").outerHeight()
          : 0),
    ),
  );
}

function set_footer_position() {
  jQuery("#w3tc-footer").insertAfter(jQuery("#wpfooter"));
  jQuery("#w3tc-footer").css(
    "bottom",
    Math.floor(0 - jQuery("#w3tc-footer").outerHeight()),
  );
}

function debounce(func) {
  var timer;
  return function (event) {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(func, 100, event);
  };
}

/**
 * Get the S3 bucket region from the selected location to be used for the hostname.
 *
 * The default location (us-east-1) returns an empty string.  All other regions return the region with a trailing dot.
 *
 * @since 2.7.2
 *
 * @param {string} location Bucket location.
 * @returns string
 */
function get_bucket_region(location) {
  let region = "";

  switch (location) {
    case "us-east-1":
      break;
    case "us-east-1-e":
      region = "us-east-1.";
      break;
    default:
      region = location + ".";
      break;
  }

  return region;
}

/**
 * Event callback for changing CDN Cloudfront (push) S3 bucket location.
 *
 * @since 2.7.2
 *
 * @see get_bucket_region()
 */
function cdn_cf_bucket_location() {
  const id = jQuery("#cdn_cf_bucket").val();

  jQuery("#cdn-cf-bucket-hostname").text(
    id +
      ".s3." +
      get_bucket_region(jQuery("#cdn_cf_bucket_location").val()) +
      "amazonaws.com",
  );
}

/**
 * Toggle the disk notice for dbcache.
 *
 * @since 2.8.0
 */
function toggle_dbcache_notice() {
  jQuery(".dbcache_disk_notice").toggle(
    jQuery("#dbcache__engine").val() === "file" &&
      jQuery("#dbcache__enabled").is(":checked"),
  );
}

/**
 * Toggle the disk notice for objectcache.
 *
 * @since 2.8.0
 */
function toggle_objectcache_notice() {
  jQuery(".objectcache_disk_notice").toggle(
    jQuery("#objectcache__engine").val() === "file" &&
      jQuery("#objectcache__enabled").is(":checked"),
  );
}

/**
 * Toggle the disk notice for fragmentcache.
 *
 * @since 2.8.3
 */
function toggle_fragmentcache_notice() {
  jQuery(".fragmentcache_disk_notice").toggle(
    jQuery("#fragmentcache___engine").val() === "file",
  );
}

// On document ready.
jQuery(function () {
  // Per-handler tokens live on the button (data-w3tc-nonce) or in w3tc_admin_nonces; copy into the form field before submit.
  // Track the last-clicked w3tc_ submit button so the handler copies its nonce, not the first-in-DOM button's (the General Settings form holds both Save and flush buttons).
  var w3tcLastSubmitter = null;
  jQuery(document).on(
    "click",
    'input[type=submit][name^="w3tc_"]',
    function () {
      w3tcLastSubmitter = this;
      w3tcSetAdminSubmitNonce(this);
    },
  );
  jQuery(document).on("submit", "form", function (event) {
    var form = this;
    // Pick the submit control the user actually triggered, with fallbacks.
    var native = event.originalEvent ? event.originalEvent.submitter : null;
    var $submitter = jQuery();
    if (
      native &&
      native.form === form &&
      jQuery(native).is('input[type=submit][name^="w3tc_"]')
    ) {
      $submitter = jQuery(native);
    }
    if (
      !$submitter.length &&
      w3tcLastSubmitter &&
      w3tcLastSubmitter.form === form
    ) {
      $submitter = jQuery(w3tcLastSubmitter);
    }
    if (!$submitter.length) {
      $submitter = jQuery(form).find('input[type=submit][name^="w3tc_"]:focus');
    }
    if (!$submitter.length) {
      $submitter = jQuery(form)
        .find('input[type=submit][name^="w3tc_"]')
        .first();
    }
    if ($submitter.length) {
      w3tcSetAdminSubmitNonce($submitter[0]);
    }
  });

  // Global vars.
  var $cdn_enabled = jQuery("#cdn__enabled"),
    $cdn_engine = jQuery("#cdn__engine");

  // Database cache disk usage warning.
  toggle_dbcache_notice();
  jQuery("#dbcache__enabled").change(toggle_dbcache_notice);
  jQuery("#dbcache__engine").change(toggle_dbcache_notice);

  // Object cache disk usage warning.
  toggle_objectcache_notice();
  jQuery("#objectcache__enabled").change(toggle_objectcache_notice);
  jQuery("#objectcache__engine").change(toggle_objectcache_notice);

  // Fragment cache disk usage warning.
  toggle_fragmentcache_notice();
  jQuery("#fragmentcache___engine").change(toggle_fragmentcache_notice);

  // General page.
  jQuery(".w3tc_read_technical_info").on("click", function () {
    jQuery(".w3tc_technical_info").toggle();
  });

  // General Settings Tab actions.
  jQuery(document).on(
    "click",
    ".performance_page_w3tc_general .nav-tab",
    function () {
      const $tab = jQuery(this),
        $nav_tab_wrapper = $tab.closest(".nav-tab-wrapper");
      ((tab_type = $tab.attr("data-tab-type")),
        ($inside = $tab.closest(".postbox-tabs").find(".inside")));

      // Highlight the selected tab.
      $nav_tab_wrapper.find("a").removeClass("nav-tab-active");
      $tab.addClass("nav-tab-active");

      // If the tab is a link, don't do anything.
      if ($tab.is("[href]")) {
        return;
      }

      // Start off by hiding everything.
      $inside.children().hide();

      if (!tab_type) {
        // Show children without a data-tab-type attribute.
        $inside.children(":not([data-tab-type])").show(); // Show those without data-tab-type
      } else {
        // Show children with the matching data-tab-type attribute.
        $inside.children('[data-tab-type="' + tab_type + '"]').show();
      }
    },
  );

  // Tutorial page forum links via API.
  jQuery(document).on("click", '[data-tab-type="help"]', function () {
    const $helpTab = jQuery(this),
      $inside = $helpTab.closest(".postbox-tabs").find(".inside");
    $forumTopicsContainer = $inside.find(".help-forum-topics");
    isLoaded = $forumTopicsContainer.attr("data-loaded") === "1";
    tabId = $forumTopicsContainer.attr("data-tab-id");

    // Check if topics are already loaded
    if (isLoaded) {
      return;
    }

    // Fetch topics from the API
    jQuery.ajax({
      url: ajaxurl,
      method: "POST",
      data: {
        action: "w3tc_forums_api",
        _wpnonce: w3tc_forums_api_nonce[0],
        tabId: tabId,
      },
      success: function (data) {
        // Check for timeout
        if (data.errors && data.errors.http_request_failed) {
          $forumTopicsContainer.html(
            "HTTP Error:",
            data.errors.http_request_failed,
          );
        }
        // Check for empty results
        else if (Array.isArray(data) && data.length === 0) {
          $forumTopicsContainer.html("<p>No forum topics found.</p>");
        } else {
          // Create a list of topics
          const $ul = jQuery("<ul></ul>");
          const forumData = JSON.parse(data.body);
          jQuery.each(forumData, function (index, topic) {
            const $li = jQuery("<li></li>");
            const $link = jQuery("<a></a>")
              .addClass("w3tc-control-after")
              .attr("href", topic.link)
              .attr("target", "_blank"); // Open in new tab

            // Decode HTML entities in topic.title
            const decodedTitle = jQuery("<textarea />")
              .html(topic.title)
              .text();
            $link.text(decodedTitle);

            const $icon = jQuery("<span></span>").addClass(
              "dashicons dashicons-external",
            );
            $link.append($icon);
            $li.append($link);
            $ul.append($li);
          });
          $forumTopicsContainer.html($ul);
        }
        // Mark topics as loaded to prevent duplicate requests
        $forumTopicsContainer.attr("data-loaded", "1");
      },
      error: function () {
        $forumTopicsContainer.html(
          "<p>Error loading topics. Please try again later.</p>",
        );
      },
    });
  });

  // Prevent enabling Bunny CDN for both CDN and CDNFSD.
  $cdn_enabled.on("click", cdn_bunnycdn_check);
  $cdn_engine.on("change", cdn_bunnycdn_check);
  jQuery("#cdnfsd__enabled").on("click", cdn_bunnycdn_check);
  jQuery("#cdnfsd__engine").on("change", cdn_bunnycdn_check);

  // When CDN is enabled as "cf" or "cf2", then display a notice about possible charges.
  cdn_cf_check();
  $cdn_enabled.on("click", cdn_cf_check);
  $cdn_engine.on("change", cdn_cf_check);

  /**
   * CDN page.
   * When CDN is enabled as "cf" or "cf2", then display a notice about possible charges.
   */
  jQuery('[name="cdn__flush_manually"]').on("click", cdn_cf_check);

  // Pagecache page.
  w3tc_input_enable(
    "#pgcache_reject_roles input[type=checkbox]",
    jQuery("#pgcache__reject__logged_roles:checked").length,
  );
  jQuery("#pgcache__reject__logged_roles").on("click", function () {
    w3tc_input_enable(
      "#pgcache_reject_roles input[type=checkbox]",
      jQuery("#pgcache__reject__logged_roles:checked").length,
    );
  });

  // Browsercache page.
  w3tc_toggle2("browsercache_last_modified", [
    "browsercache__cssjs__last_modified",
    "browsercache__html__last_modified",
    "browsercache__other__last_modified",
  ]);
  w3tc_toggle2("browsercache_expires", [
    "browsercache__cssjs__expires",
    "browsercache__html__expires",
    "browsercache__other__expires",
  ]);
  w3tc_toggle2("browsercache_cache_control", [
    "browsercache__cssjs__cache__control",
    "browsercache__html__cache__control",
    "browsercache__other__cache__control",
  ]);
  w3tc_toggle2("browsercache_etag", [
    "browsercache__cssjs__etag",
    "browsercache__html__etag",
    "browsercache__other__etag",
  ]);
  w3tc_toggle2("browsercache_w3tc", [
    "browsercache__cssjs__w3tc",
    "browsercache__html__w3tc",
    "browsercache__other__w3tc",
  ]);
  w3tc_toggle2("browsercache_compression", [
    "browsercache__cssjs__compression",
    "browsercache__html__compression",
    "browsercache__other__compression",
  ]);
  w3tc_toggle2("browsercache_brotli", [
    "browsercache__cssjs__brotli",
    "browsercache__html__brotli",
    "browsercache__other__brotli",
  ]);
  w3tc_toggle2("browsercache_replace", [
    "browsercache__cssjs__replace",
    "browsercache__other__replace",
  ]);
  w3tc_toggle2("browsercache_querystring", [
    "browsercache__cssjs__querystring",
    "browsercache__other__querystring",
  ]);
  w3tc_toggle2("browsercache_nocookies", [
    "browsercache__cssjs__nocookies",
    "browsercache__other__nocookies",
  ]);

  w3tc_security_headers();

  // Minify page.
  w3tc_input_enable(
    ".html_enabled",
    jQuery("#minify__html__enable:checked").length,
  );
  w3tc_input_enable(
    ".js_enabled",
    jQuery("#minify__js__enable:checked").length,
  );
  w3tc_input_enable(
    ".css_enabled",
    jQuery("#minify__css__enable:checked").length,
  );

  w3tc_minify_js_theme(jQuery("#js_themes").val());
  w3tc_minify_css_theme(jQuery("#css_themes").val());

  jQuery("#minify__html__enable").on("click", function () {
    w3tc_input_enable(".html_enabled", this.checked);
  });

  jQuery("#minify__js__enable").on("click", function () {
    w3tc_input_enable(".js_enabled", jQuery(this).is(":checked"));
  });

  jQuery("#minify__css__enable").on("click", function () {
    w3tc_input_enable(".css_enabled", jQuery(this).is(":checked"));
  });

  jQuery(".js_file_verify,.css_file_verify").on("click", function () {
    var file = jQuery(this).parents("li").find(":text").val();
    if (file == "") {
      alert("Empty URI");
    } else {
      var url = "";
      if (/^https?:\/\//.test(file)) {
        url = file;
      } else {
        url = "/" + file;
      }
      w3tc_popup(url, "file_verify");
    }
  });

  jQuery(".js_file_template").on("change", function () {
    jQuery(this)
      .parents("li")
      .find(":text")
      .attr(
        "name",
        "js_files[" +
          jQuery("#js_themes").val() +
          "][" +
          jQuery(this).val() +
          "][" +
          jQuery(this).parents("li").find(".js_file_location").val() +
          "][]",
      );
  });

  jQuery(".css_file_template").on("change", function () {
    jQuery(this)
      .parents("li")
      .find(":text")
      .attr(
        "name",
        "css_files[" +
          jQuery("#css_themes").val() +
          "][" +
          jQuery(this).val() +
          "][include][]",
      );
  });

  jQuery(".js_file_location").on("change", function () {
    jQuery(this)
      .parents("li")
      .find(":text")
      .attr(
        "name",
        "js_files[" +
          jQuery("#js_themes").val() +
          "][" +
          jQuery(this).parents("li").find(".js_file_template").val() +
          "][" +
          jQuery(this).val() +
          "][]",
      );
  });

  jQuery(".js_file_delete").on("click", function () {
    var parent = jQuery(this).parents("li");
    if (
      parent.find("input[type=text]").val() == "" ||
      confirm("Are you sure you want to remove this JS file?")
    ) {
      parent.remove();
      w3tc_minify_js_file_clear();
      w3tc_beforeupload_bind();
    }

    return false;
  });

  jQuery(".css_file_delete").on("click", function () {
    var parent = jQuery(this).parents("li");
    if (
      parent.find("input[type=text]").val() == "" ||
      confirm("Are you sure you want to remove this CSS file?")
    ) {
      parent.remove();
      w3tc_minify_css_file_clear();
      w3tc_beforeupload_bind();
    }

    return false;
  });

  jQuery("#js_file_add").on("click", function () {
    w3tc_minify_js_file_add(
      jQuery("#js_themes").val(),
      "default",
      "include",
      "",
    );
  });

  jQuery("#css_file_add").on("click", function () {
    w3tc_minify_css_file_add(jQuery("#css_themes").val(), "default", "");
  });

  jQuery("#js_themes").on("change", function () {
    w3tc_minify_js_theme(jQuery(this).val());
  });

  jQuery("#css_themes").on("change", function () {
    w3tc_minify_css_theme(jQuery(this).val());
  });

  jQuery("#minify_form").on("submit", function () {
    var js = [],
      css = [],
      invalid_js = [],
      invalid_css = [],
      duplicate = false,
      query_js = [],
      query_css = [];

    jQuery("#js_files :text").each(function () {
      var v = jQuery(this).val(),
        n = jQuery(this).attr("name"),
        c = v + n,
        g = "";
      var match = /js_files\[([a-z0-9_\/]+)\]/.exec(n);
      if (match) {
        g =
          "[" +
          jQuery("#js_themes option[value=" + match[1] + "]").text() +
          "] " +
          v;
      }
      if (v != "") {
        for (var i = 0; i < js.length; i++) {
          if (js[i] == c) {
            duplicate = true;
            break;
          }
        }

        js.push(c);

        var qindex = v.indexOf("?");
        if (qindex != -1) {
          if (!/^(https?:)?\/\//.test(v)) {
            query_js.push(g);
          }
          v = v.substr(0, qindex);
        } else if (!/\.js$/.test(v)) {
          invalid_js.push(g);
        }
      }
    });

    jQuery("#css_files :text").each(function () {
      var v = jQuery(this).val(),
        n = jQuery(this).attr("name"),
        c = v + n,
        g = "";
      var match = /css_files\[([a-z0-9_\/]+)\]/.exec(n);
      if (match) {
        g =
          "[" +
          jQuery("#css_themes option[value=" + match[1] + "]").text() +
          "] " +
          v;
      }
      if (v != "") {
        for (var i = 0; i < css.length; i++) {
          if (css[i] == c) {
            duplicate = true;
            break;
          }
        }

        css.push(c);

        var qindex = v.indexOf("?");
        if (qindex != -1) {
          if (!/^(https?:)?\/\//.test(v)) {
            query_css.push(g);
          }
          v = v.substr(0, qindex);
        } else if (!/\.css$/.test(v)) {
          invalid_css.push(g);
        }
      }
    });

    if (jQuery("#js_enabled:checked").length) {
      if (
        invalid_js.length &&
        !confirm(
          "The following files have invalid JS file extension:\r\n\r\n" +
            invalid_js.join("\r\n") +
            "\r\n\r\nAre you confident these files contain valid JS code?",
        )
      ) {
        return false;
      }

      if (query_js.length) {
        alert(
          "We recommend using the entire URI for files with query string (GET) variables. You entered:\r\n\r\n" +
            query_js.join("\r\n"),
        );
        return false;
      }
    }

    if (jQuery("#css_enabled:checked").length) {
      if (
        invalid_css.length &&
        !confirm(
          "The following files have invalid CSS file extension:\r\n\r\n" +
            invalid_css.join("\r\n") +
            "\r\n\r\nAre you confident these files contain valid CSS code?",
        )
      ) {
        return false;
      }

      if (query_css.length) {
        alert(
          "We recommend using the entire URI for files with query string (GET) variables. You entered:\r\n\r\n" +
            query_css.join("\r\n"),
        );
        return false;
      }
    }

    if (duplicate) {
      alert(
        "Duplicate files have been found in your minify settings, please check your settings and re-save.",
      );
      return false;
    }

    return true;
  });

  // CDN.
  jQuery(".w3tc-tab").on("click", function () {
    jQuery(".w3tc-tab-content").hide();
    jQuery(this.rel).show();
  });

  w3tc_input_enable(
    "#cdn_reject_roles input[type=checkbox]",
    jQuery("#cdn__reject__logged_roles:checked").length,
  );
  jQuery("#cdn__reject__logged_roles").on("click", function () {
    w3tc_input_enable(
      "#cdn_reject_roles input[type=checkbox]",
      jQuery("#cdn__reject__logged_roles:checked").length,
    );
  });

  jQuery("#cdn_export_library").on("click", function () {
    w3tc_popup(
      "admin.php?page=w3tc_cdn&w3tc_cdn_export_library&_wpnonce=" +
        jQuery(this).metadata().nonce,
      "cdn_export_library",
    );
  });

  jQuery("#cdn_import_library").on("click", function () {
    w3tc_popup(
      "admin.php?page=w3tc_cdn&w3tc_cdn_import_library&_wpnonce=" +
        jQuery(this).metadata().nonce,
      "cdn_import_library",
    );
  });

  jQuery("#cdn_queue").on("click", function () {
    w3tc_popup(
      "admin.php?page=w3tc_cdn&w3tc_cdn_queue&_wpnonce=" +
        jQuery(this).metadata().nonce,
      "cdn_queue",
    );
  });

  jQuery("#cdn_rename_domain").on("click", function () {
    w3tc_popup(
      "admin.php?page=w3tc_cdn&w3tc_cdn_rename_domain&_wpnonce=" +
        jQuery(this).metadata().nonce,
      "cdn_rename_domain",
    );
  });

  jQuery("#cdn_purge").on("click", function () {
    w3tc_popup(
      "admin.php?page=w3tc_cdn&w3tc_cdn_purge&_wpnonce=" +
        jQuery(this).metadata().nonce,
      "cdn_purge",
    );
  });

  jQuery(".cdn_export").on("click", function () {
    var metadata = jQuery(this).metadata();
    w3tc_popup(
      "admin.php?page=w3tc_cdn&w3tc_cdn_export&cdn_export_type=" +
        metadata.type +
        "&_wpnonce=" +
        metadata.nonce,
      "cdn_export_" + metadata.type,
    );
  });

  jQuery("#validate_cdn_key").on("click", function () {
    var me = jQuery(this);
    var metadata = me.metadata();
    w3tc_validate_cdn_key_result(metadata.type, metadata.nonce);
  });

  jQuery("#use_poll_zone").on("click", function () {
    var me = jQuery(this);
    var metadata = me.metadata();
    w3tc_use_poll_zone(metadata.type, metadata.nonce);
  });

  jQuery("#cdn_test").on("click", function () {
    var me = jQuery(this);
    var metadata = me.metadata();
    var cnames = w3tc_cdn_get_cnames();
    var params = {
      w3tc_cdn_test: 1,
      _wpnonce: metadata.nonce,
    };

    switch (metadata.type) {
      case "ftp":
        jQuery.extend(params, {
          engine: "ftp",
          "config[host]": jQuery("#cdn_ftp_host").val(),
          "config[type]": jQuery("#cdn_ftp_type").val(),
          "config[user]": jQuery("#cdn_ftp_user").val(),
          "config[path]": jQuery("#cdn_ftp_path").val(),
          "config[pass]": jQuery("#cdn_ftp_pass").val(),
          "config[pasv]": jQuery("#cdn__ftp__pasv:checked").length,
          "config[default_keys]": jQuery("#cdn__ftp__default_keys:checked")
            .length,
          "config[pubkey]": jQuery("#cdn_ftp_pubkey").val(),
          "config[privkey]": jQuery("#cdn_ftp_privkey").val(),
        });

        if (cnames.length) {
          params["config[domain][]"] = cnames;
        }
        break;

      case "s3":
        jQuery.extend(params, {
          engine: "s3",
          "config[key]": jQuery("#cdn_s3_key").val(),
          "config[secret]": jQuery("#cdn_s3_secret").val(),
          "config[bucket]": jQuery("#cdn_s3_bucket").val(),
          "config[bucket_location]": jQuery("#cdn_s3_bucket_location").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "cf":
        jQuery.extend(params, {
          engine: "cf",
          "config[key]": jQuery("#cdn_cf_key").val(),
          "config[secret]": jQuery("#cdn_cf_secret").val(),
          "config[bucket]": jQuery("#cdn_cf_bucket").val(),
          "config[bucket_location]": jQuery("#cdn_cf_bucket_location").val(),
          "config[id]": jQuery("#cdn_cf_id").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "cf2":
        jQuery.extend(params, {
          engine: "cf2",
          "config[key]": jQuery("#cdn_cf2_key").val(),
          "config[secret]": jQuery("#cdn_cf2_secret").val(),
          "config[origin]": jQuery("#cdn_cf2_origin").val(),
          "config[id]": jQuery("#cdn_cf2_id").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "rscf":
        jQuery.extend(params, {
          engine: "rscf",
          "config[user]": jQuery("#cdn_rscf_user").val(),
          "config[key]": jQuery("#cdn_rscf_key").val(),
          "config[location]": jQuery("#cdn_rscf_location").val(),
          "config[container]": jQuery("#cdn_rscf_container").val(),
          "config[id]": jQuery("#cdn_rscf_id").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "azure":
        jQuery.extend(params, {
          engine: "azure",
          "config[user]": jQuery("#cdn_azure_user").val(),
          "config[key]": jQuery("#cdn_azure_key").val(),
          "config[container]": jQuery("#cdn_azure_container").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "azuremi":
        jQuery.extend(params, {
          engine: "azuremi",
          "config[user]": jQuery("#cdn_azuremi_user").val(),
          "config[client_id]": jQuery("#cdn_azuremi_clientid").val(),
          "config[container]": jQuery("#cdn_azuremi_container").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "mirror":
        jQuery.extend(params, {
          engine: "mirror",
        });

        if (cnames.length) {
          params["config[domain][]"] = cnames;
        }
        break;

      default:
        jQuery.extend(params, {
          engine: metadata.type,
        });
    }

    var status = jQuery("#cdn_test_status");
    status.removeClass("w3tc-error");
    status.removeClass("w3tc-success");
    status.addClass("w3tc-process");

    var status2 = jQuery("#cdn_create_container_status");
    status2.removeClass("w3tc-error");
    status2.removeClass("w3tc-success");
    status2.html("");

    status.html("Testing...");

    jQuery
      .post(
        "admin.php?page=w3tc_dashboard",
        params,
        function (data) {
          status.addClass(data.result ? "w3tc-success" : "w3tc-error");
          status.html(data.error);
        },
        "json",
      )
      .fail(function () {
        status.addClass("w3tc-error");
        status.html("Test failed");
      });
  });

  jQuery("#cdn_create_container").on("click", function () {
    var me = jQuery(this);
    var metadata = me.metadata();
    var cnames = w3tc_cdn_get_cnames();
    var container_id = null;
    var params = {
      w3tc_cdn_create_container: 1,
      _wpnonce: metadata.nonce,
    };

    switch (metadata.type) {
      case "s3":
        jQuery.extend(params, {
          engine: "s3",
          "config[key]": jQuery("#cdn_s3_key").val(),
          "config[secret]": jQuery("#cdn_s3_secret").val(),
          "config[bucket]": jQuery("#cdn_s3_bucket").val(),
          "config[bucket_location]": jQuery("#cdn_s3_bucket_location").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "cf":
        container_id = jQuery("#cdn_cf_id");

        jQuery.extend(params, {
          engine: "cf",
          "config[key]": jQuery("#cdn_cf_key").val(),
          "config[secret]": jQuery("#cdn_cf_secret").val(),
          "config[bucket]": jQuery("#cdn_cf_bucket").val(),
          "config[bucket_location]": jQuery("#cdn_cf_bucket_location").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "cf2":
        container_id = jQuery("#cdn_cf2_id");

        jQuery.extend(params, {
          engine: "cf2",
          "config[key]": jQuery("#cdn_cf2_key").val(),
          "config[secret]": jQuery("#cdn_cf2_secret").val(),
          "config[origin]": jQuery("#cdn_cf2_origin").val(),
          "config[bucket_location]": jQuery("#cdn_cf2_bucket_location").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "rscf":
        container_id = jQuery("#cdn_cnames input[type=text]:first");

        jQuery.extend(params, {
          engine: "rscf",
          "config[user]": jQuery("#cdn_rscf_user").val(),
          "config[key]": jQuery("#cdn_rscf_key").val(),
          "config[location]": jQuery("#cdn_rscf_location").val(),
          "config[container]": jQuery("#cdn_rscf_container").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "azure":
        jQuery.extend(params, {
          engine: "azure",
          "config[user]": jQuery("#cdn_azure_user").val(),
          "config[key]": jQuery("#cdn_azure_key").val(),
          "config[container]": jQuery("#cdn_azure_container").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;

      case "azuremi":
        jQuery.extend(params, {
          engine: "azuremi",
          "config[user]": jQuery("#cdn_azuremi_user").val(),
          "config[clientid]": jQuery("#cdn_azuremi_clientid").val(),
          "config[container]": jQuery("#cdn_azuremi_container").val(),
        });

        if (cnames.length) {
          params["config[cname][]"] = cnames;
        }
        break;
    }

    var status = jQuery("#cdn_create_container_status");
    status.removeClass("w3tc-error");
    status.removeClass("w3tc-success");
    status.addClass("w3tc-process");

    var status2 = jQuery("#cdn_test_status");
    status2.removeClass("w3tc-error");
    status2.removeClass("w3tc-success");
    status2.html("");

    status.html("Creating...");

    jQuery
      .post(
        "admin.php?page=w3tc_dashboard",
        params,
        function (data) {
          status.addClass(data.result ? "w3tc-success" : "w3tc-error");
          status.html(data.error);

          if (container_id && container_id.length && data.container_id) {
            container_id.val(data.container_id);
          }
        },
        "json",
      )
      .fail(function () {
        status.addClass("w3tc-error");
        status.html("failed");
      });
  });

  jQuery("#memcached_test").on("click", function () {
    var status = jQuery("#memcached_test_status");
    status.removeClass("w3tc-error");
    status.removeClass("w3tc-success");
    status.addClass("w3tc-process");
    status.html("Testing...");
    jQuery
      .post(
        "admin.php?page=w3tc_dashboard",
        {
          w3tc_test_memcached: 1,
          servers: jQuery("#memcached_servers")
            .val()
            .replace(/(\r\n|\r|\n)/g, ","),
          binary_protocol: jQuery("[id$=__memcached__binary_protocol]").is(
            ":checked",
          ),
          username: jQuery("#memcached_username").val(),
          password: jQuery("#memcached_password").val(),
          // Masked field submits empty once stored; send the owning module so the server can fall back to the saved value.
          module: (jQuery("#memcached_password").attr("name") || "").split(
            "__",
          )[0],
          _wpnonce: jQuery(this).metadata().nonce,
        },
        function (data) {
          status.addClass(data.result ? "w3tc-success" : "w3tc-error");
          status.html(data.error);
        },
        "json",
      )
      .fail(function () {
        status.addClass("w3tc-error");
        status.html("Request failed");
      });
  });

  jQuery(".w3tc_common_redis_test").on("click", function () {
    var status = jQuery(".w3tc_common_redis_test_result");
    status.removeClass("w3tc-error");
    status.removeClass("w3tc-success");
    status.addClass("w3tc-process");
    status.html("Testing...");
    jQuery
      .post(
        "admin.php?page=w3tc_dashboard",
        {
          w3tc_test_redis: 1,
          servers: jQuery("#redis_servers")
            .val()
            .replace(/(\r\n|\r|\n)/g, ","),
          verify_tls_certificates: jQuery(
            "[id$=__redis__verify_tls_certificates]",
          ).is(":checked"),
          dbid: jQuery("#redis_dbid").val(),
          password: jQuery("#redis_password").val(),
          // Masked field submits empty once stored; send the owning module so the server can fall back to the saved value.
          module: (jQuery("#redis_password").attr("name") || "").split("__")[0],
          _wpnonce: jQuery(this).metadata().nonce,
        },
        function (data) {
          status.addClass(data.result ? "w3tc-success" : "w3tc-error");
          status.html(data.error);
        },
        "json",
      )
      .fail(function () {
        status.addClass("w3tc-error");
        status.html("Request failed");
      });
  });

  jQuery(".minifier_test").on("click", function () {
    var me = jQuery(this);
    var metadata = me.metadata();
    var params = {
      w3tc_test_minifier: 1,
      _wpnonce: metadata.nonce,
    };

    switch (metadata.type) {
      case "yuijs":
        jQuery.extend(params, {
          engine: "yuijs",
          path_java: jQuery("#minify__yuijs__path__java").val(),
          path_jar: jQuery("#minify__yuijs__path__jar").val(),
        });
        break;

      case "yuicss":
        jQuery.extend(params, {
          engine: "yuicss",
          path_java: jQuery("#minify__yuicss__path__java").val(),
          path_jar: jQuery("#minify__yuicss__path__jar").val(),
        });
        break;

      case "ccjs":
        jQuery.extend(params, {
          engine: "ccjs",
          path_java: jQuery("#minify__ccjs__path__java").val(),
          path_jar: jQuery("#minify__ccjs__path__jar").val(),
        });
        break;
      case "googleccjs":
        jQuery.extend(params, {
          engine: "googleccjs",
        });
        break;
    }

    var status = me.next();
    status.removeClass("w3tc-error");
    status.removeClass("w3tc-success");
    status.addClass("w3tc-process");
    status.html("Testing...");

    jQuery.post(
      "admin.php?page=w3tc_dashboard",
      params,
      function (data) {
        status.addClass(data.result ? "w3tc-success" : "w3tc-error");
        status.html(data.error);
      },
      "json",
    );
  });

  // CDN cnames.
  jQuery("body").on("click", "#cdn_cname_add", function () {
    jQuery("#cdn_cnames").append(
      '<li><input type="text" name="cdn_cnames[]" value="" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>',
    );
    w3tc_cdn_cnames_assign();
    jQuery(this).trigger("size_change");
  });

  jQuery(".cdn_cname_delete").on("click", function () {
    var p = jQuery(this).parent();
    if (
      p.find("input[type=text]").val() == "" ||
      confirm("Are you sure you want to remove this CNAME?")
    ) {
      p.remove();
      w3tc_cdn_cnames_assign();
      w3tc_beforeupload_bind();
    }
  });

  jQuery("#cdn_form").on("submit", function () {
    var cnames = [],
      ret = true;

    jQuery("#cdn_cnames input[type=text]").each(function () {
      var cname = jQuery(this).val();

      if (cname) {
        if (jQuery.inArray(cname, cnames) != -1) {
          alert('CNAME "' + cname + '" already exists.');
          ret = false;

          return false;
        } else {
          cnames.push(cname);
        }
      }
    });

    return ret;
  });

  // Add sortable.
  if (jQuery.ui && jQuery.ui.sortable) {
    jQuery("#js_files,#css_files").sortable({
      axis: "y",
      stop: function () {
        jQuery(this)
          .find("li")
          .each(function (index) {
            jQuery(this)
              .find("td:eq(0)")
              .html(index + 1 + ".");
          });
      },
    });

    jQuery("#cdn_cnames").sortable({
      axis: "y",
      stop: w3tc_cdn_cnames_assign,
    });

    jQuery("#mobile_groups").sortable({
      axis: "y",
      stop: function () {
        jQuery("#mobile_groups")
          .find(".mobile_group_number")
          .each(function (index) {
            jQuery(this).html(index + 1 + ".");
          });
      },
    });

    jQuery("#referrer_groups").sortable({
      axis: "y",
      stop: function () {
        jQuery("#referrer_groups")
          .find(".referrer_group_number")
          .each(function (index) {
            jQuery(this).html(index + 1 + ".");
          });
      },
    });
  }

  // Show hide rules.
  jQuery(".w3tc-show-rules").on("click", function () {
    var btn = jQuery(this),
      rules = btn.parent().find(".w3tc-rules");

    if (rules.is(":visible")) {
      rules.css("display", "none");
      btn.val("view code");
    } else {
      rules.css("display", "block");
      btn.val("hide code");
    }
  });

  // Show hide missing files.
  jQuery(".w3tc-show-required-changes").on("click", function () {
    var btn = jQuery(this),
      rules = jQuery(".w3tc-required-changes");

    if (rules.is(":visible")) {
      rules.css("display", "none");
      btn.val("View required changes");
    } else {
      rules.css("display", "block");
      btn.val("Hide required changes");
    }
  });

  // Show hide missing files.
  jQuery(".w3tc-show-ftp-form").on("click", function () {
    var btn = jQuery(this),
      rules = jQuery(".w3tc-ftp-form");

    if (rules.is(":visible")) {
      rules.css("display", "none");
      btn.val("Update via FTP");
    } else {
      rules.css("display", "block");
      btn.val("Cancel FTP Update");
    }
  });

  // Show hide missing files.
  jQuery(".w3tc-show-technical-info").on("click", function () {
    var btn = jQuery(this),
      info = jQuery(".w3tc-technical-info");

    if (info.is(":visible")) {
      info.css("display", "none");
      btn.val("Technical Information");
    } else {
      info.css("display", "block");
      btn.val("Hide technical information");
    }
  });

  // Add ignore class to the ftp form elements.
  jQuery("#ftp_upload_form")
    .find("input")
    .each(function () {
      jQuery(this).addClass("w3tc-ignore-change");
    });

  // Toggle hidden content.
  jQuery(".w3tc_link_more").on("click", function () {
    var target_class = jQuery(this).metadata().for_class;
    jQuery("." + target_class).slideToggle();
  });

  // Test score block hover toggle.
  jQuery(".w3tc-test-container-intro").click(function () {
    var $testContainer = jQuery(this).next(".w3tc-test-container"),
      $score = jQuery(this).find(".w3tc-test-score");

    if ($score.css("visibility") === "hidden") {
      $score.css("visibility", "visible").fadeTo(300, 1); // Fade in score element
    } else {
      $score.fadeTo(300, 0, function () {
        // Fade out score element
        jQuery(this).css("visibility", "hidden");
      });
    }

    jQuery(this)
      .find(".dashicons")
      .toggleClass("dashicons-arrow-down-alt2 dashicons-arrow-up-alt2");

    if ($testContainer.is(":visible")) {
      $testContainer.stop(true, true).animate(
        {
          height: "toggle",
          opacity: "toggle",
          marginTop: "toggle",
          marginBottom: "toggle",
          paddingTop: "toggle",
          paddingBottom: "toggle",
        },
        300,
      );
    } else {
      $testContainer
        .stop(true, true)
        .css({
          display: "flex",
          opacity: 0,
          marginTop: 0,
          marginBottom: 0,
        })
        .animate(
          {
            opacity: 1,
            marginTop: "15px",
            marginBottom: "15px",
          },
          300,
        );
    }
  });

  // Check for unsaved changes.
  jQuery("#w3tc input,#w3tc select,#w3tc textarea").on("change", function () {
    var ignore = false;
    jQuery(this)
      .parents()
      .addBack()
      .each(function () {
        if (
          jQuery(this).hasClass("w3tc-ignore-change") ||
          jQuery(this).hasClass("lightbox")
        ) {
          ignore = true;
          return false;
        }
      });

    if (!ignore) {
      w3tc_beforeupload_bind();
    }
  });

  jQuery("body").on("click", ".w3tc-button-save", w3tc_beforeupload_unbind);

  jQuery(".contextual-help-tabs ul li a").on("click", function () {
    var id = jQuery(this).attr("aria-controls");
    var i = jQuery("#" + id + " .w3tchelp_content");
    w3tc_load_faq_section(i);
  });

  jQuery("#contextual-help-link").on("click", function () {
    var i = jQuery(".w3tchelp_content").first();
    w3tc_load_faq_section(i);
  });

  // wp cron settings.
  jQuery(document).on("change", "#allcache__wp_cron", function () {
    let $enabled = jQuery(this).prop("checked");

    jQuery("#allcache__wp_cron_time").prop("disabled", !$enabled);
    jQuery("#allcache__wp_cron_interval").prop("disabled", !$enabled);
  });

  jQuery(document).on("change", "#pgcache__wp_cron", function () {
    let $enabled = jQuery(this).prop("checked");

    jQuery("#pgcache__wp_cron_time").prop("disabled", !$enabled);
    jQuery("#pgcache__wp_cron_interval").prop("disabled", !$enabled);
  });

  jQuery(document).on("change", "#dbcache__wp_cron", function () {
    let $enabled = jQuery(this).prop("checked");

    jQuery("#dbcache__wp_cron_time").prop("disabled", !$enabled);
    jQuery("#dbcache__wp_cron_interval").prop("disabled", !$enabled);
  });

  jQuery(document).on("change", "#minify__wp_cron", function () {
    let $enabled = jQuery(this).prop("checked");

    jQuery("#minify__wp_cron_time").prop("disabled", !$enabled);
    jQuery("#minify__wp_cron_interval").prop("disabled", !$enabled);
  });

  jQuery(document).on("change", "#objectcache__wp_cron", function () {
    let $enabled = jQuery(this).prop("checked");

    jQuery("#objectcache__wp_cron_time").prop("disabled", !$enabled);
    jQuery("#objectcache__wp_cron_interval").prop("disabled", !$enabled);
  });

  var w3tchelp_loaded = {};

  function w3tc_load_faq_section(i) {
    var section = i.data("section");

    if (w3tchelp_loaded[section]) return;

    i.html(
      '<div class="w3tchelp_loading_outer">' +
        '<div class="w3tc-loading w3tchelp_loading_inner"></div></div>',
    );

    w3tchelp_loaded[section] = true;

    jQuery
      .getJSON(
        ajaxurl,
        {
          action: "w3tc_ajax",
          _wpnonce: w3tcGetAjaxNonce("faq"),
          w3tc_action: "faq",
          section: section,
        },
        function (data) {
          i.html(data.content);
        },
      )
      .fail(function () {
        i.html("Failed to obtain data");
      });
  }

  // Extensions page.
  jQuery(".w3tc_extensions_manage_input_checkall").on("click", function (v) {
    var c = jQuery(this).is(":checked");

    jQuery(".w3tc_extensions_manage_input_checkall").prop("checked", c);
    jQuery(".w3tc_extensions_input_active").each(function (index) {
      if (!jQuery(this).is(":disabled")) jQuery(this).prop("checked", c);
    });
  });

  // Go Pro block.
  jQuery(".w3tc-gopro-more").on("click", function (e) {
    e.preventDefault();
    if (!jQuery(this).data("expanded")) {
      jQuery(this).data("expanded", "1");
      jQuery(this).html(
        'Show Less <span class="dashicons dashicons-arrow-up-alt2"></span>',
      );
      jQuery(this)
        .parent()
        .find(".w3tc-gopro-description")
        .css("max-height", "300px");
    } else {
      jQuery(this).data("expanded", "");
      jQuery(this).html(
        'Show More <span class="dashicons dashicons-arrow-down-alt2"></span>',
      );
      jQuery(this)
        .parent()
        .find(".w3tc-gopro-description")
        .css("max-height", "");
    }

    if (window.w3tc_ga) {
      w3tc_ga("event", "anchor", {
        eventCategory: "click",
        eventLabel: jQuery(this).data("href"),
      });
    }
  });

  // Bootstrap dropdown toggle.
  jQuery(".dropdown-toggle").on("click", function () {
    jQuery(".dropdown-toggle").not(this).next().hide();
    jQuery(this).next().toggle();
  });

  // Footer subscribe hide response.
  jQuery("#mc-embedded-subscribe").on("click", function (e) {
    // Hide response after 20 seconds.
    setTimeout(function () {
      jQuery("#w3tc-footer .response").hide();
    }, 20000);
  });

  // Bootstrap dropdown hide on click away.
  jQuery(document).mouseup(function (e) {
    var dropdowns = jQuery(".dropdown-toggle");
    if (!dropdowns.is(e.target) && dropdowns.has(e.target).length === 0) {
      dropdowns.next().hide();
    }
  });

  // Options menu anchor links.
  jQuery("#w3tc-top-nav-bar a").on("click", function (e) {
    if (window.w3tc_ga) {
      w3tc_ga("event", "link", {
        eventCategory: "w3tc_topnav_bar",
        eventLabel: jQuery(this).text(),
      });
    }
  });

  // Options menu anchor links.
  jQuery("#w3tc-options-menu a").on("click", function (e) {
    if (window.w3tc_ga) {
      w3tc_ga("event", "anchor", {
        eventCategory: "w3tc_options_menu",
        eventLabel: jQuery(this).text(),
      });
    }
  });

  // Form control bar buttons.
  jQuery(".w3tc_form_bar input").on("click", function (e) {
    if (window.w3tc_ga) {
      w3tc_ga("event", "button", {
        eventCategory: "w3tc_form_bar",
        eventLabel: jQuery(this).text(),
      });
    }
  });

  // Footer links.
  jQuery("#w3tc-footer a").on("click", function (e) {
    if (window.w3tc_ga) {
      w3tc_ga("event", "link", {
        eventCategory: "w3tc_footer",
        eventLabel: jQuery(this).text(),
      });
    }
  });

  // General settings advanced options links.
  jQuery(".advanced-settings a").on("click", function (e) {
    if (window.w3tc_ga) {
      w3tc_ga("event", "link", {
        eventCategory: "w3tc_general_advanced_tab",
        eventLabel: jQuery(this).attr("gatitle"),
      });
    }
  });

  // Extra links.
  jQuery(".extra-link a").on("click", function (e) {
    if (window.w3tc_ga) {
      w3tc_ga("event", "link", {
        eventCategory: "w3tc_general_extra_link_tab",
        eventLabel: jQuery(this).attr("gatitle"),
      });
    }
  });

  // Analytics events.
  if (typeof w3tc_ga != "undefined") {
    jQuery(".w3tc_error").each(function () {
      var id = jQuery(this).attr("id");
      var text = jQuery(this).text();
      if (id && window.w3tc_ga) {
        w3tc_ga("event", "w3tc_error", {
          eventCategory: id,
          eventLabel: text,
        });
      }
    });
    jQuery(".w3tc_note").each(function () {
      var id = jQuery(this).attr("id");
      var text = jQuery(this).text();
      if (id && window.w3tc_ga) {
        w3tc_ga("event", "w3tc_note", {
          eventCategory: id,
          eventLabel: text,
        });
      }
    });

    jQuery("body").on("click", "a", function () {
      var url = jQuery(this).attr("href");
      if (url && window.w3tc_ga) {
        w3tc_ga("event", "anchor", {
          eventCategory: "click",
          eventLabel: url,
        });
      }
    });

    jQuery("body").on("click", 'input[type="button"]', function () {
      var name = jQuery(this).attr("name");
      if (name && window.w3tc_ga) {
        w3tc_ga("event", "button", {
          eventCategory: "click",
          eventLabel: name,
        });
      }
    });

    jQuery("body").on("click", 'input[type="submit"]', function () {
      var name = jQuery(this).attr("name");
      var id = jQuery(this).attr("id");
      if (!id) id = name;

      if (name && window.w3tc_ga) {
        w3tc_ga("event", "button", {
          eventCategory: id,
          eventLabel: name,
        });
      }
    });

    jQuery("body").on("click", 'input[type="checkbox"]', function () {
      var name = jQuery(this).attr("name");
      var action = jQuery(this).is(":checked") ? "check" : "uncheck";

      if (name && window.w3tc_ga) {
        w3tc_ga("event", "checkbox", {
          eventCategory: action,
          eventLabel: name,
        });
      }
    });

    jQuery("body").on("change", "select", function () {
      var name = jQuery(this).attr("name");
      var value = jQuery(this).val();

      if (name && value && window.w3tc_ga) {
        w3tc_ga("event", "select", {
          eventCategory: value,
          eventLabel: name,
        });
      }
    });

    // Log if the admin notice containing the renew license button is present.
    if (jQuery(".button-renew-plugin").length > 0) {
      if (window.w3tc_ga) {
        w3tc_ga("event", "w3tc_error", {
          eventCategory: "w3tc_renew_notice",
          eventLabel: "Renew Now",
        });
      }
    }
  }

  jQuery("a").on("click", function (event) {
    if (
      this.hash !== "" &&
      this.href.replace(this.hash, "") ===
        window.location.href.replace(window.location.hash, "")
    ) {
      event.preventDefault();
      var hash = this.hash,
        wpadminbar_height =
          jQuery(window).width() > 600 && jQuery("#wpadminbar").length
            ? jQuery("#wpadminbar").outerHeight()
            : 0,
        nav_bar_height = jQuery("#w3tc-top-nav-bar").length
          ? jQuery("#w3tc-top-nav-bar").outerHeight()
          : 0,
        options_menu_height = jQuery("#w3tc > #w3tc-options-menu").length
          ? jQuery("#w3tc > #w3tc-options-menu").outerHeight()
          : 0,
        form_bar_height = jQuery(".w3tc_form_bar").length
          ? jQuery(".w3tc_form_bar").outerHeight()
          : 0;
      var target_id = hash.substring(1);
      var target_el = document.getElementById(target_id);
      if (!target_el) {
        return;
      }
      jQuery("html, body").animate(
        {
          scrollTop:
            jQuery(target_el).offset().top -
            wpadminbar_height -
            nav_bar_height -
            options_menu_height -
            form_bar_height,
        },
        600,
      );
    }
  });

  var hash = window.location.hash;
  if (hash) {
    var target_el = document.getElementById(hash.substring(1));
    if (target_el) {
      // Start at top of page rather than instantly loading at the anchor point.
      window.scrollTo(0, 0);
      var wpadminbar_height =
          jQuery(window).width() > 600 && jQuery("#wpadminbar").length
            ? jQuery("#wpadminbar").outerHeight()
            : 0,
        nav_bar_height = jQuery("#w3tc-top-nav-bar").length
          ? jQuery("#w3tc-top-nav-bar").outerHeight()
          : 0,
        options_menu_height = jQuery("#w3tc > #w3tc-options-menu").length
          ? jQuery("#w3tc > #w3tc-options-menu").outerHeight()
          : 0,
        form_bar_height = jQuery(".w3tc_form_bar").length
          ? jQuery(".w3tc_form_bar").outerHeight()
          : 0;
      // Scroll to taget after .5 seconds.
      setTimeout(function () {
        jQuery("html, body").animate(
          {
            scrollTop:
              jQuery(target_el).offset().top -
              wpadminbar_height -
              nav_bar_height -
              options_menu_height -
              form_bar_height,
          },
          600,
        );
      }, 500);
    }
  }

  jQuery(window).resize(
    debounce(function () {
      set_sticky_bar_positions();
      set_footer_position();
    }),
  );

  // Target notices without the 'inline' class.
  jQuery(
    ".notice:not(.inline), .updated:not(.inline), .update-nag:not(.inline), .error:not(.inline), .info:not(.inline), .warning:not(.inline)",
  ).each(function () {
    // Prevent the notice from being moved.
    jQuery(this).addClass("inline");
  });

  // Update the CDN Cloudfront (push) S3 bucket location hostname.
  jQuery("body").on(
    "change",
    "#cdn_cf_bucket_location",
    cdn_cf_bucket_location,
  );
  jQuery("body").on("keyup", "#cdn_cf_bucket", cdn_cf_bucket_location);

  // Run functions after the page is loaded.
  cdn_cf_bucket_location();
  set_sticky_bar_positions();
  set_footer_position();
});
