1

我正在尝试将 WordPress 短代码插入 JS,但到目前为止还没有成功。我找到了一些 jQuery 代码,我需要将其翻译成 vanilla JS,我很确定我没有做正确的事情,因为它不起作用。我不完全理解我遇到的代码,这意味着我需要一些帮助来了解我出错的地方以及为什么我的短代码没有显示在我的网站上。也许PHP代码没有正确链接到JS文件,我不太确定。

目标是让短代码(在这种情况下为 WP 表单)在单击时显示在模式中。任何帮助是极大的赞赏!

这是jQuery代码(AJAX 请求):

        $.ajax({
          url: `<?php echo admin_url('admin-ajax.php'); ?>`,
          type: "GET",
          data: {
            action: "runThisPhpFunction",
          },
          success: function (data) {
            $("#trigger_target").html(data);
          },
        });

这是我的模态JS代码,我试图将短代码放入其中:

function newsletterModal() {
  const ajaxurl = `<?php echo admin_url('admin-ajax.php'); ?>`;

  const btn = document.querySelector("#menu-item-2745");
  btn.setAttribute("id", "trigger_my_shortcode");
  const modal = document.createElement("div");
  modal.setAttribute("id", "trigger_target");
  modal.classList.add("modal");

  modal.innerHTML = `<div class="modal-content">
    <span class="close">&times;</span>
    <h2>Sign up to our newsletter</h2>
    <h5>And get hold of your 10% discount!</h5>
    <p>insert [wpforms id="1703"] here</p>
    </div>`;
    
    btn.onclick = function (e) {
    e.preventDefault();
    modal.style.display = "block";

    document
      .querySelector("#trigger_my_shortcode")
      .addEventListener("click", (e) => {
        e.preventDefault();

          fetch(ajaxurl, {
          type: "GET",
          data: {
            action: "runThisPhpFunction",
          },
          success: function (data) {
            document.querySelector("#trigger_target").html(data);
          },
        });
      });
  };

  modal.querySelector(".close").onclick = function () {
    modal.style.display = "none";
  };
  window.onclick = function (e) {
    if (e.target == modal) {
      modal.style.display = "none";
    }
    document.body.appendChild(modal);
  };
}

functions.php代码:

function runThisPhpFunction() {
    if ( isset($_REQUEST) ) {
    
      echo do_shortcode( '[wpforms id="1703"]' );
  
    }
    die();
  }
  add_action( 'wp_ajax_runThisPhpFunction', 'runThisPhpFunction' );
  add_action( 'wp_ajax_nopriv_runThisPhpFunction', 'runThisPhpFunction' );
4

1 回答 1

2

您的代码有很多事情要做,所以答案不会很短。将代码拆分为具有特定用途的较小函数通常是一种很好的做法。所以我冒昧地重写了一些函数,以便它们可以帮助你到达你需要去的地方。

下面的代码如下工作: 该buildModal函数为您的模态构建所有 HTML,并且可以将 aform作为参数。那form应该是文本,因为它需要与同一字符串中的其他元素进行插值(组合)。

buildModal函数将从getFormAndBuildModal函数中调用。该getFormAndBuildModal函数用于fetch向服务器发送请求并将响应解释为文本。此文本是您的表单,它将被传递buildModal给以构建包含表单的模式。

带有 的按钮#menu-item-2745将是发送请求和构建表单的触发器。

以这种方式工作意味着每次您单击按钮时,它都会调用服务器,构建一个新模式并将其显示在页面上。然后在关闭模式时,它会从页面中删除模式。

我试图尽可能多地解释代码中发生了什么以及每个步骤在做什么。如果有些事情仍然不清楚,请告诉我,我会尽力解决。

function buildModal(form) {
  const modal = document.createElement("div");
  modal.id = "trigger_target"
  modal.classList.add("modal");

  /**
   * Create close button here so we can attach the 
   * event listener without having to select it later.
   */
  const modalClose = document.createElement("span");
  modalClose.classList.add("close");
  modalClose.addEventListener("click", function() {

    /**
     * Remove the modal completely from the document.
     * This isn't mandatory and you can change it if you'd like.
     */
    modal.remove();
  });

  const modalContent = document.createElement("div");
  modalContent.classList.add("modal-content");

  /**
   * The form will be a string of HTML that gets injected
   * into another string of HTML here below. The innerHTML setter
   * will then parse the entire string, with form, to HTML.
   */
  modalContent.innerHTML = `
    <div class="modal-content">
      <h2>Sign up to our newsletter</h2>
      <h5>And get hold of your 10% discount!</h5>
      <p>${form}</p>
    </div>`;

  /**
   * First append the close button, then the content.
   */
  modal.append(modalClose, modalContent);

  /**
   * Return the HTML modal element.
   */
  return modal;
}

