Link to home
Start Free TrialLog in
Avatar of jongalli
jongalliFlag for Gibraltar

asked on

horizontal image scroller speeds up every time it goes through loop, when it should stay same speed

if you visit my weblink, http://www.rar.gi/jongalli/test.html you will notice i have done a horizontal image scroller using javascript which scrolls image up to a certain point on the screen. however as it passes each time through the loop the images that are scrolling speed up to a point where the cpu cant take any more and just 'slows'# down the process.
any ideas on why this happens? or any possible fixes?
javascript code is shown below:

<!--
      function scroll_imge(img_name,img_overlap,img_reset)
      {
                        var img_pos=document.getElementById(img_name).style.left;
                        //removes 'px' from string leaving the Y/image position integer value
                        img_pos=img_pos.substr(0, img_pos.indexOf('px'));
                        //performs image scrolling across screen (based on length specified) and previous images position so that they all meet at same end point
                        scroll_length=100;//parseInt(screen.width/2);
                        img_pos_vis=parseInt(scroll_length) + parseInt(img_overlap);
                        if (img_pos < img_pos_vis)
                        {
                              //increments img_pos Y coordinate, thus moving image across the screen
                              img_pos=parseInt(img_pos) + 1;
                              document.getElementById(img_name).style.left=img_pos + "px";
                        }
                        else
                        {
                              //hide image from user once it reaches a certain location on the page
                              document.getElementById(img_name).style.visibility="hidden";
                              //increments img_pos Y coordinate, thus moving hidden image across the screen
                              img_pos=parseInt(img_pos) + 1;
                              document.getElementById(img_name).style.left=img_pos + "px";
                              //checks if last image is hidden so that images can visibly scroll the screen again
                              if (img_reset == "1")
                              {
                                    //alert("true, reset images at this point");
                                    //img_reset=0;
                                    reset_scroll="1";
                                    list_img(reset_scroll);
                              }
                        }
                        timerID = window.setTimeout("scroll_imge('" + img_name + "','" + img_overlap + "','" +img_reset+ "');", 5);
      }

      function list_img(reset_scroll)
      {
            //counts how many images there are on the web document
            var img_counter=document.images.length;
            var img_overlap=0;
            var      img_last=(img_counter-1);
            //starts for loop based on number of images on page
            for (start=0;start<img_counter;start++)
            {
                  //declares variable with first image on array list
                  var counter=(parseInt(document.images.length)-1)-parseInt(start);
                  var img=document.images[counter];
                  //checks image to see if it matches name and if so runs through IF statement
                  if (img.name.indexOf("shame") >=0)
                  {
                        //overlap represents how the distance each image must meet before it becomes hidden to user
                        if (reset_scroll=="1")
                        {
                              document.getElementById(img.name).style.left="0px";
                              document.getElementById(img.name).style.visibility="visible";
                        }
                        if (start==img_last) {var img_reset=1;} else {var img_reset=0;}
                        var img_overlap=parseInt(document.images[counter].width) + parseInt(img_overlap);
                        scroll_imge(img.name,img_overlap,img_reset);
                  }
            }
      }
      //load scroll list when javascript read into memory on load
      list_img(0);
//-->      
Avatar of cookre
cookre
Flag of United States of America image

What did you intend the timeout for?  Since I don't see where scroll_imge() can exit without calling itself, each call to scroll_imge() in the main loop is going to add another never-ending chain of scroll_imge() calling itself over, and over, and over...
Avatar of jongalli

ASKER

the timeout was to cause the images to move on the screen. thats how i saw that some websites achieved the moving image effect. i know it causes a never ending chain, and its got to a point where i dont know how else i can fix it. i tried stopping the timer once it made the last image in the list invisible, but no luck as it just produced an even more weird effect in that one image moved at the same pace throughout each loop and the rest of the images speeded up each time it passed through the loop. i am thinking of redesigning it however, if u can find a better solution or fix the one i have tried to get working, i would be most grateful.
points would also be justified :)
How about something like:


while (some condition that says to stop the show)
        {
        Initialize_And_Paint_Beginning_State()
        while (Some_Picture_Is_Still_Visible)
                 {
                 Move_All_Pictures_Right_One_Smidgen()
                 }
        }

...

Move_All_Pictures_Right_One_Smidgen()
{
Some_Picture_Is_Still_Visible=false;
for (i=NumPictures; i>0; i--)
     {
     Move_Picture_Right_One_Smidgen(i)
     Some_Picture_Is_Still_Visible=Is_Picture_Still_Visible[i];
     }
// Upon exit, Some_Picture_Is_Still_Visible will reflect the state of the left-most picture
}

...

Move_Picture_Right_One_Smidgen(i)
{
if ( ! Is_Picture_Still_Visible[i]) return;
--code to move picture i 1 smidgen to the right and then set  Is_Picture_Still_Visible[i]
}
to be honest, i am not entirely convinced with your method, however i will attempt to encorporate some of the ideas you mentioned, some may even help fix the problem i have had. i wont award any points yet (sorry) until i get the new code sorted. this way i can better grade your help and adjust point value.
if you still wish to provide other useful hints, feel free, as i find that perseverance and desire to help, boost up my generosity in giving points.
thanks
Avatar of dakyd
dakyd

Try the following - it's quick & dirty, but I think it'll do what you want.  It increments the left position of each image by 1 every 20 ms.  The trick is that every single image has the exact same left position, even though some of them are already offset by a non-zero number of pixels.  This makes those images disappear off the edge of the screen before img.left == fullWidth.  Once the left-most image hits the edge of the screen, then img.left == fullWidth for ALL of the images, and all the images are reset.  It's probably not the most elegant solution, but it should work.

You can also change the scroll speed by changing the second argument to the setInterval function.  Hope that helps.

<head>
<script type="text/javascript" language="javascript">
function scrollImages() {
  fullWidth = screen.availWidth;
  for (i = 0; i < document.images.length; i ++) {
    img = document.images[i];
    if (img.name.indexOf("img") > -1) {
      leftStr = img.style.left;
      leftStr = leftStr.substr(0, leftStr.length - 2);
      leftNum = +leftStr;
      img.style.left = (leftNum + 1) % fullWidth;
    }
  }
}
</script>
</head>

<body onLoad="setInterval('scrollImages()', 20)">
  <img src="img0.jpg" name="img0" style="position: relative; left: 0; top: 0">
  <img src="img1.jpg" name="img1" style="position: relative; left: 0; top: 0">
  <img src="img2.jpg" name="img2" style="position: relative; left: 0; top: 0">
</body>
read the code you had done, and i must admit, very concise and does the job. however i also made my own scroller which is slightly more complex, and it works too.
however i do get one problem when i transfer the new code onto a html file on my webpage. it says object not found. i narrowed down the search and found out that the arrays which are storing the images when javascript file is loaded doesnt keep when it calls the function which scrolls the images. funnily enough it works on the test page i created when working on the scroller (http://jongalli.rar.gi/test.html). however when merging with test homepage (http://jongalli.rar.gi/test02.html) it comes up the object error.
if u can visit both weblinks, and you will see my frustration. if u have ne ideas, it would be real helpful.
the new javascript code is down below:

scroller.js
<!--
      //finds out how many images are on page, and stores selected images into array
      var img_count = document.images.length;
      var shift_right=0;
      //to change coordinates where image disappears from right side change img_pos value below.
      //table_select=document.getElementById("middle");
      var img_pos=screen.width;
      var img_hide=0;
      var scroll_images=0;
      var stop_timer=0;
      img_count=img_count-1;
      img_name = new Array();
      img_left= new Array();
      img_width= new Array();
      img_visible_right=new Array();
      img_visible_left=new Array();
      //starts for loop to store images onto array counter
      for(start=0;start<=img_count;start++)
      {
            var img=document.images[start];
            if (img.name.indexOf("shame")>=0)
            {
                  //sets array for image name, width,
                  img_name[start] =img.name;
                  img_width[start]=img.width;
                  
                  //sets coordinates for when image is to be hidden and made visible
                  img_hide=parseInt(img_width[start]) + parseInt(img_hide);
                  //sets variable from where image is to be made hidden from right hand side of screen
                  img_visible_right[start]=parseInt(img_hide) + parseInt(img_pos);
                  //sets variable from where image is to be made visible from left hand side of screen
                  img_visible_left[start]=img_hide;
                  
                  //relocates starting position of images so that they dont all appear in one go on the screen.
                  img_left[start]=document.getElementById(img_name[start]).style.left;
                  img_left[start]=img_left[start].substr(0, img_left[start].indexOf('px'));
                  //to get images starting at different coordinate, change img_left[start] value below
                  img_left[start]=img_left[start] - img_hide;
                  document.getElementById(img_name[start]).style.left=img_left[start]+"px";
                  
                  scroll_images++;
            }
      }
      shift_right=parseInt("-"+img_hide);
      
      function shift_images()
      {
            shift_right++;
            for(start=0;start<scroll_images;start++)
            {
                  //reversal of for loop counter which is used for making images disappear from right to left, instead of left to right
                  img_reverse=(scroll_images-1)-start;
                  //shifts image one pixel to the right and making relevant images appear/disappear
                  if (-shift_right > img_visible_left[start])
                  {
                        document.getElementById(img_name[start]).style.visibility="hidden";
                        document.getElementById(img_name[start]).style.left=shift_right + "px";
                  }
                  else if (shift_right < img_visible_right[img_reverse])
                  {
                        document.getElementById(img_name[start]).style.visibility="visible";
                        document.getElementById(img_name[start]).style.left=shift_right + "px";
                  }
                  else
                  {
                        document.getElementById(img_name[start]).style.visibility="hidden";
                        document.getElementById(img_name[start]).style.left=shift_right + "px";
                  }
                  //checks if last image has reached its coordinates and if it has, it sets a var which stops the timer
                  if ((shift_right == img_visible_right[start]) && ((scroll_images-1) == start)) {stop_timer=1;} else {stop_timer=0;}
            }
            if (stop_timer=="0") {timerID = window.setTimeout("shift_images();", 5);} else {window.clearTimeout(timerID);reset_images();}
      }
      
      function reset_images()
      {
            //resets the images coordinates to their original state
            for(start=0;start<scroll_images;start++)
            {
                  //sets image back to original location and makes them visible to the user
                  document.getElementById(img_name[start]).style.left=img_left[start]+"px";
                  document.getElementById(img_name[start]).style.visibility="visible";
            }
            //resets shift variable which moves the images
            shift_right=parseInt("-"+img_hide);
            //calls the shift_images function which scrolls the images
            shift_images();
      }
      shift_images();
      
//-->      
It looks like you're calling the function scrollImages() in the actual site (http://jongalli.rar.gi/test.html), which isn't defined.  There's no call to this function in the test page you made, so that probably explains why you're not seeing the problem there.  

Since you call scrollImages() a bunch of times, I assume you meant to include it in js/preload.js, because I don't see it in scroller.js .  I'd check for little errors like mis-spelling the function name.  If that's not it, could you post the code for preload.js, too?  That might help to figure out what's going on.

Hope that helps...
in test.html, the function is being called when the javascript file is loaded i.e. <Script .....scroller.js> and not in the actual site (if thats what you meant).
as for test02.html i uploaded the wrong file, sorry. if you check it now, it should be correct. the same object error comes out (http://jongalli.rar.gi/test02.html). as for spelling mistakes, checked thousands of times, hoping it could be that, but unfortunately not.
preload.js only contains the rollover images (done by dreamweaver) which are preloaded into the webpage when first loaded. i have posted the code either way, although it doesnt affect the image scroller.
if there is code which you need that i havent posted, you can always save the webpage on your desktop and it should copy all the files necessary for the webpage to load, including the js files (unless its easier for you to read the code which i paste here)
code for preload.js.
<!--
function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
//-->
I opened up http://jongalli.rar.gi/test02.html, and this line is causing trouble:
img_left[start]=document.getElementById(img_name[start]).style.left;

img_name[start] is an object, but you're treating it like a string.  However, instead of using getElementById to look up the element again, you could just re-use the variable you set earlier.  You already defined img to be document.images[start], so you can use that.
Long and short of it, you can basically change the offending line to:

img_left[start] = img.style.left;

Hope that helps...
oops, forget to mention, that line is in scroller.js
had a look at what you said, and fixed the area you said. i am surprised i didnt see it earlier, must have slipped my mind.
long story short, i still get the object required error msg.
i am treating img_name[start] as a string because i want to store all the relevant image details in an array so that when it comes to resetting the coordinates of the image, its within 'easy reach'. i dont need it to be an object.
the problem in the code is that once i have declared the array when scroller.js is loaded, when i call the shift_images() function, it seems to lose it values.
it works fine in http://jongalli.rar.gi/test.html but the issue that confuses me is why does it work on test.html but not test02.html? there is no logic.
can you think of any other reasons why i get the error msg?
i am raising the points up incase that might trigger someone's brain cells into trying to solve this error msg i am getting with javascript.
Okay, so here's what I noticed - the loop that assigns the arrays goes from 0 to document.images.length.  In this case, that's from 0 to 12 (if I remember correctly).  Even though you have the if clause there, the counter still increments on each iteration through the for loop.  Long story short, you're not assigning to img_name[0] for the first image in the wall of shame, you're assigning to something like img_name[8].  So when you try to get img_name[0] later on in shift_images(), you get null, and document.getElementById(img_name[0]) doesn't work (and you get that error message).

The fix should be this - when you want to assign to your arrays, assign to array[scroll_images] instead of array[start].  So, for example, you want:
               img_name[scroll_images] =img.name;
instead of:
               img_name[start] =img.name;

Note, this worked for http://jongalli.rar.gi/test.html because there were only enough images for the scrolling div.  Basically, scroll_images = start for that page.  But when you add more images that aren't part of the scroller (like you did for http://jongalli.rar.gi/test02.html), then you start to have problems.

Hopefully, that makes sense to you.  If not, lemme know and I'll try to explain.  Again, hope that helps...
oh ****, i think your right. how did i not see it earlier, lol. i guess it does take some1 else's point of view to see your mistakes.
i am going to change code, later on in the day, and i will let you know how i got on. i still cant believe that i didnt see this earlier.
ok, changed my code and it all works now, thank god!
however now another problem arises. the images scroll but they dont disappear and reappear on the screen, one by one like b4.
if u look at http:\\jongalli.rar.gi/test.html you will see a working model of what it should do, whereas when u look at http://jongalli.rar.gi/test02.html, it doesnt do the same thing. i realised that its not coming back with the img.width, in test02.html, and thats why the images are not disappearing and reappearing like they should. i also set an alert msg giving me the img width so that u can see my dilemma on test02.htm and the working model on test.html.
i have tried different ways of parsing the variable like instead of img.width i have specified document.getElementById(img_name).width, and img.getAttribute("width"), etc with no luck.
any ideas why this is happening?
sorry for the late reply, been really busy with courseworks,
In http:\\jongalli.rar.gi/test.html, you set a width attribute:
<img src="MyFile/Dscn0648_tn.gif" name="shame01" width="45" height="60" border="0" id="shame01" style="left:0px; position:relative; visibility:visible;" onMouseOver="clearTimeout(timerID);" onMouseOut="shift_images();">

However, in http://jongalli.rar.gi/test02.html, you don't assign a width to the images:
<img onMouseOver="clearTimeout(timerID);" onMouseOut="shift_images();" style="left:0px; position:relative; visibility:visible;" src="MyFile/Dscn0648_tn.gif" id="shame01" name="shame01" border="0">

That's why you get 0 when you try to use img.width.  There is no width specified, so javascript treats the value of the width attribute as 0.  Obviously, the fix is to assign the widths the same way you did for http:\\jongalli.rar.gi/test.html.  Hope that helps ...
sorry gave you the wrong link because i forgot to rename the html file extension. i had assigned the width values of the images, but i still got a 0 when it tried to read it in javascript.
visit http://jongalli.rar.gi/test02.html again. updated the llink properly. sorry about that.
ASKER CERTIFIED SOLUTION
Avatar of dakyd
dakyd

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ok thanks for your advice. i shall have to convert to div tags. i just found that for what i wanted, tables best positioned my stuff. guess i shall to read more into div tags. i know they are useful, for some things, yet i normally prefer tables for this sort of layout.
i think its only fair that if i have to redesign my page, that this question be answered as any new problems wouldnt be linked to original question.
so enjoy, and thanks for your help.