【问题标题】:Weird Javascript Bug (jQuery) in simple Testpage简单测试页中的奇怪 Javascript Bug (jQuery)
【发布时间】:2010-03-01 13:27:22
【问题描述】:

我正在编写一个 Mediawiki 扩展程序。我实际上处于非常早期的阶段;)。你可以在这里找到代码(好吧,我只能提交一个链接,所以想象一个 github url)/eugenkiss/discussion-extension

我遇到了一个奇怪的 jQuery 问题,即使使用 firebug 并尝试调试我的代码也无法解决。我在这里上传了当前代码和一个示例:http://jsfiddle.net/NMpU5/

尝试打开讨论并点击至少两个“回复”链接。然后单击出现的第一个表单的取消按钮。我不知道为什么,但是当您单击取消按钮时,另一个表单将关闭,而不是所需的表单。

你也可以改变这个。例如,打开两个窗体并关闭最后一个 openend 窗体。起初它似乎工作。但是当您尝试关闭另一个表单(通过单击取消)时,它不会消失。但是,该事件被触发,如 firebug 所示。有时,当我在那之后点击另一个回复锚点时,会打开与我点击另一个表单看似不起作用的取消按钮一样多的表单。

好吧,对于我想要的扩展,我当然可以将打开的表单的存在限制为一个 - 为什么您需要打开两个或更多?但我只想找到该死的错误,因为我已经投入了大量时间来寻找它!这对我来说是一个宝贵的错误,你知道的;)

顺便说一句,我使用的是 jQuery 1.4.2

javascript


$(document).ready(function() {
    // Hide the discussion bodys per default
    $(".discussion").addClass("closed")
        .children(".discussion-body").hide();

    // Register two custom events for the individual discussion divs      
    // "open" & "close" in order to make the discussion bodys
    // collapsable and be able to toggle the events by clicking
    // the "discussion-header-button" anchor
    $(".discussion")
    .bind("open", function(e) {
       if(!$(this).hasClass("opened")) {
           $(this).children(".discussion-body").slideDown();
           $(this).find(".discussion-header-button").html("[-]");
           $(this).addClass("opened");
           $(this).removeClass("closed");
       }
    })
    .bind("close", function(e) {
       if(!$(this).hasClass("closed")) {
           $(this).children(".discussion-body").slideUp();
           $(this).find(".discussion-header-button").html("[+]");
           $(this).addClass("closed");
           $(this).removeClass("opened");
       }
    })
    .find(".discussion-header-button").click(function(){
        relatedDiscussion = $(this).parents(".discussion");
        if(relatedDiscussion.hasClass("closed")) {
            relatedDiscussion.trigger("open");
        }
        else if(relatedDiscussion.hasClass("opened")) {
            relatedDiscussion.trigger("close");
        }
    });

    // Register custom "showForm" & "destroyForm" events on posts       
    // in order to make the "Reply" button work
    // TODO: Maybe add "preview" & "submit"
    $(".discussion-body .post")
    .bind({
        showForm: function(){
            post = $(this);
            postBody = post.find(".post-body").first();
            postHeader = post.find(".post-header").first();

            postBody.append(postCommentFormHtml);
            replyLink = postHeader.find(".reply");
            replyLink.unbind();

            form = postBody.find(".post-comment-form");
            form.slideDown();

            // create actions for the form buttons
            form.find(".cancel").click(function(){
                post.triggerHandler("destroyForm");
            });
            form.find(".preview").click(function(){
                // Hier muss mit Ajax und der Datenbank gespielt
                // werden um ein preview erstellen zu können
            });
            form.find(".submit").click(function(){
                // Hier muss mit Ajax und der Datenbank gespielt
                // werden um den Post abschicken zu können
            });
        },
        destroyForm: function(){
            post = $(this);
            postBody = post.find(".post-body").first();
            postHeader = post.find(".post-header").first();

            replyLink = postHeader.find(".reply");
            replyLink.click(replyAction);

            form = postBody.find(".post-comment-form");
            form.slideUp(function(){
                    $(this).remove();
            });
        }
    });
    //$(".discussion-post-comment").click(createPostCommentForm);
    $(".discussion .reply").click(replyAction);

    function replyAction(event){
        // Note: It is important to use triggerHandler instead of trigger
        // otherwise the "showForm" event of all parents is triggered
        // recursively (bubbling) and this is not desired
        event.preventDefault();
        relatedPost = $(this).parents(".post").first();
        relatedPost.triggerHandler("showForm");
    }
});
postCommentFormHtml = "\
    <div class='post-comment-form' style='display:none;'><br>\
    <form action='textarea.htm'>\
        <textarea name='post' cols='50' rows='8'></textarea>\
        <br>\
        <input class='submit' type='submit' value=' Post '>\
        <input class='preview' type='submit' value=' Preview '>\
        <input class='cancel'type='reset' value=' Cancel '>\
    </form>\
    </div>";​

HTML


<div class="discussion">
<div class="discussion-header">
    <a class="discussion-header-button">[+]</a>
    Diskussion: 3 Kommentar(e)
    <a class="discussion-post-comment">Post Comment</a>
