admin管理员组

文章数量:1319484

I'm having problems with debugging DOM changes introduced by some JavaScript code I'm running. Somewhere in the code an element's class is changed, and I'm trying to pinpoint where exactly. Unfortunately, the new class name is so generic that searching through all the JS code gives too many results to be a viable option.

I've tried debugging a bit with Firebug, but despite the nice "Break on Attribute Change" feature, I can't get it to work in a way I would want. The Firebug demo works correctly, but it's a post load situation.

The problem seems to be that I want to watch for mutations before the page is fully loaded. I assume that the changes occur somewhere in $(document).ready(), so it's in the DOM, but I can't select elements for UI breakpoints as would be the case with the demo (after page load).

Is there some way to debug this kind of situation other than grepping/going through the code by hand?

I'm having problems with debugging DOM changes introduced by some JavaScript code I'm running. Somewhere in the code an element's class is changed, and I'm trying to pinpoint where exactly. Unfortunately, the new class name is so generic that searching through all the JS code gives too many results to be a viable option.

I've tried debugging a bit with Firebug, but despite the nice "Break on Attribute Change" feature, I can't get it to work in a way I would want. The Firebug demo works correctly, but it's a post load situation.

The problem seems to be that I want to watch for mutations before the page is fully loaded. I assume that the changes occur somewhere in $(document).ready(), so it's in the DOM, but I can't select elements for UI breakpoints as would be the case with the demo (after page load).

Is there some way to debug this kind of situation other than grepping/going through the code by hand?

Share Improve this question asked Apr 30, 2011 at 13:12 Karol J. PiczakKarol J. Piczak 5851 gold badge5 silver badges25 bronze badges 4
  • 2 Use the script tab and set breakpoints. If you're using a mess of closures with jQuery, you may want to explore a module approach so you can accurately describe your code and detect gets or sets. – rxgx Commented Apr 30, 2011 at 13:36
  • 1 I'm afraid manually setting up code breakpoints is no better than logically browsing through the whole codebase. What I hoped for is applying Break on Attribute Change functionality after the DOM is ready, but before a full page load occurs. But I have yet to find a way to achieve it in Firebug. Even if I manually break in $(document).ready() I'm not able to freely inspect the document. I don't know if it's a limitation/bug/by design. After a plete page load further debugging works fine, but it's water over the dam, the changes are already in place. – Karol J. Piczak Commented Apr 30, 2011 at 16:26
  • 1 And the whole issue is bearable if you more or less know the codebase, but diving into open source projects you have no experience with makes for a painfully slow debugging sessions. So that's why I'm looking for a way to speed things up a bit. – Karol J. Piczak Commented Apr 30, 2011 at 16:28
  • 1 Thank you for all your answers, it was hard to choose whom to award the bounty, but in the end I decided @jsgoupil's answer was first and helpful. For more plex non-jQuery mutations I would probably choose some other tricks presented here. Thanks! – Karol J. Piczak Commented May 6, 2011 at 10:06
Add a ment  | 

4 Answers 4

Reset to default 4 +50

I propose that you remove the target element where its classname is changed. With some luck, you may be able to generate an error in the JavaScript code, so you will find where is your problem.

Otherwise, if it's done by JQuery (addClass), you may want to modify the JQuery code itself just to figure out the callstack.

The code would look like this (make sure this code is the first code called after JQuery inclusion):

(function () {
    var addClass = jQuery.fn.addClass;
    jQuery.fn.addClass = function (value) {
        for (var i = 0, l = this.length; i < l; i++) {
            // Here you put your method to start the debugger if you get your right element
            if (this[i].id === "abc") {
                debugger;
            }
        }
        addClass(value);
    }
})();

Hope that helps.

This answer may sound pretty lame, but I honestly think the best solution for bugs like this is "deconstructing" your program. Just make a copy of the entire project, then rip it apart. Take out chunks of code one by one. Turn function calls into stub functions or whatever to keep things running. Find the minimal amount of code that triggers the bug. Then the solution should be obvious.

Have you considered adding a mutation event? The event I think you want, DOMAttrModified, is not supported in webkit, so you might have to test with Firefox or Opera. In fact it is deprecated in DOM level 3.

There are two jQuery plugins for mutation events here (documentation) and here but since you want to do this before page load they might not be the answer.

You are probably best writing your own JavaScript bind for this event - there is an example in the answer to is there an alternative to DOMAttrModified that will work in webkit

I hope this helps.

If you want to use the "Break on Attribute Change" feature to debug, you can do the following:

  1. Comment out all JS in the page (which is hopefully all in the head) except for the base jQuery load.

  2. Load the page and set your watch points.

  3. Add a button, which fires the JS, to the HTML. Or, optionally fire it from the console.

  4. Trigger the JS load/fire. Hopefully your watch and break points will fire as desired.

For example, suppose your page loads/has:

<script src="http://ajax.googleapis./ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
<script src="/Library_X.js" type="text/javascript"></script>
<script src="/MyJS.js" type="text/javascript"></script>

Then you could run this code in the console after setting the watch points:

function addJS_Node (text, s_URL)
{
    var scriptNode                      = document.createElement ('script');
    scriptNode.type                     = "text/javascript";

    if (text)  scriptNode.textContent   = text;
    if (s_URL) scriptNode.src           = s_URL;

    document.head.appendChild (scriptNode);
}

addJS_Node (null, '/Library_X.js');
//-- Possible pause here.
addJS_Node (null, '/MyJS.js');
// etc.

Or temporarily code a button that fires the same JS, into the page's HTML.

本文标签: javascriptDebug DOM mutations with Firebug before page loadStack Overflow