编辑:跳过结束以更好地解释我所追求的内容,thx
我有大约以下的html(这只是摘录),其中有一个嵌套的章节组织:
<span class="chapter Art" id="00034">
<li><span class="chapterheading">Art<span>some stuff</span></li>
<ul>
<span class="chapter" id="00035">
<li><span class="chapterheading selectednode">Sound</span><span>more stuff</span></li>
<div class="idea">even more stuff</div>
</span>
</ul>
</span>
现在我希望使用javascript只显示紧接在下面的章节标题,并且紧接在类'idea'的div下面,以便看到任何'想法',你必须点击它的直接父章。
花了大约三个小时后(因为我对jquery有点绿,我花了一段时间才意识到子选择器真的如何工作),我想出了一个非常复杂的查询,它可以满足我的需求。显示相关节点(假设它们在运行此代码之前被隐藏):
t.find("li > *, ul > .chapter, ul > .chapter > li, ul > .chapter > li *, > .idea, > .idea *").show();
其中't'是最近点击的节点,它具有类'selectednode'(编辑:是该节点的父节点的父节点)。
那么在这里表达我需要的东西会有更短的方式吗?
编辑:以下是一个更大的代码片段,需要很多行李。寻找评论“隐藏相同深度的兄弟姐妹的孩子们。”
我已经对它进行了一些修剪,但它没有做我想做的事情:我无法让它显示只是下面的直接章节和想法,它显示了一切。
function toggleNode(node, value) {
//_("setting " + nv(node) + " to " + value + "\n");
$(node).toggleClass("selectednode", value);
if($(node).hasClass("selectednode") == true)
selectednode = node;
if($(selectednode).hasClass("selectednode") == false) // is this check really necessary?
selectednode = 0;
}
function zoomTo(node, select) {
var zoom, oldzoom, depth, t;
//_("zoomTo(" + (node ? $(node).text() : "0") + ", " + select + ")");
oldzoom = zoomednode;
if(node != zoomednode) {
savedepth = t = depth = $(node).parents("ul").length;
if(!zoomednode)
zoomednode = topChapter;
if(!node)
node = topChapter;
/* capture values */
var sz;
var capp = cBaseSz.slice((sz = parseFloat(cBaseSz)).length);
/* end capture */
zoom = zoomnum = sz;
while(--t > 0) {
zoomnum = (zoom *= 1.15);
}
//_("zoom: " + zoomnum +"\ncapp: " +capp);
zoom += capp;
//_("zoom: " + zoomnum);
depth -= $(zoomednode).parents("ul").length;
if(depth < 0)
depth *= -1;
switch(select) {
case 0:
case false:
default:
break;
case true:
case 1:
toggleNode(zoomednode, false);
toggleNode(zoomednode = node, true);
break;
case 2:
toggleNode(zoomednode, false);
zoomednode = 0;
}
/* Handle showing/hiding */
if(1) {
var hide;
t = ($(selectednode) || $(".chapterheading:first"));
_("t.text():" + t.text());
t = t.parent().parent();
_("isclass: " + t.attr("class"));
var prs = $(t).parents(".chapter");
prs = $(prs)[0] || t;
hide = $(prs).siblings(".chapter");
_("topparent: " + $(prs).text().slice(0,80));
$(hide).each( function() { {
_(($(this).html()||$(this).text()).slice(0, 80));
}});
$("li *, > ul, > idea", t).show();
//t.siblings().show();
//t.siblings().find().hide();
//hide.children(".chapterheading").find().show();
//showall(t.find("li *, ul > .chapter > li *"));
// Hide deeper children of this chapter (t)
// $(t).find("ul *:not(ul > .chapter > li, ul > li *)").hide();
// t.find("li > *, ul > .chapter, ul > .chapter > li, ul > .chapter > li *, > .idea, > .idea *").show();
// Show immediate children of this chapter (t)
//$(t).find("> li *, ul > .chapter").show();
// t.find(".chapterheading, .ideacount").show();
//$(hide).children().find(":not(.chapterheading, .ideacount)").hide();
// Hide children of sibling chapters of the same depth.
$("ul > .chapter", t).hide();
// Hide children of siblings of the top-most parent chapter of the selected chapter.
$("ul > .chapter, ul > .chapter .chapter", hide).hide();
// Show the selected chapter
$("ul > .chapter, ul > chapter .chapter", t.parent()).show();
}
//////////////////////////////
// old version below, but keeping for reference
else {
var showzoom = 1, showselect = 1, showidea = 1, seldepth, zdepth, showlist, hidelist = {};
/* This is the 'brute force' way of doing it, horribly inefficient */
if(zoomednode)
zdepth = $(zoomednode).parents(".chapter").length;
if(selectednode)
seldepth = $(selectednode).parents(".chapter").length;
else
seldepth = zdepth;
if(!seldepth)
seldepth = zdepth = 0;
_("seldepth: " + seldepth + "\nzdepth: " + zdepth);
(showlist=$(".chapter").filter( function() {
if($(this).parents(".chapter").length < (zdepth+showzoom))
return true;
else {
hidelist = $(hidelist).add(this);
return false;
}
}));
// hidelist = $("all").not(showlist);
if(hidelist)
_("hidelist size: " + hidelist.length);
_("showlist size: " + showlist.length);
$(showlist).show()/*.not(hidelist)*/;
if(hidelist && hidelist.length) {
//_("Hiding " + $(hidelist).length + " elements.");
$(hidelist).hide();
}
}
/* End showing/hiding */
/* Begin animating */
$("#contents").animate({ fontSize: zoom }, {duration: 0, queue: false });
$("html").animate(
{ scrollTop: $(node).offset().top - topAdjust }, {duration: 60+60*depth, queue: false }, 0);
$(window).scrollLeft($(node).offset().left - leftAdjust);
} else {
zoomTo(0, 1 + (selectednode == zoomednode));
}
}
function setupEvents() {
$("#contents .chapterheading").click( function() { _("\n-- -- -- CLICK -- -- --\n-- -- -- -- -- -- -- --\n"), zoomTo(this, true); });
}
编辑:为了进一步参考,标记具有以下类别(递归表示):
<ul> <!-- A: chapter heading list -->
<span class="chapter">
<li><span class="chapterheading">Title</span></li>
<!-- 0 or more of the following --> <div class="idea"><!-- more stuff --></div>
<!-- 0 or more of A: chapter heading list -->
</span>
</ul>
并且,变量't'指向类“selectednode”的地方也将被追加,这是我希望发生以下情况的地方:
答案 0 :(得分:2)
重构HTML以使其有效。我的建议是:
<div id="toc">
<h2>Table of Contents</h2>
<ul>
<li id="00034" class="art">
<span class="chapterheading">Title</span>
<!-- more stuff -->
<div class="idea"> ... </div>
...
<ul>
<li id="00035">
<span class="chapterheading selected">Subtitle</span>
</li>
...
</ul>
</li>
<li>
<span class="chapterheading">Second Title</span>
...
</li>
...
</ul>
</div>
这不使用chapter
类,它只是假设li
中的所有#toc
元素代表一个章节。
使用这种结构,构建的DOM(应用所有选择器等,您可以在开发人员控制台中检查它)看起来与HTML标记完全相同。在您的代码中,span
元素中的ul
标记很可能会移动到li
个项目中。
现在,要隐藏章节后面的所有元素,我们使用此代码CSS代码:
#toc li > * {
display: none;
}
但如果选择了li则显示它们:
#toc li > span.chapterheading, #toc li.selected > * {
display: block;
}
使用Javascript,我们现在只需根据点击次数移动selected
类:
$(document).ready(function() {
$("#toc").on("click", "span.chapterheading", function(ev) {
$(this).closest("li")
.addClass("selected")
.siblings().removeClass("selected");
});
});
答案 1 :(得分:1)
很难说你正在使用什么,因为你没有显示足够的代码。
基于您的标记模式以及我认为您在一行JavaScript之外所做的事情,我觉得这可能对您有用:
$( '.chapterheading' ).click( function(){
var t = $( this );
//I assume you are doing other stuff with t...
t.parent().next().show();
});
答案 2 :(得分:0)
另一种类型的列表更适合此类问题 - 即定义列表<dl>
以及定义词<dt>
和定义描述<dd>
。
HTML:
<div id="toc">
<h2>Table of Contents</h2>
<dl>
<dt id="00034">Title 00034</dt>
<dd class="text">text 00034</dd>
<dd class="idea">idea 00034</dd>
<dd class="sub">
<dl>
<dt id="00035">Subtitle 0035</dt>
<dd class="text">text 00035</dd>
<dd class="idea">idea 00035</dd>
</dl>
</dd>
</dl>
<dl>
<dt id="00036">Title 00036</dt>
<dd class="text">text 00036</dd>
<dd class="idea">idea 00036</dd>
</dl>
</div>
和javascript:
$("#toc dt").on('click', function() {
$(this).closest("dl")
.children(".idea").hide().end()
.children(".text, .sub").toggle().end()
.siblings().find("dd").hide();
});
$("#toc dd.text").on('click', function() {
$(this).closest("dl").children(".idea").toggle();
});
<强> DEMO 强>
所有控制都由javascript直接执行。 DEMO中的所有CSS都是用于外观,而不是用于隐藏/显示。
可能不是您想要的,特别是关于事件处理程序如何附加,但应该让您知道如何处理它。