[JS][CSS] scherm wordt niet ge-update*

Pagina: 1
Acties:

  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 22:29

hamsteg

Species 5618

Topicstarter
Ik dacht geniaal te zijn en heb in een JS functie die een beetje tijd vrat, een kleine progress bar in elkaar gedraaid. Was met Opera aan het testen alles werkte goed ... todat ik op Firefox en IE ging testen. Onderstaande code is een werkende maar vereenvoudigde versie van de werkelijkheid (heb het zo compact mogelijk samengevat, svp niet klagen over structuur).

Bij Opera verschijnen de blokjes 1 voor 1,
Bij Firefox en IE pas als JavaScript is afgelopen.

Als ik de nu uitgecommentarieerde alert gebruik komt alles wel blokje voor blokje. Ik heb het ook met images geprobeerd en dan de src veranderen ... ook geen resultaat.

Het lijkt er op dat JS de schermopbouw blokkeert ... weet iemand hier de achtergrond van (en eventueel een oplossing)?

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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=windows-1250">
<script type="text/javascript">
  var ProgressBarCounter = 0; 
  function getObjectById(id) {
    var Obj;
    if (document.getElementById) {
      Obj = document.getElementById(id);
    } else if(document.layers) {
        Obj = document.layers[id];
      } else {
        Obj = document.all.item(id); }
    return Obj;
  }
  function updateBar()  {
    getObjectById("ID_"+ProgressBarCounter).style.border="1px solid #000000";
    getObjectById("ID_"+ProgressBarCounter).style.backgroundColor="#aaaaaa";
    ProgressBarCounter++;
  }
  function pause(NumberMillis)  { 
    var now = new Date(); var ExitTime = now.getTime() + NumberMillis;
    while (true) { now = new Date(); if (now.getTime() > ExitTime) return; }
  }
  function test( MaxCount )  {
    for( var Outer = 0; Outer < MaxCount; Outer++)
    {
      pause( 750 ); // dummy function call
      updateBar();
//    alert( Outer );
    }
  }
</script>  
  <title>Style test</title></head>
  <body><table><tr>
    <td id="ID_0">&nbsp;</td><td id="ID_1">&nbsp;</td><td id="ID_2">&nbsp;</td>
    <td id="ID_3">&nbsp;</td><td id="ID_3">&nbsp;</td><td id="ID_4">&nbsp;</td>
    <td id="ID_5">&nbsp;</td><td id="ID_6">&nbsp;</td><td id="ID_7">&nbsp;</td>
    <td id="ID_8">&nbsp;</td><td id="ID_9">&nbsp;</td>
    </tr></table><script type="text/javascript">test(10);</script></body>
</html>

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 17-02 09:49

killercow

eth0

Ik zou gewoon je Pause functie eruit kicken

Die functie vreet cpu cycles, en voegt werkelijk niks toe.

Gebruik gewoon een setTimeout timer.
Zodra ik een tab open zou hebben met jouw site erin ben ik dus meteen cycles aan het burnen, waar mijn hele computer experience dus onder leid. (als de browser niet al vraagt of jouw script gestopt moet worden)

JavaScript:
1
2
3
4
5
6
7
function test( MaxCount )  {
    timers=new Array();
for( var Outer = 1; Outer <= MaxCount; Outer++)
    {
     timers[Outer]=setTimeout( "updateBar();" ,Outer*750 );
    }
  } 

[ Voor 23% gewijzigd door killercow op 26-06-2006 16:35 ]

openkat.nl al gezien?


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Idd. gewoon setTimeout gebruiken. Je kunt die zelfs een functie object meegeven en dat is ook aan te raden.

Noushka's Magnificent Dream | Unity


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 22:29

hamsteg

Species 5618

Topicstarter
@moderator ... titel had nog "scherm wordt niet ge-update" moeten hebben ... wat is de procedure om de titel aangepast te krijgen ?

@killercow ... de pause functie is hier een dummy, in werkelijkheid zit er een berekeningsfunctie maar voor de uitleg heb ik even een korte werkende versie gemaakt. De werkelijke functie kost gemiddeld op mijn PC 1.5-2 sec.. en roept zelf de updatebar() functie (10x) aan. Met setTimeout heb ik ook al gespeeld om om de 100msec een display te forceren maar dat werkt niet. Had gehoopt dat de functie aangeroepen door setTimeout in een andere (display) context liep ... niet dus.

Nogmaals het gaat mij niet om de code die hier staat, die is illustratief, het gaat om het feit dat er geen update van het scherm plaatsvindt totdat de javacode klaar is terwijl er wel scherm updates worden uitgevoerd.

