[Javascript] Highlight tekst in zoek op pagina

Pagina: 1
Acties:
  • 386 views sinds 30-01-2008
  • Reageer

  • RickDB
  • Registratie: Oktober 2001
  • Laatst online: 13-11 18:59
Wat ik eigenlijk zoek is als je een woord in een tekstbox intypt dat deze dan alles wat op erop lijkt(een deel of het hele woord bv)oplicht zonder de pagina te herladen.
In php heb ik er al veel hierover gevonden op dit forum, en ook op verschillende website's(dynamic drive,hotscripts etc..) vond ik wel wat er op leek maar het moet namelijk in asp gedaan worden en dan leek javascript het handigst.
Maar de meeste voor asp waren woord voor woord zoeken in plaats van alle woorden tegelijk met een kleur te "highlighten".

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 28-11 08:35

curry684

left part of the evil twins

Professionele website nodig?


  • RickDB
  • Registratie: Oktober 2001
  • Laatst online: 13-11 18:59
In het verkeerde subforum geplaatst |:(

[ Voor 13% gewijzigd door RickDB op 30-01-2004 13:03 ]


  • André
  • Registratie: Maart 2002
  • Laatst online: 27-11 10:04

André

Analytics dude

Je moet met javascript gewoon een search en replace doen in de document.body.innerHTML. Het kan netter door met de DOM te werken overigens.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

André schreef op 30 januari 2004 @ 13:03:
Je moet met javascript gewoon een search en replace doen in de document.body.innerHTML. Het kan netter door met de DOM te werken overigens.
persoonlijk zou ik met een functie door de DOM-tree heenlopen, en alleen textNodes selecteren en die door een regexp halen :)

Intentionally left blank


Verwijderd

Je zou ook met window.find() ed kunnen werken en dan alle afzonderlijke selecties kunnen opvangen en bewaren en daarna via range methodes de boel gaan kleuren. Is wel een heel gedoe.
document.body.innerHTML is wel ranzig, maar ook lekker makkelijk en snel (en meer cross-browser)

Verwijderd

Verwijderd schreef op 30 januari 2004 @ 13:15:
document.body.innerHTML is wel ranzig, maar ook lekker makkelijk en snel (en meer cross-browser)
Niet zo heel makkelijk, hoor, omdat je dan tags eruit moet gaan vissen, daarom is de methode van crisp toch beter.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

Verwijderd schreef op 30 januari 2004 @ 13:30:
[...]

Niet zo heel makkelijk, hoor, omdat je dan tags eruit moet gaan vissen, daarom is de methode van crisp toch beter.
Helaas zit er nog wel wat meer achter; je kan in een textNode niet zondermeer een span invoegen; je zult de textNode in stukken moeten opbreken en elementNodes moeten appenden...

Intentionally left blank


Verwijderd

crisp schreef op 30 januari 2004 @ 13:45:
Helaas zit er nog wel wat meer achter; je kan in een textNode niet zondermeer een span invoegen; je zult de textNode in stukken moeten opbreken en elementNodes moeten appenden...
True, maar als je van innerHTML :X gebruik maakt kun je dat omzeilen...
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Bevat alle textNodes in de pagina        
var _aSearchNodes = new Array();
//  --------------------------------
function SearchPage( ) {
//  --------------------------------

    // Vraag de zoekterm aan de gebruiker
    var sSearch = prompt('Zoekterm');
    
    if(sSearch) {
    
        // Begin ergens met zoeken
        var oStartNode = document.getElementById('Content');

        // Gooi de array leeg en vul 'm maar weer
        _aSearchNodes = new Array();
        CollectTextNodes(oStartNode );

        // Loop door alle textNodes heen
        for(var i=0; i<_aSearchNodes.length; i++) {
            var oNode =_aSearchNodes[i];
            var sText = oNode.nodeValue;
            if(sText.indexOf(sSearch)!=-1) {
                // Vervang de complete textNode met een span
                var oClone = document.createElement('SPAN');
                var r1 = new RegExp('('+sSearch+')','gi');
                var sText = sText.replace(r1, '<span style="background:#FF0;">'+sSearch+'</span>');
                
                // Hier ga ik cheaten :)
                oClone.innerHTML = sText;
                oNode.parentNode.replaceChild(oClone,oNode);
            }
        }
    }
}


// Loopt recursief door een nodeTree
// en bouwt _aSearchNodes op
//  --------------------------------
function CollectTextNodes( oStartNode ) {
//  --------------------------------
    var iLength = oStartNode.childNodes.length;
    for(var i=0; i<iLength; i++) {
        var oNode = oStartNode.childNodes[i];
        switch(oNode.nodeType) {
            case 1:
                CollectTextNodes(oNode);
                break;
            case 3:
                _aSearchNodes[_aSearchNodes.length] = oNode;
                break;
        }
    }
}

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

nice Blues :)
de replaceChild was ook waar ik aan zat te denken, maar dan in combinatie met splitText. Het mooist is om het replacen en het verzamelen van textNodes in 1 loop te combineren, eventueel met behulp van een stack ;)

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

