Toon posts:

[Javascript] .select() geeft probs met hidden elementen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Greetings,
Ik ben hier bezig aan een ontdekkingstocht doorheen Javascript maar stuiter op eens probleem welke ik maar niet kan oplossen.

Google en GoT search hebben me niet echt kunnen helpen maar dat kan waarschijnlijk komen omdat ik niet goed wist hoe het te formuleren..
Zoeken naar select() of createTextRange() +hidden div gaf helaas niet veel nuttige informatie op.

Het probleem is als volgt, ik heb een zoekfunctie gemaakt met wat hulp van het Internet. Deze zoekt perfect in men iFrame, althans in een iFrame waar alle divs worden weergegeven..

En volgens mij zijn er twee soorten oplossingen, ik weet enkel niet of die 2 beide mogelijk zijn en als ze al mogelijk zijn, hoe te realiseren.

Ik stek men zoek range als volgt in:
code:
1
2
    var win = content;
    var sZoekRange = win.document.body.createTextRange();


Een eerste oplossing zou zijn, om die range op een of andere manier duidelijk te maken dat ie NIET in hidden elementen mag gaan zoeken. (Niet enkel divs, maar ook p elementen)
Maar dat zie ik niet direct mogelijk..

De andere optie zou zijn is voor de select() hem zeggen waar ie niet mag selecteren. Ik dacht dan om alle elementen in het document te overlopen en zien of die document.style leeg is of niet, en als ie leeg is mag ie er niet in selecteren, anders wel.
Nu heb ik geen id hoe ik zon lus/array maak die in elk element de style.display gaat opzoeken.

Alvast bedankt

  • faabman
  • Registratie: Januari 2001
  • Laatst online: 08-08-2024
een loopje maken wat je
-> hele documentstructuur doorloopt
-> bij het vinden van een element.style.display != 'none'
-> op de innerText je zoekopdracht uitvoeren (eventueel via een regexp)

Op zoek naar een baan als Coldfusion webdeveloper? Mail me!


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

crisp

Devver

Pixelated

element.style.display geeft enkel iets terug op het moment dat de style ook inline opgegeven is; ik denk dat je eerder de computedStyle of currentStyle moet gaan opvragen. Al met al een lastig klusje, en zeker niet eenvoudig crossbrowser te krijgen (Opera kan je dan sowieso al vergeten).

Intentionally left blank


Verwijderd

Topicstarter
@faabman, die logica snap ik ook wel, ik snap enkel niet hoe ik het kan doen.

@crisp, het hoeft enkel IE minded te zijn, crossbrowser is voor veel later, IE is men belangrijkste doel atm, ik snap enkel niet hoe ik zoiets kan doorzoeken :s

Edit: Ik vrees dat dit nogal als een scriptrequestje lijkt :s
Als iemand me gewoon op weg kan helpen? Niet met de gedachtengang want die heb ik wel beet ;)

[ Voor 25% gewijzigd door Verwijderd op 03-05-2004 01:42 ]


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

crisp

Devver

Pixelated

Wat je volgens mij het beste kan doen is dmv de DOM methods door je elementen heenlopen. Elementen waarvan de currentStyle.display 'none' is of currentStyle.visibility 'hidden' is sla je daarbij over. textNodes binnen elementen die wel zichtbaar zijn doorzoek je op de zoekterm.
In feite deed het CA script van onze 1 April grap al iets soortgelijks, alleen hield die geen rekening met verborgen elementen. Dat was eigenlijk een kleine stack-based DOM parser ;)

Ergens hier in W&G zwerft wel een script rond dat woorden in een HTML-document highlight; dat lijkt me al een goede basis.

edit: [rml]crisp in "[ Javascript] Highlight tekst in zoek op ..."[/rml]

[ Voor 19% gewijzigd door crisp op 03-05-2004 05:44 ]

Intentionally left blank


Verwijderd

Topicstarter
Dank je crisp, ik ga er wat mee knutselen :)

Verwijderd

Topicstarter
Ik heb aan de hand die crisp gepost heeft toch wat verder kunnen raken.
Ik heb een manier gevonden om alle hidden divs over te slaan, ik krijg echter nog steeds dezelfde error:
code:
1
2
Line: 144
Error: Could not complete the operation due to eror 800a025e.


En dat is net bij de lijn van de .select();.
Ik dacht dus dat ik het opgelost had met die verborgen divs, maar blijkbaar is het nog net hetzelfde gebleven :s
Kan iemand me vertellen waardoor het nog foutloopt?

