views:

114

answers:

1

I spent 2 hours this morning trying to figure out why my jQuery function worked in one part of the page but not another.

I finally narrowed it down to vertical padding on a container.

If I had this in my CSS:

div.collapsiblePanel {
padding: 0px 1%;
}

then, via jQuery, I can find the parent (.collapsiblePanel) element and could traverse into that div and manipulate the child elements. However, if I change just this one thing in my style sheet to this:

div.collapsiblePanel {
padding: 5px 1%;
}

Then jQuery can find the parent (.collapsiblePanel) but is unable to traverse the children.

Crazy, right? Any theories as to what is going on? I was banging my head on this one thinking it HAD to be something with my jQuery but it ultimately was a CSS issue.

Per request, some more snippets of markup/css/code:

The specific jQuery function that wasn't (seemingly) working:

function finishUp(ajaxContainer,originalContainer,loadingAlert) {  
 $(ajaxContainer).find("input.btnSave").css("border","3px solid red");
 var saveButtonn = $(ajaxContainer).find("input.btnSave");
 console.log(ajaxContainer);
 console.log(originalContainer);
 console.log(loadingAlert);
 console.log(saveButton);
 $(ajaxContainer).find("input.btnSave").css("border","3px solid red").click(function(){
  alert("you clicked the save button");
  savePanel($(this));
 });

};

What that's doing is, after previous functions load content via AJAX and then display the container, this function comes in and attaches a click event to the button.

As you can see I have a bunch of extra logging code in there. When my CSS vertical padding is set to '0', Firebug logs the proper object name of each of those. When I change my CSS vertical padding to anything else, the last object (saveButton) comes back as empty/blank in Firebug.

The HTML:

<div class="ajaxEditPanel editablePanel collapsiblePanel" style="display: block;">       
    <form>
         <fieldset class="sideLabels dividers">
         <legend>Edit Realtionship Information</legend>

              ...the form...
                <div class="formItem formButtons"
                    <input value="save" class="button btnSave" type="button">
                    <input value="cancel" class="button btnCancel" type="button">
                </div>                    
         </fieldset>        
    </form>
 </div>

Note that that DIV is being created by previous jQuery functions and loaded with content. At first I thought it was a timing issue, where I was trying to attach an event to an object that hadn't yet loaded into the DOM. However, that didn't explain why the same exact functions worked elsewhere on the page. The one variable I could change that would make this work or not work ended up being that bit of CSS padding. If, in the parts of the page where the function current works, I also add some vertical padding to the container, they also break jQuery selecting the child elements.

A: 

I believe I've come across something similar to this before - it could be a timing issue where the DOM is rendered slighlty after the JS is being told to bind to the elements. In your case the padding may be making firefox take a few milliseconds longer to render those divs and therefore causing the binding to trigger before there is anything to bind to. I understand Firebug can also slow-down the rendering process since it jumps-in at points to render the source in its frame.

To confirm it isn't this, try adding a setTimeout(function(){ ... }, 500) around your binding code (also maybe turning firebug off) to see whether it binds after that. If it does, then there's your problem.

Another approach may be to change your inputs into links and use event delegation to trigger the event: jQuery('.btnSave').live('click', function(){savePanel($('selector>for>panel')); })

digitala