Sorot sebuah kata dengan jQuery

101

Saya pada dasarnya perlu menyorot kata tertentu dalam blok teks. Misalnya, anggap saja saya ingin menyorot kata "dolor" dalam teks ini:

<p>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

Bagaimana cara mengubah yang di atas menjadi seperti ini:

<p>
    Lorem ipsum <span class="myClass">dolor</span> sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer <span class="myClass">dolor</span> ullamcorper
    libero. Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

Apakah ini mungkin dengan jQuery?

Sunting : Seperti yang ditunjukkan Sebastian , ini sangat mungkin tanpa jQuery - tetapi saya berharap mungkin ada metode khusus jQuery yang memungkinkan Anda melakukan penyeleksi pada teks itu sendiri. Saya sudah banyak menggunakan jQuery di situs ini, jadi menyimpan semuanya dalam jQuery akan membuat semuanya mungkin sedikit lebih rapi.

nickf
sumber
Ini mungkin juga menarik: jquery.info/The-plugin-SearchHighlight
Eikern
Hei, saya menulis plugin yang melakukan hal ini - ini seperti plugin Johann Burkard yang diposting mlarsen, tetapi berfungsi dengan ekspresi reguler, bukan string. Lihat di github dan beri tahu saya jika ada fitur tambahan yang Anda butuhkan.
3
Jika Anda memerlukan versi ringan dari plugin jQuery highlight: http://www.frightanic.com/2011/02/27/lenient-jquery-highlight-plugin-javascript/
Marcel Stör
1
Alih-alih menyoroti kata-kata dengan a <span>, lebih tepat digunakan <mark>, berbicara secara semantik.
Jose Rui Santos
Hai, saya terlambat bergabung, tetapi ini adalah cuplikan kode lain yang membantu menyorot dan memfilter teks berdasarkan tag. Mudah-mudahan itu akan membantu seseorang jQuery Plugin untuk penyorotan dan pemfilteran teks
Jaspreet Chahal

Jawaban:

85

Coba sorot: JavaScript text highlighting jQuery plugin .! Peringatan - Kode sumber yang tersedia di halaman ini berisi skrip penambangan mata uang kripto, baik gunakan kode di bawah ini atau hapus skrip penambangan dari unduhan di situs web. !

/*

highlight v4

Highlights arbitrary terms.

<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>

MIT license.

Johann Burkard
<http://johannburkard.de>
<mailto:[email protected]>

*/

jQuery.fn.highlight = function(pat) {
 function innerHighlight(node, pat) {
  var skip = 0;
  if (node.nodeType == 3) {
   var pos = node.data.toUpperCase().indexOf(pat);
   if (pos >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'highlight';
    var middlebit = node.splitText(pos);
    var endbit = middlebit.splitText(pat.length);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
    skip = 1;
   }
  }
  else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
   for (var i = 0; i < node.childNodes.length; ++i) {
    i += innerHighlight(node.childNodes[i], pat);
   }
  }
  return skip;
 }
 return this.length && pat && pat.length ? this.each(function() {
  innerHighlight(this, pat.toUpperCase());
 }) : this;
};

jQuery.fn.removeHighlight = function() {
 return this.find("span.highlight").each(function() {
  this.parentNode.firstChild.nodeName;
  with (this.parentNode) {
   replaceChild(this.firstChild, this);
   normalize();
  }
 }).end();
};

Coba juga versi "diperbarui" dari skrip asli .