</div>
<div class="discussion-body">
<div class="post">
    <div class="post-header">
        <span class="post-header-name">Eugen</span>
        <span class="post-header-date">2010-02-25 12:32:30</span>
        <a class="reply" href="#">Reply</a>
        <a class="edit" href="#">Edit</a>
        <a class="delete" href="#">Delete</a>
    </div>
    <div class="post-body">
        Ich denke das sollte anders sein!
    </div>
    <div class="post">
        <div class="post-header">
            <span class="post-header-name">Markus</span>
            <span class="post-header-date">2010-02-25 12:32:31</span>
            <a class="reply" href="#">Reply</a>
         <a class="edit" href="#">Edit</a>
         <a class="delete" href="#">Delete</a>
        </div>
        <div class="post-body">
            Ich denke nicht
        </div>
    </div>
</div>
<div class="post"> 
    <div class="post-header">
        <span class="post-header-name">Jan</span> 
        <span class="post-header-date">2010-03-25 12:32:30</span>
        <a class="reply" href="#">Reply</a>
        <a class="edit" href="#">Edit</a>
        <a class="delete" href="#">Delete</a>
    </div>
    <div class="post-body">
        Mal was ganz anderes: Denkt ihr das selbe was ich denke?
    </div>
</div>
</div>
</div>

编辑: 我想补充一点,将 id 更改为 classes 并没有帮助。另外,如果这对您有帮助:我发现(使用 Firebug)“post”(以及“postbody”)变量(在“destroyForm”事件中)实际上指向错误的帖子,因此错误的表单被删除。但我无法理解为什么 post 变量首先指向错误的帖子

编辑2: 将所有 ID 更改为类 http://jsfiddle.net/NMpU5/1/

【问题讨论】:

  • 您必须更改“id”值,以便它们无论如何都是唯一的,所以这样做,然后也许人们可以提供帮助。事实上,它是错误的,不值得调试。
  • 您是使用 ide 进行调试还是仅使用 firebug?
  • 我这样做了jsfiddle.net/NMpU5/1,但错误仍然存​​在。我应该用带有类而不是 id 的新版本更新 stackoverflow 中的代码吗?
  • @drorhan 我只使用萤火虫
  • 我正在使用 aptana for jquery 非常有用。

标签: javascript jquery html


【解决方案1】:

在我看来,事件处理函数中的许多变量(特别是“post”和“relatedDiscussion”)似乎没有在每个函数中用“var”声明。我试图弄清楚这可能会做什么,但我很困惑。然而,当您不声明局部变量时,它们就是全局变量。这意味着将“post”设置为某个新值的每个函数都在更改“post”在所有其他可能处于活动状态的函数中使用的值。

改成

 var post = $(this);

等等

【讨论】:

  • 哦,谢谢,这是错误!这就是我不记得 javascript 基础知识的结果!我实际上想知道萤火虫向我展示了(不是这样的)局部变量在分配 s.th 之前已经有一个值。给他们。但我认为这只是萤火虫的不一致。你可以在这里看到更新的版本jsfiddle.net/NMpU5/4 再次感谢 ;)
【解决方案2】:

让我印象深刻的第一件事是:ID 应该是唯一的。将 A 标签的 ID 更改为类,看看是否可以清除它。

【讨论】:

  • 是的,我尝试过(在 git 分支中)但它没有解决我的问题,所以我恢复了
  • 再试一次 - 你不能在多个元素之间共享“id”值。每个“id”在任何页面上都必须是完全唯一的。
【解决方案3】:

您应该使用 jQuery 的 live 事件来绑定到表单,而不是在创建后将点击绑定到每个按钮。

我在您的脚本中发布了update

我基本上是把表单点击函数都抽出来了,转成live函数

$(".cancel").live("click", function(){
    $(this).closest(".post-comment-form").slideUp('',function(){ $(this).remove(); });
});
$(".preview").live("click", function(){
    // Hier muss mit Ajax und der Datenbank gespielt
    // werden um ein preview erstellen zu können
});
$(".submit").live("click", function(){
    // Hier muss mit Ajax und der Datenbank gespielt
    // werden um den Post abschicken zu können
});

我没有使用您的 post.triggerHandler("destroyForm"); 函数,因为坦率地说,我以前从未使用过它,而且我无法让它工作 LOL。

【讨论】:

  • 您可能还想考虑将.parents() 更改为.closest()。当我试图弄清楚帖子的位置以及您的回复有多远时,代码变得非常混乱。我想说完全删除您的 .bind() 函数并用 .live() 替换它们
  • 感谢您的评论,但问题已经解决。 destroyForm 是我使用 bind() 创建的自定义事件。我会调查closest()
【解决方案4】:

当您使用像“#something”这样的 jQuery 选择器时,库使用“document.getElementById()”来查找元素。如果您对多个元素使用相同的“id”值,您不能期望事情会起作用;事实上,您会得到完全如您所描述的结果。您使用“find()”通过共享“id”查找元素这一事实并不重要。

撇开这个问题不谈,无论如何,您都需要为表单输入字段使用“名称”属性。

【讨论】:

  • 好的,我把所有的 id 都改成了类,但是 bug 仍然存在 jsfiddle.net/NMpU5/1 感谢关于表单字段的评论
【解决方案5】:

您不必将 de ID 更改为类。您只需要每个元素的唯一 ID,这样您就可以获得正确的 ID。

【讨论】:

  • 嗯,好吧,我认为这会起作用。但无论如何,jQuery 选择器应该找到正确的形式,因为我是这样嵌套的,find() 应该找到正确的形式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多