[javascript / AJAX] Content toevoegen aan een div

Pagina: 1
Acties:

  • posttoast
  • Registratie: April 2000
  • Laatst online: 11:36
Ik heb hier een div ("talen") met daarin een selectbox waarmee de gebruiker een taal kan selecteren. Wanneer er een taal gekozen is moet eronder automagisch een nieuwe selectbox verschijnen om nóg een taal te kunnen kiezen. Ik heb twee problemen:
  1. In Firefox wordt de gekozen optie van de eerste selectbox "geleegd", in IE blijft hij wel staan
  2. Ik wil dat er alleen een selectbox wordt toegevoegd als de onderste niet leeg is. Ik wil dus nooit meerdere lege boxen onder elkaar hebben.
Ik ben tot nu toe aan het werk gegaan met innerHTML. Ik weet dat het chiquer is om netjes via DOM te werken, maar dat krijg ik niet goed voor elkaar (de HTML code wordt op het scherm getoond en niet door de browser gerenderd).

De code:

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
<div id="talen">
    <select name="talen_1" id="talen_1" class="sle_small" onchange="getMoreOptions('talen','1');">
        <option></option>
<?
$getItems = mssql_query("SELECT * FROM talen") or die (mysql_error());
while ($item = mssql_fetch_array($getItems)){
?>
        <option><?= $item['taal']; ?></option>
<?
}
?>
    </select>
    <select name="talenlevel_1" id="talenlevel_1" class="sle_small">
        <option></option>
<?
$getItems = mssql_query("SELECT * FROM taallevels") or die (mysql_error());
while ($item = mssql_fetch_array($getItems)){
?>
        <option><?= $item['level']; ?></option>
<?
}
?>
    </select><br /><br />
</div>


Het javascript:
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
function createRequestObject() {
    var ro;
    var browser = navigator.appName;
    if(browser == "Microsoft Internet Explorer"){
        ro = new ActiveXObject("Microsoft.XMLHTTP");
    }else{
        ro = new XMLHttpRequest();
    }
    return ro;
}

var http = createRequestObject();

function getMoreOptions(soort,nr) {
    http.open('get', 'scripts/getMoreOptions.php?soort='+soort+'&nr='+nr);
    http.onreadystatechange = createFunc(soort);
    http.send(null);
}

function createFunc(v) {
    return function() {
        if(http.readyState == 4){
            var response = http.responseText;
            var div = document.getElementById(v);
            div.innerHTML += http.responseText; 
        }
    }
}


getMoreOptions.php spuugt een stuk HTML uit wat eronder geplaatst moet worden, ik denk dat jullie dat wel snappen :)

Wie kan mij verder op weg helpen? Ik wil graag leren dit op een betere manier aan te pakken, maar ik zit nu een beetje vast...

omniscale.nl


  • RM-rf
  • Registratie: September 2000
  • Laatst online: 15:22

RM-rf

1 2 3 4 5 7 6 8 9

posttoast schreef op maandag 22 januari 2007 @ 17:42:

Ik ben tot nu toe aan het werk gegaan met innerHTML. Ik weet dat het chiquer is om netjes via DOM te werken, maar dat krijg ik niet goed voor elkaar (de HTML code wordt op het scherm getoond en niet door de browser gerenderd).
ik vermoed dat dat net direkt ook je probleem is, als je volledig correct met gerenderde nodes wilt omgaan en onwenselijke effecten wilt vermijden, moet je ook op een node-wijze ermee omgaan en dat betekent dat je erg beperkt bent in het omgaan met 'string'-html als innerHTML

met innerHTML kun je wel gewoon een platte string als te redneren HTML aanvullen, maar feitelijk laat je dan de hele html binnen die node herrenderen als een platte string ...

volgens mij is de beste oplossing als je 'platte' HTML als string wilt toevoegen, dat je dan een nieuwe node aanmaakt, bv een DIV en in deze DIV vervolgens de toe te voegen innerHTML plaatst:

code:
1
2
3
var newelm = document.createElement("div")
newelm.innerHTML = je-nieuwe-toe-te-voegen-htmlstukje
node.appendChild( newelm )