Dit is het scriptje:
code:
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
var aantalKeer = 0;

function zoekInPagina(sSearchString) {
    if (sSearchString == "") return false;

    //Hij moet zoeken in het iframe 'content'
    var win = content;

    //Een zoek range aanmaken, hij moet in dit geval zoeken in de iframe 'content'
    var sZoekRange = win.document.body.createTextRange();

    //Deze boolean komt op 'true' te staan als de text gevonden werd
    var boolGevonden;

    //De string kan meer dan eenmaal voorkomen in het document dus dit moet ook opgevonden worden
    for (var i=0; i<=aantalKeer; i++) {
        boolGevonden = sZoekRange.findText(sSearchString);
        if (boolGevonden != false) {
            //moveStart("unit", count);
            //Te kiezen uit deze unit's: character | word | sentence
            //Wij moeten per karakter zoeken dus moveStart("character", 1);
            sZoekRange.moveStart("character", 1);

            //moveEnd("word") verplaatst het eindpunt naar "word"
            //"textedit" zorgt ervoor dat dit verplaatst wordt naar het einde van de zoek range
            sZoekRange.moveEnd("textedit");
        }
    }

    //Als we de string gevonden hebben moeten we die selecteren en in zicht brengen
    if (boolGevonden) {

        //Enkel zoeken in een visible 'div'
        for(var i=0; i<win.document.getElementsByTagName("div").length; i++) {
            if(win.document.getElementsByTagName("div")[i].style.display == "") {
                //alert('NOT HIDDEN:: Div ' + i + ': ' + win.document.getElementsByTagName("div")[i].id);
                //In de non-hidden divs mogen we wel zoeken

                //We moeten de selectie beginnen van net voor de string
                sZoekRange.moveStart("character", -1);
                //Dan zoeken we de string (dus we gaan zoveel karakters verder)
                sZoekRange.findText(sSearchString);

                //En dan selecteren we de string
                sZoekRange.select();

                //Deze selectie kan ook helemaal onderin een lange pagina zijn, 
                //dus zorgen we ervoor dat onze selectie in beeld gebracht word
                sZoekRange.scrollIntoView();

            } else {
                //alert('HIDDEN:: Div ' + i + ': ' + win.document.getElementsByTagName("div")[i].id);
                //Hier mag niet gezocht worden aangezien dit niet weergegeven wordt
            }
        }

        //We vermeerderen aantalKeer omdat de string meer dan 1 keer kan voorkomen
        aantalKeer++;
    }
    //Als we de string niet meer vinden, opnieuw beginnen
    else {
        if (aantalKeer > 0) {
            aantalKeer = 0;
            zoekInPagina(sSearchString);
        }
        //Als we de string nergens vinden, berichtje geven
        else {
            alert("Uw zoekopdracht naar: " + sSearchString + " leverde helaas geen resultaten op.");
        }
    }

    //Op deze manieren returnen we de false naar het formulier, 
    // dit zorgt ervoor dat de pagina niet ververst wordt
    //Zo blijft ook de selectie geselecteerd
    return false;
}

[ Voor 6% gewijzigd door Verwijderd op 06-05-2004 18:17 ]


Verwijderd

Topicstarter
*bumpje*

Is er iemand de me hier soms mee verder kan helpen aub?
Heb het echt nodig.
Bij voorbaat dank!

Verwijderd