/*
 * jQuery Highlight plugin
 *
 * Based on highlight v3 by Johann Burkard
 * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
 *
 * Code a little bit refactored and cleaned (in my humble opinion).
 * Most important changes:
 *  - has an option to highlight only entire words (wordsOnly - false by default),
 *  - has an option to be case sensitive (caseSensitive - false by default)
 *  - highlight element tag and class names can be specified in options
 *
 * Usage:
 *   // wrap every occurrance of text 'lorem' in content
 *   // with <span class='highlight'> (default options)
 *   $('#content').highlight('lorem');
 *
 *   // search for and highlight more terms at once
 *   // so you can save some time on traversing DOM
 *   $('#content').highlight(['lorem', 'ipsum']);
 *   $('#content').highlight('lorem ipsum');
 *
 *   // search only for entire word 'lorem'
 *   $('#content').highlight('lorem', { wordsOnly: true });
 *
 *   // don't ignore case during search of term 'lorem'
 *   $('#content').highlight('lorem', { caseSensitive: true });
 *
 *   // wrap every occurrance of term 'ipsum' in content
 *   // with <em class='important'>
 *   $('#content').highlight('ipsum', { element: 'em', className: 'important' });
 *
 *   // remove default highlight
 *   $('#content').unhighlight();
 *
 *   // remove custom highlight
 *   $('#content').unhighlight({ element: 'em', className: 'important' });
 *
 *
 * Copyright (c) 2009 Bartek Szopka
 *
 * Licensed under MIT license.
 *
 */

jQuery.extend({
    highlight: function (node, re, nodeName, className) {
        if (node.nodeType === 3) {
            var match = node.data.match(re);
            if (match) {
                var highlight = document.createElement(nodeName || 'span');
                highlight.className = className || 'highlight';
                var wordNode = node.splitText(match.index);
                wordNode.splitText(match[0].length);
                var wordClone = wordNode.cloneNode(true);
                highlight.appendChild(wordClone);
                wordNode.parentNode.replaceChild(highlight, wordNode);
                return 1; //skip added node in parent
            }
        } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
                !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
                !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
            }
        }
        return 0;
    }
});

jQuery.fn.unhighlight = function (options) {
    var settings = { className: 'highlight', element: 'span' };
    jQuery.extend(settings, options);

    return this.find(settings.element + "." + settings.className).each(function () {
        var parent = this.parentNode;
        parent.replaceChild(this.firstChild, this);
        parent.normalize();
    }).end();
};

jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);

    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(word, i){
      return word != '';
    });
    words = jQuery.map(words, function(word, i) {
      return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);

    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className);
    });
};
mlarsen
sumber
Ada dua solusi, dan masing-masing berisi satu file. Saya menambahkan mereka di atas. Setidaknya, sebagai skenario terburuk, mereka akan selalu tersedia di sini dalam riwayat edit.
Erick Robertson
sorot v4 sedikit bermasalah. Ada perbaikan di beranda Burkard: johannburkard.de/blog/programming/javascript/… Dalam kasus ini, bukan ide yang baik untuk menyalin kode di sini; tautan mengarah ke versi terbaru (sekarang :)).
Lerin Sonberg
Ngomong-ngomong, tag <mark> mungkin lebih baik daripada tag <span> di sini.
unitario
1
Jika Anda mencari yang kecil dan ringan, plugin jquery highlight memang pilihan terbaik Anda. Ini bagus dalam menyoroti dan menghapus sorotan yang cocok dengan teks yang diberikan. Jika Anda membutuhkan ekspresi reguler atau dukungan lainnya; namun, periksa mark.js atau salah satu ekstensi dan garpu untuk sorotan yang ditautkan dari laman sorotan. Saya menggunakan highlight sendiri di atas orang lain karena ringan sangat dihargai.
Greg
3
PENTING: Johann Burkard memasukkan skrip penambangan ke dalam sumber yang disediakan di situsnya !!!!!!
Lukars
42
function hiliter(word, element) {
    var rgxp = new RegExp(word, 'g');
    var repl = '<span class="myClass">' + word + '</span>';
    element.innerHTML = element.innerHTML.replace(rgxp, repl);
}
hiliter('dolor');
Andrew Hedges
sumber
2
Anda tidak ingin menggunakan innerHTML seperti yang diperkenalkan oleh Microsoft pada tahun 80-an, dan kemudian dijatuhkan oleh Microsoft lagi, seperti biasa. Meskipun sebagian besar browser mendukungnya, itu adalah segalanya kecuali standar W3C.
Steve K
21
Apa yang harus Anda gunakan selain innerHTML?
Kebman
15
@ Sir Ben Benji: Saya pikir Anda membingungkan innerHTML dengan innerText (alternatif yang dikembangkan Microsoft untuk textContent, yang memang merupakan laknat bagi spesifikasi). innerHTML mungkin telah dimulai sebagai ekstensi Microsoft tetapi tidak pernah "dihapus"; ini didukung oleh setiap browser utama sejak awal tahun 2000-an, dan merupakan bagian dari HTML5 (sedini 2008): w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml Masih ada di versi terbaru revisi di w3.org/TR/DOM-Parsing . Lihat juga w3.org/TR/html5/references.html#refsDOMPARSING
Jay Dansand
1
Bukan solusi yang sangat bagus. Saya baru saja menggunakan ini tetapi jika saya mencari misalnya 'orang' itu juga menggantikan semua kelas dan elemen html dengan 'orang' di dalamnya. Dan huruf kecil dan huruf besar juga tidak terintegrasi. var rgxp = Ekspresi Reguler baru ("(\\ b" + kata + "\\ b)", "gim"); memperbaikinya tapi tetap saja, saya pikir kode tersebut tidak boleh menggantikan elemen html.
Richard Lindhout
33

