Avatar billede arriva Nybegynder
19. maj 2006 - 16:08 Der er 19 kommentarer og
1 løsning

Hastighedsproblem med IE

Hej eksperter,

jeg har noget javascript på min side hvis formål er at sætte brugeren i stand til at besvare en række radiobuttons med de numeriske taster (1-4 eller 1-5).

Som det fremgår af koden har jeg i den første del hentet inspiration på nettet.

Dette script kører rigtig godt i Firefox, og det virker også i IE. MEN! Det kører utrolig sløvt i IE ift. Firefox. Er der noget jeg ikke ved om IE og som jeg evt. kunne optimere?

Koden:
<script type="text/javascript">
function textsizer(e){
var evtobj=window.event? event : e //distinguish between IE's explicit event object (window.event) and Firefox's implicit.
var unicode=evtobj.charCode? evtobj.charCode : evtobj.keyCode
var actualkey=String.fromCharCode(unicode);
var CurrentSpm = findCurrentSpm();
var radioName = 'r' + CurrentSpm;
if(document.forms[0].elements[radioName][actualkey-1]!=null) {
document.forms[0].elements[radioName][actualkey-1].checked=true;
document.forms[0].elements[radioName][actualkey-1].focus();
window.scrollBy(0, 25);
if(document.getElementById('spm'+CurrentSpm)!=null) {
document.getElementById('spm'+CurrentSpm).style.color='';
document.getElementById('spm'+CurrentSpm).style.textDecoration='';
}
if(document.getElementById('spm'+(CurrentSpm+1))!=null) {
document.getElementById('spm'+(CurrentSpm+1)).style.color='blue';
document.getElementById('spm'+(CurrentSpm+1)).style.textDecoration='underline';
}
}
}
document.onkeypress = textsizer;

function findCurrentSpm()
{
var CurrentSpm = 1;
for(var i=0;i<document.forms[0].elements.length;i++)
{
if(document.getElementById('spm'+i)!=null) {
if(document.getElementById('spm'+i).style.color=='blue') CurrentSpm=i;}
}
return CurrentSpm;
}

function setCurrentSpm(currentSpm)
{
for(var i=0;i<document.forms[0].elements.length;i++)
{
if(document.getElementById('spm'+i)!=null)
{
if(document.getElementById('spm'+i).style.color=='blue')
{
document.getElementById('spm'+i).style.color='';
document.getElementById('spm'+i).style.textDecoration='';
}
}
}
document.getElementById('spm'+(currentSpm+1)).style.color='blue';
document.getElementById('spm'+(currentSpm+1)).style.textDecoration='underline';
}

</script>
Avatar billede olebole Juniormester
19. maj 2006 - 18:55 #1
<ole>

Det er jo svært at vide, om det er mest optimalt at klippe dig med en brodersaks, en trimmer, en hækkesaks eller en flammekaster, når man ikke kender dit hår  :)

Foreløbig kender vi kun dit valg af værktøj ...

/mvh
</bole>
Avatar billede arriva Nybegynder
19. maj 2006 - 18:58 #2
Det var meget poetisk - men jeg forstår ikke hvad du mener ;o)

Jeg forestiller mig at det måske er for-løkkerne der trækker ned i IE's performance idet der er 92 "spm"+i det kan gennemløbe.
Avatar billede olebole Juniormester
19. maj 2006 - 20:32 #3
Det er det, jeg mener ... vi kender ikke koden, den skal 'gennemrode'  :)

Derudover er der ikke noget så demotiverende, som et script uden nogen somhelst form for indrykning. Det tager 10 gange så lang tid at sætte sig ind i - og det er helt unødvendigt.
Skriv din kode ordentligt. Så er det lettere for dig selv at overskue den - og folk gider gå langt for at hjælpe  ;o)
Avatar billede arriva Nybegynder
19. maj 2006 - 22:23 #4
Okay, så forstår jeg :o)
Scriptet bliver skrevet ind fra noget asp.net code-behind, men det er selvfølgelig ingen undskyldning for manglende indrykning, kun dovenskab.
Selve siden bliver også renderet via asp.net i code-behind, og det er ret omfattende, men outputtet (som vel er det interessante når vi taler om client-side scripting). Siden kommer derved til at indeholde en tabel med 92 rækker med spørgsmål, som:
(...)
<tr id="spm11" class="boollist" >
<td align="left" valign="top" style="font-size:10px;font-weight:bold;">11.</td>
<td align="left" valign="top" style="font-size:10px;">spørgsmålstekst</td>

