1

i have an .each() loop doing something on all matching elements. but i also have a way to add those elements.... i'm trying to get livequery to realize that a new element has been added and run it through the same each loop.

here's a general setup: http://jsfiddle.net/CUURF/1/

basically, how do i use livequery and each together?

ultimately it is so that i can dynamically add tinymce editor textboxes in metaboxes, but i am fairly certain the problem is that my IDs aren't autoincremting on the add/clone, since the new element isn't in the DOM for the each loop.

edit- i think the biggest thing is that i need the index counter that comes standard w/ .each to work w/ livequery?

edit- here's the code from wpalchemy for looping/cloning

/* <![CDATA[ */
        jQuery(function($)
        {
            $(document).click(function(e)
            {       
                var elem = $(e.target);

                if (elem.attr('class') && elem.filter('[class*=dodelete]').length)
                {
                    e.preventDefault();

                    var p = elem.parents('.postbox'); /*wp*/

                    var the_name = elem.attr('class').match(/dodelete-([a-zA-Z0-9_-]*)/i);

                    the_name = (the_name && the_name[1]) ? the_name[1] : null ;

                    /* todo: expose and allow editing of this message */
                    if (confirm('This action can not be undone, are you sure?'))
                    {
                        if (the_name)
                        {
                            $('.wpa_group-'+ the_name, p).not('.tocopy').remove();
                        }
                        else
                        {
                            elem.parents('.wpa_group').remove();
                        }

                        the_name = elem.parents('.wpa_group').attr('class').match(/wpa_group-([a-zA-Z0-9_-]*)/i)[1];

                        checkLoopLimit(the_name);

                        $.wpalchemy.trigger('wpa_delete');
                    }
                }
            });

            $('[class*=docopy-]').click(function(e)
            {
                e.preventDefault();

                var p = $(this).parents('.postbox'); /*wp*/

                var the_name = $(this).attr('class').match(/docopy-([a-zA-Z0-9_-]*)/i)[1];

                var the_group = $('.wpa_group-'+ the_name +':first.tocopy', p);

                var the_clone = the_group.clone().removeClass('tocopy');

                var the_props = ['name', 'id', 'for'];

                the_group.find('input, textarea, select, button, label').each(function(i,elem)
                {
                    for (var j = 0; j < the_props.length; j++)
                    {
                        var the_prop = $(elem).attr(the_props[j]);

                        if (the_prop)
                        {
                            var the_match = the_prop.match(/\[(\d+)\]/i);

                            if (the_match)
                            {
                                the_prop = the_prop.replace(the_match[0],'['+(+the_match[1]+1)+']');

                                $(elem).attr(the_props[j], the_prop);
                            }
                        }
                    }
                });

                if ($(this).hasClass('ontop'))
                {
                    $('.wpa_group-'+ the_name +':first', p).before(the_clone);
                }
                else
                {
                    the_group.before(the_clone);
                }

                checkLoopLimit(the_name);

                $.wpalchemy.trigger('wpa_copy', [the_clone]);
            });

            function checkLoopLimit(name)
            {
                var elem = $('.docopy-' + name);

                var the_match = $('.wpa_loop-' + name).attr('class').match(/wpa_loop_limit-([0-9]*)/i);

                if (the_match)
                {
                    var the_limit = the_match[1];

                    if ($('.wpa_group-' + name).not('.wpa_group.tocopy').length >= the_limit)
                    {
                        elem.hide();
                    }
                    else
                    {
                        elem.show();
                    }
                }
            }

            /* do an initial limit check, show or hide buttons */
            $('[class*=docopy-]').each(function()
            {
                var the_name = $(this).attr('class').match(/docopy-([a-zA-Z0-9_-]*)/i)[1];

                checkLoopLimit(the_name);
            });
        });
        /* ]]> */
        </script> 

and the markup for inside my metabox:

<div id="testimonials"> 

    <h2>Testimonials</h2> 

    <a style="float:right; margin:0 10px;" href="#" class="dodelete-testimonials button"><span class="icon delete"></span>Remove All</a> 


        <div id="wpa_loop-testimonials" class="wpa_loop wpa_loop-testimonials"><div class="wpa_group wpa_group-testimonials first">   



        <a href="#" class="dodelete button"><span class="icon delete"></span>Remove</a> 

      <div class="slide_preview"> 
                <div class="preview_wrap"> 
        <img class="preview" src="" alt="preview" /> 
        </div> 
        <input type="hidden" name="_sidebar_meta[testimonials][0][testimonial_image]" value="" class="img_src" /> 


                <input type="hidden" name="_sidebar_meta[testimonials][0][slide_image_alt]" value="" class="img_alt" /> 


        <button class="upload_image_button button" type="button"><span class="icon upload"></span>Change Photo</button> 

      </div> 

      <div class="slide_text"> 

        <label>About Testimonial</label> 
        <div class="customEditor minimal"> 
                <textarea rows="5" cols="50" name="_sidebar_meta[testimonials][0][testimonial_desc]">I realized it was ME causing all the problems</textarea> 
        </div> 
      </div> 


    </div>      <div class="wpa_group wpa_group-testimonials last tocopy">    

    <h3 class="slide">Testimonial Name:     
            <input type="text" name="_sidebar_meta[testimonials][1][testimonial_name]" value=""  /> 
    </h3> 

        <a href="#" class="dodelete button"><span class="icon delete"></span>Remove</a> 

      <div class="slide_preview"> 
                <div class="preview_wrap"> 
        <img class="preview" src="http://localhost/multi/wp-content/themes/callingintheone/functions/WPAlchemy/images/default_preview.png" alt="_sidebar_meta[testimonials][1][testimonial_image] Preview" /> 
        </div> 
        <input type="hidden" name="_sidebar_meta[testimonials][1][testimonial_image]" value="" class="img_src" /> 


                <input type="hidden" name="_sidebar_meta[testimonials][1][slide_image_alt]" value="" class="img_alt" /> 


        <button class="upload_image_button button" type="button"><span class="icon upload"></span>Upload Photo</button> 

      </div> 

      <div class="slide_text"> 

        <label>About Testimonial</label> 
        <div class="customEditor minimal"> 
                <textarea rows="5" cols="50" name="_sidebar_meta[testimonials][1][testimonial_desc]"></textarea> 
        </div> 
      </div> 


    </div></div>     
    <p style="margin-bottom:15px; padding-top:5px;"><a href="#" class="docopy-testimonials button"><span class="icon add"></span>Add Testimonial</a></p>    

</div>

the .tocopy class gets shifted by the alchemy code to a new hidden (by CSS) and last element

helgatheviking
  • 25,596
  • 11
  • 95
  • 152
  • Which version of jQuery are you using? As of 1.3 I believe, live events are now built-in: [jQuery live()](http://api.jquery.com/live/) – clmarquart May 04 '11 at 20:23
  • 1.5. i was under the impression that live only binds to click, submit, etc. and that just the 'appearance' of a new matching element wouldn't trigger it- which is why i went to livequery. – helgatheviking May 04 '11 at 20:42
  • You aren't doing this very efficiently. I'll have a post up soon with a more efficient way of doing this. – Levi Morrison May 04 '11 at 21:05
  • lol. never claimed i was. :) look forward to your post. – helgatheviking May 04 '11 at 21:07
  • I'll look into the update sometime today, mate. – Levi Morrison May 05 '11 at 12:53
  • much appreciated! i am looking at it now still and the Alchemy code has a css-hidden version of the textarea that needs copying. on the Add button click, this area becomes visible, and loses its .tocopy class to a new hidden clone. i 'think' i am having trouble selecting the NEW last (and hidden) element and adding it to the editors array since i'm not the one cloning it. – helgatheviking May 05 '11 at 13:26
  • What's the html code for the Add button? Also, do you have the ability to edit the wpalchemy script? – Levi Morrison May 05 '11 at 14:39
  • Add Testimonial i could edit the alchemy script. i'd prefer not to so i dont overwrite it on upgrade, but if it is the only way then it's the only way. – helgatheviking May 05 '11 at 19:11

2 Answers2

1

Your problem was that each was not executing with the clik. And after that there was nothing to make it run.

fixed code

Bakudan
  • 19,134
  • 9
  • 53
  • 73
0

Answer: http://jsfiddle.net/morrison/CUURF/6/

Notes:

  • Does not use livequery. There's no need to in this instance.
  • Keeps track of existing editors in an array. This is faster than cycling through the DOM every time you want an editor. DOM stuff is slow, arrays are fast. This also gives you easy access to any or all of the editors for other things you might do.
  • Doesn't cycle when a new editor is created. It simply modifies the new editor to have an id of the last one plus 1. This is a huge performance boost.
Levi Morrison
  • 19,116
  • 7
  • 65
  • 85
  • super neat! thanks for that, i never would have thought you could do it w/o livequery. definitely solves my issue as described. but, my problem in adapting it will be that i'm using the WP_alchemy class to build metaboxes, and IT handles the cloning of the elements- so i can't quite hook into click/clone event the same way. not to mention that eventually i need tinymce to load on the new textarea. – helgatheviking May 04 '11 at 22:03
  • I fail to see how any of this is a problem. Perhaps you could update your original post to include code for your specific situation? – Levi Morrison May 04 '11 at 22:21