开发者

Whats happening? One day its OK, the next day its 'undefined'?

开发者 https://www.devze.com 2023-03-03 13:00 出处:网络
I am writing a greasemonkey script. Recently i had this same problem twice and i have no idea why is this happening.

I am writing a greasemonkey script. Recently i had this same problem twice and i have no idea why is this happening.

function colli(){
.....
var oPriorityMass = bynID('massadderPriority');//my own document.getElementById() function
var aPriorities = [];
if (oPriorityMass) {
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
        if (bynID('adder' + sCollNumber + '_check').checked)
            aPriorities.push(parseInt(sCollNumber));
    }
}
.....
}

So the mystery of this is, one day i had oPriorityMass named as oPririoty. It was working fine, but the whole function was not yet complete and i started working on another functions for my script. These functions have no connection with each other.

Few days later i decided to go back to my function in the above example and finish it. I ran a test on it without modifying anything and got an error in the firefox's (4) javascr开发者_运维问答ipt error console saying that oPriority.chilNodes[cEntry] is undefined. NOTE, few days back i have tested it exactly the same way and there was no such problem at all.

Ok, so, i decided to rename oPriority to oPriorityMass. Magically, problem got solved.

At first i thought, maybe there was some conflict of 2 objects, with the same name being used in different functions, which somehow continued to live even outside of function scope. My script is currently over 6000 lines big, but i did a search and found out that oPriority was not mentioned anywhere else but in this exact function.

Can somebody tell me, how and why is this happening? I mentioned same thing happened twice now and they happened in different functions, but the same problem node.childNodes[c] is undefined yet node is not null and node.childNodes.length show correct child count. What is going on? How do i avoid such problems?

Thank you

EDIT: The error given by error console is Error: uncaught exception: TypeError: oPriorityMass.childNodes[cEntry] is undefined

In response to Brocks comment: GM_log(oPriorityMass.childNodes[cEntry]) returns undefined as a message. So node.childNodes[c] is the thing that is undefined in general.

My script creates a div window. Later, the above function uses elements in this div. Elements do have unique IDs and i am 100% sure the original site don't know about them. My script has a start/stop button to run one or the other function when i need to. I have been refreshing the page and running my script function now. I have noticed that sometimes (but not always) script will fail with the described error on the first run, however, if i run it again (without refreshing the page) it starts working.

The page has a javascript that modifies it. It changes some of it's element widths so it changes when the browser is resized. But i know it has no effect on my div as it is left unchanged when i resize browser.

EDIT2:

function bynID(sID) {
    return top.document.getElementById(ns(sID));
}
function ns(sText) {
    return g_sScriptName + '_' + sText;
}

ns function just adds the script name in front of the ID. I use it when creating HTML element so my elements never have the same id as the web page. So bynID() is simple function that saves some typing time when i need to get element by ID.

I have modified my colli() function to include check

if (oPriorityMass) {
    if (!oPriorityMass.childNodes[0]) {
        GM_log('Retrying');
        setTimeout(loadPage,2000);
        return;
    }
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
        if (bynID('adder' + sCollNumber + '_check').checked)
            aPriorities.push(parseInt(sCollNumber));
    }
}

The loadPage function does 1 AJAX call, then i run few XPATH queries on it, but the actual contents are never appended/shown on the page, just kept inside document.createElement('div'), then this function calls colli(). So now, as i have modified my function, i checked the error console and saw that it may take up to 5 tries for it to start working correctly. 5 x 2seconds, thats 10 seconds. It is never 5 retries always, may vary There's got to be something else going on?


In Firefox, childNodes can include #text nodes. You should check to make sure that childNodes[cEntry] has nodeType == 1 or has a getAttribute method before trying to call it. e.g.

<div id="d0">
</div>
<div id="d1"></div>

In the above in Firefox and similar browsers (i.e. based on Gecko and WebKit based browsers like Safari), d0 has one child node, a text node, and d1 has no child nodes.

So I would do something like:

var sCollNumber, el0, el1;

if (oPriorityMass) {
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        el0 = oPriorityMass.childNodes[cEntry];

        // Make sure have an HTMLElement that will
        // have a getAttribute method
        if (el0.nodeType == 1) {
          sCollNumber = el0.getAttribute('coll');
          el1 = bynID('adder' + sCollNumber + '_check');

         // Make sure el1 is not falsey before attempting to
         // access properties
         if (el1 && el1.checked)

            // Never call parseInt on strings without a radix
            // Or use some other method to convert to Number
            aPriorities.push(parseInt(sCollNumber, 10));
    }
}

Given that sCollNumber seems like it is a string integer (just guessing but it seems likely), you can also use:

Number(sCollNumber)

or

+sCollNumber

whichever suits and is more maintainable.


So, according to your last edit, it now works, with the delay, right?

But when I suggested the delay it was not meant to do (even more?) ajax calls while waiting!!

NOT:

if (!oPriorityMass.childNodes[0]) {
    GM_log('Retrying');
    setTimeout(loadPage,2000);
    return;

More like:

setTimeout (colli, 2000);

So the ajax and the other stuff that loadPage does could explain the excessive delay.


The random behavior could be caused by:

return top.document.getElementById(ns(sID));

This will cause erratic behavior if any frames or iframes are present, and you do not block operation on frames. (If you do block such operation then top is redundant and unnecessary.)
GM does not operate correctly in such cases -- depending on what the script does -- often seeming to "switch" from top scope to frame scope or vice versa.

So, it's probably best to change that to:

return document.getElementById (ns (sID) );


And make sure you have:

if (window.top != window.self)  //-- Don't run on frames or iframes
    return;

as the top lines of code.


Beyond that, it's near impossible to see the problem, because of insufficient information.

Either boil the problem into a Complete, Self Contained, Recipe for duplicating the failure.

OR, post or link to the Complete, Unedited, Script.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号