even helemaal opnieuw :)
Hier mijn pruts0l:

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<html>
<head>
<title>highlight</title>
<script type="text/javascript">

function highlight() {

  var t = document.getElementById('highlight').value;
  if (t == '') return;
  t = t.replace(/([\\|^$()[\]{}.*+?])/g, '\\$1');
  var r, p = document.getElementById('case').checked? 'g':'gi';
  if (document.getElementById('literal').checked) {
    r = new RegExp(t, p);
  } else {
    if (/^\s*$/.test(t)) return;
    r = new RegExp(t.split(/\s+/).join('|'), p);
  }
  var h = document.createElement('SPAN');
  h.style.backgroundColor = '#ff0';
  var s = [document.documentElement||document.body], i = 0, e, j, l, o, k;

  do {

    e = s[i];

    if (e.nodeType == 3) {

      r.lastIndex = 0;
      l = r.exec(e.nodeValue);
      if (l != null) {
        k = l[0].length;
        if (r.lastIndex > k) {
          e.splitText(r.lastIndex-k);
          e = e.nextSibling;
        }
        if (e.nodeValue.length > k) {
          e.splitText(k);
          s[i++] = e.nextSibling;
        }
        o = h.cloneNode(true);
        o.appendChild(document.createTextNode(l[0]));
        e.parentNode.replaceChild(o, e);
      }

    } else {

      j = e.childNodes.length;
      while (j) s[i++] = e.childNodes.item(--j);

    }

  } while(i--);

}

</script>
</head>
<body>
Wat ik eigenlijk zoek is als je een woord in een tekstbox intypt dat
 deze dan alles wat op erop lijkt (een deel of het hele woord bv)
 oplicht zonder de pagina te herladen.<br />
In php heb ik er al veel hierover gevonden op dit forum, en ook op
 verschillende website's (dynamic drive,hotscripts etc..) vond ik wel
 wat er op leek maar het moet namelijk in asp gedaan worden en dan
 leek javascript het handigst.<br />
Maar de meeste voor asp waren woord voor woord zoeken in plaats van
 alle woorden tegelijk met een kleur te "highlighten".<br /><br />
<input type="text" id="highlight" />
<input type="checkbox" id="literal" /> letterlijk
<input type="checkbox" id="case" /> case-sensitive
<input type="button" value="highlight" onclick="highlight()" /><br />
Druk op F5 om highlighting te verwijderen
</body>
</html>


Probeer maar uit:


letterlijk case-sensitive
Druk op F5 om highlighting te verwijderen

:)

[ Voor 3% gewijzigd door crisp op 01-02-2004 01:03 ]

Intentionally left blank


Verwijderd

Te gek, crisp. Die splitText methode kende ik uberhaupt nog niet :o
Volgens mij schuilt hier trouwens een waanzinnig handige bookmarklet in!

[ Voor 44% gewijzigd door crisp op 01-02-2004 15:57 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

Verwijderd schreef op 01 februari 2004 @ 15:49:
Te gek, crisp. Die splitText methode kende ik uberhaupt nog niet :o
Volgens mij schuilt hier trouwens een waanzinnig handige bookmarklet in!
Ja, met een prompt ipv een invoerveld kan je er zo een bookmarklet van maken :)

offtopic:
mmz, edit bericht ipv quote met modrechten is niet handig...

Intentionally left blank


  • party42
  • Registratie: Oktober 2000
  • Laatst online: 01-12 13:32
cool scriptje hoor Crisp... Misschien een leuk idee voor een subforum. Scriptuitwisseling enzo... :)

[ Voor 58% gewijzigd door party42 op 01-02-2004 16:17 ]

Everyday's an endless stream, of cigarettes and magazines...


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

party42 schreef op 01 februari 2004 @ 16:17:
cool scriptje hoor Crisp... Misschien een leuk idee voor een subforum. Scriptuitwisseling enzo... :)
daar hebben we in principe http://www.codebase.nl voor, alleen gebeurd daar niet zo veel...

Intentionally left blank


Verwijderd

crisp schreef op 01 februari 2004 @ 15:58:
Ja, met een prompt ipv een invoerveld kan je er zo een bookmarklet van maken :)
Ik heb 'm nu en het is echt superhandig! Vooral als je door lange lappen tekst heenmoet, zoals W3C specs ofzo. Veel beter dan F3-en met de normale search.

  • RickDB
  • Registratie: Oktober 2001
  • Laatst online: 13-11 18:59
Bedankt allemaal voor de scripts _/-\o_

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

bookmarklet voorbeeld

Deze kan je zo toevoegen aan je favorieten :)

[ Voor 3% gewijzigd door crisp op 02-02-2004 11:45 ]

Intentionally left blank


  • RickDB
  • Registratie: Oktober 2001
  • Laatst online: 13-11 18:59
Hey nog 1 vraag is het ook mogelijk om zonder f5 de vorige highlighted items te wissen als er een nieuwe zoekopdracht gedaan word?
Is hoofdzakelijk voor de mindere gevorderde internet gebrukers die de f5 niet kunnen vinden of geen zin hebben om deze te gebruiken :P

  • André
  • Registratie: Maart 2002
  • Laatst online: 27-11 10:04

