Javascript en JAH

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

  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Beste Tweakers,

Ik zit al dagen te hameren op hetzelfde probleem, ik heb diverse oplossingen geprobeerd maar geen van allen werken ze naar behoren. Dus nu probeer ik er met jullie hulp uit te komen... ;)

Het zit als volgt: stel ik heb twee pagina's, index.php en subindex.php. De subindex word met behulp van het zogenaamde JAH script in de index geladen. Het probleem is echter dat subindex.php verschillende javascripts nodig heeft om goed te kunnen werken, bijvoorbeeld SWFObject en sIFR3.

Dit dacht ik op te kunnen lossen door het volgende scriptje toe te voegen aan jah.js


JavaScript: jah.js
32
33
34
35
36
 var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.getElementsByTagName('head')[0].appendChild(script); 
} 


Voor een simpel script werkt dit prima, maar voor de eerder genoemde scripts niet |:(
Hieronder de volledige JAH code zoals ik hem nu gebruik:

JavaScript: jah.js
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
function jah(url,target) {
    // native XMLHttpRequest object
    document.getElementById(target).innerHTML = '<p class="loader"><img src="skins/wzvc2/images/loading.gif"><p>';
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        req.onreadystatechange = function() {jahDone(target);};
        req.open("GET", url, true);
        req.send(null);
        
    // IE/Windows ActiveX version
    } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req) {
            req.onreadystatechange = function() {jahDone(target);};
            req.open("GET", url, true);
            req.send();
        }
    }
}    


function load_script(src)
{
var document_scripts = document.getElementsByTagName("script");

for (document_scripts_index = 0; document_scripts_index < document_scripts.length; ++document_scripts_index)
{
var document_script = document_scripts[document_scripts_index];
if (document_script.src == src) return false;
}

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.getElementsByTagName('head')[0].appendChild(script); 
}


function jahDone(target) {
    // only if req is "loaded"
    if (req.readyState == 4) { 
        // only if "OK"
        if (req.status == 200) {
            results = req.responseText;
            document.getElementById(target).innerHTML = results; 
            load_script("skins/wzvc2/sIFR/js/sifr.js");  
            load_script("skins/wzvc2/sIFR/js/sifr-config.js");  
            load_script("skins/wzvc2/js/swfobject.js");  
            load_script("skins/wzvc2/js/test.js");                              
            
        } else {
            document.getElementById(target).innerHTML="jah error:\n" +
                req.statusText;
        }
    }
}


Zoals je ziet word hier ook het bestand test.js aangeroepen. test.js bevat een simpel lijntje code dat een alert weergeeft...en je raad het al...die is wel te zien bij het inladen van de subindex.

Snappen jullie het nog? 8)7

  • RM-rf
  • Registratie: September 2000
  • Laatst online: 01-12 10:11

RM-rf

1 2 3 4 5 7 6 8 9

kan dit misschien eraan liggen dat die script de 'onload' handler nodig hebben?

juist doordat hij de content eenvoudig wegschrijft via innerHTML, ontbreekt de 'onload'

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


  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Maar dan zou je dus een onload moeten toevoegen aan de subindex. En aangezien deze niet uit een standaard DOM-structuur bestaat is dat volgens mij nogal lastig?

  • krvabo
  • Registratie: Januari 2003
  • Laatst online: 30-11 15:16

krvabo

MATERIALISE!