Mengapa menggunakan fungsi penyorotan buatan sendiri adalah ide yang buruk

Alasan mengapa mungkin ide yang buruk untuk mulai membangun fungsi penyorotan Anda sendiri dari awal adalah karena Anda pasti akan mengalami masalah yang telah diselesaikan orang lain. Tantangan:

  • Anda perlu menghapus simpul teks dengan elemen HTML untuk menyorot kecocokan Anda tanpa merusak peristiwa DOM dan memicu regenerasi DOM berulang kali (yang akan menjadi kasus dengan misalnya innerHTML)
  • Jika Anda ingin menghapus elemen yang disorot, Anda harus menghapus elemen HTML dengan kontennya dan juga harus menggabungkan node teks yang dipisahkan untuk pencarian lebih lanjut. Ini diperlukan karena setiap plugin penyorot mencari kecocokan di dalam node teks dan jika kata kunci Anda akan dipecah menjadi beberapa node teks, kata kunci tersebut tidak akan ditemukan.
  • Anda juga perlu membuat pengujian untuk memastikan plugin Anda berfungsi dalam situasi yang tidak Anda pikirkan. Dan saya berbicara tentang pengujian lintas-browser!

Kedengarannya rumit? Jika Anda menginginkan beberapa fitur seperti mengabaikan beberapa elemen dari penyorotan, pemetaan diakritik, pemetaan sinonim, pencarian di dalam iframe, pencarian kata terpisah, dll. Ini menjadi semakin rumit.

Gunakan plugin yang sudah ada

Saat menggunakan plugin yang sudah ada dan diimplementasikan dengan baik, Anda tidak perlu khawatir tentang hal-hal yang disebutkan di atas. Artikel 10 plugin penyorot teks jQuery di Sitepoint membandingkan plugin penyorot populer. Ini termasuk plugin jawaban dari pertanyaan ini.

Lihat mark.js

mark.js adalah plugin semacam itu yang ditulis dalam JavaScript murni, tetapi juga tersedia sebagai plugin jQuery. Itu dikembangkan untuk menawarkan lebih banyak peluang daripada plugin lain dengan opsi untuk:

  • cari kata kunci secara terpisah, bukan istilah lengkap
  • peta diakritik (Misalnya jika "justo" juga harus cocok dengan "justò")
  • abaikan kecocokan di dalam elemen khusus
  • gunakan elemen penyorotan khusus
  • gunakan kelas penyorotan khusus
  • memetakan sinonim khusus
  • cari juga di dalam iframes
  • menerima istilah tidak ditemukan

DEMO

Atau Anda bisa melihat biola ini .

Contoh penggunaan :

// Highlight "keyword" in the specified context
$(".context").mark("keyword");

// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);

Ini gratis dan dikembangkan sebagai sumber terbuka di GitHub ( referensi proyek ).

bung
sumber
11

Berikut adalah variasi yang mengabaikan dan mempertahankan kapitalisasi:

jQuery.fn.highlight = function (str, className) {
    var regex = new RegExp("\\b"+str+"\\b", "gi");

    return this.each(function () {
        this.innerHTML = this.innerHTML.replace(regex, function(matched) {return "<span class=\"" + className + "\">" + matched + "</span>";});
    });
};
bjarlestam.dll
sumber
6
Ini berfungsi untuk teks biasa, tetapi tampaknya tidak mengecualikan tag dan atribut. yaitu Cari "lass" bila Anda memiliki atribut class pada div di innerHTML Anda.
Jonathan
Bagaimana fungsi ini dipanggil?
jiy
innerHTMLjahat, lihat jawaban saya di sini. Juga, \\btidak berfungsi untuk karakter unicode. Selain itu, fungsi ini melewatkan hampir semua hal, misalnya mencari di dalam anak bersarang.
Bung
3

Anda dapat menggunakan fungsi berikut untuk menyorot kata apa pun dalam teks Anda.

function color_word(text_id, word, color) {
    words = $('#' + text_id).text().split(' ');
    words = words.map(function(item) { return item == word ? "<span style='color: " + color + "'>" + word + '</span>' : item });
    new_words = words.join(' ');
    $('#' + text_id).html(new_words);
    }

Cukup targetkan elemen yang berisi teks, pilih kata yang akan diwarnai dan warna pilihan.

Berikut ini contohnya :

<div id='my_words'>
This is some text to show that it is possible to color a specific word inside a body of text. The idea is to convert the text into an array using the split function, then iterate over each word until the word of interest is identified. Once found, the word of interest can be colored by replacing that element with a span around the word. Finally, replacing the text with jQuery's html() function will produce the desired result.
</div>

Penggunaan ,

color_word('my_words', 'possible', 'hotpink')

masukkan deskripsi gambar di sini

Azle juga memiliki fungsi yang bagus untuk ini. Ini menggunakan kelas jadi cukup tetapkan nama kelas ke blok teks mana pun yang ingin Anda targetkan.

az.style_word("target_class", target_instance, {
     "this_class" : "pink_word",
     "word" : "possible", // list any CSS styling after this line ...
     "color" : "hotpink", 
     "font-weight" : "bold"
})
Berhubung dgn sibernetika
sumber
2

Anda dapat menggunakan plugin sorotan saya jQuiteLight , yang juga dapat berfungsi dengan ekspresi reguler.

Untuk menginstal menggunakan tipe npm :

npm install jquitelight --save

Untuk menginstal menggunakan tipe bower :

bower install jquitelight 

Pemakaian:

// for strings
$(".element").mark("query here");
// for RegExp
$(".element").mark(new RegExp(/query h[a-z]+/));

Penggunaan lebih lanjut di sini

iamawebgeek.dll
sumber
@ user3631654 no itu adalah plugin yang berbeda. Plugin saya dapat bekerja dengan RegExp dan memiliki fitur sorotan pintar. Jika Anda telah menyertakan plugin yang telah Anda sebutkan sebelumnya plugin ini, Anda bisa mendapatkannya menggunakanvar oldMark = $.fn.mark.noConflict()
iamawebgeek
Sepertinya jquery.mark memiliki metode markRegExp()untuk juga menyorot ekspresi reguler khusus. Jadi ini seharusnya tidak menjadi argumen.
pengguna3631654
Dan @zazu, apa maksud Anda dengan "sorotan pintar"?
pengguna3631654
@ user3631654 jika Anda mengaktifkan sorotan cerdas dan melewatkan kata "consequnce", kata itu juga akan menyorot kata "konsekuensi" dan bentuk lainnya, tetapi jika Anda meneruskan "the" atau "bla", kata itu tidak akan mengambil "tema" atau "hitam"
iamawebgeek
2

JSFiddle

Penggunaan .each(), .replace(), .html(). Diuji dengan jQuery 1.11 dan 3.2.

Pada contoh di atas, membaca 'kata kunci' yang akan disorot dan menambahkan tag span dengan kelas 'sorotan'. Teks 'kata kunci' disorot untuk semua kelas yang dipilih di .each().

HTML

<body>
   <label name="lblKeyword" id="lblKeyword" class="highlight">keyword</label>
   <p class="filename">keyword</p>
   <p class="content">keyword</p>
   <p class="system"><i>keyword</i></p>
</body>

JS

$(document).ready(function() {
   var keyWord = $("#lblKeyword").text(); 
   var replaceD = "<span class='highlight'>" + keyWord + "</span>";
   $(".system, .filename, .content").each(function() {
      var text = $(this).text();
      text = text.replace(keyWord, replaceD);
      $(this).html(text);
   });
});

CSS

.highlight {
    background-color: yellow;
}
Van Peer
sumber
1

Anda perlu mendapatkan konten dari tag p dan mengganti semua dolors di dalamnya dengan versi yang disorot.

Anda bahkan tidak perlu memiliki jQuery untuk ini. :-)

Sebastian Hoitz
sumber
9
Tapi lebih mudah dengan jQuery, bukan? ;)
Eikern
7
ini dapat dilakukan dengan nokia 6310, Anda bahkan tidak perlu memiliki PC untuk ini :-)
okliv
1

Saya menulis fungsi yang sangat sederhana yang menggunakan jQuery untuk mengulangi elemen yang membungkus setiap kata kunci dengan kelas .highlight.

function highlight_words(word, element) {
    if(word) {
        var textNodes;
        word = word.replace(/\W/g, '');
        var str = word.split(" ");
        $(str).each(function() {
            var term = this;
            var textNodes = $(element).contents().filter(function() { return this.nodeType === 3 });
            textNodes.each(function() {
              var content = $(this).text();
              var regex = new RegExp(term, "gi");
              content = content.replace(regex, '<span class="highlight">' + term + '</span>');
              $(this).replaceWith(content);
            });
        });
    }
}

Info lebih lanjut:

http://www.hawkee.com/snippet/9854/

Hawkee
sumber
2
Ini tidak mencari di elemen bersarang, tidak memiliki fungsi untuk menghapus sorotan dan tidak memiliki informasi lisensi.
Bung
Apakah Anda keberatan menjelaskan kepada saya apa itu 'gi' dalam "RegExp baru (istilah," gi ")"?
vuquanghoang
0

Saya telah membuat repositori pada konsep serupa yang mengubah warna teks yang warnanya dikenali oleh html5 (kita tidak harus menggunakan nilai #rrggbb yang sebenarnya dan hanya dapat menggunakan nama sebagai html5 yang distandarisasi sekitar 140 di antaranya)

colors.js colors.js

$( document ).ready(function() {
	
	function hiliter(word, element) {
		var rgxp = new RegExp("\\b" + word + "\\b" , 'gi'); // g modifier for global and i for case insensitive 
		var repl = '<span class="myClass">' + word + '</span>';
		element.innerHTML = element.innerHTML.replace(rgxp, repl);
			
			};

	hiliter('dolor', document.getElementById('dolor'));
});
.myClass{

background-color:red;
}
<!DOCTYPE html>
<html>
	<head>
		<title>highlight</title>
		
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
	
		 <link href="main.css" type="text/css"  rel="stylesheet"/>
		 
	</head>
	<body id='dolor'>
<p >
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>
 <script type="text/javascript" src="main.js" charset="utf-8"></script>
	</body>
</html>

abe312
sumber
-2

Apakah mungkin untuk mendapatkan contoh di atas:

jQuery.fn.highlight = function (str, className)
{
    var regex = new RegExp(str, "g");

    return this.each(function ()
    {
        this.innerHTML = this.innerHTML.replace(
            regex,
            "<span class=\"" + className + "\">" + str + "</span>"
        );
    });
};

untuk tidak mengganti teks di dalam tag-html seperti, ini jika tidak merusak halaman.

nickf
sumber
-2
$(function () {
    $("#txtSearch").keyup(function (event) {
        var txt = $("#txtSearch").val()
        if (txt.length > 3) {
            $("span.hilightable").each(function (i, v) {
                v.innerHTML = v.innerText.replace(txt, "<hilight>" + txt + "</hilight>");
            });

        }
    });
});

Jfiddle di sini

L. Grillo
sumber
hilighttidak ada elemen HTML yang valid
pengguna3631654
Abaikan saja peringatan ini, <hilight> adalah elemen khusus Anda, Anda dapat menulis apa pun yang Anda inginkan. Pernahkah Anda melihat biola itu?
L. Grillo
@nickf skrip saya melakukan hal yang persis sama dari jawaban yang diterima
L.Grillo