代码之家  ›  专栏  ›  技术社区  ›  B''H Bi'ezras -- Boruch Hashem

javascript和css:突出显示具有相同背景的多个单词

  •  1
  • B''H Bi'ezras -- Boruch Hashem  · 技术社区  · 6 年前

    我正在尝试制作一个基本的web应用程序,人们可以在其中突出显示多个单词(即,单击第一个单词,然后进一步单击一个单词,所有内容都将突出显示,甚至在另一行)。

    到目前为止,我已经能够将所有单词包装在标记中,并为每个单词设置一个click事件监听器,从而将其类名更改为“highlight”,这只是 background-color:yellow 是的。

    问题是只突出显示单个单词的背景,但我希望两个(或更多,甚至在不同的行上)单词之间的所有内容都突出显示。

    更复杂一点的是,我在单词之间也有标点符号和其他东西,它们不被跨度标记包围,但我希望单词之间的所有内容都有不同的背景色/被选中。

    我只是想把所选的单词放在各自独立的span标记中,但是,我不确定如何使其动态变化,我还希望用户保存所选内容,然后用按钮或其他东西重新选择,这意味着一个单词可以放在两个不同的短语中,我不知道一个词怎么会在两个不同的跨度标记中…

    所以基本上:如何在javascript中选择多个单词,包括突出显示两个单词之间的所有内容?

    编辑 有人要求我尝试过的一些代码,所以我试图简化相关部分:

    var h= eid("HebrewS");
    var currentPhrase=[];
    var equal=false;
    var shtikles = [
    
    ];
    
    h.innerHTML = h.innerHTML.replace(/([\u0590-\u05FF\"\']+)/g,'<span class="shtikle""">$1</span>');
    
    var words = q("#HebrewS span");
    words.forEach(function(item, idx){
    
    
    shtikles[idx] = {obj:item, id:idx, heb:item.innerHTML, translation:"means "+ idx};
    item.addEventListener("click", function(e) {
    
    
    if(currentPhrase.length == 0) {
        currentPhrase.push(idx);
        currentPhrase[1]=idx;
        equal=true;
    }
    else {
        currentPhrase[1]=idx;
    
        if(currentPhrase[1] < currentPhrase[0]) {
            currentPhrase.reverse();
        }
        if(currentPhrase[0]==currentPhrase[1]) 
            if(!equal) {
                equal=true;
            } else {
                currentPhrase = new Array();
                equal=false;
            }
        else 
            equal=false;
    
        }
    
    selectPhrase(currentPhrase);
    
    });
    
    function selectPhrase(p) {
    
    for(var i =0;i<shtikles.length;i++) {
        if(shtikles[i].obj)
        if(p.length > 0) {
        if(i  < p[0] || i > p[1]) {
            if(shtikles[i].obj.className != "shtikle") {
    
                shtikles[i].obj.className ="shtikle";
            }
        }
        } else {
            shtikles[i].obj.className = "shtikle";
        }
    } 
    for(var i = p[0]; i <= p[1]; i++) {
        shtikles[i].obj.className="phrasePart";
    }
    }
    
    function q(a) {
    return document.querySelectorAll(a);
    
    }
    function eid(id) {
    return document.getElementById(id);
    
    }
    

    现在对于HTML:

    <div style="" id ="HebrewS">today I will show,.  you how] to read.. {Maamarim! וחזקת והיית לאיש1, הנה ידוע2 שהמאמר שאמר אדמו"ר (מהורש"ב) נ"ע ביום השביעי3 דחגיגת הבר מצוה של בנו יחידו כ"ק מו"ח אדמו"ר, י"ט תמוז4 תרנ"ג [שמאמר זה הוא סיום וחותם ההמשך תפילין דמארי עלמא5 שהתחיל לומר בי"ב תמוז, יום הבר מצוה] היתה התחלתו בפסוק זה. – השייכות דפסוק זה (וחזקת והיית לאיש) לבר מצוה בפשטות היא, ע"פ הידוע6 דזה שבן שלש עשרה (דוקא) מחוייב במצוות הוא כי אז דוקא נק' בשם איש. וצריך להבין, דמכיון שבן י"ג שנה נעשה איש (ע"פ טבע), מהי ההדגשה לומר (בחגיגת בר מצוה) וחזקת והיית לאיש. וגם צריך להבין, הרי המעלה דבן י"ג שנה היא שאז נעשה בר דעת7, דדעת הוא במוחין, ובפרט לפי המבואר בהמאמר ד"ה איתא במדרש תילים תרנ"ג [שהוא אחד המאמרים שחזר אותם כ"ק מו"ח אדמו"ר בחגיגת הבר  שלו]8 שהמעלה דבן י"ג שנה היא שאז יש לו עצם המוחין9, ומהו הדיוק בבן י"ג שנה בהתואר איש שמורה10 על המדות
    

    现在css:

    <style type="text/css">
    
    .shtikle:hover{
        background-color:yellow;
    }
    
    .phrasePart{
        background-color: purple;
        border: 0px solid black;
    }
    
    </style>
    

    我还没有测试代码的简化版本,但如果您尝试它应该可以工作。

    基本点是:它单独选择每个单词,但不突出单词之间的内容(我不想把当前短语中的所有单词都放到它们自己的范围中,因为我想保存这个短语并让它以后可以选择,而且对于多个短语,有些单词可能同时在这两个短语中)

    1 回复  |  直到 6 年前
        1
  •  0
  •   Maciej Kwas    6 年前

    将所有内容拆分为单个节点,然后使用范围。简单的实现可能如下所示。它可以在两次单击(右键单击删除选择)时工作,并准备好实现单击和滑动(您必须使用一些布尔标志实现mouseenter事件侦听器)。所以关键是,在选中每个节点的每个单击id之后,它要么成为范围的起点,要么使用for循环关闭范围,该循环为中间的每个节点添加类。

    然后,您可以将id范围存储在某个地方,并在单击按钮时激活它们。

    //编辑

    检查下面的编辑,这是完全混乱,但我相信它应该适合你的需要。

    const txt = 'this is some word in a wordy place where all words are kind of, well... this is some word in a wordy place where all words are kind of something so: this is some word in a wordy place where all words are kind of, and then -> this is some word in a wordy place where all words are kind of nothing';
    let startIndex = null;
    let lines = document.querySelector('.lines');
    lines.innerHTML = txt.split(' ').map((z, i) => {
    
      return (z.replace(new RegExp("\\w+|\\W+", "g"), (t) => { return /\w+/.test(t) ? `<span data-id="${i}" data-word>${t}</span>` : `<span data-id="${i}">${t}</span>` }));
    }).join(' ');
    nodes = Array.prototype.slice.call(document.querySelectorAll('.lines span'));
    nodes.forEach(z => {
    	if(z.hasAttribute('data-word')) {
        z.addEventListener('mousedown', (e) => {
      	const id = Number(e.target.getAttribute('data-id'));
      	if (startIndex === null) {
        	startIndex = id;
        	e.target.classList.add('active');
        } else {
        	const range = id > startIndex ? [startIndex, id] : [id, startIndex];
          for(let i = range[0]; i<= range[1]; i++) {
          	(Array.prototype.slice.call(document.querySelectorAll('span[data-id="' + i + '"]'))).forEach(e => e.classList.add('active'));
          };
          startIndex = null;
        }
      });
      }
    });
    
    window.oncontextmenu = function ()
    {
        startIndex = null;
        nodes.forEach(z => z.classList.remove('active'))
        return false;
    }
    .lines {
      user-select: none;
    }
    .lines span {
      display: inline-block;
      padding:3px;
      box-decoration-break: clone;
      transition:.2s;
    }
    .lines span.active { 
      background: salmon;
      box-shadow: 3px 0 0 salmon, -3px 0 0 salmon;
    }
    [data-word] {
      cursor:pointer;
    }
    <div class="lines"></div>