views:

294

answers:

2

I am trying to do a text replace, but to do so, i need to loop through the text nodes of a div.

Each Div upon clicking, loads via ajax it's appropriate content. But then I need to do text-replacing inside any of the text nodes inside there.

My current code, after loading the ajax content, loops through all text nodes of the whole page, and therefore is too resource intensive.

I have been looking for hours trying to find out how to both loop thru a div, and get the text nodes...

and this has to work in firefox, google chrome and ie6.

Any thoughts or suggestions?

As Requested, here is the code:

function ajaxLoader(url, id) {
    if (document.getElementById) {
        var x = (window.ActiveXObject) ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
    }
    if (x) {
        x.onreadystatechange = function () {
            if (x.readyState == 4 && x.status == 200) {
                el = document.getElementById(id);
                el.innerHTML = x.responseText;
            }
        }
        x.open("GET", url, true);
        x.send(null);
    }
    // alert(id);
    CheckTranslate(id);
    // setTimeout('CheckTranslate(this);', 1000);

}

function CheckTranslate(id) {

    // function to get text of a node
    var content = function (node, txt) {
        if (txt) {
            if (node.textContent) {
                node.textContent = txt;
            } else if (node.nodeValue) {
                node.nodeValue = txt;
            }
        } else {
            return node.textContent ? node.textContent : node.nodeValue;
        }
    };
    // recuse div by id content
    $("#"+id).each(function() {
        // assign object handler
        var obj = $(this).html();

        // check how many text nodes there
        var mylen = obj.length;

        if (mylen > 0) {
            // loop thru each text node
        }
    });
    // recurse ajax content
    (function (parent) {
    var childs = parent.childNodes;

    // if there are children to this
    if (childs && childs.length) {

        // loop through each text node
        for (var i = 0, node; node = childs[i]; i++) {

        // text node found, do the replacement          
        if (node.nodeType == 3) { 

            // grab value of current text node
            var value = content(node);

            // grab class name of current text node
            var myclass = $(this).attr("class");

            // grab data property of this node
            var ist = $(this).data('translated');

            // check if this is correct class and has no data property and value is not undefined
            if (typeof(value) != 'undefined' && myclass != 'box_title' && ist != 'yes' && (myclass == 'status_bar' || myclass == '' || myclass == 'box_title_small' || myclass == 'status_bar_select')) {

                // loop thru english array to find matches
                for (var x = 0; x < en_count; x++) {

                    // get current english phrase
                    var from = en_lang[x];

                    // get current other language phrase
                    var to = other_lang[x];

                    if (value.match(from)) {

                        content(node, value.replace(from, to));
                        if ($.browser.msie == 'false') {
                            $(node).data('translated', 'yes');
                        }
                    }
                    // end check value match
                }
            }
        } else {
            arguments.callee(node);
        }
    }
    }
    })(document.body);
}   

There are 2 functions, ajaxLoader, which loads the ajax content for divs, and then the CheckTranslate, which does translation after the new content is loaded.

The problem being is the function(parent) section looks at all text nodes, where for performance, i'd rather only look at text nodes inside the div.

But I just don't get how to refer to those...

It is very hard to figure this kind of stuff out, and jquery's documentation is not really easy to learn...

A: 

Looking for something like this?

$(".your_ajax_div_class").each(function(i){});

You could probably append or nest this or something similar inside your ajaxComplete() function to trigger once the content has loaded.

Todd
but how to do identify and get the text nodes inside my div? and no i can not use class name, but in my code the id of the div is being passed.So I do have access to that.
crosenblum
It would help to see an example of what you're trying to do as far as your find/replace. Are you trying to get to particular children nodes of the DIV? If not, inside the function I posted, just access $(this).html() to access the inner HTML of the DIV.
Todd
A: 

I'm sure there's a better way to do this, but in plain javascript, you can just write a recursive function:

function ReplaceChildText(node, findText, replaceText) {
    if (node.nodeType == 3) {
        node.innerHTML = node.innerHTML.replace(findText, replaceText);
    } else {
        for (var child in node.childNodes) {
            ReplaceChildText(child, findText, replaceText);
        }
    }

You can call it like this:

ReplaceChildText(document.getElementById('divID'),'findText','replacement');
tloflin
My problem being is how to do so only inside a div. Not through out the whole page. I have a totally seperate piece of code that just does that part.
crosenblum
If you just pass the div in when you call the function, it will only process the div and its children...
tloflin
Can I loop thru each text node inside the div?
crosenblum
Yes, that's what it does. Whatever you pass it, it looks at to see if it's a text node. If so, it does a text replace. If not, it loops through each of its child nodes and does the same to them.
tloflin
I am sorry but that is just not working for me. Is there perhaps a way to change parent.childNodes to refer to the childnodes of the div id?
crosenblum
Is it just that you didn't know how to get the div you wanted? I'm unclear on how this isn't working for you. This function *only* checks the children of the div that you pass it. Did you mean that you don't want it to be recursive? E.g. if you had a `p` inside your div, you don't want it to replace any text inside that `p`?
tloflin
Here is the basic logic.1. loop thru each seperate text inside a div2. loop thru number of phrases stored in array3. compare node phrase with phrase inside array, if match replacethe problem is that i need to seperate out each text node, rather than do a search/replace against all text inside div.
crosenblum
Looking back at your source code, have you tried just replacing `document.body` with `document.getElementById('myDivID')`? Also, it would probably be easier if you gave your recursive function a name and called it separately instead of using an anonymous function.
tloflin
By the way, when you said, "i need to seperate out each text node, rather than do a search/replace against all text inside div", I think you've demonstrated a bit of a problem. *All* the text inside a div will be in a text node. That's what a text node is; it's a piece of text. Even if you've got a span or something, the text inside the span is really inside a text node inside the span.
tloflin
So there is no way to treat each word inside the div, as seperate?
crosenblum
Uh, not really. A text node is just a bunch of text, it doesn't split into words or anything automatically. You could build a function to parse through each text node and split it into an array of words... Why, though, wouldn't a search/replace on the entire text node work for you?
tloflin
Just to be sure we're getting our terminology right: `<div>This is some text. <span>This is some more.</span></div>` contains two text nodes. The first, containing "This is some text. ", is a direct child of the div. The second, containing "This is some more.", is a child of the span, which is a child of the div.
tloflin
Okay I think I understand now.
crosenblum
If it helps any, it should be pretty easy to split into words if that's really what you want to do. Just use `textNode.innerHTML.split(" ")`, which will return an array split on spaces.
tloflin
What I would rather do, is modify my current code, and somehow limit it to the div content, instead of the whole page content, as it does with var childs = parent.childNodes. I just don't understand the sytnax of how to do that.
crosenblum
I don't think I understand what you mean. If you specify the div as the parent node (call your function on `document.getElementById('divID')` instead of `document.body`), the childnodes *will* be limited to that div, and will *not* affect the entire page content. Are you saying that doesn't work, and somehow *still* replaces the text over the entire page?
tloflin