<td align="center"><input type="radio" name="r11" title="Altid" value="1" onclick="setCurrentSpm(11)" /></td>
<td align="center"><input type="radio" name="r11" title="Ofte" value="2" onclick="setCurrentSpm(11)" /></td>
<td align="center"><input type="radio" name="r11" title="Sommetider" value="3" onclick="setCurrentSpm(11)" /></td>
<td align="center"><input type="radio" name="r11" title="Sjældent" value="4" onclick="setCurrentSpm(11)" /></td>
<td align="center"><input type="radio" name="r11" title="Aldrig / næsten aldrig" value="5" onclick="setCurrentSpm(11)" /></td>
</tr>
<tr id="spm12" class="boollist" >
<td align="left" valign="top" style="font-size:10px;font-weight:bold;">12.</td>
<td align="left" valign="top" style="font-size:10px;">spørgsmålstekst</td>
<td align="center"><input type="radio" name="r12" title="Altid" value="1" onclick="setCurrentSpm(12)" /></td>
<td align="center"><input type="radio" name="r12" title="Ofte" value="2" onclick="setCurrentSpm(12)" /></td>
<td align="center"><input type="radio" name="r12" title="Sommetider" value="3" onclick="setCurrentSpm(12)" /></td>
<td align="center"><input type="radio" name="r12" title="Sjældent" value="4" onclick="setCurrentSpm(12)" /></td>
<td align="center"><input type="radio" name="r12" title="Aldrig / næsten aldrig" value="5" onclick="setCurrentSpm(12)" /></td>
</tr>
(...)

Javascriptet (nu med indrykning):
function answer(e){
  var evtobj=window.event? event : e //distinguish between IE's explicit event object (window.event) and Firefox's implicit.
  var unicode=evtobj.charCode? evtobj.charCode : evtobj.keyCode
  var actualkey=String.fromCharCode(unicode);
  var CurrentSpm = findCurrentSpm();
  if(CurrentSpm!=null) {
      var radioName = 'r' + CurrentSpm;
      if(document.forms[0].elements[radioName][actualkey-1]!=null) {
        document.forms[0].elements[radioName][actualkey-1].checked=true;
        document.forms[0].elements[radioName][actualkey-1].focus();
        window.scrollBy(0, 25);
        if(document.getElementById('spm'+CurrentSpm)!=null) {
            document.getElementById('spm'+CurrentSpm).style.color='';
        }
        if(document.getElementById('spm'+(CurrentSpm+1))!=null) {
            document.getElementById('spm'+(CurrentSpm+1)).style.color='blue';
        }
      }
  }
}

document.onkeypress = answer;

function findCurrentSpm(){
  var CurrentSpm = 1;
  for(var i=0;i<document.forms[0].elements.length;i++)
  {
      if(document.getElementById('spm'+i)!=null) {
        if(document.getElementById('spm'+i).style.color=='blue') CurrentSpm=i;}
      }
      return CurrentSpm;
  }

function setCurrentSpm(currentSpm){
  for(var i=0;i<document.forms[0].elements.length;i++)
  {
      if(document.getElementById('spm'+i)!=null)
      {
        if(document.getElementById('spm'+i).style.color=='blue')
        {
            document.getElementById('spm'+i).style.color='';
        }
      }
  }
  if(document.getElementById('spm'+(currentSpm+1))==null)
  {
      document.getElementById('spm'+(currentSpm)).style.color='blue';
  }else{
      document.getElementById('spm'+(currentSpm+1)).style.color='blue';
  }
}
Avatar billede olebole Juniormester
19. maj 2006 - 22:33 #5
Mon ikke, du kunne oprette et array eller object, hvis elementer får sat en værdi, alt efter hvilken radio, der er klikket på? Det giver vist en meget mindre søgning.

