views:

118

answers:

2

I have a collection of divs that contain either images or checkboxes. My end goal is to have the onclick event on the checkbox also check all previous checkboxes.

Here is my layout (dynamically created so id #'s can change based on page load data):

   <div id="Main1">
      <div id="Secondary1">
         <div id="div1">
            <img id="section1" src="image1" alt="" />
            <span>Div 1 text</span>
          </div>
         <div id="div2">
            <img id="section2" src="image2" alt="" />
            <span>Div 2 text</span>
          </div>
         <div id="div3">
            <input type="checkbox" id="section3">
             Div 3 text
             </input>
         </div>
         <div id="div4">
            <input type="checkbox" id="section4">
             Div 4 text
             </input>
         </div>
         <div id="div5">
            <input type="checkbox" id="section5">
             Div 5 text
             </input>
         </div>
         <div id="div6">
            <input type="checkbox" id="section6">
             Div 6 text
             </input>
         </div>
      </div>
   </div>

I want to be able to check the section5 and have it auto check the previous checkboxes.

The code I've been using, which is producing sporadic results is below:

$('input[id^=section]').click(function() {
   if($(this).attr('checked')) {
       var slide = $(this).attr('id').replace('section', '');
       $(this).replaceWith('<img src="images/ajax-loader.gif" id="loader" alt="" />'); //replace checkbox with loader animation
       $.ajax({
            type: 'POST',
            url: 'URL to AJAX page',
            data: '{ data for ajax call }',
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function() {
               $('#loader').parents('div[id^=Secondary]').children('div[id^=section]').each(function() {
                    if($(this).children('input[id^=section]').attr('id') != undefined) {
                          if($(this).children('input[id^=section]').attr('id').replace('section', '') < slide) {
                             $(this).children('input[id^=section]').replaceWith('<img src="images/checkmark.gif" alt="" />');
                       }
                    }
              });
            },
            error: function() {
                   //handle errors
            }
        });
   }
});

Seems to me I'm going about this inefficiently, I had tried .prev() and .prevAll() but without success. However I could have been using them incorrectly as well. Any assistance is appreciated.

+2  A: 

Try this: http://jsfiddle.net/kgc4M/

if(this.checked) {
    $(this).closest('div').prevAll('div:has(:checkbox)')
                         .find(':checkbox').attr('checked','checked');

}

EDIT: From your comment, you want to use .replaceWith() to replace the checkbox with an image, yet reuse the ID of the checkbox.

Try this:

if(this.checked) {
    $(this).closest('div').prevAll('div:has(:checkbox)')
                .find(':checkbox')
                .replaceWith(function() {
                      return "<img src='/some/path.jpg' id='" + this.id + "' />";
                }).remove();
}

Note that I'm also calling unbind() on the checkboxes being replaced, since I don't think replaceWith() will clean that up for you. I'll double check though.

EDIT: Appears as though .replaceWith() removes the events and data, but keeps an entry in jQuery.cache for the removed elements. To be thorough, I got rid of unbind() but added .remove() at the end, which completely removes them from the cache.

patrick dw
Perfect! Thanks for your prompt response. 1 more question, is it possible to extract the ID of the element as well?I am replacing the checkboxes with images and want to give the image the same ID that the checkbox had. Using your snippet and substituting .attr('checked', 'checked') with .replaceWith() instead, but i'd like to pull the ID of the element being replaced dynamically. Is this possible?
jon3laze
@jon - Yes. If you're using jQuery 1.4 or later, you can pass a function to `.replaceWith()` that returns the HTML string as the replacement. Inside the function, you can use `this.id` to reference the ID of the checkbox. I'll update with an example.
patrick dw
Awesome! Thank you again, this helped a ton.
jon3laze
A: 

.prev() and .prevAll() select siblings. Even though the checkboxes are on the same level of the DOM tree, they are not siblings. Siblings must share the same immediate parent. Those checkboxes are more like cousins.

Try something like this inside your click event:

if(this.checked) {
       $(this).parent().prevAll().children(':checkbox').attr('checked', 'checked');
}

Here's a demo: http://jsfiddle.net/dTK6n/

Ender