简体   繁体   English

用AJAX加载div后无法执行Javascript代码

[英]Javascript code not executing after loading div with AJAX

I have a php file called landscape.php. 我有一个名为landscape.php的php文件。 In here, I invoke another php file called colorList.php. 在这里,我调用了另一个名为colorList.php的php文件。 Inside this file I have 3 buttons to select the number of colors: 4,5 and 6. When I click in any button, I call a js file which has an ajax function to show in the div=container the proper set of selects. 在此文件中,我有3个按钮来选择颜色数量:4,5和6。单击任何按钮时,我都会调用一个js文件,该文件具有ajax函数,以在div = container中显示正确的选择集。

Landscape.php 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 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;
        }
    }
}

In test.php I have that If dataType is 1 then I show 4 selects, if 2 then 5 selects and if 3 then 6 selects. 在test.php中,如果dataType为1,则显示4个选择;如果2,则选择5;如果3,则选择6。 All of them have the list of colors retrieved from the db using mysql. 所有这些都具有使用mysql从数据库中检索到的颜色列表。 The idea is not to repeat any color in any selector, for that, I disable whatever color I already selected with this script: 想法是不要在任何选择器中重复任何颜色,为此,我禁用了已使用此脚本选择的任何颜色:

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;                               
                            }
                        }       
                    }
                }               
            }   

And then, the selectors are defined like this: 然后,选择器的定义如下:

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

This code works perfectly fine if I don't use the ajax call. 如果我不使用ajax调用,则此代码可以正常工作。 That is, if I load everything in a single php page, for example, I copy and paste what I have in test.php in landscape.php, everything is working. 也就是说,例如,如果我将所有内容加载到单个php页面中,则将我在test.php中拥有的内容复制并粘贴到landscape.php中,则一切正常。 But as soon as I load that content with AJAX, it doesn't. 但是,只要我使用AJAX加载该内容,就不会。

My problem is not with the javascript nor the php, cause that is working fine. 我的问题不是javascript或php,原因是工作正常。 My problem is that as soon as I add AJAX to the equation, it stops working. 我的问题是,只要将AJAX添加到方程式中,它就会停止工作。 So I guess it is a matter of invoking the loadColors() function. 因此,我想这是调用loadColors()函数的问题。 I tried having the code in landscape.php, in test.php, calling code.js (where the ajax and loadColors function is), load the script in the body of landscape.php but nothing... 我尝试将代码包含在landscape.php,test.php中,调用code.js(其中ajax和loadColors函数所在的位置),将该脚本加载到landscape.php主体中,但是什么也没有...

Any help, please? 有什么帮助吗?

As I said in my comment, the problem is (I think) in your selects themselves. 正如我在评论中所说,问题出在我自己的选择上。 The selects are being created by the AJAX call, right? 选择是通过AJAX调用创建的,对吗? In that event, having an onchange="..." on the select will never actually be handled. 在那种情况下,将永远不会真正处理选择上的onchange =“ ...”。 DOM events like that are handled on page load. 此类DOM事件在页面加载时处理。 After page load, the DOM can be considered static -- you can add to or remove from the DOM, but if you add an element to the page and try to add an event handler to that new element via the DOM, it will not process. 页面加载后,可以将DOM视为静态-您可以在DOM中添加或删除DOM,但是如果您向页面添加元素并尝试通过DOM向该新元素添加事件处理程序,则该DOM不会处理。

Instead, you might want to look at how you're attaching that listener. 取而代之的是,您可能想看看如何附加该侦听器。 First, I would remove the onchange entirely. 首先,我将完全删除onchange。 It doesn't help. 没有帮助 Those are dynamic elements. 这些是动态元素。 In order to have your DOM listening to changes on dynamic elements, attach the event itself to a static ancestor of that element. 为了让您的DOM侦听动态元素的更改,请将事件本身附加到该元素的静态祖先。 In the case of your code, how about attaching an event to the container that listens for changes to the selects? 就您的代码而言,如何将事件附加到侦听选择内容更改的容器? Try something like this: 尝试这样的事情:

// 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);
        }
    }
};

Then, filterSelects might be used somewhat like this: 然后,可以像下面这样使用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> 

Do note that, in my working example, I have not attached the events to the dynamic elements themselves. 请注意,在我的工作示例中,我没有将事件附加到动态元素本身。 You can't. 你不能 Not if you want them to work. 如果您希望他们工作,那就不是。 Instead, I've created a listener on a STATIC parent of those dynamic elements. 相反,我在这些动态元素的STATIC父级上创建了一个侦听器。 Then, in the handling function, I can check that the target of the change event is the target I want, whether matches('select') or by checking for class or whatever. 然后,在处理函数中,我可以检查change事件的目标是否是我想要的目标,无论是matchs('select')还是通过检查类或其他方法。 But the important bit is, if I add more selects or remove them, the listener is affixed to a static part of the DOM and remains unaffected by such shenanigans. 但是重要的一点是,如果我添加或删除更多选择,则侦听器将附加到DOM的静态部分,并且不会受到这种恶作剧的影响。

Note also, as this is a pet peeve, I haven't attached my listener to the document or to the body. 另请注意,由于这是一个小问题,因此我没有将听众附加到文档或正文上。 Find the nearest static ancestor, try to encapsulate your code in the smallest part possible. 找到最近的静态祖先,尝试将您的代码封装在尽可能小的部分。 That's just my soap box, and maybe one day I'll rant on it. 那只是我的肥皂盒,也许有一天我会抱怨。 But note that I'm attached to the container, and have that container listening, not the document or the body. 但是请注意,我已连接到容器,并且要监听该容器,而不是文档或正文。 Just saying. 只是说。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM