Wie kann ich Zeichenfolgen auf einer Webseite dynamisch hervorheben?

Lesezeit: 9 Minuten

Ich möchte Seiten mit URLs erstellen wie:

http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver

Diese speziellen URLs würden alle den exakt gleichen Inhalt enthalten (die Seite „2015Aug24_Aug28“), würden aber alle Instanzen des Namens hervorheben, die bis zum Ende getaggt sind. Zum Beispiel, “http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones” würde jede Instanz des Namens “Billy Bones” hervorgehoben anzeigen, als ob auf der Seite über den Browser ein “Suchen” für diesen Namen ausgeführt worden wäre.

Ich stelle mir vor, dass auf Client-Seite so etwas erforderlich ist:

var employee = getLastURLPortion(); // return "Billy_Bones" (or whatever)
employee = humanifyTheName(employee); // replaces underscores with spaces, so that it's "Billy Bones" (etc.)
Highlight(employee); // this I have no clue how to do

Geht das in HTML/CSS oder wird dafür auch JavaScript oder jQuery benötigt?

  • Bier auch nicht, aber an einem heißen Tag ist es schrecklich gut.

    – B. Ton Shannon-B. Krähenrabe

    23. August 2015 um 13:00 Uhr

  • Verwenden Sie ein Textmarker-Plugin

    – charlietfl

    23. August 2015 um 13:04 Uhr

  • Ich denke, die eigentliche Frage ist, wie die Seiten gerendert werden, und können Sie etwas in der Vorlage dafür hinzufügen?

    – Kelly J. Andrews

    23. August 2015 um 13:13 Uhr

  • @Xufox, deshalb habe ich vorgeschlagen, ein Plugin zu verwenden, das bereits kampferprobt ist. Sobald sich jemand damit beschäftigt, stellt er fest, dass es keine triviale Übung ist, die HTML-Struktur beizubehalten und Ereignisse nicht zu stören

    – charlietfl

    23. August 2015 um 13:27 Uhr


  • Es sieht nicht so aus wie beim OP irgendein recherchieren Sie überhaupt, bevor Sie diese Frage stellen. OP scheint zu glauben, dass es möglich sein könnte, 3 spezifische Technologien zu verwenden, macht sich jedoch nicht die Mühe, jeweils eine grundlegende Suche durchzuführen (z. B. “Text mit Javascript hervorheben” oder “Text mit CSS hervorheben”). Sie sollten recherchieren, bevor Sie Ihre Frage stellen, Kinder!

    – Zimt

    23. August 2015 um 15:28 Uhr

Benutzer-Avatar
Sebastian Simon

Wenn Sie die Funktion aufrufen

highlight(employee);

So würde diese Funktion in ECMAScript 2018+ aussehen:

function highlight(employee){
  Array.from(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)"))
    .flatMap(({childNodes}) => [...childNodes])
    .filter(({nodeType, textContent}) => nodeType === document.TEXT_NODE && textContent.includes(employee))
    .forEach((textNode) => textNode.replaceWith(...textNode.textContent.split(employee).flatMap((part) => [
        document.createTextNode(part),
        Object.assign(document.createElement("mark"), {
          textContent: employee
        })
      ])
      .slice(0, -1))); // The above flatMap creates a [text, employeeName, text, employeeName, text, employeeName]-pattern. We need to remove the last superfluous employeeName.
}

Und dies ist eine ECMAScript 5.1-Version:

function highlight(employee){
  Array.prototype.slice.call(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)")) // First, get all regular elements under the `<body>` element
    .map(function(elem){
      return Array.prototype.slice.call(elem.childNodes); // Then extract their child nodes and convert them to an array.
    })
    .reduce(function(nodesA, nodesB){
      return nodesA.concat(nodesB); // Flatten each array into a single array
    })
    .filter(function(node){
      return node.nodeType === document.TEXT_NODE && node.textContent.indexOf(employee) > -1; // Filter only text nodes that contain the employee’s name.
    })
    .forEach(function(node){
      var nextNode = node.nextSibling, // Remember the next node if it exists
        parent = node.parentNode, // Remember the parent node
        content = node.textContent, // Remember the content
        newNodes = []; // Create empty array for new highlighted content

      node.parentNode.removeChild(node); // Remove it for now.
      content.split(employee).forEach(function(part, i, arr){ // Find each occurrence of the employee’s name
        newNodes.push(document.createTextNode(part)); // Create text nodes for everything around it

        if(i < arr.length - 1){
          newNodes.push(document.createElement("mark")); // Create mark element nodes for each occurrence of the employee’s name
          newNodes[newNodes.length - 1].innerHTML = employee;
          // newNodes[newNodes.length - 1].setAttribute("class", "highlighted");
        }
      });

      newNodes.forEach(function(n){ // Append or insert everything back into place
        if(nextNode){
          parent.insertBefore(n, nextNode);
        }
        else{
          parent.appendChild(n);
        }
      });
    });
}

Der Hauptvorteil des Ersetzens einzelner Textknoten besteht darin, dass Ereignis-Listener nicht verloren gehen. Die Website bleibt intakt, nur die Text Änderungen.

Anstatt der mark Element können Sie auch a verwenden span und kommentieren Sie die Zeile mit dem aus class -Attribut und geben Sie es in CSS an.

Dies ist ein Beispiel, in dem ich diese Funktion und eine nachfolgende verwendet habe highlight("Text"); auf der MDN-Seite für Text Knoten:

Eine Website, auf der alle Vorkommen von „Text“ hervorgehoben sind

(Das einzige Vorkommen, das nicht hervorgehoben ist, ist ein SVG-Knoten hinter einem <iframe>).

Benutzer-Avatar
László Kardinál

Ich habe die folgende Regex verwendet, um alle übereinstimmenden URLs zu ersetzen, um Anker mit hervorgehobenem Text zu erstellen:

(http://xyzcorp/schedules/(.*?)/)(.*?)( |<|\n|\r|$)

Visualisierung regulärer Ausdrücke

Debuggex-Demo

Der folgende Code ersetzt alle einfachen URLs. Wenn Sie sie nicht durch Links ersetzen müssen, markieren Sie sie einfach und entfernen Sie die Tags:

var str = "http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver ";

var highlighted = str.replace( new RegExp("(http://xyzcorp/schedules/(.*?)/)(.*?)( |<|\n|\r|$)","g"), "<a href="https://stackoverflow.com/questions/32166803/">$1<span style="background-color: #d0d0d0">$3</span></a>" );

Der Inhalt der hervorgehobenen Zeichenfolge ist:

<a href="http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins">http://xyzcorp/schedules/2015Aug24_Aug28/<span style="background-color: #d0d0d0">Jim_Hawkins</span></a>
<a href="http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones">http://xyzcorp/schedules/2015Aug24_Aug28/<span style="background-color: #d0d0d0">Billy_Bones</span></a>
<a href="http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver">http://xyzcorp/schedules/2015Aug24_Aug28/<span style="background-color: #d0d0d0">John_Silver</span></a>

AKTUALISIEREN:

Diese Funktion ersetzt die übereinstimmenden Namen aus dem Eingabetext:

function highlight_names( html_in )
{
    var name = location.href.split("https://stackoverflow.com/").pop().replace("_"," ");
    return html_in.replace( new RegExp( "("+name+")", "g"), "<span style="background-color: #d0d0d0">$1</span>" );
}

  • Beeindruckend, aber es sind nicht die URLs, die hervorgehoben werden sollten (sie erscheinen nur in der Adressleiste); Was hervorgehoben werden sollte, ist jedes Vorkommen von „Billy Bones“ auf der Seite (vorausgesetzt, die URL endet mit „\Billy_Bones“).

    – B. Ton Shannon-B. Krähenrabe

    23. August 2015 um 13:45 Uhr

Benutzer-Avatar
Manji

Eine Lösung wäre, nach dem Laden des Fensters alle Knoten rekursiv zu durchlaufen und Suchbegriffe in Textknoten mit einer Highlight-Klasse einzuschließen. Auf diese Weise bleiben die ursprüngliche Struktur und die Ereignisabonnements nicht erhalten.

(Hier mit jquery, aber es geht auch ohne):

Javascript:

$(function() {
  // get term from url
  var term = window.location.href.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
  // search regexp
  var re = new RegExp('(' + term + ')', 'gi');
  // recursive function
  function highlightTerm(elem) {
    var contents = $(elem).contents();
    if(contents.length > 0) {
      contents.each(function() {
        highlightTerm(this);
      });
    } else {
      // text nodes
      if(elem.nodeType === 3) {
        var $elem = $(elem);
        var text = $elem.text();
        if(re.test(text)) {
          $elem.wrap("<span/>").parent().html(text.replace(re, '<span class="highlight">$1</span>'));
        }
      }
    }
  }
  highlightTerm(document.body);
});

CSS:

.highlight {
    background-color: yellow;
}

$(function() {
  // get term from url
  //var term = window.location.href.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
  var term = 'http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones/'.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
  // search regexp
  var re = new RegExp('(' + term + ')', 'gi');
  // recursive function
  function highlightTerm(elem) {
    var contents = $(elem).contents();
    if(contents.length > 0) {
      contents.each(function() {
        highlightTerm(this);
      });
    } else {
      // text nodes
      if(elem.nodeType === 3) {
        var $elem = $(elem);
        var text = $elem.text();
        if(re.test(text)) {
          $elem.wrap("<span/>").parent().html(text.replace(re, '<span class="highlight">$1</span>'));
        }
      }
    }
  }
  highlightTerm(document.body);
});
.highlight  {
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <div>
      <div class="post-text" itemprop="text">
        <p>I want to create pages with urls such as:</p>
        <pre style="" class="default prettyprint prettyprinted">
          <code>
            <span class="pln">http</span>
            <span class="pun">:</span>
            <span class="com">//xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins</span>
            <span class="pln">
http</span>
            <span class="pun">:</span>
            <span class="com">//xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones</span>
            <span class="pln">
http</span>
            <span class="pun">:</span>
            <span class="com">//xyzcorp/schedules/2015Aug24_Aug28/John_Silver</span>
          </code>
        </pre>
        <p>These particular URLs would all contain the exact same content (the "2015Aug24_Aug28" page), but would highlight all instances of the name tagged on to the end. For example, "                    <code>http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones</code>

" would show every instance of the name "Billy Bones" highlighted, as if a "Find" for that name was executed on the page via the browser.</p>
        <p>I imagine something like this is required, client-side:</p>
        <pre style="" class="default prettyprint prettyprinted">
          <code>
            <span class="kwd">var</span>
            <span class="pln"> employee </span>
            <span class="pun">=</span>
            <span class="pln"> getLastURLPortion</span>
            <span class="pun">();</span>
            <span class="pln"></span>
            <span class="com">// return "Billy_Bones" (or whatever)</span>
            <span class="pln">
employee </span>
            <span class="pun">=</span>
            <span class="pln"> humanifyTheName</span>
            <span class="pun">(</span>
            <span class="pln">employee</span>
            <span class="pun">);</span>
            <span class="pln"></span>
            <span class="com">// replaces underscores with spaces, so that it's "Billy Bones" (etc.)</span>
            <span class="pln"></span>
            <span class="typ">Highlight</span>
            <span class="pun">(</span>
            <span class="pln">employee</span>
            <span class="pun">);</span>
            <span class="pln"></span>
            <span class="com">// this I have no clue how to do</span>
          </code>
        </pre>
        <p>Can this be done in HTML/CSS, or is JavaScript or jQuery also required for this?</p>
      </div>

Demo: http://plnkr.co/edit/rhfqzWThLTu9ccBb1Amy?p=preview

1006770cookie-checkWie kann ich Zeichenfolgen auf einer Webseite dynamisch hervorheben?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy