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

时间:2018-04-18 20:01:57

标签: javascript jquery html ckeditor4.x

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

目前我想有一个很好的解决方案,只选择LEVEL 1元素并将所有包含的TEXT大写,而不触及子级HTML结构,然后在不触及LEVEL1的情况下将LEVEL 2大写。 我尝试了很多排除有许多指向组合的方法。 我们不能使用类和id。

似乎当我们使用函数进行大写时,我们从它回来的STRINGS(内容文本),当我们将它们插入到代码中时,会弄乱HTML结构。

当前目标:不要通过将它们全部连接并将它们移动到父元素来销毁嵌套结构。

当前进展:

  • 我们只能将LEVEL 1元素大写 - 但有副作用: 加入子级别并将它们添加到LEVEL 1父元素。
  • 我们只能将嵌套的LEVEL 2元素大写。
  • 我们可以将LEVEL 1和LEVEL 2元素同时大写 - 但是 副作用:加入子级别并将它们添加到LEVEL 1父级 元件。

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

现在似乎是重要问题的时刻: 是否需要更具体的方式来选择元素,更换文本的更好方法,还是需要采用完全不同且更复杂的方法?

我已经准备了一个包含当前版本代码和示例数据的测试环境 - 现在有两个函数用于显示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);
                                    });
                          }

 });

2 个答案:

答案 0 :(得分:1)

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

$("#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));
  });
});

基本上,只选择遵循body > ul > li层次结构的项目。

答案 1 :(得分:1)

我不知道我是否正确为您提供帮助,但您正在寻找对嵌套元素的一些控制权。这是一个没有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();})})
            }

要获得&#39;级别&#39;,这是一个返回包含该级别的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

现在,将第二级别的牌照变为大写:

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>

我写了这个adhoc&amp;在运行中,边缘情况下的错误检查可能需要编辑或两次。