Ehm als ik het zo zie dan kan je function jahDone(target) { nooit werken.
Die req.readyState is niet binnen een andere functie te gebruiken dan de AJA(H/X)-functie (function jah(url,target))?

[edit]
Hm als ik naar info-pagina ga, is dat ook gewoon AJAH(tml), die het op dezelfde manier doet :? :X

[ Voor 21% gewijzigd door krvabo op 04-06-2007 18:16 ]

Pong is probably the best designed shooter in the world.
It's the only one that is made so that if you camp, you die.


  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
krvabo schreef op maandag 04 juni 2007 @ 18:14:
Hm als ik naar info-pagina ga, is dat ook gewoon AJAH(tml), die het op dezelfde manier doet :? :X
JAH is nagenoeg hetzelfde als AHAH

  • Chilly_Willy
  • Registratie: April 2000
  • Laatst online: 10-10 14:59
Tip, dit is volgens MS de juiste manier om een xmlhttp request te doen met de goeie versie van msxml (6 of 3). http://blogs.msdn.com/xml...in-internet-explorer.aspx

JavaScript: jah.js
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Ajax object aanmaken
function jah(url,target) {
    if (Web.Application.get_type() == Web.ApplicationType.InternetExplorer) {
        var progIDs = [ 'MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.3.0'];
        for (var i = 0; i < progIDs.length; i++) {
            try {
                req = new ActiveXObject(progIDs[i]);
            } catch (ex) {
            }
        }
    } else {
        req = new XMLHttpRequest(); 
    }
    req.onreadystatechange = function() {jahDone(target);};
    req.open("GET", url, true);
    req.send(null);
}


Verder worden functies die in de xmlhttprequest staan niet uitgevoerd, je moet de functies al in de huidige pagina hebben staan, je kan je namelijk wel aanroepen.

Coïtus ergo sum


  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Chilly_Willy schreef op maandag 04 juni 2007 @ 20:19:
Tip, dit is volgens MS de juiste manier om een xmlhttp request te doen met de goeie versie van msxml (6 of 3). http://blogs.msdn.com/xml...in-internet-explorer.aspx
Bij deze code krijg ik de melding "Web is not defined" en werk de functie jah(url,target) niet meer...

Misschien handig om te vermelden: Héél af en toe werkt het sIFR script wel. Maar dat is alleen na een rare (onbekende) combinatie van refreshen en reloaden en alleen bij hoge uitzondering. Hoe het komt? Geen idee! :? Dit geldt voor zowel IE7 als Firefox btw

EDIT: als het script niet word uitgevoerd krijg ik in IE (soms) de volgende fout:
document.getElementById(...) is leeg of geen object

[ Voor 16% gewijzigd door MG-studios op 05-06-2007 12:33 ]


Verwijderd

Dat dit af en toe niet werkt komt omdat het request pas echt verwerkt wordt als je JavaScript idle is. Dat is niet zo makkelijk uit te leggen, maar het is vergelijkbaar met dit:

JavaScript:
1
2
3
4
5
6
7
// een timeout van 0, dus zo snel mogelijk
setTimeout(function () { alert('hai'); }, 0);

// iets dat je cpu opeet
for (var i = 0; i < 1000000; i++) {}

// hier wordt de timeout pas getriggerd, omdat hij het voorheen te druk had


Op dezelfde manier, met een asynchroon request:

JavaScript:
1
2
3
4
5
6
7
8
9
var xho = getXMLHttpRequest();
xho.onreadystatechange = function () { alert('hai'); };
xho.open('GET', 'http://iets.dat/vrijwel/direct/beschikbaar/is', true);
xho.send();

// iets dat je cpu opeet
for (var i = 0; i < 1000000; i++) {}

// hier wordt het request pas verwerkt, omdat hij het voorheen te druk had


Je kunt dus ook niet na het request in een lus blijven hangen en steeds checken of de code al geladen is (door de aanwezigheid van een functie of variabele of element te controleren), omdat zo'n zogenaamde "busy-wait" alle asynchrone code blokkeert. (Asynchroon in JavaScript is dus ook niet echt asynchroon, je krijgt alleen de nadelen, en geen van de voordelen.)

Hetzelfde geldt ook voor het toevoegen van een script-tag aan het document met DOM of innerHTML. Dat is een van de verschrikkelijk irritante dingen aan JavaScript, en er is bijna geen oplossing voor.

Ik zeg bijna, want het zou mogelijk moeten zijn om in de globale scope (dus niet in een functie) met behulp van XMLHttpRequest je code op te halen, en deze door eval te halen. Ik heb het echter nooit getest en maak maar gewoon voorzichtig gebruik van een functie die een script-tag aan de DOM toevoegt. :P

  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Verwijderd schreef op donderdag 07 juni 2007 @ 15:03:
Ik zeg bijna, want het zou mogelijk moeten zijn om in de globale scope (dus niet in een functie) met behulp van XMLHttpRequest je code op te halen, en deze door eval te halen.
Dat is dus exact wat ik probeer te bereiken maar daar schijnt niemand écht een oplossing voor te weten...niet alleen hier maar op meerdere websites :S

Ondanks dat me dit toch een veel voorkomend probleem lijkt te zijn, al dan niet met AJAX ipv van JAH of AHAH. Het principe komt op hetzelfde neer.

Het toevoegen van de zogenaamde cpu-vreter ;) lost het probleem met de scripts helaas niet op btw

[ Voor 10% gewijzigd door MG-studios op 07-06-2007 20:05 ]


Verwijderd

Hier is een kant-en-klaar voorbeeld van wat ik bedoel:

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
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
        <head>
                <title>JavaScript dynamic include test</title>
                <script type="text/javascript">
function getXMLHttpRequest() {
        try {
                req = new XMLHttpRequest();
        } catch(err1) {
                try {
                        req = new ActiveXObject("Msxml2.XMLHTTP");
                } catch (err2) {
                        try {
                                req = new ActiveXObject("Microsoft.XMLHTTP");
                        } catch (err3) {
                                req = false;
                        }
                }
        }
        return req;
}

function include(url) {
        // synchronous request to get the code
        var xho = getXMLHttpRequest();
        xho.open('GET', url, false);
        xho.send('');

        return xho.responseText;
}

eval(include('jsinclude2.js'));
hello();
                </script>
        </head>
        <body>
        </body>
</html>


En dan in jsinclude2.js:
JavaScript:
1
2
3
function hello() {
  alert('included file');
}


Je zult zien dat de code in jsinclude2.js altijd eerder wordt uitgevoerd dan de code na de include()-call. Dit komt omdat alle operaties om de code op te halen en uit te voeren synchroon zijn. De functie die in jsinclude2.js wordt gedefinieerd is dus meteen beschikbaar.

Vervolgens kun je bijvoorbeeld een array maken van de bestanden die je wilt includen:

JavaScript:
1
2
3
4
5
6
7
8
9
var files = [
  'jsinclude2.js',
  'jsinclude3.js'
];

for (var i = 0, len = files.length; i < len; i++)
  eval(include(files[i]));

hello();


Wat je echter niet kunt doen:
JavaScript:
1
2
3
function include_script(url) {
  eval(include(url));
}


Dan wordt de code uitgevoerd in de private scope van de functie, en is geen enkele variabele of functie die in het geincludede script wordt gedefinieerd globaal. Als je in een functie eval(include(script)) doet kun je de globals van dat script dus alleen in deze functie gebruiken.

Ik denk niet dat het makkelijker kan dan dit, helaas.

  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Bedankt! Het ziet er allemaal heel logisch uit. Ga er vanavond mee aan de gang. Ik ben echt een hopeloos geval op dit gebied :N vandaar ook dat ik voor een simpel script als JAH heb gekozen. Ik hoop mede dankzij jullie hulp van bovenstaande tips iets te leren...ik waardeer iig jullie inzet tot nu toe! d:)b

Als het niet me allemaal niet lukt dan horen jullie het wel ;)

[ Voor 48% gewijzigd door MG-studios op 08-06-2007 12:11 ]


  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Ok ben even bezig geweest. De bovenstaande manier werkt prima, maarrr.... toch stuit ik weer op dezelfde problemen als eerst. de simpele alertjes worden iedere keer netjes weergegeven, maar het sIFR script werkt alleen bij hoge uitzondering en SWFobject vertikt het helemaal om zijn taakje uit te voeren. |:(

In Firefox zijn geen errors te zien in de foutconsole.
In IE7 is het nog erger dan voorheen. De site toont zijn content maar alles lijkt uitgeschakeld cq. vastgelopen. linkjes etc zijn niet meer klikbaar.

Heeft iemand nog enig idee wat er aan de hand zou kunnen zijn? :?

Verwijderd

Staat het hele zaakje misschien ergens online, of kun je de relevante code precies zoals je die nu hebt hier plaatsen?

  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Ok, ik ben er nu bijna. Was achteraf toch makkelijker dan ik dacht. De meeste scripts werkte niet omdat de codes binnen innerhtml niet werden uitgevoerd. Dit was iets wat ik wist, maar ik probeerde dit op de verkeerde manier op te lossen. Ik heb nu het volgende:

JavaScript: jah.js
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
function execJS(node)
{
  var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
  var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
  var bMoz = (navigator.appName == 'Netscape');

  if (!node) return;

  /* IE heeft liever hoofdletters */
  var st = node.getElementsByTagName('SCRIPT');
  var strExec;

  for(var i=0;i<st.length; i++)
  {
    if (bSaf) {
      strExec = st[i].innerHTML;
      st[i].innerHTML = "";
    } else if (bOpera) {
      strExec = st[i].text;
      st[i].text = "";
    } else if (bMoz) {
      strExec = st[i].textContent;
      st[i].textContent = "";
    } else {
      strExec = st[i].text;
      st[i].text = "";
    }

    try {
      var x = document.createElement("script");
      x.type = "text/javascript";

      /* Voor IE gebruiken we .text! */
      if ((bSaf) || (bOpera) || (bMoz))
        x.innerHTML = strExec;
      else x.text = strExec;

      document.getElementsByTagName("head")[0].appendChild(x);
    } catch(e) {
      alert(e);
    }
  }
};

function jah(url,target) {
    // native XMLHttpRequest object
    document.getElementById(target).innerHTML = '<p class="loader"><img src="skins/wzvc2/images/loading.gif"><p>';
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        req.onreadystatechange = function() {jahDone(target);};
        req.open("GET", url, true);
        req.send(null);
        
    // IE/Windows ActiveX versie
    } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req) {
            req.onreadystatechange = function() {jahDone(target);};
            req.open("GET", url, true);
            req.send();
        }
    }
}    

function jahDone(target) {
    // als de status gelijk is aan "loaded"
    if (req.readyState == 4) { 
        // als de status gelijk is aan "OK"
        if (req.status == 200) {
            results = req.responseText;
            document.getElementById(target).innerHTML = results; 
            execJS(document.getElementById('columns'));           

        } else {
            document.getElementById(target).innerHTML="jah error:\n" +
                req.statusText;
        }
    }
}


swfobject werkt op deze manier direct in zowel IE als in Firefox. voor sifr moeten we aan het begin van de pagina's die extern worden ingeladen alleen nog even de volgende code toevoegen:

JavaScript: externe content voor in div
1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/javascript">
sIFR.replace(bookantiqua, {
selector: 'h2'
,css: [
'.sIFR-root { color: #00baff; font-size: %; font-weight: none; margin-left: 0; background-color: #000000; }'
,'a { color: #00baff; text-decoration: none; }'
,'a:visited { color: #00baff; text-decoration: none; }'
,'a:hover { color: #00baff; text-decoration: none; }'
]
, wmode: 'transparent' 
});
</script>


In Firefox werkt dit allemaal vlekkeloos, maar je raad het al...in IE niet.
De foutconsole van Firefox zegt het volgende:
Waarschuwing: ‘undefined’ gevonden waar ‘:’ verwacht. Declaratie genegeerd.

Wat precies de oorzaak probeer ik nog te achterhalen. Voldoen de bovenstaande codes trouwens een beetje aan de 'algemene-correcte-coderings' norm of zijn het deprimerende lijntjes code? :P

ps. site staat helaas nog niet online, hij is nog volop in ontwikkeling via localhost

[ Voor 3% gewijzigd door MG-studios op 09-06-2007 15:11 ]


  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Ok. Problem solved. IE wilde de scripts bovenaan de geinclude content toch niet uitvoeren. Dus dan maar zo:

JavaScript: jah.js
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
function execJS(node)
{
  var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
  var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
  var bMoz = (navigator.appName == 'Netscape');

  if (!node) return;

  /* IE heeft liever hoofdletters */
  var st = node.getElementsByTagName('SCRIPT');
  var strExec;

  for(var i=0;i<st.length; i++)
  {
    if (bSaf) {
      strExec = st[i].innerHTML;
      st[i].innerHTML = "";
    } else if (bOpera) {
      strExec = st[i].text;
      st[i].text = "";
    } else if (bMoz) {
      strExec = st[i].textContent;
      st[i].textContent = "";
    } else {
      strExec = st[i].text;
      st[i].text = "";
    }

    try {
      var x = document.createElement("script");
      x.type = "text/javascript";

      /* Voor IE gebruiken we .text! */
      if ((bSaf) || (bOpera) || (bMoz))
        x.innerHTML = strExec;
      else x.text = strExec;

      document.getElementsByTagName("head")[0].appendChild(x);
    } catch(e) {
      alert(e);
    }
  }
};