André

Analytics dude

Het kan wel, maar dat kost wel weer een lap code, je zult alle code tags die de tekst kleuren er weer uit moeten slopen.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

Rick164 schreef op 03 februari 2004 @ 16:18:
Hey nog 1 vraag is het ook mogelijk om zonder f5 de vorige highlighted items te wissen als er een nieuwe zoekopdracht gedaan word?
Is hoofdzakelijk voor de mindere gevorderde internet gebrukers die de f5 niet kunnen vinden of geen zin hebben om deze te gebruiken :P
In theorie wel; door de span-elementen weer te verwijderen, en de textNodes weer aan elkaar te plakken...

Intentionally left blank


Verwijderd

Voortbordurend op Crisp z'n script (die het 'zware' werk doet):
Ipv een span, maakt deze gebruik van het selectie object.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<html>
<head>
<title>highlight</title>
<script type="text/javascript">

function highlight() {
var sel=window.getSelection();
sel.removeAllRanges();
  var t = document.getElementById('highlight').value;
  if (t == '') return;
  t = t.replace(/([\\|^$()[\]{}.*+?])/g, '\\$1');
  var r, p = document.getElementById('case').checked? 'g':'gi';
  if (document.getElementById('literal').checked) {
    r = new RegExp(t, p);
  } else {
    if (/^\s*$/.test(t)) return;
    r = new RegExp(t.split(/\s+/).join('|'), p);
  }
  var s = [document.documentElement||document.body], i = 0, e, j, l, o, k;

  do {

    e = s[i];

    if (e.nodeType == 3) {

      r.lastIndex = 0;
      l = r.exec(e.nodeValue);
      if (l != null) {
        k = l[0].length;
        if (r.lastIndex > k) {
          e.splitText(r.lastIndex-k);
          e = e.nextSibling;
        }
        if (e.nodeValue.length > k) {
          e.splitText(k);
          s[i++] = e.nextSibling;
        }
        range=document.createRange();
                                range.selectNode(e);
                                sel.addRange(range);

      }

    } else {

      j = e.childNodes.length;
      while (j) s[i++] = e.childNodes.item(--j);

    }

  } while(i--);

}

</script>
<style>
::-moz-selection{
background-color:yellow;
}
</style>
</head>
<body>
Wat ik eigenlijk zoek is als je een woord in een tekstbox intypt dat
 deze dan alles wat op erop lijkt (een deel of het hele woord bv)
 oplicht zonder de pagina te herladen.<br />
In php heb ik er al veel hierover gevonden op dit forum, en ook op
 verschillende website's (dynamic drive,hotscripts etc..) vond ik wel
 wat er op leek maar het moet namelijk in asp gedaan worden en dan
 leek javascript het handigst.<br />
Maar de meeste voor asp waren woord voor woord zoeken in plaats van
 alle woorden tegelijk met een kleur te "highlighten".<br /><br />
<input type="text" id="highlight" value="zoek" />
<input type="checkbox" id="literal" /> letterlijk
<input type="checkbox" id="case" /> case-sensitive
<input type="button" value="highlight" onclick="highlight()" /><br />
Druk op F5 om highlighting te verwijderen
</body>
</html>

Deze werkt alleen in Mozilla, dus je zal er waarschijnlijk niet veel aan hebben.
Geen idee hoe dit in IE zou moeten.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

Hier een functie om de highlighting weer te verwijderen en de textNodes weer netjes samen te voegen; hiertoe geef ik de highlight span een custom attribuut genaamd highlight met een waarde '1':

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function remove_highlight() {

  var e = document.getElementsByTagName('SPAN'), i = e.length, t;
  while (i--) {

    if (e.item(i).getAttribute('highlight')) {

      t = '';
      if (e.item(i).previousSibling && e.item(i).previousSibling.nodeType == 3) {
        t += e.item(i).previousSibling.nodeValue;
        e.item(i).parentNode.removeChild(e.item(i).previousSibling);
      }
      t += e.item(i).childNodes.item(0).nodeValue;
      if (e.item(i).nextSibling && e.item(i).nextSibling.nodeType == 3) {
        t += e.item(i).nextSibling.nodeValue;
        e.item(i).parentNode.removeChild(e.item(i).nextSibling);
      }

      e.item(i).parentNode.replaceChild(document.createTextNode(t), e.item(i));

    }

  }

}

Intentionally left blank


  • RickDB
  • Registratie: Oktober 2001
  • Laatst online: 13-11 18:59
Bedankt ik ga em zo ff invoegen :)

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:27

crisp

Devver

Pixelated

Rick164 schreef op 04 februari 2004 @ 14:39:
Bedankt ik ga em zo ff invoegen :)
vergeet niet deze regel toe te voegen aan de highlight functie:
JavaScript:
1
h.setAttribute('highlight', '1');


;)

Intentionally left blank

Pagina: 1