开发者

Why does this function work for literals but not for more complex expressions?

开发者 https://www.devze.com 2022-12-09 03:58 出处:网络
I am having some insidious JavaScript problem that I need help with.I am generating HTML from a JSON structure.The idea is that I should be able to pass a list like:

I am having some insidious JavaScript problem that I need help with. I am generating HTML from a JSON structure. The idea is that I should be able to pass a list like:

['b',{'class':'${class_name}'}, ['i', {}, 'Some text goes here']]

...and get (if class_name = 'foo')...

<b class='foo'><i>Some text goes here.</i></b>

I use the following functions:

function replaceVariableSequences(str, vars) {
    /* @TODO Compiling two regexes is probably suboptimal. */
    var patIdent = /(\$\{\w+\})/;  // For identification.
    var patExtr = /\$\{(\w+)\}/;  // For extraction.

    var pieces = str.split(patIdent);

    for(var i = 0; i < pieces.length; i++) {
        if (matches = pieces[i].match(patExtr)) {
            pieces[i] = vars[matches[1]];
        }
     }

     return pieces.join('');
 }

function renderLogicalElement(vars, doc) {
    if (typeof(doc[0]) == 'string') {

        /* Arg represents an element. */

        /* First, perform variable substitution on the attribute values. */
        if (doc[1] != {}) {
            for(var i in doc[1]) {
                doc[1][i] = replaceVariableSequences(doc[1][i], vars);
            }
        }

        /* Create element and store in a placeholder variable so you can
           append text or nodes later. */

        var elementToReturn = createDOM(doc[0], doc[1]);

    } else if (isArrayLike(doc[0])) {

        /* Arg is a list of elements. */
        return map(partial(renderLogicalElement, vars), doc);

    }

    if (typeof(doc[2]) == 'string') {

        /* Arg is literal text used as innerHTML. */
        elementToReturn.innerHTML = doc[2];

    } else if (isArrayLike(doc[2])) {

        /* Arg either (a) represents an element
                   or (b) represents a list of elements. */
        appendChildNodes(elementToReturn, renderLogicalElement(vars, doc[2]));

    }

    return elementToReturn;
}

This works beautifully sometimes, but not others. Example from the calling code:

/* Correct; Works as expected. */
var siblings = findChildElements($('kv_body'), ['tr']);
var new_id = 4;

appendChildNodes($('kv_body'),
                 renderLogicalElement({'i开发者_如何学Cd': new_id},
                                      templates['kveKeyValue']));




/* Incorrect; Substitutes "0" for the expression instead of the value of
   `siblings.length` . */
var siblings = findChildElements($('kv_body'), ['tr']);
var new_id = siblings.length;  // Notice change here!

appendChildNodes($('kv_body'),
                 renderLogicalElement({'id': new_id},
                                      templates['kveKeyValue']));

When I trap out the first argument of renderLogicalElement() using alert(), I see a zero. Why is this?? I feel like it's some JavaScript type thing, possibly having to do with object literals, that I'm not aware of.

Edit: I have this code hooked up to the click event for a button on my page. Each click adds a new row to the <tbody> element whose ID is kv_body. The first time this function is called, siblings is indeed zero. However, once we add a <tr> to the mix, siblings.length evaluates to the proper count, increasing each time we add a <tr>. Sorry for not being clearer!! :)

Thanks in advance for any advice you can give.


If new_id is 0, doesn't it mean that siblings.length is 0? Maybe there is really no sibling.


Perhaps siblings.length is actually 0? Try debugging further (e.g. with Firebug)


OK, I fixed it. As it turns out, I was modifying my source JSON object with the first function call (because in JS you are basically just passing pointers around). I needed to write a copy function that would make a new copy of the relevant data.

http://my.opera.com/GreyWyvern/blog/show.dml/1725165

I ended up removing this as a prototype function and just making a regular old function.

0

精彩评论

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