function jah(url,target) {
    // native XMLHttpRequest object
    document.getElementById(target).innerHTML = '<p class="loader"><img src="skins/wzvc2/images/loading.gif"><p>';
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        req.onreadystatechange = function() {jahDone(target);};
        req.open("GET", url, true);
        req.send(null);
        
    // IE/Windows ActiveX versie
    } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req) {
            req.onreadystatechange = function() {jahDone(target);};
            req.open("GET", url, true);
            req.send();
        }
    }
}    

function sIFRreload() {
    sIFR.replace(bookantiqua, {
selector: 'h2'
,css: [
'.sIFR-root { color: #00baff; font-size: %; font-weight: none; margin-left: 0; background-color: #000000; }'
,'a { color: #00baff; text-decoration: none; }'
,'a:visited { color: #00baff; text-decoration: none; }'
,'a:hover { color: #00baff; text-decoration: none; }'
]
, wmode: 'transparent' 
});
    }

function jahDone(target) {
    // als de status gelijk is aan "loaded"
    if (req.readyState == 4) { 
        // als de status gelijk is aan "OK"
        if (req.status == 200) {
            results = req.responseText;
            document.getElementById(target).innerHTML = results; 
            execJS(document.getElementById('columns')); 
            Behaviour.apply();
            sIFRreload()

                    

        } else {
            document.getElementById(target).innerHTML="jah error:\n" +
                req.statusText;
        }
    }
}


Het werkt nu in zowel IE als Firefox. Firefox geeft in de foutconsole echter wel nog steeds de volgende melding aan:

Waarschuwing: ‘undefined’ gevonden waar ‘:’ verwacht. Declaratie genegeerd.
Bronbestand: http://localhost/test-jah/
Regel: 0


Geen idee waar het vandaan komt. Misschien dat iemand met wat meer ervaring het bovenstaand script kan controlen op netheid? Iedereen bedankt voor de hulp! d:)b

Verwijderd

Aan het woord 'declaratie' te zien is dat een error in je stylesheets, niet in de scripts.

En qua netheid: het is me volstrekt onduidelijk wat je allemaal doet met opgehaalde code. Je steekt het in de innerHTML van een of ander element, en haalt het daarna uit een element met id 'columns', waar het dan weer in 'script'-tags in staat, en die script-tags maak je dan opnieuw aan in de head... Daar lijkt het op in ieder geval. :P

  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Verwijderd schreef op maandag 11 juni 2007 @ 09:10:
Aan het woord 'declaratie' te zien is dat een error in je stylesheets, niet in de scripts.

En qua netheid: het is me volstrekt onduidelijk wat je allemaal doet met opgehaalde code. Je steekt het in de innerHTML van een of ander element, en haalt het daarna uit een element met id 'columns', waar het dan weer in 'script'-tags in staat, en die script-tags maak je dan opnieuw aan in de head... Daar lijkt het op in ieder geval. :P
Hmm, dan maar ff de stylesheet nalopen. De werking die je omschrijft is wel ongeveer juist. Script-elementen die zich bevinden in de innerhtml die word ingeladen worden standaard niet uitgevoerd door de browser. Op deze manier wel :)

  • MG-studios
  • Registratie: Juni 2007
  • Laatst online: 15-11 20:38
Om even op bovenstaande code terug te komen. Kan het zijn dat er ergens een memoryleak optreed? Want daar lijkt het op. Heb de site al getest met Drip en sIEve maar die output zegt mij niet zoveel. En nog iets; is er iemand die ervaring heeft met een goede manier om de back en forward functionaliteit van de browser te herstellen bij gebruik van InnerHTML?

[ Voor 38% gewijzigd door MG-studios op 14-06-2007 15:22 ]

Pagina: 1