【问题标题】:Javascript code not executing after loading div with AJAX使用 AJAX 加载 div 后未执行 Javascript 代码
【发布时间】:2017-11-29 02:38:44
【问题描述】:

我有一个名为landscape.php 的php 文件。在这里,我调用另一个名为 colorList.php 的 php 文件。在这个文件中,我有 3 个按钮来选择颜色的数量:4,5 和 6。当我单击任何按钮时,我会调用一个具有 ajax 功能的 js 文件,以在 div=container 中显示正确的选择集。

Landscape.php

<table width="980">
<tr>
<td width="1000" style="vertical-align: top">
    <?php include('colorList.php'); ?>
</td>
    <td width="700" style="vertical-align: top">
    <div id="contenido">
    </div>
    </td>
</tr>
</table>

code.js

function showData(dataType)
{

    var capa=document.getElementById("content");

    var ajax=newAjax();

    ajax.open("POST", "test.php", true);
    ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    ajax.send("d="+dataType);

    ajax.onreadystatechange=function()
    {
        if (ajax.readyState==4)
        {
            capa.innerHTML=ajax.responseText;
        }
    }
}

在 test.php 中,如果 dataType 为 1,则显示 4 个选择,如果为 2,则显示 5 个选择,如果为 3,则显示 6 个选择。它们都有使用 mysql 从数据库中检索到的颜色列表。我们的想法是不在任何选择器中重复任何颜色,为此,我禁用了我已经使用此脚本选择的任何颜色:

function loadColors() { 
                for (i = 0;i < document.test.elements.length;i++) {
                    for (j = 0;j < document.test.elements[i].options.length;j++) {
                        document.test.elements[i].options[j].disabled = false;
                        for (k = 0;k < document.test.elements.length;k++) {
                            if (i != k) {
                                if (document.test.elements[i].options[j].text == document.test.elements[k].options[document.test.elements[k].selectedIndex].text)
                                    document.test.elements[i].options[j].disabled = true;                               
                            }
                        }       
                    }
                }               
            }   

然后,选择器的定义如下:

<select name="color1" id="color1" onchange="loadColors()">

如果我不使用 ajax 调用,这段代码可以正常工作。也就是说,如果我在单个 php 页面中加载所有内容,例如,我将 test.php 中的内容复制并粘贴到 Landscape.php 中,一切正常。但是,一旦我使用 AJAX 加载该内容,它就不会。

我的问题不在于 javascript 也不在于 php,因为它工作正常。我的问题是,一旦我将 AJAX 添加到等式中,它就会停止工作。所以我想这是调用 loadColors() 函数的问题。我尝试将代码放在landscape.php 中,在test.php 中,调用code.js(ajax 和loadColors 函数所在的位置),将脚本加载到landscape.php 的主体中,但什么也没有……

有什么帮助吗?

【问题讨论】:

  • 我在你的另一篇文章中回答了这个问题——这与你的听众在哪里联系有关。如果您将它们附加到选择本身(似乎是这种情况),它们将不会继承侦听器。相反,您可能想要研究事件委托,因此您可以让主体侦听与您的选择器匹配的元素上的任何事件。应该解决问题。
  • 嗨@Snowmonkey,感谢您的宝贵时间,但您给我的解决方案不起作用。我将javascript代码添加到第一个landscape.php,然后添加到test.php,然后添加到code.js,然后添加到所有这些中,但它不起作用。我可以在每次选择中选择相同的颜色。我什至没有收到任何错误消息。请问有什么帮助吗?提前致谢。

标签: javascript php html ajax


【解决方案1】:

正如我在评论中所说,问题(我认为)在于您的选择本身。选择是由 AJAX 调用创建的,对吗?在那种情况下,永远不会真正处理 select 上的 onchange="..." 。像这样的 DOM 事件在页面加载时处理。页面加载后,DOM 可以被认为是静态的——您可以在 DOM 中添加或删除,但是如果您向页面添加元素并尝试通过 DOM 向该新元素添加事件处理程序,它将不会处理.

相反,您可能想看看您是如何附加该侦听器的。首先,我将完全删除 onchange。它没有帮助。这些是动态元素。为了让您的 DOM 监听动态元素的变化,请将事件本身附加到该元素的静态祖先。对于您的代码,如何将事件附加到侦听选择更改的容器?试试这样的:

// make these available to both functions.
var capa, selectedOptions;

function showData(dataType)
{
    capa=document.getElementById("content");
    var ajax=newAjax();

    ajax.open("POST", "test.php", true);
    ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    ajax.send("d="+dataType);

    ajax.onreadystatechange=function()
    {
        if (ajax.readyState==4)
        {
            capa.innerHTML=ajax.responseText;
            capa.addEventListener("change", filterSelects);
        }
    }
};

那么,filterSelects 可能有点像这样使用:

var myContainer = document.querySelector(".container");
 var selectOptions = [];
myContainer.addEventListener("change", filterSelects);

/***
 * The above code simply sets the stage,
 *  implementing the filterSelects function
 *  in much the same way you would for els
 *  added via AJAX. Note that, as the rest
 *  of your code seems to be going vanilla,
 *  I've rewritten this to be pure vanilla
 *  and not jQuery.
 ***/

function filterSelects(event) {
  if(!event.target.matches("select")) return;
  
  var workingEl = event.target;
  var allSelectEls = document.querySelectorAll(".colorSelector");
  
  // First, we'll iterate through the select els, and figure out the
  //  index of the currently active el. This will be the index of that
  //  select in the collection, and will also be used as the index in the
  //  selectOptions array.
  for (var i=0; i<allSelectEls.length; i++){
    // if we are currently looping over the active select...
    if (allSelectEls[i] == workingEl) {
      // ... and it has an actual working value
      if (workingEl[workingEl.selectedIndex].value != "...") {
        selectOptions[i] = workingEl[workingEl.selectedIndex].value;    
      } else {
        selectOptions[i] = null;
      }
    }
    
    // also, while we're here, we'll re-enable all options.
    for (var j=0; j<allSelectEls[i].options.length; j++){
      allSelectEls[i].options[j].removeAttribute("disabled");
    }
  }
  
  /*****
   * jQuery makes this so easy, but here it is as vanilla JS
   *  we will loop through every one of our selectOptions
   *  (remember, that's an array of the select values), and
   *  run an inner loop going through all select elements,
   *  and inside THAT loop through each option in the current select.
   *  loop 'i' = the selectOptions array
   *  loop 'j' = the select collection
   *  loop 'k' = the options in the current select
   *****/
  for (var i=0; i<selectOptions.length; i++){
    var currentOptionToDisable = selectOptions[i];
    for (var j = 0; j<allSelectEls.length; j++){
      var currentSelectEl = allSelectEls[j];
      // If the current selectOption is NOT from the current select
      if (i !== j) {
        for (var k = 0; k<currentSelectEl.options.length; k++) {
          currentSelectOption = currentSelectEl.options[k];
          
          // if the value in selectOption = the value of the current option
          if(currentSelectOption.value == currentOptionToDisable) {
            // we disable that option.
            currentSelectOption.disabled = true;
          }
        }
      }
    }
  }  
};
<div class="container">
<select name="color1" id="color1" class="colorSelector">
  <option>...</option>
  <option value="red">Red</option>
  <option value="orange">Orange</option>
  <option value="yellow">Yellow</option>
  <option value="green">Green</option>
  <option value="blue">Blue</option>
  <option value="indigo">Indigo</option>
  <option value="violet">Violet</option>
</select>
<select name="color2" id="color0" class="colorSelector">
  <option>...</option>
  <option value="red">Red</option>
  <option value="orange">Orange</option>
  <option value="yellow">Yellow</option>
  <option value="green">Green</option>
  <option value="blue">Blue</option>
  <option value="indigo">Indigo</option>
  <option value="violet">Violet</option>
</select>
<select name="color3" id="color3" class="colorSelector">
  <option>...</option>
  <option value="red">Red</option>
  <option value="orange">Orange</option>
  <option value="yellow">Yellow</option>
  <option value="green">Green</option>
  <option value="blue">Blue</option>
  <option value="indigo">Indigo</option>
  <option value="violet">Violet</option>
</select>

</div>

请注意,在我的工作示例中,我没有将事件附加到动态元素本身。你不能。如果你想让他们工作就不行。相反,我在这些动态元素的 STATIC 父级上创建了一个侦听器。然后,在处理函数中,我可以检查更改事件的目标是否是我想要的目标,无论是匹配('select')还是通过检查类或其他方式。但重要的是,如果我添加更多选择或删除它们,侦听器将附加到 DOM 的静态部分,并且不受此类恶作剧的影响。

另外请注意,由于这是一个小问题,我没有将我的听众附加到文档或正文上。找到最近的静态祖先,尝试将您的代码封装在尽可能小的部分中。那只是我的肥皂盒,也许有一天我会在上面咆哮。但请注意,我已连接到容器,并让该容器侦听,而不是文档或正文。只是说说而已。

【讨论】:

  • 嗨 Snowmonkey,感谢您为帮助我所付出的时间和精力,我真的很愿意,但是该代码无法正常工作,好吧,最好说...我不知道该怎么做让它起作用。很抱歉我对这方面的了解非常有限。我试图将您提供的代码包含在地雷中,但我无法使其运行。什么都没发生。我可以在每次选择中选择相同的颜色。我还使用您在此处指定的代码创建了一个新文档,但它也不起作用。 1/2
  • 一开始我得到:无法读取我通过 if(myContainer){ myContainer.addEventListener("change", filterSelects);} 解决的 null 属性 addeventlistener 错误消失但仍然无法正常工作. 2/2
  • 是的,不会工作,除非你已经定义了 myContainer。我假设你正在做的是没有分配 myContainer,然后因为 myContainer 没有定义,所以事件监听器根本就没有附加。在我的代码的第一行,我将 myContainer 分配给一个 DOM 元素引用。您当前的代码是什么样的?您是否在某个地方发布了一些内容,或者这一切都在本地主机上运行?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多