Intelligente mensen zoeken in tijden van crisis naar oplossingen, Idioten zoeken dan schuldigen


  • posttoast
  • Registratie: April 2000
  • Laatst online: 11:36
RM-rf schreef op maandag 22 januari 2007 @ 17:50:
[...]


ik vermoed dat dat net direkt ook je probleem is, als je volledig correct met gerenderde nodes wilt omgaan en onwenselijke effecten wilt vermijden, moet je ook op een node-wijze ermee omgaan en dat betekent dat je erg beperkt bent in het omgaan met 'string'-html als innerHTML

met innerHTML kun je wel gewoon een platte string als te redneren HTML aanvullen, maar feitelijk laat je dan de hele html binnen die node herrenderen als een platte string ...

volgens mij is de beste oplossing als je 'platte' HTML als string wilt toevoegen, dat je dan een nieuwe node aanmaakt, bv een DIV en in deze DIV vervolgens de toe te voegen innerHTML plaatst:

code:
1
2
3
var newelm = document.createElement("div")
newelm.innerHTML = je-nieuwe-toe-te-voegen-htmlstukje
node.appendChild( newelm )
Bedankt voor je snelle antwoord. Maar ik denk dat ik toch nog een zetje nodig heb (*schaam*)...

Dit werkt niet:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
function createFunc(v) {
    return function() {
        if(http.readyState == 4){
            var response = http.responseText;
            var div = document.getElementById(v);
            
            var newelm = document.createElement("div")
            newelm.innerHTML = http.responseText;
            node.appendChild(newelm)
        }
    }
}


Logisch natuurlijk, maar ik snap niet hoe ik het wél kan laten werken. Het hele DOM-verhaal is voor mij nog een beetje abracadabra...

omniscale.nl


  • StevenK
  • Registratie: Februari 2001
  • Nu online
posttoast schreef op maandag 22 januari 2007 @ 17:42:
JavaScript:
1
            div.innerHTML += http.responseText; 


getMoreOptions.php spuugt een stuk HTML uit wat eronder geplaatst moet worden, ik denk dat jullie dat wel snappen :)

Wie kan mij verder op weg helpen? Ik wil graag leren dit op een betere manier aan te pakken, maar ik zit nu een beetje vast...
Volgens mij is 't probleem dat datgene wat je toevoegt direct gerenderd wordt. Wat in mijn ervaring beter werkt is iets van
JavaScript:
1
2
3
var mycontent=div.innerHTML;
mycontent+=http.responseText;
div.innerHTML=mycontent;

Was advocaat maar vindt het juridische nog steeds leuk


  • posttoast
  • Registratie: April 2000
  • Laatst online: 11:36
StevenK schreef op maandag 22 januari 2007 @ 19:21:
[...]

Volgens mij is 't probleem dat datgene wat je toevoegt direct gerenderd wordt. Wat in mijn ervaring beter werkt is iets van
JavaScript:
1
2
3
var mycontent=div.innerHTML;
mycontent+=http.responseText;
div.innerHTML=mycontent;
Volgens mij neemt hij hier niet alsnog de huidige selectie mee in Firefox. Het probleem is dat wanneer de innerhtml opnieuw wordt opgebouwd hij dit gewoon reset.

Daarom denk ik dat de oplossing van RM-rf perfect is (je wijzigt niet, maar voegt slechts toe). Alleen weet ik niet hoe ik hem moet implementeren ;)

omniscale.nl


  • RM-rf
  • Registratie: September 2000
  • Laatst online: 15:22

RM-rf

1 2 3 4 5 7 6 8 9

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
function createFunc(v) {
    return function() {
        if(http.readyState == 4){
            var response = http.responseText;
            var myDiv = document.getElementById(v);
            
            var newelm = document.createElement("div")
            newelm.innerHTML = http.responseText;
            myDiv.appendChild(newelm)
        }
    }
}

zou beter moeten werken :)

Intelligente mensen zoeken in tijden van crisis naar oplossingen, Idioten zoeken dan schuldigen


  • posttoast
  • Registratie: April 2000
  • Laatst online: 11:36
RM-rf schreef op maandag 22 januari 2007 @ 19:59:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
function createFunc(v) {
    return function() {
        if(http.readyState == 4){
            var response = http.responseText;
            var myDiv = document.getElementById(v);
            
            var newelm = document.createElement("div")
            newelm.innerHTML = http.responseText;
            myDiv.appendChild(newelm)
        }
    }
}

zou beter moeten werken :)
d:)b

Helemaal goed! Nu alleen nog even fixen dat hij geen nieuwe selectbox aanmaakt als er al een lege bestaat, maar ik denk dat ik zelf wel weer een stuk verder kom zo. Ik zal het hier posten als dat mij gelukt is :)

omniscale.nl


  • XWB
  • Registratie: Januari 2002
  • Niet online

XWB

Devver
innerHTML :z Wanneer er nu een error optreedt wordt die gewoon in de div gespuugd en krijgt iedereen deze te zien. Allereerst, laat de server een xml bestand met de resultaten returnen. Via het DOM kan je deze dan erg eenvoudig aflopen.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
header('Content-Type: text/xml'); 
echo '<?xml version="1.0" standalone="yes"?>';
echo '<lijst>'; 

$getItems = mssql_query("SELECT * FROM taallevels") or die (mysql_error()); 

while ($item = mssql_fetch_array($getItems))
{
    echo '<taal>' . $item['taal'] . '</taal>';
}

$getItems = mssql_query("SELECT * FROM taallevels") or die (mysql_error()); 

while ($item = mssql_fetch_array($getItems))
{
    echo '<taallevel>' . $item['level'] . '</taallevel>';
}

echo '</lijst>';


Hiermee krijg je een mooi xml bestand terug :) En dan ben je zo klaar:

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
function createFunc(v, http) {
    return function() {
        if(http.readyState == 4 && http.status == 200)
        {
            var response = http.responseXML;
            var talen = response.getElementsByTagName('taal');
            var taallevels = response.getElementsByTagName('taallevel');
            var myDiv = document.getElementById(v);
            var newelm = document.createElement("div");
            var i;
            var option;
            
            var firstSelect = document.createElement ( 'select' );
            for ( i = 0; i < talen.length; i++ )
            {
                option = document.createElement ( 'option' );
                option.appendChild ( document.createTextNode ( talen[i].firstChild.nodeValue ) );
                
                firstSelect.appendChild ( option );
            }
            
            newelm.appendChild ( firstSelect );
            
            var secondSelect = document.createElement ( 'select' );
            for ( i = 0; i < taallevels.length; i++ )
            {
                option = document.createElement ( 'option' );
                option.appendChild ( document.createTextNode ( taallevels[i].firstChild.nodeValue ) );
                
                secondSelect.appendChild ( option );
            }           
            
            newelm.appendChild ( secondSelect );
            
            myDiv.appendChild(newelm) ;
        }
    }
}


Dit is ook niet betrouwbaar:

JavaScript:
1
if(browser == "Microsoft Internet Explorer")


Je kan het beter zo doen:

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
function createRequestObject ()
{
    var xmlhttp = false;
    var msxmlTypes = [
        'MSXML2.XMLHTTP.6.0',
        'MSXML2.XMLHTTP.3.0'
    ];  
    
    if (window.XMLHttpRequest) 
    {
        xmlhttp = new XMLHttpRequest();
    }
    else
    {
      for (var i = 0; i < msxmlTypes.length; i++)
      {
          try
          {
            xmlhttp = new ActiveXObject(msxmlTypes[i]);
          }
          catch(e) {}
      }     
    }
    
    return xmlhttp;
}


Nog een tip, het xmlhttp object hou je beter lokaal.

JavaScript:
1
2
3
4
5
6
function getMoreOptions(soort,nr) {
    var http = createRequestObject();
    http.open('get', 'scripts/getMoreOptions.php?soort='+soort+'&nr='+nr);
    http.onreadystatechange = createFunc(soort);
    http.send(null);
}


Zullen vast wel fouten in staan, het komt zo uit de hand, niks getest dus.

March of the Eagles


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:35

crisp