Desuden skal du tænke på, at du i et udtryk som dette:

      if(document.forms[0].elements[radioName][actualkey-1]!=null) {
        document.forms[0].elements[radioName][actualkey-1].checked=true;
        document.forms[0].elements[radioName][actualkey-1].focus();

- går ud og leder efter det samme objekt tre gange. Sæt i stedet en variabel - og referer til dén.
Avatar billede olebole Juniormester
19. maj 2006 - 23:01 #6
PS: netop den konstruktion, jeg refererede til ovenfor, indeholder hele tre array-kald i hver objekt-reference.
Dvs, at JS/DOM først skal ned i 'dokument.forms' - derefter ned i 'FORM.elements' - og til sidst ned i radio-gruppen - for at finde elementet. Det gør du tre gange, hvor du kunne nøjes med én  :)
Avatar billede arriva Nybegynder
19. maj 2006 - 23:31 #7
Godt foreslag.. jeg har prøvet at ændre det nu således det bliver:
var spmTD = document.getElementById('spm'+CurrentSpm);

Desværre gav det næsten ikke noget i IE. Det må være noget andet der er krævende, jeg har set cpu belastningen i IE peaker på 100% med scriptet. Jeg har læst lidt rundt på nettet, kan det passe at IE ikke er glad for arbejde med style på objekter?
Avatar billede arriva Nybegynder
20. maj 2006 - 01:10 #8
Jeg har lavet et lidt tidstagning og arbejdet mig ned til at problemet ligger i mine "getElementById", dette tager mere end 10x så lang tid i IE som i FF. Når det så ovenikøbet ligger i en løkke - ja, gæt resten.

Jeg har lavet lidt flere optimeringer, men ovenstående er stadigvæk flaskehalsen.

Forslag er velkomne.. (så noget her må da værre en pine ved ajax)
Avatar billede olebole Juniormester
20. maj 2006 - 01:33 #9
Jeg ville som sagt nok lave et array eller objekt og spørge på det i stedet.

Har du prøvet at udkommentere style-delen, når du tager tid? Det kunne være interessant, selvom jeg tvivler på, det vil give det store  :)
Avatar billede olebole Juniormester
20. maj 2006 - 01:55 #10
Nu har jeg lavet en kopi af dit dokument - og jeg fatter ikke en ringende bjælde af, hvad det skal kunne gøre for mig  :)
Avatar billede arriva Nybegynder
20. maj 2006 - 02:00 #11
hvor jeg dog bare hader når man lige har skrevet en masse og så trykker på et link og springer væk fra siden.. gab..

nå, men jeg har optimeret lidt mere og taget nogle målinger. Det der virkelig rykkede var at indsætte nogle breaks i mine løkker. Det burde jo så kun hjælpe på de første spørgsmål og så blive værre og værre. Men! Det gjorde det ikke, slet ikke endda. JEg har lavet en flot lille graf her: http://www.broze.dk/javascript.png
Min forklaring er at mine TD's må ligge først i "elements" hvis length iøvrigt er 569 (gab!).
Avatar billede arriva Nybegynder
20. maj 2006 - 02:02 #12
hehe, idéen med det er at man skal kunne bruge det numeriske tastetur til hurtigt at svare på nogle spørgsmål. Der er f.eks. 5 svarmuligheder, og når man så trykker 1-5 afkrydses muligheden og der springes videre til næste.

x-aksen er måling og y-aksen millisekunder ;o)
Avatar billede arriva Nybegynder
20. maj 2006 - 02:07 #13
dit forslag om at lave et array kan jeg ikke helt gennemskue. Det skulle man så gøre første gang, gemme det på en-eller-anden måde og så bruge det til søgning næste gang?

iøvrigt har jeg også leget lidt med document.all som alternativ, dog med værre resultat.
Avatar billede olebole Juniormester
20. maj 2006 - 02:37 #14
Prøv dette:

var actSpm = null;
function answer(e) {
    var evtobj=window.event? event : e //distinguish between IE's explicit event object (window.event) and Firefox's implicit.
    var unicode = evtobj.charCode? evtobj.charCode : evtobj.keyCode
    var actualkey = parseInt(String.fromCharCode(unicode));
    if (actualkey<1 || actualkey>5) return;
    if (!actSpm) setActSpm(1);
    else setActSpm(actSpm.inx + 1);
    var aInp = actSpm.elm.getElementsByTagName("input");
    aInp[actualkey-1].checked = true;
    scrollBy(0, 25);
}
function setActSpm(inx) {
    if (actSpm) actSpm.elm.style.color = "";
    else actSpm = {};
    actSpm.inx = inx;
    actSpm.elm = document.getElementById("spm"+inx);
    actSpm.elm.style.color = "blue";
}
document.onkeypress = answer;
Avatar billede olebole Juniormester
20. maj 2006 - 02:39 #15
- undskyld, jeg kom til at omdøbe din funktion ... sådan:

