JavaScript - 单击另一个元素后将元素恢复为原始样式

时间:2015-08-22 02:55:21

标签: javascript html css

所以我正在构建一个日历程序,我希望用户能够选择一天。使用<table>时,<td>会在className="NewStyle"应用<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> 时突出显示。我希望在单击另一个单元格后该单元格恢复正常,但它仍然保持其新样式。

当点击另一个单元格时,如何让JS将任何未单击的单元格恢复为正常?

这是一个JSFiddle。谢谢你的帮助!

HTML

细胞看起来像这样:

td_4

单击td_6将成功更改样式。但点击td_4也会成功更改样式,但请将function change(x) { document.getElementById("td_" + x).className = "selected"; } 保留为新样式,而不是将其恢复。

的JavaScript

$myCarousel.carousel('pause');

4 个答案:

答案 0 :(得分:4)

只需跟踪您点击的元素并将其取消分类即可。 fiddle

var previousEl
function change(x) {
  if (previousEl) previousEl.className = ""
  previousEl = document.getElementById("td_" + x)
  previousEl.className = "selected"
}

更新:值得一提的另一件事是你可以利用事件冒泡,这样你的父容器就可以监听事件,从事件对象中获取被点击元素的id。 updated fiddle

var previousEl
function change(event) {
  if (previousEl) previousEl.className = "";
  previousEl = document.getElementById(event.target.id)
  previousEl.className = "selected";
}

并在您的html中删除所有<td onclick="change()">并将其放在父级,传递事件:

<table onclick="change(event)">

答案 1 :(得分:3)

这就是我将如何实现您正在寻找的效果,但首先要注意几个:

  1. 不要使用内联JavaScript
  2. 如果必须重复大量代码,可能会以更简单的方式完成。 (阅读:DRY
  3. 我们只会在此脚本中使用两个事件侦听器。

    第一个事件侦听器将使用委托将所选类分配给单击的元素。当您单击某个元素时,该事件将“冒泡”通过所单击的元素,一直向上通过DOM。所以我们可以听一个共同的父元素,然后检查事件的起源。

    这里我们要检查元素是否是<td>元素,以及它是否没有类no_border。然后我们想要使用Event.stopPropagation()来阻止点击事件冒泡过公共父级,这将避免第二个侦听器出现一些复杂情况。我们要做的最后一项检查是查看被点击的元素是否是所选元素。如果是,那么我们跳过下一步,只删除选定的类。

    我们使用公共变量来存储单击的元素,直到单击下一个元素。在下一个单击事件时,如果存在元素,我们将从存储元素的类列表中删除所选类。然后我们将新点击的元素分配给公共变量并为其提供所选的类。

    第二个事件侦听器将侦听整个文档的单击事件。如果存在选定元素,则应隐藏该元素。现在的诀窍是,因为如果点击的元素是<td>元素并且没有类no_border,我们就停止了从表中传播click事件,我们不必再次比较单击的元素,以便不与第一个事件侦听器冲突。我们需要检查的是是否存在所选元素,如果是,则删除该类并重置公共变量。

    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>

答案 2 :(得分:1)

没有太多简单的解决方案,但请尝试:

function change(x) {
    document.getElementsByTagName('td').forEach(function (el) {
        if (el.className === 'selected') {
            el.className = '';
        }
    });
    document.getElementById("td_" + x).className = "selected";
}

或者

function change(x) {
    document.getElementsByClassName('selected').forEach(function (el) {
        el.className = '';
    });
    document.getElementById("td_" + x).className = "selected";
}

答案 3 :(得分:1)

使用querySelector确定当前已检查的td

function change(x) {
  var sel= document.querySelector('td.selected');
  if(sel) sel.className= '';
  document.getElementById("td_" + x).className = "selected";
}

Fiddle 1

您还可以使用table上的一个点击处理程序替换所有内联点击处理程序。确保事件的目标是tde.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';
  }
});

Fiddle 2