Topicstarter
Sorry om nogmaals te moeten bumpen..
Kan er me dan echt niemand helpen? :(

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

crisp

Devver

Pixelated

code:
1
if(win.document.getElementsByTagName("div")[i].style.display == "")

dit gaat niet altijd op; enkel namelijk wanneer de div inline een display property heeft. Bedenk daarbij dat je niet alleen divs kunt hiden, maar ook elk ander element, en dat het ook een parent kan zijn die niet zichtbaar is waardoor alle child-elementen ook niet zichtbaar zijn.
Naast display moet je ook rekening houden met visibility.
Kortom: op deze manier ga je er niet uitkomen; via de DOM alle nodes doorlopen en kijken naar de currentStyle is de enige optie die ik kan bedenken.

Intentionally left blank


Verwijderd

Topicstarter
Is het echt niet mogelijk om daar een stukje code van te laten zien want ik vat het echt niet :/

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

crisp

Devver

Pixelated

Verwijderd schreef op 10 mei 2004 @ 16:32:
Is het echt niet mogelijk om daar een stukje code van te laten zien want ik vat het echt niet :/
wil ik best doen, maar het ontbreekt me helaas aan tijd daarvoor :/

Intentionally left blank


Verwijderd

Verwijderd schreef op 10 mei 2004 @ 16:32:
Is het echt niet mogelijk om daar een stukje code van te laten zien want ik vat het echt niet :/
De bedoeling is dat je door alle nodes (tags) van het document heenloopt en ze één voor één checkt of ze zichtbaar zijn of niet. Dat kan bijvoorbeeld met currentStyle.display:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//  --------------------------------
function WalkBody( ) {
//  --------------------------------
    var oRoot = document.getElementsByTagName('body')[0];
    
    // Begin te lopen bij de body
    if(oRoot) TreeWalk(oRoot);
}

//  --------------------------------
function TreeWalk( oNode ) {
//  --------------------------------
    if(oNode.currentStyle) alert(oNode.nodeName + ' : ' + oNode.currentStyle.display);

    // Ga recursief z'n kinderen af
    for(var i=0; i<oNode.childNodes.length; i++) {
        oChild = oNode.childNodes[i];
        TreeWalk(oChild);
    }
}

Duidelijker?

Verwijderd

Topicstarter
Stukken duidelijker, maar ik heb dat in mijn zoekfunctie gewerkt en ik blijf dezelfde foutmelding krijgen..
Mijn loopje was volgens mij ook wel in orde, maar het moet iets anders zijn waar het foutloopt..
Ook al zeg ik enkel als die div visible is, select, toch doet ie nog iets niet goed :s
Ik heb het nu naar dit dus aangepast die ene if structuur:

Java:
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
//Als we de string gevonden hebben moeten we die selecteren en in zicht brengen
if (boolGevonden) {

   var oRoot = win.document.getElementsByTagName('body')[0];

   // Begin te lopen bij de body
   if(oRoot) TreeWalk(oRoot);

   function TreeWalk( oNode ) {
       if (oNode.currentStyle) {
            if ((oNode.nodeName == "DIV") && (oNode.currentStyle.display == "block")) {
                //alert(oNode.nodeName + ' ( ' + oNode.id  + ' ) : ' + oNode.currentStyle.display);

                //We moeten de selectie beginnen van net voor de string
                sZoekRange.moveStart("character", -1);
                //Dan zoeken we de string (dus we gaan zoveel karakters verder)
                sZoekRange.findText(sSearchString);

                //En dan selecteren we de string
                sZoekRange.select();

                //Deze selectie kan ook helemaal onderin een lange pagina zijn,
                //dus zorgen we ervoor dat onze selectie in beeld gebracht word
                sZoekRange.scrollIntoView();

            }
       }

       // Ga recursief z'n kinderen af
       for(var i=0; i<oNode.childNodes.length; i++) {
           oChild = oNode.childNodes[i];
           TreeWalk(oChild);
       }
    }

    //We vermeerderen aantalKeer omdat de string meer dan 1 keer kan voorkomen
    aantalKeer++;
}


Volgens mij zit ik ergens kei fout bezig, en niet ivm die functie om alles te doorlopen, want dat deed ie goed en doet ie nu ook wel goed.
Het ligt ergens anders, maar wat is het dan?

Verwijderd

Topicstarter
Iemand? :x

Verwijderd

Topicstarter
Laatste maal..

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

crisp

Devver

Pixelated

Ik heb hier nog even naar gekeken. Het grote nadeel van createTextRange is dat je het niet op een enkele textNode kan loslaten; als je een methode ontwikkeld die alle nodes doorloopt en overslaat als ze niet zichtbaar zijn (op basis van currentStyle), dan zal je dus ook zelf je highlighting moeten gaan verzorgen. Voordeel is dan wel dat het crossbrowser te maken is, maar het is wel een stuk complexer.

Dingen als moveStart(), findText() en select() zijn enkel uit te voeren op een textRange object, dus dat kan je gewoon vergeten. In mijn highlighter zet ik de gevonden tekst dynamisch in een span.

Intentionally left blank


Verwijderd

Topicstarter
Hartelijk bedankt dat je hier nog even op gereageerd hebt crisp.
Ik heb jou highlight script eerder al bekeken, maar dat gaat me echt iets te ver, zoiets begrijp ik nog niet helemaal :)
Is nu nog maar een aantal maanden dat ik via school echt aanraking heb met deze kant van javascript en dat gaat nog wat te ver :p

Het is iets heel nets wat je gebouwd hebt, die highlighter, maar helaas nog wat te gevorderd :p
Bedankt voor alle moeite zou ik zeggen, ik ga het gewoon zo indienen en mezelf vertegenwoordigen :)
Pagina: 1