使用jQuery在点击事件中交替更改类名

8

我在这里感到非常傻 - 我不能在jQuery中实现一个简单的类切换语句!过去45分钟,我一直在搜索Stack Overflow的问题和答案,但没有找到。

我的目标是:在单击具有colorClick id(已含有“white”默认类)的项目时,将该项在绿色、黄色、橙色、红色和白色之间旋转(无限循环)。

CSS很简单-每个类对应不同的背景颜色。

HTML也很简单-带有两个CSS类(一个静态,一个由jQuery更改)的div标签。

jQuery也很简单-读取所单击项目上的类并更改它。

现在,你明白了我所困扰的问题。这是我到目前为止的工作:

$("#colorClick").click(function () {
    if ($(this).hasClass('white')) {
        $(this).removeClass("white").addClass("green");
    } else if ($(this).hasClass('green')) {
        $(this).removeClass('green').addClass('yellow');
    } else if ($(this).hasClass('yellow')) {
        $(this).removeClass('yellow').addClass('orange');
    } else if ($(this).hasClass('orange')) {
        $(this).removeClass('orange').addClass('red');
    } else if ($(this).hasClass('red')) {
        $(this).removeClass('red').addClass('white');
});
.toDoItem {
    text-align: left;
    padding: 3px;
    margin-bottom: 5px;
    border: 1px solid;
    border-color: #e8e7e7;
}
.white {
    background-color: #ffffff;
}
.green {
    background-color: #b2d8b2;
}
.yellow {
    background-color: #ffffb2;
}
.orange {
    background-color: #ffe4b2;
}
.red {
    background-color: #ffb2b2;
}
<div class="toDoItem white" id="colorClick">To-do list item</div>
<div class="toDoItem white" id="colorClick">To-do list item</div>
<div class="toDoItem white" id="colorClick">To-do list item</div>

链接到示例代码: http://jsfiddle.net/andrewcbailey89/4Lbm99v0/2/


3
看到有人为一些只是介绍琐碎工作的个人具体教程而提供赏金有点令人不安。这样做有什么意义吗? - Denys Séguret
这里有一个非常相似的问题 jQuery switching between more than two classes,虽然答案不像这里那么出色,但是还是值得奖励吗? - halfzebra
@Jarrod 开始狂删吧!什么?! - A. Wolff
为了好玩,这里提供一个仅使用CSS的解决方案 - A. Wolff
3
我认为@TinyGiant是一个很棒的社区成员,是好回答的榜样。他非常努力地帮助维护网站的清洁度,一旦他达到10K声望值,就可以更多地为网站做贡献。花费声望来打分只是我的个人选择,与你无关。 - user177800
3个回答

30

首先,在制作列表时,您应该使用正确的列表元素。您的 "待办事项" 列表符合定义为描述列表 (<dl>),因此您应该使用它而不是 <div> 元素。

通过去掉类并创建颜色数组,您可以节省很多代码行。确保颜色以您想要显示的相同顺序排列。我们将使用此数组根据递增计数器设置背景颜色。

var colors = ['#b2d8b2', '#ffffb2', '#ffe4b2', '#ffb2b2', '#fff'];

你可以通过使用一个“工厂”函数来大大简化你的脚本,这个函数定义了一个作用域并构建了一个事件监听函数,并返回它。这样创建了一个安全的作用域,让每个监听函数都可以在其中驻留,并且我们可以定义变量,在事件之间存储信息。

在下面的代码片段中,我们定义了一个count变量,每次单击时都会将其增加。我们使用增加的变量余数,通过模运算符%除以颜色数组的长度。如果该数字小于数组长度,则返回该数字,否则将返回模除长度后的余数,使我们能够持续循环。

function todoItemListener() {
    var count = 0;
    return function () {
        $(this).css({ 'background-color': colors[count++ % colors.length] });
    }
}

那么,我们不再像平常一样分配函数声明(不使用括号),而是分配工厂函数的结果,只需添加括号,该函数将执行并返回生成的侦听器函数。这使我们能够添加任意数量的侦听器函数,因此如果您正在添加新的待办事项列表项,我们可以简单地构建另一个侦听器函数。

$('.todo-list dd').each(function () {
    $(this).on('click', todoItemListener());
});

$('.add-item').on('click', function () {
    var list = this.parentNode.parentNode;
    $('<dd>To-do list item</dd>').appendTo(list).on('click', todoItemListener());
});
这种方法还允许您随意更改颜色数组。所以,如果在页面上选择了某个选项,另一种颜色可能会变得可用或不可用。
此外,为了获得更好的用户体验,我添加了CSS代码,使其在单击时停止选择文本(这可能会很烦人),并将光标更改为指针以增强交互性。
以下是完整演示,包括多个待办事项列表以展示它可以实现的功能。

var colors = ['#b2d8b2', '#ffffb2', '#ffe4b2', '#ffb2b2', '#fff'];

function todoItemListener() {
    var count = 0;
    return function () {
        $(this).css({ 'background-color': colors[count++ % colors.length] });
    }
}

$('.todo-list dd').each(function () {
    $(this).on('click', todoItemListener());
});

$('.add-item').on('click', function () {
    var list = this.parentNode.parentNode;
    $('<dd>To-do list item</dd>').appendTo(list).on('click', todoItemListener());
});
.glyphicon-plus-sign {
    font-size: 15px;
}
.todo-list {
    background: #efefef;
    padding: 3px;
}
.todo-list dd {
    margin: 0;
    text-align: left;
    padding: 3px;
    margin-bottom: 7px;
    border: 1px solid;
    border-color: #e8e7e7;
    background-color: #fff;
}
.add-item, .todo-list dd {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
    cursor: pointer;
}
.add-item {
    float: right;
    margin: 4px;
}
.todo-list dh::after {
    content: "";
    display: block;
    clear: both;
}
.todo-list dh h3 {
    float: left;
    margin: 0px;
    max-width: 100%;
    overflow: hidden;
}

/* This rule is for the demo only */
.wrp {
    float: left;
    width: 33.33333333%;
    padding: 1px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

<div class="wrp">

    <dl class="todo-list" id="todo-list-1">
        <dh>
            <h3 class="center" contenteditable>To Do List 1</h3>
            <span class="add-item glyphicon glyphicon-plus-sign"></span>
        </dh>
        <dd>To-do list item</dd>
        <dd>To-do list item</dd>
        <dd>To-do list item</dd>
    </dl>
    
</div>
<div class="wrp">

    <dl class="todo-list" id="todo-list-2">
        <dh>
            <h3 class="center">To Do List 2</h3>
            <span class="add-item glyphicon glyphicon-plus-sign"></span>
        </dh>
        <dd>To-do list item</dd>
        <dd>To-do list item</dd>
        <dd>To-do list item</dd>
    </dl>
    
</div>
<div class="wrp">

    <dl class="todo-list" id="todo-list-3">
        <dh>
            <h3 class="center">To Do List 3</h3>
            <span class="add-item glyphicon glyphicon-plus-sign"></span>
        </dh>
        <dd>To-do list item</dd>
        <dd>To-do list item</dd>
        <dd>To-do list item</dd>
    </dl>
    
</div>


8
你在几个地方缺少引号,并且没有关闭最后一个if语句。
例如:$(this).hasClass(green) 应该是 $(this).hasClass('green') 此外,你应该将colorClick更改为类别,而不是ID,因为有多个这样的元素。
我还为了保持一致性,将所有引号更改为单引号。
以下是有效的代码片段:

$(".colorClick").click(function () {
    if ($(this).hasClass('white')) {
        $(this).removeClass('white').addClass('green');
    } else if ($(this).hasClass('green')) {
        $(this).removeClass('green').addClass('yellow');
    } else if ($(this).hasClass('yellow')) {
        $(this).removeClass('yellow').addClass('orange');
    } else if ($(this).hasClass('orange')) {
        $(this).removeClass('orange').addClass('red');
    } else if ($(this).hasClass('red')) {
        $(this).removeClass('red').addClass('white');    
    }
});
.toDoItem {
    text-align: left;
    padding: 3px;
    margin-bottom: 5px;
    border: 1px solid;
    border-color: #e8e7e7;
}
.white {
    background-color: #ffffff;
}
.green {
    background-color: #b2d8b2;
}
.yellow {
    background-color: #ffffb2;
}
.orange {
    background-color: #ffe4b2;
}
.red {
    background-color: #ffb2b2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="colorClick toDoItem white">To-do list item</div>
<div class="colorClick toDoItem white">To-do list item</div>
<div class="colorClick toDoItem white">To-do list item</div>


1
首先,您正在为多个元素使用相同的“id”。每个元素的“id”应该是唯一的。您可以使用“toDoItem”类来绑定单击事件,而不是使用“colorClick”“id”。为了摆脱复杂的“if else”语句,您可以按照所需的顺序将所有“class”放入数组中。然后,在单击“toDoItem”时,根据数组的顺序更改“class”。如果到达数组的最后一个项目,则返回到第一个。

var colors = ['white', 'green', 'yellow', 'orange', 'red'];
var total = colors.length-1;

$(".toDoItem").click(function() {
    var color = $(this).attr('class').split(' ')[1];
    var index = colors.indexOf(color);
    index = index==total? 0 : index+1;
    
    $(this).removeClass(color).addClass(colors[index]);
});
.toDoItem {
  text-align: left;
  padding: 3px;
  margin-bottom: 5px;
  border: 1px solid;
  border-color: #e8e7e7;
}

.white {
  background-color: #ffffff;
}

.green {
  background-color: #b2d8b2;
}

.yellow {
  background-color: #ffffb2;
}

.orange {
  background-color: #ffe4b2;
}

.red {
  background-color: #ffb2b2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="toDoItem white">To-do list item</div>
<div class="toDoItem white">To-do list item</div>
<div class="toDoItem white">To-do list item</div>

{{链接1:JS FIDDLE演示}}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接