使用 JavaScript 将路径转换为嵌套的无序列表:
Convert paths into a nested unordered list using JavaScript:
我有一个包含以下路径的列表:
<ul class="list">
<li class="item">/animal/dog/treats/biscuits</li>
<li class="item">/animal/dog/treats/cookies</li>
<li class="item">/clothes/shirts</li>
</ul>
我想使用 JavaScript 将上面列表中的每个路径转换为嵌套的无序列表,如下所示:
<ul>
<li>animals
<a href="/animal">Shop</a>
<ul>
<li>dogs
<a href="/animal/dog">Shop</a>
<ul>
<li>treats
<a href="/animal/dog/treats">Shop</a>
<ul>
<li>
<a href="/animal/dog/treats/biscuits">biscuits</a>
</li>
<li>
<a href="/animal/dog/treats/cookies">cookies</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>clothes
<a href="/clothes">Shop</a>
<ul>
<li><a href="/clothes/shirts">shirts</a></li>
</ul>
</li>
</ul>
这是预期的输出:
output
如果有人可以指导我使用 JavaScript 实现这一目标,我将不胜感激。谢谢!
这里有一些原版 JavaScript 可以完全按照您指定的方式进行操作。我在 'shop' 和列表条目名称之间添加了一个 space 以阻止它们相互生成。希望这对您有所帮助!
let list = document.querySelector('#list'); // get list
let items = list.querySelectorAll('[class*="item"]'); // get all items in list
let newList = document.createElement('ul');
items.forEach( item => {
const paths = item.innerText.split('/');
paths.splice(0,1); // remove first element since it's empty
let dir = newList;
let globalPath = "";
for( path of paths ){
globalPath = globalPath + '/' + path;
if( dir[path] == undefined ){
let subList = document.createElement('li'); // begin sublist
subList.innerText = path + ' '; // add space between the list entry and href
let href = document.createElement('a'); // begin href
href.href = globalPath;
subList.appendChild( href ); // end href
if( path != paths[paths.length-1] ){ // prep another ul to go deeper in the list
href.innerText = "shop";
let ul = document.createElement('ul');
subList.appendChild( ul );
dir[path] = ul;
}
dir.appendChild(subList); // end sublist
}
dir = dir[path]; // dive deeper
}
} );
list.innerHTML = newList.innerHTML; // replace old list with new list
<ul class="list" id="list">
<li class="item">/animal/dog/treats/biscuits</li>
<li class="item">/animal/dog/treats/cookies</li>
<li class="item">/clothes/shirts</li>
</ul>
星期六 afternoon/evening 无所事事......这就是我整理的。不是第一个答案,而是另一个答案。 ;-)
// convert the menu object into the nested <ul> structure:
function buildShop(pth,mn){
return Object.entries(mn).sort(([k],[l])=>k.localeCompare(l))
.map(([sh,o])=>
'<li>'+
(Object.entries(o).length
? sh+' <a href="'+pth+sh+'">Shop</a><ul>'+ buildShop(pth+sh+'/',o)+'</ul>'
: '<a href="'+pth+sh+'">'+sh+'</a>')+
'</li>').join("\n")
}
// Create a "menu" object containing all shops and items:
const menu={};
document.querySelectorAll("ul.list>li").forEach(el=>
el.textContent.substr(1).split("/")
.reduce((m,sh)=>m[sh]=m[sh]||{},menu)
);
document.querySelector("ul.list").innerHTML=buildShop('/',menu);
<ul class="list">
<li class="item">/animal/dog/collar</li>
<li class="item">/animal/dog/treats/biscuits</li>
<li class="item">/animal/dog/treats/cookies</li>
<li class="item">/clothes/shirts</li>
<li class="item">/animal/dog/leash</li>
</ul>
我刚刚为每个级别添加了字母排序。这样一开始定义路径的顺序就无关紧要了。
我有一个包含以下路径的列表:
<ul class="list">
<li class="item">/animal/dog/treats/biscuits</li>
<li class="item">/animal/dog/treats/cookies</li>
<li class="item">/clothes/shirts</li>
</ul>
我想使用 JavaScript 将上面列表中的每个路径转换为嵌套的无序列表,如下所示:
<ul>
<li>animals
<a href="/animal">Shop</a>
<ul>
<li>dogs
<a href="/animal/dog">Shop</a>
<ul>
<li>treats
<a href="/animal/dog/treats">Shop</a>
<ul>
<li>
<a href="/animal/dog/treats/biscuits">biscuits</a>
</li>
<li>
<a href="/animal/dog/treats/cookies">cookies</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>clothes
<a href="/clothes">Shop</a>
<ul>
<li><a href="/clothes/shirts">shirts</a></li>
</ul>
</li>
</ul>
这是预期的输出: output
如果有人可以指导我使用 JavaScript 实现这一目标,我将不胜感激。谢谢!
这里有一些原版 JavaScript 可以完全按照您指定的方式进行操作。我在 'shop' 和列表条目名称之间添加了一个 space 以阻止它们相互生成。希望这对您有所帮助!
let list = document.querySelector('#list'); // get list
let items = list.querySelectorAll('[class*="item"]'); // get all items in list
let newList = document.createElement('ul');
items.forEach( item => {
const paths = item.innerText.split('/');
paths.splice(0,1); // remove first element since it's empty
let dir = newList;
let globalPath = "";
for( path of paths ){
globalPath = globalPath + '/' + path;
if( dir[path] == undefined ){
let subList = document.createElement('li'); // begin sublist
subList.innerText = path + ' '; // add space between the list entry and href
let href = document.createElement('a'); // begin href
href.href = globalPath;
subList.appendChild( href ); // end href
if( path != paths[paths.length-1] ){ // prep another ul to go deeper in the list
href.innerText = "shop";
let ul = document.createElement('ul');
subList.appendChild( ul );
dir[path] = ul;
}
dir.appendChild(subList); // end sublist
}
dir = dir[path]; // dive deeper
}
} );
list.innerHTML = newList.innerHTML; // replace old list with new list
<ul class="list" id="list">
<li class="item">/animal/dog/treats/biscuits</li>
<li class="item">/animal/dog/treats/cookies</li>
<li class="item">/clothes/shirts</li>
</ul>
星期六 afternoon/evening 无所事事......这就是我整理的。不是第一个答案,而是另一个答案。 ;-)
// convert the menu object into the nested <ul> structure:
function buildShop(pth,mn){
return Object.entries(mn).sort(([k],[l])=>k.localeCompare(l))
.map(([sh,o])=>
'<li>'+
(Object.entries(o).length
? sh+' <a href="'+pth+sh+'">Shop</a><ul>'+ buildShop(pth+sh+'/',o)+'</ul>'
: '<a href="'+pth+sh+'">'+sh+'</a>')+
'</li>').join("\n")
}
// Create a "menu" object containing all shops and items:
const menu={};
document.querySelectorAll("ul.list>li").forEach(el=>
el.textContent.substr(1).split("/")
.reduce((m,sh)=>m[sh]=m[sh]||{},menu)
);
document.querySelector("ul.list").innerHTML=buildShop('/',menu);
<ul class="list">
<li class="item">/animal/dog/collar</li>
<li class="item">/animal/dog/treats/biscuits</li>
<li class="item">/animal/dog/treats/cookies</li>
<li class="item">/clothes/shirts</li>
<li class="item">/animal/dog/leash</li>
</ul>
我刚刚为每个级别添加了字母排序。这样一开始定义路径的顺序就无关紧要了。