[英]JavaScript - Revert element to original style after clicking another element
So I'm building a calendar program, and I want the user to be able to select a day. 所以我正在构建一个日历程序,我希望用户能够选择一天。 Using a
<table>
, the <td>
highlights when clicked by applying className="NewStyle"
to the box. 使用
<table>
,通过将className="NewStyle"
到框中, <td>
突出显示。 I want that cell to go back to normal after clicking on another cell, but it just remains in its new style. 我希望在单击另一个单元格后该单元格恢复正常,但它仍然保持其新样式。
How do I make JS revert any non-clicked cell to normal when another cell is clicked? 当单击另一个单元格时,如何使JS将任何未单击的单元格还原为正常?
Here's a JSFiddle . 这是一个JSFiddle 。 Thanks for any help!
谢谢你的帮助!
HTML HTML
The cells look like this: 细胞看起来像这样:
<td id="td_4" onclick="change(4)">4</td>
<td id="td_5" onclick="change(5)">5</td>
<td id="td_6" onclick="change(6)">6</td>
Clicking td_4
will successfully change the style. 单击
td_4
将成功更改样式。 But clicking td_6
will also successfully change styles, but leave td_4
in its new style instead of reverting it. 但是单击
td_6
也会成功更改样式,但是将td_4
保留为新样式而不是还原它。
JavaScript JavaScript的
function change(x) {
document.getElementById("td_" + x).className = "selected";
}
Just keep track of the element you clicked and unclass it. 只需跟踪您单击的元素并将其取消分类即可。 fiddle
小提琴
var previousEl
function change(x) {
if (previousEl) previousEl.className = ""
previousEl = document.getElementById("td_" + x)
previousEl.className = "selected"
}
UPDATE: Another thing worth mentioning is that you can take advantage of event bubbling so that your parent container can listen to events, getting the id of the clicked element from the event object. 更新:值得一提的另一件事是你可以利用事件冒泡,这样你的父容器就可以监听事件,从事件对象中获取被点击元素的id。 updated fiddle
更新小提琴
var previousEl
function change(event) {
if (previousEl) previousEl.className = "";
previousEl = document.getElementById(event.target.id)
previousEl.className = "selected";
}
and in your html get rid of all your <td onclick="change()">
and put it on parent, passing event: 并在您的HTML中删除所有
<td onclick="change()">
并将其放在父级,传递事件:
<table onclick="change(event)">
This is how I would achieve the effect you're looking for, but first a couple notes: 这就是我将如何实现您正在寻找的效果,但首先是几个注释:
We are only going to use two event listeners in this script. 我们只在这个脚本中使用两个事件监听器。
The first event listener will use delegation to assign the selected class to the clicked element. 第一个事件侦听器将使用委托将所选类分配给单击的元素。 When you click on an element, the event will "bubble" up past the clicked element, all the way up through the DOM.
当您单击某个元素时,该事件将“冒泡”通过所单击的元素,一直向上通过DOM。 So we can listen to a common parent element, then check to see where the event originated.
所以我们可以听一个共同的父元素,然后检查事件的起源。
Here we want to check if the element is a <td>
element, and if it does not have the class no_border
. 这里我们要检查元素是否是
<td>
元素,以及它是否没有类no_border
。 Then we want to use Event.stopPropagation()
to stop the click event from bubbling past the common parent, which will avoid some complications with the second listener. 然后我们想使用
Event.stopPropagation()
来阻止click事件冒泡到公共父级,这将避免第二个侦听器出现一些并发症。 The last check we are going to do is to see if the clicked element is the selected element. 我们要做的最后一项检查是查看被点击的元素是否是所选元素。 If it is then we skip the next step and just remove the selected class.
如果是,那么我们跳过下一步并删除所选的类。
We use a common variable to store the clicked element in until the next element is clicked. 我们使用公共变量来存储单击的元素,直到单击下一个元素。 Upon the next click event we remove the selected class from the stored element's class list if there is a stored element.
在下一个单击事件时,如果存在元素,我们将从存储元素的类列表中删除所选类。 Then we assign the newly clicked element to the common variable and give it the selected class.
然后我们将新单击的元素分配给公共变量并为其提供所选的类。
The second event listener will listen to click events for the entire document. 第二个事件侦听器将侦听整个文档的单击事件。 If there is a selected element, it should hide that element.
如果存在选定元素,则应隐藏该元素。 Now the trick here is that, because we stopped the propagation of the click event from the table if the clicked element was a
<td>
element and didn't have the class no_border
, we don't have to compare the clicked element again in order to not clash with the first event listener. 现在的诀窍是,因为如果被点击的元素是
<td>
元素并且没有类no_border
,我们停止了从表中传播click事件,我们不必再次比较被点击的元素为了不与第一个事件监听器发生冲突。 All we have to check is whether there is a selected element or not and if so, remove the class and reset the common variable. 我们需要检查的是是否存在选定的元素,如果是,则删除该类并重置公共变量。
var selected; document.getElementById( 'calendar' ).onclick = function( e ) { var c = e.target; if( c.tagName === 'TD' && c.className.indexOf( 'no_border' ) === -1 ) { e.stopPropagation(); if( c.className.indexOf( 'selected' ) === -1 ) { if( selected ) selected.className = selected.className.replace( /\\s?selected/, '' ); selected = c; selected.className += ' selected'; } else c.className = c.className.replace( /\\s?selected/, '' ); } } document.body.onclick = function( e ) { if( selected ) { selected.className = selected.className.replace( /\\s?selected/, ''); selected = false; } }
td { padding:4px; border:solid #ccc 1px; text-align: center; } td::after { /* I added this to keep a consistent width */ content: ""; display: block; width: 2em; } .no_border { border: 1px solid transparent; } .selected { border: solid #69F 1px; }
<table id="calendar"> <thead> <tr><td class="no_border">Sun</td><td class="no_border">Mon</td><td class="no_border">Tue</td><td class="no_border">Wed</td><td class="no_border">Thu</td><td class="no_border">Fri</td><td class="no_border">Sat</td></tr> </thead> <tbody> <tr><td class="no_border" colspan="6"></td><td>1</td></tr> <tr><td>2</td> <td>3</td> <td>4</td> <td>5</td> <td>6</td> <td>7</td> <td>8</td></tr> <tr><td>9</td> <td>10</td><td>11</td><td>12</td><td>13</td><td>14</td><td>15</td></tr> <tr><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td><td>22</td></tr> <tr><td>23</td><td>24</td><td>25</td><td>26</td><td>27</td><td>28</td><td>29</td></tr> <tr><td>30</td><td>31</td></tr> </tbody> </table>
There is not much of a simple solution but try: 没有太多简单的解决方案,但尝试:
function change(x) {
document.getElementsByTagName('td').forEach(function (el) {
if (el.className === 'selected') {
el.className = '';
}
});
document.getElementById("td_" + x).className = "selected";
}
Or 要么
function change(x) {
document.getElementsByClassName('selected').forEach(function (el) {
el.className = '';
});
document.getElementById("td_" + x).className = "selected";
}
Use querySelector to determine the currently-checked td
: 使用querySelector确定当前检查的
td
:
function change(x) {
var sel= document.querySelector('td.selected');
if(sel) sel.className= '';
document.getElementById("td_" + x).className = "selected";
}
You could also replace all your inline click handlers with one click handler on the table
. 您还可以使用
table
上的一个单击处理程序替换所有内联单击处理程序。 Make sure the event's target is a td
( e.target.tagName === 'TD'
), which contains a number ( !isNaN(e.target.textContent
): 确保事件的目标是
td
( e.target.tagName === 'TD'
),其中包含一个数字( !isNaN(e.target.textContent
):
document.querySelector('table').addEventListener('click', function(e) {
if(e.target.tagName === 'TD' && !isNaN(e.target.textContent)) {
var sel= document.querySelector('td.selected');
if(sel) sel.className= '';
e.target.className= 'selected';
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.