On Apr 24, 7:16 pm, Jason <[EMAIL PROTECTED]> wrote:
> Hi everyone.
>
> I'm kind of stuck with a problem an I hope you can give me a hint on
> how to solve it.
>
> I have a page with several (varying amount) checkboxes on it (called
> memberemail). I have a script looping over all checkboxes, adding the
> value (if selected) to a link.
>
> --
>     link='mailto:';
>     sel=0;
>     for( i=0; i<document.form.memberemail.length; i++){
>         if(document.form.memberemail[i].checked){
>             link=link+document.form.memberemail[i].value+';';
>             sel++;
>         }
>     }
> --
>
> Since I'm using prototype in some other pages, I wanted to migrate
> this too. I tried the following which is working with <select> tags
> and other <input> tags.
>
> --
>     link='mailto:';
>     sel=0;
>     for( i=0; i<$('memberemail').length; i++){
>         if($('memberemail')[i].checked){
>             link=link+$('memberemail')[i].value+';';
>             sel++;
>         }
>     }
> --

If you want to use Prototype.js to do this, you need to convert the
collection to an array, then use the each method.  But as I show
below, there's no point in using that just to be cool and use
Array.each, it's faster to write your own function to iterate over the
collection rather than convert it to an array then iterate over it.


> After trying some other variants I derived from documentation or other
> examples, but I can't get it working. Furthermore performance is an
> issue here, because there are up to 2k checkboxes in the page.

Putting 2,000 elements in a page is absurd, but if that's what you
want to do, write your own function to loop over the them, it's much
faster than using Prototype.js's each() (Safari was 3x, Firefox 2x)
and doesn't take any more code.  Here's a simple example:

<script type="text/javascript">

 function getCheckedP(f){
   var el, els = $A(f.getElementsByTagName('input'));
   var result = [];
   els.each(function(el){
     if (el.checked) result.push(el.value);
   });
   return result.join(';');
 }

 function showCheckedP(f){
   var sTime = new Date();
   var s = getCheckedP(f);
   var ms = new Date() - sTime;
   $('xx').innerHTML = ms + 'ms<br>' + s;
 }

 function getChecked(f) {
   var el, els = f.getElementsByTagName('input');
   var result = [];
   for (var i=0, len=els.length; i<len; i++){
     el = els[i];
     if (el.checked) result.push(el.value);
   }
   return result.join(';');
 }

 function showChecked(f){
   var sTime = new Date();
   var s = getChecked(f);
   var ms = new Date() - sTime;
   $('xx').innerHTML = ms + 'ms<br>' + s;
 }

 </script>

<div id="xx"></div>
<form action="">
  <input type="button" value="Show checked plain"
   onclick="showChecked(this.form);"><br>
  <input type="button" value="Show checked Prototype.js"
   onclick="showCheckedP(this.form);"><br>
  <script type="text/javascript">
    var x = [],
        i = 2000;
    while (i--){
      x.push('<input type="checkbox" value="'+i+'">');
      if (!(i%100)) x.push('<br>');
    }
    document.write(x.join(''));
  </script>
</form>


Before people say "but you should be using Form.getElements()", try
it, it's 3x slower than using $A(...).  In Safari[1] that's 9ms (plain
js) versus 160ms (Prototype.js and Form.getElements) - the first
Prototype run takes 1.5 seconds.  In Opera the plain js was 10x faster
(6ms versus 61ms), again the first run took about 1.4 seconds.

Others are welcome to suggest faster ways.  If order is unimportant, a
while loop might be faster in some browsers, a do loop might be faster
still and maintain order - test thoroughly.


1. Using a 2.0 GHz MacBook Core2Duo.


--
Rob


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Spinoffs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to