Devver

Pixelated

Hacku schreef op maandag 22 januari 2007 @ 21:30:
innerHTML :z Wanneer er nu een error optreedt wordt die gewoon in de div gespuugd en krijgt iedereen deze te zien. Allereerst, laat de server een xml bestand met de resultaten returnen. Via het DOM kan je deze dan erg eenvoudig aflopen.
Ik ben het met je eens dat een gestructureerd data-formaat vele malen handiger en robuuster is, maar XML vind ik meestal weer net iets te zwaar en onhandig om te handlen in Javascript. Tenzij je al een XML-interface hebt zou ik eerder kiezen voor een serialized formaat wat je snel en eenvoudig kan omzetten naar een javascript object zoals bijvoorbeeld JSON of het PHP serialized formaat.

Intentionally left blank


  • XWB
  • Registratie: Januari 2002
  • Niet online

XWB

Devver
Dat is een persoonlijke smaak, xml met js afhandelen vind ik helemaal niet onhandig (wat bedoel je eigenlijk met onhandig, teveel code moeten gebruiken oid ?). En zwaar, mja, ik weet dat jij graag de snelste oplossingen hebt maar de client gaat hier geen verschil merken.
Tenzij je al een XML-interface
Ik heb idd een eigen XML interface - ooit eens geschreven - en voor mij werkt dit allemaal erg vlot. Maar ik sta altijd open voor nieuwe zaken, mocht je zin hebben om een voorbeeldje te tonen hoe jij dat doet dan zie ik dat graag :)

[ Voor 11% gewijzigd door XWB op 22-01-2007 22:48 ]

March of the Eagles


  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Beetje offtopic, als je microsoft sql server gebruikt, dan zou het misschien wel handig zijn om ook bij de error-handling/displaying mssql-functies te gebruiken ipv mysql ;).

http://nl2.php.net/manual...ssql-get-last-message.php

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:35

crisp

Devver

Pixelated

Hacku schreef op maandag 22 januari 2007 @ 22:47:
Dat is een persoonlijke smaak, xml met js afhandelen vind ik helemaal niet onhandig (wat bedoel je eigenlijk met onhandig, teveel code moeten gebruiken oid ?). En zwaar, mja, ik weet dat jij graag de snelste oplossingen hebt maar de client gaat hier geen verschil merken.
Vergelijk het volgende:
XML:
1
2
3
4
5
<root>
  <land code="nl">Nederland</land>
  <land code="de">Duitsland</land>
  <land code="be">België</land>
</root>

en
JavaScript:
1
2
3
4
5
{
  "nl": "Nederland",
  "de": "Duitsland",
  "be": "België"
}

Niet alleen is het vele malen sneller om het tweede voorbeeld om te zetten naar een Javascript object , ook de code die je daarvoor nodig hebt kan veel generieker zijn en het tweede voorbeeld heeft qua syntax veel minder overhead. Als je output gaat genereren voor een specifieke toepassing (in dit geval een Ajax applicatie) dan ligt een dataformaat dat veel meer aansluit bij de applicatie die het moet verwerken gewoon voor de hand.

En vergis je niet: in Ajax-heavy applicaties speelt performance toch zeker een cruciale rol. In dit geval praat je niet over een paar procent performancewinst op de verwerking maar over een aanzienlijke factor.

[ Voor 9% gewijzigd door crisp op 22-01-2007 23:15 ]

Intentionally left blank


  • posttoast
  • Registratie: April 2000
  • Laatst online: 11:36
Shadowman schreef op maandag 22 januari 2007 @ 23:03:
Beetje offtopic, als je microsoft sql server gebruikt, dan zou het misschien wel handig zijn om ook bij de error-handling/displaying mssql-functies te gebruiken ipv mysql ;).

http://nl2.php.net/manual...ssql-get-last-message.php
Offtopic, maar wel bedankt! :) Deze applicatie draaide oorspronkelijk op Apache/MySQL, maar wordt nu door mij omgezet naar MSSQL. Dit had ik even over het hoofd gezien. Straks toch maar even een search doen op alle files. ;)

omniscale.nl

Pagina: 1