【问题标题】:Call function inside document.ready wont workdocument.ready 中的调用函数不起作用
【发布时间】:2012-01-10 18:03:43
【问题描述】:

我希望能够从链接调用一个函数(这个函数将删除相应的行)。如果我将函数放入准备好的文档中,它将不会在调用时加载。但它在外面工作。该函数是位于末尾的 delRow(id)。

我尝试制作“$("#participants").click(function() {" 的“副本”并像“Lägg until deltagare”链接一样调用它(添加用户链接)。

如何以最好的方式解决这个问题?为什么你不能在 document.ready 中调用函数,为什么我的参与者 click.function 副本不能工作? (我在代码示例中没有它,我将其命名为 "$("#deleterow").click(function() 并将按钮的 id 设置为 deleterow)

网址:http://min.xn--spyp-toa.se/addrows.php(部分 DNS 服务器有此问题,请运行 googles DNS!8.8.8.8)

<?php 
//Inkluderar fil för inläsning av databasinfo.
require("core.inc");       
?>

    <script type="text/javascript" src="js/jquery-1.7.1.min.js"></script>

    <script type="text/javascript">

        $(document).ready(function () {

         //Denna kod ska hämta users i databasen till js-arrayen users
           var users = new Array();

            $.ajax({
                url: 'getuser.php',
                dataType: 'json',
                error: function(){alert("Kunde inte hämta data från databas");},
                success: function(data){
                    users = data;
                }
            });

        //Denna kod lägger till en ny rad
            var rowCount = 1; // Räknare som räknar hur många rader man lagt till
            var selectedUsers = new Array(); //Denna array innehåller användare man lagt till

            $("#participants").click(function() {

                var participantSelect = document.getElementById('participantSelect'); //Denna variabel håller värdet från selecten

                //En funktion som loopar fram användarna i databasen till <option> taggar
                function addOption(){

                    var option; //Denna variabel lagrar alla options som genereras i loopen

                    for (var i=0; i < users.length-1; i++)  {

                        var user = users[i].id;

                        if(jQuery.inArray(user, selectedUsers) > -1) {

                        }
                        else{
                           option += ('<option value="'+users[i].id+'">'+users[i].name+'</option>'); 
                        }
                    }
                    return option; //Skickar alla genererade <option>-taggar till append-scriptet
                }

                //Funktionen som uppdaterar <select>-satsen
                function updateSelect(){
                    $('#participantSelect').replaceWith('<select name="participantSelect" id="participantSelect">'+addOption()+'</select>');
                }

                //Function som matas in i apenden, den plockar ut namnet som hör till ID som kommer från selecten
                function name(){

                    //kör igenom arraeyn men avslutar när den hittar en träff
                    for(var i=0; users.length; i++){

                        if(users[i].id == participantSelect.value){ //Om användar ID är samma som ID från select

                            selectedUsers.push(users[i].id); //Denna lägger till valda användare i en array för filtrering av redan använda användare

                            //Denna funktion anropar koden som genererar om <select> och utelämnar redan valda användare
                            updateSelect();

                            return users[i].name; //Return i if-satsen för att avbryta vid träff.
                        } 
                    }
                }

                //Skriver in en input som är read-only med den valda användaren
                $('#container').append('<input type="text" name="participant_'+rowCount+'" id="'+participantSelect.value+'" value="'+name()+'" class="participant_1" readonly="readonly" /> <a href="#" name="participant_'+rowCount+'" id="'+rowCount+'" class="participant_1" onclick="bajs(this.name)">Ta bort deltagare</a><br>');

               rowCount++;                   
            });

            //Denna kod tar bort redan inmatad användare och lägger tillbaka denne i <select>
                function delRow(id){
                    alert(id);
                    alert("test");
                }
        });

    </script>

    <!-- Här väljer man vilka användare som deltagit, sedan trycker man på lägg till-knappen -->
    <select name="participantSelect" id="participantSelect">
                <?php

                $result = mysql_query("SELECT id, name FROM user");

                while ($db_field = mysql_fetch_assoc($result)) {
                    echo '<option value="'.$db_field['id'].'">'.$db_field['name'].'</option>';
                }

                mysql_free_result($result);

              ?>
    </select>

    <!-- Knapp för att lägga till ny rad inom container-diven -->
    <a href="#" id="participants" class="myButton">L&auml;gg till deltagare</a>

    <!-- Container diven hit vad alla användare kommer läggas till-->
    <h2>Deltagare:</h2>
    <div id="container" class="container">
   <!-- Här kommer allt läggas in -->
    </div>  

    <button name="participant_1" id="delete_participants" onclick="delRow()">Ta bort deltagare</button><br>

【问题讨论】:

    标签: javascript jquery function document-ready


    【解决方案1】:

    当您使用旧式 DOM0 处理程序连接 (onclick="...") 时,您在该字符串中引用的任何函数都必须是全局函数。您的 delRow 函数不是全局函数,它包含在您传递给 ready 的函数中——这是一件好事,全局命名空间已经太满了。

    处理此问题的两种选择:

    1。用 jQuery 连接起来

    (在我看来)处理它的最佳方法是在您的 ready 函数中使用 jQuery 连接您的 button。例如:

    $("#delete_participants").click(delRow);
    

    2。仅导出该函数

    或者,您可以通过在ready 函数中执行此操作来创建一个指向delRow 的全局:

    window.delRow = delRow;
    

    之所以有效,是因为所有全局变量都是浏览器中 window 对象的属性,因此通过将 delRow 的引用分配给 window 上的 delRow 属性,您可以明确地使其在全局中可用命名空间(不会将全局命名空间与任何其他函数混淆)。然后onclick="..." 处理程序将能够看到它。但是如果可以避免的话,我不会提倡使用全局变量。不过,当您从旧样式过渡到新样式时,这是一种有用的桥接技术。


    旁注:你没有使用ready函数,你可以把你的脚本放在页面底部(就在结束&lt;/body&gt;标签之前或之后)并这样做:

    (function() {
        // Your code here
    })();
    

    它将稍微更快地运行,并且仍然可以访问页面上的所有 DOM 元素 (ref | ref)。但是ready 也基本没问题。


    在下方回复您的评论:

    我为动态按钮指定了 ID“delete_participants”并创建了$("#delete_participants").click(delRow);,但它没有被调用。它适用于静态按钮。

    这是因为您不能在一个页面上拥有多个具有相同id 的元素。 id必须是唯一的。

    如果您要添加和删除行,并且如果您使用 jQuery 来连接,您有两个额外的选择:

    A.单独连接它们

    这只是在创建新按钮后在新按钮上调用click(function() { ... }) 的问题,例如:

    var tr = '<tr><td><input type="button" name="delete"></td></tr>';
    tr.find('input').click(delRow);
    tr.appendTo(/* ...presumably a table body or something...*/);
    

    例如,这里有一个完整的例子:

    HTML:

    <table id="participants">
      <tfoot>
        <tr>
          <td colspan='2'>
            <input type="button" name="add" value="Add Participant">
          </td>
        </tr>
      </tfoot>
      <tbody>
        <tr>
          <td>
            Joe Bloggs
          </td>
          <td>
            <input type="button" name="delete" value="Delete">
          </td>
        </tr>
      </tbody>
    </table>
    

    JavaScript:

    jQuery(function($) {
    
      $("#participants")
        .delegate('input[name="add"]', "click", addParticipant)
        .delegate('input[name="delete"]', "click", delParticipant);
    
      function addParticipant() {
        var td, tr, name;
    
        // Obviously you'd use something more modern than `prompt`
        name = prompt("Name for new participant: ", "");
        if (name) {
          // And this code is no thing of beauty, either, but you get the idea
          td = $('<td>').text(name);
          tr = $('<tr>');
          tr.append(td);
          tr.append('<td><input type="button" name="delete" value="Delete"></td>');
          tr.hide();
          $("#participants tbody").append(tr);
          tr.fadeIn();
          // Note we don't have to do anything to hook the new button;
          // delegation handles that
        }
      }
    
      function delParticipant() {
        var tr = $(this).closest('tr');
        tr.fadeOut(function() {
          tr.remove();
        });
      }
    
    });
    

    Live copy

    B.使用事件委托

    但在这种情况下,另一种技术通常更好:事件委托。在事件委托中,您将事件(“点击”)挂接到所有可能接收该点击的容器上,然后当点击发生时,检查事件是否已通过任何相关元素的数量(因为大多数事件,包括从实际发生点击的元素到其父级、祖父级和其他祖先的“点击”、“冒泡”)。 jQuery 使用 delegate:

    让委托变得非常简单
    $("selector_for_container").delegate("selector_for_element", "click", function() {
        // This will get called if the click matches the element selector
    });
    

    或者,从 1.7 或更高版本开始,使用 on 的几个变体之一:

    $("selector_for_container").on("click", "selector_for_element", function() {
        // This will get called if the click matches the element selector
    });
    

    (请注意,参数的顺序略有不同。)

    完整示例(使用delegate,因为很多人还没有使用 1.7):

    HTML:

    (同上)

    JavaScript:

    jQuery(function($) {
    
      $("#participants")
        .delegate('input[name="add"]', "click", addParticipant)
        .delegate('input[name="delete"]', "click", delParticipant);
    
      function addParticipant() {
        var td, tr, name;
    
        // Obviously you'd use something more modern than `prompt`
        name = prompt("Name for new participant: ", "");
        if (name) {
          // And this code is no thing of beauty, either, but you get the idea
          td = $('<td>').text(name);
          tr = $('<tr>');
          tr.append(td);
          tr.append('<td><input type="button" name="delete" value="Delete"></td>');
          tr.hide();
          $("#participants tbody").append(tr);
          tr.fadeIn();
          // Note we don't have to do anything to hook the new button;
          // delegation handles that
        }
      }
    
      function delParticipant() {
        var tr = $(this).closest('tr');
        tr.fadeOut(function() {
          tr.remove();
        });
      }
    
    });
    

    Live copy

    【讨论】:

    • 感谢您的信息!我在 [link]min.spypå.se/addrows.php[/link] 更新了代码,现在我可以从底部的“ta bort deltagare”按钮调用该函数(现在名称为“ta bort deltagare,test”)。但我不能从我动态添加的按钮中调用它。
    • @DannyThunder:添加它们后只需将它们连接起来,再次使用相关的 jQuery 函数(clickbindon)在包含刚刚的 jQuery 对象上 -添加按钮。
    • @T-j-crowder : 我给动态按钮 ID "delete_participants" 并创建了 $("#delete_participants").click(delRow);但它不会被调用。它适用于静态按钮。 min.xn--spyp-toa.se/addrows.php
    • @DannyThunder:id 值在页面上必须是唯一的:w3.org/TR/html5/elements.html#the-id-attribute 另请注意,当您使用click 连接按钮时,该按钮必须已经存在。
    • @T-j-crowder :好的,谢谢你的信息!猜猜我必须为动态删除按钮找到另一种解决方案。那是另一个问题,所以我可以将其标记为已解决!谢谢!
    【解决方案2】:

    “您已经在闭包中定义了函数,因此在该准备好的函数之外无法访问它”

    http://forum.jquery.com/topic/call-functions-outside-document-ready

    您应该始终将您的函数放在文档就绪闭包之外,以便在全局范围内可以访问它们。

    【讨论】:

    • 或者更好的是,避免使用全局函数句号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    相关资源
    最近更新 更多