多级列表首字母大写(JS,JQUERY)

Uppercase first letters in multi-level lists (JS, JQUERY)

我正在尝试为我们使用的 CKEditor 做一些自定义大写工具。但即使没有 CKEditor,这似乎也是一个有趣的案例。

现在我想要一些好的解决方案,只选择 LEVEL 1 元素并在不触及子级别 HTML 结构的情况下将所有包含的 TEXT 大写,然后在不触及的情况下将 LEVEL 2 大写1级。 我已经尝试了许多具有许多指向组合的排除方法。 我们不能使用 类 和 id's.

似乎当我们使用大写函数时,我们从它返回的字符串(内容文本),当我们将它们插入代码时,正在弄乱 HTML 结构。

当前目标:不破坏嵌套结构,将它们全部连接起来并将它们移动到父元素。

当前进度:

我有一些想法,但也许我需要重新审视这个问题。

现在似乎是提出重要问题的时候了: 是否只需要更具体的方式来选择元素,更好的方式来替换文本,或者它是否适合完全不同和更复杂的方法?

我已经用当前版本的代码和示例数据准备了一个测试环境 - 现在有两个活动函数来显示对 LEVEL 1 和 LEVEL 2 元素的操作:

https://codepen.io/adalbertus/pen/jxOGYV

HTML:

<p>FIRST LIST after header- we want it to change:</p>

<h2>Some header to target proper lists</h2>

<ul>
<li>text 1 - Level 1</li> 
<li>text 2 - Level 1
    <ul>
        <li>text 1 - Level 2</li> 
        <li>text 2 - Level 2</li> 
    </ul>
</li>
<li>text 3 - Level 1</li>
<li>text 4 - Level 1</li>

<p>SECOND LIST after header - we don't want it to change:</p>
<ul>
<li>text 1 - Level 1</li> 
<li>text 2 - Level 1
    <ul>
        <li>text 1 - Level 2</li> 
        <li>text 2 - Level 2</li> 
    </ul>
</li>
<li>text 3 - Level 1</li>
<li>text 4 - Level 1</li>

JS:

$("#capitalize").click(function (){

function capitalizeFirstLetter(lists){
return lists.charAt(0).toUpperCase() + lists.slice(1);}

//Condition to target only lists directly after Headers is not necessary, but let say it will be there.
//So this is the reason to exist such variables like below - to easily change this in the future:
var h2Andh3TagsToTargetLiElements = $("body").find("h2,h3");
var listsToCapitalize = $("body").find("ul");
var listsAfterHeaders =     $(h2Andh3TagsToTargetLiElements).next(listsToCapitalize).find("li");
var nestedListsToCapitalize = $("body").find("ul > li > ul , ul > li > ol");
var nestedListsAfterHeaders =$(h2Andh3TagsToTargetLiElements).next(nestedListsToCapitalize).contents().find("li");


if (listsAfterHeaders.length) {

//Operation just for nested lists - just for tests
$(nestedListsAfterHeaders).each(function () {
var nested = $(this).text();
var nestedtocap = capitalizeFirstLetter(nested);
  $(this).text(nestedtocap);
                                          });
$(listsAfterHeaders).each(function () {
var totxt = $(this).text();
var tocap = capitalizeFirstLetter(totxt);
  $(this).text(tocap);
                                    });
                          }

 });

如果我正确理解了你的问题,这可以更简单地完成。

$("#capitalize").click(function() {
  function capitalizeFirstLetter(lists) {
    return lists.charAt(0).toUpperCase() + lists.slice(1);
  }

  $("body > ul > li").each(function(idx, el) {
      $(el).html($(el).html().charAt(0).toUpperCase() + $(el).html().slice(1));
  });
});

基本上,只有 select 个遵循 body > ul > li 层次结构的项目。

我不知道我的理解是否正确,但您正在寻找对嵌套元素的一些控制。这是一个没有 jquery 或可能有帮助的 querySelectors 的普通 js 解决方案:

//assuming that we have an ul variable where li descendants always
have a text node as the first child:
    var ul = document.createElement("ul");
    ul.innerHTML = `<li>text 1 - Level 1</li> 
    <li>text 2 - Level 1
        <ul>
            <li>text 1 - Level 2</li> 
            <li>text 2 - Level 2</li> 
        </ul>
    </li>
    <li>text 3 - Level 1</li>
    <li>text 4 - Level 1</li>`;


     /*create a function to capitalize the first letter,
    I'm using regex incase you want to do different manipulations other than
     capitalizing.Below, Node is a ul element, gets the immediate 
li elements and performs replace*/
             function capitalize(node){
                Array.prototype.slice.call(node.children)
                .filter(function(d,i){return d.tagName === "LI" })
                .forEach(function(d,i){
                    d.firstChild.textContent 
                    = d.firstChild.textContent
                        .replace(/^[A-Z]/gi,function(m,o,s){return m.toUpperCase();})})
            }

要获得 'levels',这里有一个函数 returns 一个包含该级别的 ul 节点的数组:

function getLevels(level,parent){
    var nodes = [parent],
        children = undefined;
    for (var i = 0;i<level;++i){
        nodes = nodes.map(function(d,i){
            return d 
            && d.nodeType 
            && (children = Array.prototype.slice.call(d.children))
            .filter(function(d,i){return d.tagName === "UL"})
        }).reduce(function(ac,d,i){
            return ac.concat(d);
        },[])
        if(!nodes.length && i !== level - 1){
            nodes = children;
        }
    }
    return nodes;
}

例如,对于 ul 变量:

getLevels(0,ul);//return the parent itself [ul]
getLevels(1,ul);//return empty [] since all immediate children are li
getLevels(2,ul);//return [ul] containing ul inside the second li

现在,要将第 2 级 ul 的 li 标签大写:

getLevels(2,ul).forEach(function(d,i){capitalize(d)})

你最终得到:

<li>text 1 - Level 1</li> 
<li>text 2 - Level 1
    <ul>
        <li>Text 1 - Level 2</li> 
        <li>Text 2 - Level 2</li> 
    </ul>
</li>
<li>text 3 - Level 1</li>
<li>text 4 - Level 1</li>

我是临时写的,所以边缘情况下的错误检查可能需要一两次编辑。