【问题标题】:Styling Contiguously Selected Table Cells为连续选定的表格单元格设置样式
【发布时间】:2011-11-03 14:24:05
【问题描述】:

我有一个带有可选单元格的表格(通过 jQuery-UI 可选)。通过 cmd/ctrl 单击和通过套索单独选择单元格。选定的单元格获得“ui-selected”类。我通过向该类添加 1 像素厚的橙色边框来设置选择的样式。 This looks silly when contiguous cells are selected.请看这个小提琴来玩它:http://jsfiddle.net/derekprior/UxwD4/

我想做的是仅在相邻单元格未被选中的一侧绘制橙色边框。相邻我的意思是在同一行和上下行。结果应该是围绕整个连续选择的单个轮廓。

这可以用纯 CSS 完成吗? CSS3 选择器是公平的游戏,只要它们在 Firefox、Chrome 和 Safari 中得到足够好的支持。如果没有,那么 Javascript 怎么样?

【问题讨论】:

    标签: javascript jquery jquery-ui css


    【解决方案1】:

    http://jsfiddle.net/UxwD4/14/

    $(function(){
    
        $("tbody").selectable({
            filter: 'td:not(.user)',
            stop: doIt
        });
    
        var cssClass = "ui-selected";
        var withBorder = "1px solid #F39814";
        var noBorder = "1px solid #dddddd";
    
        function doIt(){        
            $("td").css("border", noBorder);
    
            $("td." + cssClass).each(function(){
                var $this = $(this);
                var col = $this.index();
    
                $this.css("border", withBorder);
    
                if($this.prev().hasClass(cssClass)){
                     $this.css("border-left", noBorder);
                }
    
                if($this.next().hasClass(cssClass)){
                     $this.css("border-right", noBorder);
                }
    
                if($this.parent()
                       .prev()
                       .children().eq(col)
                       .hasClass(cssClass)){
    
                        $this.css("border-top", noBorder);
                }
    
                if($this.parent()
                       .next()
                       .children().eq(col)
                       .hasClass(cssClass)){
    
                        $this.css("border-bottom", noBorder);
                }
            });
        }
    
    });
    

    【讨论】:

    • 据我所知,这似乎满足所有要求。这是我脑海中的伪代码的工作代码,但不知道它的 API。我希望有一种方法可以用更多的 css 和更少的 JS 来做到这一点,但看起来这是最好的解决方案。谢谢!
    • 第一次选择时会有一点“跳跃”,所有边框似乎都变大了...
    • @wesley 是的,那只是因为 jquery-ui 应用的默认样式只是在底部和右侧放置了一个边框。通过调整 jquery 以执行相同的 jsfiddle.net/UxwD4/12 或默认样式具有所有 4 个边框 jsfiddle.net/UxwD4/13 或什至添加和删除类而不是直接 css 操作来轻松修复。还有其他一些小的清理问题,更多的是针对功能。
    • 表格样式默认值实际上是由 Twitter Bootstrap 加载的。我认为@luckykind 解决了边界问题并将更多的逻辑转移到 CSS 中。
    • 原来这应该使用停止处理程序而不是选定的处理程序。使用 selected 时,您无法在按住 cmd 时取消选择以前选择的单元格。将此移至已停止的事件似乎可以解决此问题
    【解决方案2】:

    这不能用纯 CSS 来完成(至少在没有 JavaScript 操作的情况下不能),但是用 jQuery(因为你已经在使用 jQuery UI 库):

    $('td').click(
        function(){
            if ($(this).prev('td').hasClass('ui-selected')){
                $(this).css('border-left-color','transparent');
                $(this).prev('td').css('border-right-color','transparent');
            }
            else if ($(this).next('td').hasClass('ui-selected')){
                $(this).css('border-right-color','transparent');
                $(this).next('td').css('border-left-color','transparent');
            }
        });
    

    JS Fiddle demo.

    【讨论】:

    • 谢谢。但是,当SELTED高于/下面的细胞时,这不会解决顶部和底部边界。通过套索选择(单击并拖动)时,如果在选择单元格 2 之前选择了单元格 1 和 3,它也会崩溃。我认为可以通过将“else if”更改为“if”来修复最后一个问题,但是呢?另外两个?
    【解决方案3】:

    这只能使用 JavaScript 来完成。 selected 事件必须用于检测选择的结束。然后,检查上一行/下一行/单元格是否有selected 类。如果有,请添加一个类来处理相关边框。

    看看代码,我用了描述性的名字。

    小提琴:http://jsfiddle.net/UxwD4/11/
    CSS:

    .ui-border-top    { border-top: #eee; }
    .ui-border-right  { border-right: #eee; }
    .ui-border-bottom { border-bottom: #eee; }
    .ui-border-left   { border-left: #eee; }
    

    JavaScript:

    $("tbody").selectable({
        filter: 'td:not(.user)',
        selected: function(){
            $('td.ui-selectee', this).each(function(){
                var cell = $(this),
                    row = cell.parent(),
                    cellIndex = cell.index();
                cell.removeClass('ui-border-top ui-border-right ui-border-bottom ui-border-left');
                if (cell.hasClass('ui-selected')) {
                    var up = row.prev().children().eq(cellIndex).hasClass('ui-selected'),
                        right = cell.next().hasClass('ui-selected'),
                        down = row.next().children().eq(cellIndex).hasClass('ui-selected'),
                        left = cell.prev().hasClass('ui-selected');
                    if (up) cell.addClass('ui-border-top');
                    if (right) cell.addClass('ui-border-right');
                    if (down) cell.addClass('ui-border-bottom');
                    if (left) cell.addClass('ui-border-left');
                }
            });
        }
    });
    

    【讨论】:

    • 这太接近了。例如,在星期一选择 Sam,在星期一和星期二选择 Mallory,然后在星期四选择 Ethan。边框不太正确(至少在 Chrome 中)。我还要玩这个。
    • 见詹姆斯的小提琴。它可以 100% 工作。不过,我得到了三个非常有用的答案 - 非常感谢。
    • @Derek .children().eq() 必须使用而不是 .children()。请参阅我的更新答案。
    • @Rob 这里的问题是你使用了.children(cellIndex)。只传递一个数字是无效的。您可以将其更改为 .children(":eq(....children().eq(...
    【解决方案4】:

    http://jsfiddle.net/LuckyKind/3pXyX/

    更多的 CSS,更少的 jQuery

    td {
        padding:1px
    }
    
    td.ui-selecting {
        background: #FECA40 !important;
    }
    
    td:not(.ui-selected) + .ui-selected {
        border-left: 1px solid #F39814 !important;
    }
    
    .ui-selected + td:not(.ui-selected) {
        border-left: 1px solid #F39814 !important;
    }
    
    tr.row-selected + tr.row-selected td.ui-selected {
        border-top: 1px solid #ddd !important;
    }
    
    tr:not(.row-selected) + tr.row-selected td.ui-selected {
        border-top: 1px solid #F39814 !important;
    }
    
    tbody > tr.row-selected:first-child td.ui-selected {
        border-top: 1px solid #F39814 !important;
    }
    
    tr.last-row-selected td.ui-selected {
        border-bottom: 1px solid #F39814 !important;
    }
    

    然后是 jQuery...

    $("tbody").selectable({
        filter: 'td:not(.user)',
        start: function(){
              $('tr.last-row-selected').removeClass('last-row-selected');        
        },
        stop: function(){
              $('td.ui-selected:last',this).parent().addClass('last-row-selected');        
              $('tr.row-selected',this).removeClass('row-selected');
              $('td.ui-selected',this).parent().addClass('row-selected');
        }
    });
    

    【讨论】:

    • 我喜欢你的想法,但不是 100% 有效。它与@Rob 的回答有类似的问题。例如,为 Sam 选择 M,Tu,W,为 Mallory 选择 Tu - 全部在一个选项中。 Sam 缺少 M 和 W 的底部边框。
    • ... 甚至更简单,选择不同行中的两个不连续单元格。例如,星期一是 Sam,星期一是 Carl。 Sam 选择的单元格应该有一个底部边框,但它没有。
    • shucks... K... 必须添加更多的 jQuery... 但是在视觉上和更简洁的代码方面做得很好。 jsfiddle.net/LuckyKind/Cwm5U
    • 非常好!我现在无法决定使用哪个。您的解决方案的唯一缺点是,在进行多项选择时,先前选择的区域会消失,直到您完成后续选择(由于 start 函数中的最后一行)。有什么办法吗?
    • 通过将最后一行从 start 放入 stop 的开头轻松修复!现在比较我最喜欢的解决方案的jquery。
    猜你喜欢
    • 2011-10-22
    • 2015-02-19
    • 2010-11-01
    • 2013-05-17
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多