在这里,我添加了如何在 JavaScript 中使用 PHP 以及解决选择按钮问题的方法。这个问题有两种解决方案,一种在第二条评论中,另一种在此之后的 PHP 片段中。

/**
 * Check the PHP snippet at the bottom how this gets here.
 * This is the result of the array turned into JSON and then
 * placed into the document with wp_add_inline_script. 
 *
 * Sidenote: __wp__ looks ugly, but it will make sure that if 
 * a browser might get updated and a new property is added to the
 * window object, it will never overwrite or break anything because
 * the name is so unique.
 */
const ajaxurl = __wp__.ajax;

/**
 * Select the button and listen for the click event.
 * When clicked, fire the getFormAndBuildModal function.
 *
 * Update: with selecting elements it is paramount that the element is
 * above the <script> tag in the document. 
 * Otherwise the element would not yet exist and the result would come up empty.
 * Another way is to wait for the document to give a signal when every element has been rendered with the DOMContentLoaded event.
 */
// document.addEventListener('DOMContentLoaded', function(event) {
//  const button = document.querySelector("#menu-item-2745");
//  button.addEventListener("click", getFormAndBuildModal);
// });

const button = document.querySelector("#menu-item-2745");
button.addEventListener("click", function(event) {
  event.preventDefault();
  getFormAndBuildModal();
});

function getFormAndBuildModal() {
  /**
   * Fetch uses the GET method by default.
   * All you need to do is to add the action to the URL
   * so that WP knows what action to call on the server.
   */
  fetch(`${ajaxurl}?action=runThisPhpFunction`)

  /**
   * Fetch can take while to load, so it uses a promise.
   * With .then() we say what happens after fetch is finished.
   * Fetch gives us a response object as a result, which we need to inspect.
   */
  .then(response => {

    /**
     * If the response has gone wrong, show an error.
     */
    if (!response.ok) {
      throw new Error("runThisPhpFunction request has failed");
    }

    /**
     * Otherwise we use the content that the response has send us.
     * Currently the "body" (your form) of the response is just bits and bytes.
     * We can tell the response how we want to use the response.
     * With the .text() method we turn the raw data into a string.
     * That string can later be used as HTML. :)
     */
    return response.text();
  })

  /**
   * response.text() also returns a promise, just like fetch. So to go to the next step
   * we use another .then() function. In here we have our form in a string.
   * Now we can build the modal and pass the form as an argument. The modal 
   * will be build and the form turned into HTML and put in the correct position.
   * When the buildModal function is done it returns the result.
   * Now append it to the body and it's done.
   */ 
  .then(form => {
    const modal = buildModal(form);
    document.body.append(modal);
  });
}

在这里,我添加了一些附加内容来将脚本加入队列以及如何以正确的方式将 PHP 转换为 JavaScript。;)

function enqueue_my_custom_script() {
  /**
   * Instead of printing PHP variables directly inside JavaScript, 
   * you could use this method to let PHP do that for you. 
   * The array here below we be turned into a JSON string, 
   * which will later be turned into a JavaScript object that you
   * can use in your main script.
   */
  $wp_js_data = json_encode( 
    array(
      'ajax' => admin_url( 'admin-ajax.php' ),
    )
  );

  /**
   * The last parameter of wp_register_script (there are 5) will
   * determine if the script will be placed in the <head> tag when 
   * the value is false, or before the end of the </body> tag when
   * the value is true. The latter will make sure that your JS executes
   * AFTER all other HTML elements have been rendered. With this you don't
   * have to listen for the DOMContentLoaded event in JavaScript.
   *
   * Use get_stylesheet_directory_uri() to get the path to your child
   * theme directory instead of hard linking to your sheet. This will
   * output the URL to the directory of your style.css file of your theme.
   */
  wp_register_script( "scriptjs", get_stylesheet_directory_uri() . "/script.js", array(), null, true );

  /**
   * Here we create a global variable on the window object. This makes
   * the data is available in every JavaScript file. Here we insert the JSON string
   * that will be turned into a usable JS object.
   *
   * Be sure to output this script BEFORE the "scriptjs" file.
   */
  wp_add_inline_script( "scriptjs", "window.__wp__ = {$wp_js_data}", "before" );

  /**
   * This used to be the first line. wp_register_script only registers
   * the script but does not output it. This enables you to do something
   * like wp_add_inline_script before outputting the script.
   * wp_enqueue_script makes sure that the registered script will be 
   * placed in the document.
   */
  wp_enqueue_script( "scriptjs" );
} 
add_action( "wp_enqueue_scripts", "enqueue_my_custom_script" );
于 2020-10-06T15:08:53.147 回答