为details元素实现jQuery备选方案

6
我正在尝试为 details 元素实现 jQuery 回退。如果你从未听说过它,那么它基本上是一个 披露小部件。如果布尔属性 open 存在,则表示要向用户显示摘要和其他信息。如果缺少该属性,则只显示摘要。以下 HTML 和 CSS 实现了这一点。
<!-- opened -->
<details open>
    <summary>Summary</summary>
    <p>Additional information</p>
</details>

<!-- closed -->
<details>
    <summary>Summary</summary>
    <p>Additional information</p>
</details>

CSS

details summary ~ * {
    display: none;
}

details[open] summary ~ * {
    display: block;
}

我随后添加了以下jQuery代码,当单击summary元素时,添加/删除open属性。

jQuery代码

$("summary").click(function() {
    if ($(this).parent().attr("open")) {
        $(this).parent().removeAttr("open");
    } else {
        $(this).parent().attr("open", "open");
    }
});

它添加和删除“open”属性,但在Chrome中,“p”元素的可见性保持不变。我做错了什么?这是一个实时示例链接:live example更新
  • 它在Firefox 4中有效。
  • manjii指出,应将“open”更改为“open =“ open””,否则第一次将无法正常工作。BoltClock也提供了另一种解决方案。不过这不是主要问题。
  • marcosfromeroBoltClock提出了Chrome动态样式支持的问题,我认为这可能与此有关。

当您再次单击时,p的可见性确实会发生变化,因此它仅在第一次单击时出现问题。 - BoltClock
@BoltClock 在Firefox 4中会发生变化,但在Chrome中不会。我编辑了问题以指出这一点。 - melhosseiny
6个回答

2

原来这是一个WebKit的bug,可以在这里查看。

Bug 21346 属性值选择器没有在属性更改时重新评估

添加以下空规则可以暂时解决我遇到的问题:

details[open] {}

与错误报告中的描述相反,似乎是在使用属性选择器后跟后代组合器时发生了问题。然而,今天发布了Chrome 12,并且它具有对“details”和“summary”元素的本地支持。

1

它只在第一次运行时无法工作,因为:

<details open>

$(this).parent().attr("open") 等于 ""(空字符串)= false => 属性不会被删除,但会被赋值为 "open" => 第二次点击将起作用。

要解决此问题,请向属性添加一个值:

<details open="open">

1
或者,if (typeof $(this).parent().attr("open") != "undefined") - BoltClock
谢谢您指出这个问题,但这不是主要问题。@BoltClock 我尝试过了,但在FF4或Chrome中并没有真正起作用。 - melhosseiny
我猜你可能没有使用jQuery 1.6。 - BoltClock
@BoltClock,我又试了一次,你是对的。第一次肯定是我搞错了什么。 - melhosseiny

1

添加对Mozilla Firefox的支持

<details>
<summary>Summary</summary>
<p id="detail">Additional information</p>
</details>


<script>
var ischrome = false;
if(/chrom(e|ium)/.test(navigator.userAgent.toLowerCase())){
    ischrome = true;
    }

$detail = $('#detail');
$detail.hide();
if(!ischrome){
    $('summary').prepend('► ');                     
}
$('summary').on('click', function(e){
    if ($detail.is(":visible")){
        $('summary').html('► summary');
        $detail.hide();                                 
    }else{              
        $('summary').html('▼ summary');             
        $detail.show(); 
    }
});                     
</script>

0

至少在Chrome中,问题不在于jQuery代码,而是在于Chrome对CSS选择器的支持。

如果您调试jQuery代码,它可以正常工作,但CSS未按预期应用。

请检查此处使用“调试控制台”的原始代码分支:

http://jsfiddle.net/marcosfromero/KQGn8/


我知道它正确地添加和删除了 open 属性,但是正如你所看到的,CSS 最初被应用为预期。第一个 details 元素是打开的,而第二个元素是关闭的。 - melhosseiny
WebKit 似乎存在与 ~ 和动态样式有关的问题。 - BoltClock
@BoltClock ~ 不是问题,因为如果你用 + 替换它,它仍然不起作用。 - melhosseiny

0

我使用this solution来使它在所有不支持的浏览器上工作。它不需要也不使用jQuery,但是如果你喜欢,你可以用jQuery增强它(它只是普通的JS)。

下面是这个解决方案的演示:

details summary {display: block;}    
details summary ~ * {
    display: none;
}
details[open] summary ~ * {
    display: block;
}
<details>
  <summary onclick="if(this.parentElement.getAttribute('open')!='open') this.parentElement.setAttribute('open','open'); else this.parentElement.removeAttribute ('open'); return false;">{{ item.title }}</summary>
  {{ item.content }}
</details>


我非常确定SO有反对重复答案的政策。为什么一个非常相似的帖子中的答案会下线?我认为这个政策只适用于(并且是为了)第三方链接,但我可能错了。 - Mr. Hugo
更新:我已经在答案中添加了解决方案。 - Mr. Hugo

0
在Safari中,您需要将evt.preventDefault()添加到单击处理程序中,否则它也会触发本地行为,将其返回到单击之前的状态(这似乎在Chrome中不会发生,奇怪)。
$("summary").click(function(evt) {
    if ($(this).parent().attr("open")) {
        $(this).parent().removeAttr("open");
    } else {
        $(this).parent().attr("open", "open");
    }
    evt.preventDefault();
});

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