[ Voor 6% gewijzigd door hamsteg op 26-06-2006 16:48 ]

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:53
JS en CSS horen niet thuis in PRG, maar in Webdesign.

-> Webdesign

https://fgheysels.github.io/


  • RM-rf
  • Registratie: September 2000
  • Laatst online: 19-02 14:03

RM-rf

1 2 3 4 5 7 6 8 9

een andere, simpelere opzet:
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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=windows-1250">
<script type="text/javascript">
  function updateBar()  {
    elm = document.createElement( "DIV" )
    elm.setAttribute( "style", "border:1px solid #000;background-color:#aaa" )
    document.getElementById( 'progressBar' ).appendChild( elm )
  }
  function test( MaxCount )  {
    for( var Outer = 0; Outer < MaxCount; Outer++){
      setTimeout( "updateBar()", Outer*750 );
    }
  }
</script>  
  <title>Style test</title>
<style type="text/css">
DIV#progressBar {
    border:1px solid red;
    height: 30px;
}
DIV#progressBar DIV {
    border:1px solid green;
    height: 16px; width: 16px;
    display: block; float: left;
    margin: 4px;
}
</style>  
</head>
<body>
  <div id="progressBar"></div>
  <script type="text/javascript">test(10);</script>
</body>
</html>
hamsteggot schreef op maandag 26 juni 2006 @ 16:43:

@killercow ... de pause functie is hier een dummy, in werkelijkheid zit er een berekeningsfunctie maar voor de uitleg heb ik even een korte werkende versie gemaakt. De werkelijke functie kost gemiddeld op mijn PC 1.5-2 sec.. en roept zelf de updatebar() functie (10x) aan. Met setTimeout heb ik ook al gespeeld om om de 100msec een display te forceren maar dat werkt niet. Had gehoopt dat de functie aangeroepen door setTimeout in een andere context liep ... niet dus.
wat volgens mij gewoon fout is, si als je denkt dat het aanroepen vaneen pause-functie, ook betekent dat de uitvoering van je andere functie 'sleep'... oftewel de functie 'wacht totdat er een uitvoer beschikbaar is, dat dient niet zo te zijn, tenzij je om een return vraagt, maar het blijft een zeer slordige manier.

setTimeout heeft inderdaad altijd de golbale scope en niet die van de functie zelf

[ Voor 34% gewijzigd door RM-rf op 26-06-2006 16:50 ]

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


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 22:29

hamsteg

Species 5618

Topicstarter
Hoi RM-rf ...

Ik heb de code nog niet geprobeerd, maar waarom zorgt de functie appendChild wel voor een update een het aanpassen van een CSS element niet (bij Opera wel)? Dat was eigenlijk mijn hoofdvraag ... of is dat niet eenvoudig uit te leggen ?

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 07:29

crisp

Devver

Pixelated

De meeste browsers wachten met DOM-wijzigingen renderen totdat de JS-engine klaar is, daarom moet je wel van timeouts of intervals gebruik maken.

Intentionally left blank


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 22:29

hamsteg

Species 5618

Topicstarter
crisp schreef op maandag 26 juni 2006 @ 18:11:
De meeste browsers wachten met DOM-wijzigingen renderen totdat de JS-engine klaar is, daarom moet je wel van timeouts of intervals gebruik maken.
Kort gezegd gaat het mij dus niet lukken om een update op het scherm te krijgen.

Het voorbeeld van RM-rf zorgt voor een 10-tal processen in de "secondary thread of execution", maar de primary thread met mijn programma draait ook nog vrolijk door (en komt dus niet in idle). Het gehele Java systeem komt dus niet in een "rust" toestand en daardoor zal er nooit en render plaatsvinden. Een "sleep"-achtig commando zal niet werken omdat de primary threat dan bussy is.

Mijn conclusies:
1. er bestaat geen geforceerde update-display functie
2. het is niet mogelijk de primary thread te suspenden
Klopt dit?

Een mogelijke geforceerde methode is dan de berekening uit de primary thread te halen, op te splitsen, een aantal time-outs te genereren volgens voorbeeld van RM-rf en dan daar in de secondary thread de deelberekeningen te laten uitvoeren. Dit maakt executie dan wel behoorlijk langer omdat elke client anders reageert in performance. Je zult dan eerst een test moeten uitvoeren, deze meten en aan de hand van deze meeting en een marge de timeouts moeten bepalen. Pittig, niet onmogelijk maar wel pittig.

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 07:29

crisp

Devver

Pixelated

Javascript is niet threaded; je moet dus je berekening op bepaalde plaatsen onderbreken en na een timeout hervatten om de renderengine de kans te geven wijzigingen te renderen. Ja, dat betekent dat je ergens zal moeten bijhouden waar je gebleven was om dat punt weer te hervatten.
Sowieso is JS-performance erg verschillend per browser...

Intentionally left blank


  • hamsteg
  • Registratie: Mei 2003
  • Laatst online: 22:29

hamsteg

Species 5618

Topicstarter
Inderdaad, JavaScript is niet threaded ... wel bestaan er twee execution threads. Normaal draait alles in de primary thread of execution, met zover ik nu kan zien 2 uitzonderingen: setTimeout en setInterval. Deze timer triggers lopen parallel in de secondary execution thread en zijn niet van invloed op de java interpreter die de primary execution thread controleert. Zodra de primary execution thread idle is kan er gerenderd worden. De geactiveerde timers in de secondary execution thread starten een functie in de primary execution thread (met voorrangniet met voorang, daarom is het gebruik van de timer functies niet precies). Als beide execution threads "leeg" zijn stopt JS.

Zie ook:
http://www.sonofsofaman.com/hobbies/code/settimeout.asp
http://www.faqts.com/know...iew.phtml/aid/1602/fid/53

Voor de geinteresseerden heb ik de oorspronkelijke posting aangepast. De berekening wordt in deelberekeningen in de functie uitgevoerd die door setTimeout vanuit de trigger in de secondary execution thread wordt uitgevoerd (in de primary execution thread). Het eerste blok wordt gebruikt om de timer-tijd te bepalen zodat je met een client afhankelijke timer werkt. Nogmaals de pause() functie is een eenvoudige vervanging van de veel ingewikkelder berekening die ik in het uiteindelijke JS laat uitvoeren.

Cross browser gechecked: Opera 9.0, IE 6.0, Firefox 1.5

Bedankt allen voor de input ... elke dag leer je weer wat bij :)

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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=windows-1250">
<script type="text/javascript">
  var ProgressBarCounter = 0; 
  function getObjectById(id) {
    var Obj;
    if (document.getElementById) {
      Obj = document.getElementById(id);
    } else if(document.layers) {
        Obj = document.layers[id];
      } else {
        Obj = document.all.item(id); }
    return Obj;
  }
  function updateBar()
  {
    getObjectById("ID_"+ProgressBarCounter).style.border="1px solid #000000";
    getObjectById("ID_"+ProgressBarCounter).style.backgroundColor="#aaaaaa";
    ProgressBarCounter++;
  }
  function pause(NumberMillis) 
  { var now = new Date(); var ExitTime = now.getTime() + NumberMillis;
    while (true) { now = new Date(); if (now.getTime() > ExitTime) return; }
  }
// Globals
var TimeoutValue = 0; var MaxCount = 0; var CurrentCount = 0;
  function testing( MaxCnt )  {
    MaxCount = MaxCnt; 
    test();
  }
  // test is called from timer in secodary execution thread
  function test() {
    if( TimeoutValue == 0 ) {  // 1st time, measure performance and calc timeout
      var Now = new Date(); var StartTime = Now.getTime();
      pause( 100 );                              //  1/10th of the calc function
      Now = new Date(); var StopTime = Now.getTime();
      TimeoutValue = Math.floor( ( StopTime - StartTime) * 1.08);  // 8% marging
    } else {
      pause( 100 );                       // 9 times 1/10th of the calc function
    }
    updateBar(); CurrentCount ++;
    if( CurrentCount < MaxCount ) setTimeout("test()", TimeoutValue );  
  }
</script>  
  <title>Style test</title></head>
  <body><table><tr>
    <td id="ID_0">&nbsp;</td><td id="ID_1">&nbsp;</td><td id="ID_2">&nbsp;</td>
    <td id="ID_3">&nbsp;</td><td id="ID_3">&nbsp;</td><td id="ID_4">&nbsp;</td>
    <td id="ID_5">&nbsp;</td><td id="ID_6">&nbsp;</td><td id="ID_7">&nbsp;</td>
    <td id="ID_8">&nbsp;</td><td id="ID_9">&nbsp;</td>
    </tr></table><script type="text/javascript">testing(10);</script></body>
</html>

[ Voor 22% gewijzigd door hamsteg op 27-06-2006 14:25 . Reden: Opmerking van crisp ]

Niet quoten, zorgvuldige reacties volgens de regels worden zo weggewerkt: *knip*, reactie op geknipte reactie.


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 07:29

crisp

Devver

Pixelated

Nee, je moet het niet zien als threads maar meer als een wachtrij. Een timeout wordt niet uitgevoerd als de JS-interpreter op dat moment al (of nog) bezig is. Pas als de interpreter idle is gaat 'ie kijken of er nog iets in de wachtrij staat dat toevallig aan de beurt is. intervals en timeouts zijn daardoor ook nooit precies.

Intentionally left blank

Pagina: 1