如何使用jQuery将类应用于输入项

时间:2014-06-02 01:39:11

标签: jquery html css

我正在使用jQuery构建购物应用程序。在文本输入中输入文本并按下Enter键会添加一个新项目。将鼠标悬停在该项目上并单击“删除”将删除该项目。点击一个项目会将其交叉。

在文本输入中添加新列表项后,将应用正确的类,但jquery函数删除和交叉项不起作用。例如,“删除”范围应隐藏在页面加载上,并在将鼠标悬停在列表项上时显示,但对于新列表项,将始终显示删除范围。为什么我的函数不适用于我通过输入添加的新项目?

HTML:

<div class="wrapper">
    <form  onsubmit="return false"> <!--return false prevents enter from refreshing page -->
        <input type="text" placeholder="I need to buy..." name="shopping_item">
    </form>
    <ul class="instructions">
        <li>Click on tile to mark complete</li>
        <li class="divider">|</li>
        <li>Hover and click “Delete” to delete</li>
    </ul>  
    <section>
        <h1 class="outline">Shopping List Items</h1>
        <ul class="shopping_item_list">
            <li class="tile">Flowers<span class="delete">Delete</span></li>
            <li class="tile middle">A gift card for mom's birthday<span class="delete">Delete</span></li>
            <li class="tile">A birthday card<span class="delete">Delete</span></li>
            <!-- Do I need to have divs to clear? It looks like it works without them. -->
            <li class="tile">Yogurt<span class="delete">Delete</span></li>
            <li class="tile middle">Applesauce<span class="delete">Delete</span></li>
            <li class="tile">Iced tea<span class="delete">Delete</span></li>

            <li class="tile">Ice cream<span class="delete">Delete</span></li>
            <li class="tile middle">Laundry detergent<span class="delete">Delete</span></li>
            <li class="tile">Sandwich bags<span class="delete">Delete</span></li>

        </ul>
    </section>
</div><!--end wrapper-->

CSS:

.shopping_item_list .delete {
display: block;
position: absolute;
bottom: 0;
left: 0;
right:0;
background-color: #000;
padding-top:10px;
padding-bottom: 10px;
font-family: Verdana, sans-serif;
font-size:18px;
text-align: center;
    }

.deleteAction {
background-color:#b7b7b7 !important; 
text-decoration:line-through;
color:#e1e1e1;
    }

JQuery的:

$(document).ready(function() {

//add list item
$("input[name='shopping_item']").change(function() {
    var item = $(this).val();   
    $("<li class='tile'>" + item + "<span class='delete'>Delete</span>" + "</li>").prependTo(".shopping_item_list");
    $(".tile").removeClass("middle");   
    $(".shopping_item_list li:nth-child(3n+2)").addClass("middle");
}); 


// hide delete button
$(".delete").hide();


// delete square
$(".tile").hover(function() {
    $(this).find(".delete").toggle();
});

$(".tile").on("click", ".delete", function() {
    $(this).closest("li.tile").remove(); 
    $(".tile").removeClass("middle");   
    $(".shopping_item_list li:nth-child(3n+2)").addClass("middle");
});


// cross off list 
$(".tile").click(function() {
    $(this).toggleClass("deleteAction");
});


}); // end of ready function

3 个答案:

答案 0 :(得分:1)

当你运行这样的代码时:

$(".tile").hover(function() {
   $(this).find(".delete").toggle();
});

它会在页面上找到类tile的所有项目,并在其上安装悬停行为。

如果您随后将 new 元素添加到具有类tile的页面,则为时已晚。安装悬停行为的代码已经运行。

解决此问题的简单方法是使用此构造:

$(document).on("mouseenter mouseleave", ".tile", function() {
   $(this).find(".delete").toggle();
});

这通常表示通过类tile来监视文档中的项目。因此,它将适用于将来添加的现有项目项目。

请注意,您可以在层次结构的任何级别执行此操作,因此,如果所有tile元素始终位于.shopping_item_list内,则可以执行此操作:

$(".shopping_item_list").on("mouseenter mouseleave", ".tile", function() {
   ...
})

这样效率更高。

答案 1 :(得分:0)

因为,例如,当您运行附加事件的此函数时,您添加的相关.delete项的元素仍然不存在。因此,虽然$(".delete").hide();在页面加载(或$(document).ready(),实际上)中对DOM中的项目非常有用,但它无法告诉.delete尚不存在的项目去做。想象一下$(document).ready()和课堂上的初始说明一样。如果你上课迟到,你会错过说明。

你基本上有两种选择。

1)利用Event Bubbling。当事件发生在DOM中的某个项目时,它会将事件冒泡到DOM中的其他父项。因此,当您点击一个按钮时,点击&#39;事件在DOM中冒泡,包含<body>在内的所有包含元素都知道它发生了。事实证明这很方便,因为您稍后添加到DOM的项目仍会将其事件冒泡。这意味着您可以将侦听器附加到外部元素(如<body>),检查哪个元素是事件的来源,然后执行某些操作。 jQuery,它已成为一个深思熟虑的库,包括一个通过on method执行此操作的简单方法。您可以像这样重写\\cross off list;方法:

$('body').on('click', '.tile', function() {
    $(this).toggleClass("deleteAction");
});

2)$(document).ready()内的所有内容包裹在function cartInit()这样的单独命名函数中,并随时$("input[name='shopping_item']").change()调用该函数。只是,不要这样做。使用事件冒泡。 :)

答案 2 :(得分:0)

问题是您是直接将事件附加到每个单独的元素,并且只有在文档准备就绪时才会执行此操作。这意味着稍后添加的所有后续元素都不会附加任何处理程序。

要解决此问题,您应该使用事件委派,这基本上意味着您将处理程序附加到父节点而不是每个单独的元素。来自孩子的事件将冒泡到父节点,在那里你可以拦截它们。 jQuery让你指定一个委托选择器,以便你可以指定感兴趣的子节点。

例如,以下内容会捕获.tile容器中.shopping_item_list元素的每次点击。

$('.shopping_item_list').on('click', '.tile', function () {
    //do something
});

现在,关于在悬停时显示/隐藏元素,我不会使用JS。 CSS足以表达该行为。例如,如果您只想在.delete元素悬停时显示.tile元素,则可以执行此操作。

.tile .delete {
    display: none;
}

.tile:hover .delete {
    display: block;
}