views:

58

answers:

2

I have a div with children that I need to crawl looking for specific links. The HTML looks like so:

<div id="ctl00_LeftNav">
    <h3>
        <a href="../App_Templates/#" rel="0">Menu 1</a></h3>
    <div>
        <p>
            <span>
                <div style="padding-left: 0px; font-weight: bold;">
                    <a href="javascript:OnLeftMenuSelection(1);">Opt 1</a></div>
                <div style="padding-left: 10px;">
                    <a href="javascript:OnLeftMenuSelection(56);">Opt 1a</a></div>
                <div style="padding-left: 0px; font-weight: bold;">
                    <a href="javascript:OnLeftMenuSelection(2);">Opt 2</a></div>
            </span>
        </p>
    </div>
    <h3>
        <a href="../App_Templates/#" rel="1">Menu 2</a></h3>
    <div>
        <p>
            <span>
                <div style="padding-left: 0px; font-weight: bold;">
                    <a href="javascript:OnLeftMenuSelection(33);">Opt 1</a></div>
                <div style="padding-left: 0px; font-weight: bold;">
                    <a href="javascript:OnLeftMenuSelection(34);">Opt 2</a></div>
                <div style="padding-left: 10px;">
                    <a href="javascript:OnLeftMenuSelection(42);">Opt 2a</a></div>
            </span>
        </p>
    </div>
    <h3>
        <a href="../App_Templates/#" rel="2">Menu 3</a></h3>
    <div>
        <p>
            <span>
                <div style="padding-left: 0px; font-weight: bold;">
                    <a href="javascript:OnLeftMenuSelection(58);">Opt 1</a></div>
                <div style="padding-left: 0px; font-weight: bold;">
                    <a href="javascript:OnLeftMenuSelection(59);">Opt 2</a></div>
            </span>
        </p>
    </div>
</div>

The Javascript that I have works fine in IE / Firefox, but fails in Chrome:

        function OnPageLoadCategorySelect(Category) {            
        var Root = $j('#ctl00_LeftNav').children();
        var Tab = 0;
        for (var i = 1; i < Root.length; i += 2) {
            var Menu = Root[i].firstChild.firstChild.childNodes;                
            var MenuLength = Menu.length;
            for (var j = 0; j < Menu.length; j++) {
                var Link = Menu[j].innerHTML;
                var Start = Link.indexOf('(');
                var End = Link.indexOf(')');
                var Res = Link.slice(Start + 1, End);
                if (Res == Category) {
                    SelectedTabIndex = Tab;                        
                    OnLeftMenuSelection(Category);
                    $j('#ShopTabs').show();
                    $j('#ctl00_LeftNav').accordion('activate', Tab);                      
                    return;
                }
            }                
            Tab++;                
        }
    }

In Chrome the 2nd for loop never executes because Menu.length is zero. What would be the best way to get these internal divs?

Solution

function OnPageLoadCategorySelect(Category) {
$j("#ctl00_LeftNav > div").each(function(Tab, el) {
            $j('a', this).each(function() {
                var id = $j(this).attr('href').replace('javascript:OnLeftMenuSelection(', '').replace(');', '');
                if (id == Category) {
                    SelectedTabIndex = Tab;
                    OnLeftMenuSelection(Category);
                    $j('#ShopTabs').show();
                    $j('#ctl00_LeftNav').accordion('activate', Tab);
                    return false; // exit the loop
                }
            })
        });
 }
+1  A: 

You should consider using jQuery.

$('#ctl00_LeftNav').children("div").each(function(index) {

   alert(index + ': ' + $(this).text()); // displays inner text of div

});

or this gets all children divs of the selector as pointed out by patrick

$('#ctl00_LeftNav > div').each(function(index) {

   alert(index + ': ' + $(this).text()); // displays inner text of div

});

Source: here for loops

gmcalab
Is there any way to just grab the div's and not the h3 tags? How would I do the internal loop?
Chris
I updated my answer so it grabs all children divs of the selector.
gmcalab
Wow, that's pretty simple. Thanks - going to give it a shot now.
Chris
This code would only look for divs that are **immediate children** of `#ctl00_LeftNav`. It would not traverse deeper descendants.
patrick dw
@patrick, yes i know. I gave him the basic idea where he should be able to get all the children he needs by using the basic idea of this.
gmcalab
Yea, it got me off to the right start. Just nested the .each's. Going to test it in all the browsers soon.
Chris
@gmcalab - Unfortunately, your second solution does the exact same as the first. Using `>` limits the selection to **immediate children**. `$('#ctl00_LeftNav > div')` selects immediate child divs, `$('#ctl00_LeftNav div')` selects **all** child divs. *Without additional code like Doug Neiner offered, it would never select the desired divs.*
patrick dw
+1  A: 

If I understand your code correctly, replace your whole function with this:

function OnPageLoadCategorySelect(Category) {
  $j("#ctl00_LeftNav > div").each(function(Tab, el){
      $j('a', this).each(function(){
          var id = $j(this).attr('href').replace('javascript:OnLeftMenuSelection(','').replace(')','');
          if( id == Category ) {
              SelectedTabIndex = Tab;                        
              OnLeftMenuSelection(Category);
              $j('#ShopTabs').show();
              $j('#ctl00_LeftNav').accordion('activate', Tab);                      
              return false; // exit the loop
          }
      })
  });
}

The first parameter of the each function is the zero based index. By supplying Tab, it counts it up for you.

Doug Neiner
Wow, thanks Doug. Just started writing my own, but this I'll try this when mine fails....
Chris
Didnt work. When I step through it with firebug it just skips right over the '$j("#ctl00_LeftNav > div").each(function(Tab, el)'.
Chris
@Chris, the selector I provided would work for the HTML you provided. Chances are, the ID has changed, or the HTML is not the same (meaning, the `div` is not a direct child of the `#ctl00...`). If you view the source of the page (**not** Firebug source), is it the same as you posted above?
Doug Neiner
@Chris - In addition to Doug's suggestion, have you made a call to `jQuery.noConflict()` before using the '$j' alias?
patrick dw
Got it. Yep its the same - the id was taking the ending ';'. Just replaced **.replace(')','');** with **.replace(');','');**. It works!
Chris
And in Chrome. Have to try Safari later - but looks great.
Chris
@Doug - Out of curiosity, why the nested `each()` instead of utilizing jQuery's selector features? Is there something I'm missing?
patrick dw
@patrick Only because he needed a index counter of `Tab`. I could have just searched the `a` elements, then used a combination of `closest('#ctl_000LeftNav > div')` and `index()` but this seemed more straight forward.
Doug Neiner
@Doug - Ah, got it. Thank you for the response.
patrick dw