var actSpm = null;
function answer(e) {
    var evtobj=window.event? event : e //distinguish between IE's explicit event object (window.event) and Firefox's implicit.
    var unicode = evtobj.charCode? evtobj.charCode : evtobj.keyCode
    var actualkey = parseInt(String.fromCharCode(unicode));
    if (actualkey<1 || actualkey>5) return;
    if (!actSpm) setCurrentSpm(1);
    else setCurrentSpm(actSpm.inx + 1);
    var aInp = actSpm.elm.getElementsByTagName("input");
    aInp[actualkey-1].checked = true;
    scrollBy(0, 25);
}
function setCurrentSpm(inx) {
    if (actSpm) actSpm.elm.style.color = "";
    else actSpm = {};
    actSpm.inx = inx;
    actSpm.elm = document.getElementById("spm"+inx);
    actSpm.elm.style.color = "blue";
}
document.onkeypress = answer;
Avatar billede olebole Juniormester
20. maj 2006 - 02:45 #16
- og for ikke at få en fejl, når alle spm. er løbet igennem, skal du nok lige lægge en begrænsning:


    if (actualkey<1 || actualkey>5) return;
    if (!actSpm) setCurrentSpm(1);
    else if (actSpm.inx>91) return; // <- HER
    else setCurrentSpm(actSpm.inx + 1);
Avatar billede olebole Juniormester
20. maj 2006 - 03:19 #17
De sidste forbedringer:

var actSpm = null;
function getPos(elm) {
    for (var zx=zy=0;elm!=null;zx+=elm.offsetLeft,zy+=elm.offsetTop,elm=elm.offsetParent);
    return {x:zx,y:zy}
}
function answer(e) {
    var evtobj=window.event? event : e //distinguish between IE's explicit event object (window.event) and Firefox's implicit.
    var unicode = evtobj.charCode? evtobj.charCode : evtobj.keyCode;
    if (unicode<49 || unicode>53) return; // <-- Filtrer her i stedet
    var actualkey = parseInt(String.fromCharCode(unicode));
    if (!actSpm) setCurrentSpm(1);
    else if (actSpm.inx>91) return;
    else setCurrentSpm(actSpm.inx + 1);
    var aInp = actSpm.elm.getElementsByTagName("input");
    aInp[actualkey-1].checked = true;
    if ( getPos(aInp[0]).y-document.documentElement.scrollTop>75 ) scrollBy(0, 24);
}
function setCurrentSpm(inx) {
    if (actSpm) actSpm.elm.style.color = "";
    else actSpm = {};
    actSpm.inx = inx;
    actSpm.elm = document.getElementById("spm"+inx);
    actSpm.elm.style.color = "blue";
}
document.onkeypress = answer;

En bedre filtrering af keys - og så scroller vi kun, hvis den aktive radio ligger mere end 75px fra toppen af vinduet.

Så tror jeg heller ikke, der er flere ændringer fra mig, før der foreligger respons  :)
Avatar billede arriva Nybegynder
20. maj 2006 - 22:18 #18
Det er jo meget smart.. man glemmer hurtigt at et "server-hit" ikke er nødvendigt i client-side, så man sagtens kan arbejde med lokale variable.
De 91 er dog ikke fast, så en enkelt count må nok ind, men det kunne jo foregå i forbindelse med asp.net renderingen istedet hvor jeg alligevel har det.

Scroll-by giver dog stadigvæk lidt problemer. Tror måske jeg laver en focus og så scroller ekstra bagefter.

Tusind tak for hjælpen!
Smid et svar, så skal du få points :o)
Avatar billede olebole Juniormester
21. maj 2006 - 02:42 #19
Selvtak. Du kunne evt. lade serveren indskrive de 91 - eller hvad det nu måtte være. Så slipper du for løkker  :)
Avatar billede olebole Juniormester
21. maj 2006 - 20:23 #20
Tak for points ... og pæne ord  ;o)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester