0

Though I see lots of posts about this overall topic (best way to get child nodes) I can't find anything regarding iteration and assignment in two-layer nested children. I have seen examples online of children being called with []'s and ()'s. Thanks in advance.

Let's assume I have this HTML and want a string of all the file names (excluding URL path or file extension) inside of the "sortable" UL element.

<ul id="sortable" class="ui-sortable">
    <li class="ui-state-default">
        <img id="aImg" alt="sortable image" src="images/a.jpg" />
    </li>
    <li class="ui-state-default">
        <img id="bImg" alt="sortable image" src="images/b.jpg" />
    </li>
    <li class="ui-state-default">
        <img id="cImg" alt="sortable image" src="images/c.jpg" />
    </li>
</ul>

My JavaScript looks like this:

 var theImageOrder = "";
 var theCounter = 0;
 while (theCounter < $('#sortable').children().length) 
 {
    var theImageName = $('#sortable').children(theCounter).children(0).attr("src").toString().substring($('#sortable').children(theCounter).children(0).attr("src").toString().lastIndexOf("/") + 1, $('#sortable').children(theCounter).children(0).attr("src").toString().lastIndexOf("."));
    theImageOrder = theImageOrder + theImageName;
    theCounter++;
}

I would expect the output would be abc but instead I'm getting aaa.

3
  • 1
    why dont you do a $.each() ?? Commented May 15, 2013 at 17:59
  • 1
    Instead of .children(theCounter), use .children().eq(theCounter), although there are much better ways to do this than this type of looping Commented May 15, 2013 at 17:59
  • 1
    I just made a jsfiddle earlier today answering a similar question. Check this out! Scroll past the giant object to see the JS and you might get a better idea of how .each itterates through objects. Commented May 15, 2013 at 18:03

4 Answers 4

4

An UL should have only LI children, and I'm guessing selecting images would be clever, as you're looking for the src attribute. $.map returns everyting in an array, you can choose to join it to get a string. Using > makes sure it's only direct children etc :

var images = $.map($('#sortable > li > img'), function(el,i) {
    return el.src.split('/').pop();
}).join(', ');

FIDDLE

Sign up to request clarification or add additional context in comments.

2 Comments

I forgot to mention, I'm dynamically forming the HTML for the images that appear in the "sortable" UL so I don't really know how many there nor what their names might be. Also, I don't believe I'm violating the (Only LI in UL) unless you're saying I shouldn't put IMG tags inside of LI tags, if that's the case can you link me something that supports that?
@Kulingar - You can put anything inside an UL, but usually only LI as direct children, everything else should be nested inside the list items (LI). It does'nt really matter how many images there are, as long as they are direct children of LI elements that themselves are direct children of the sortable UL. You used children() in your code in the question, wich finds only direct children, so I assumed that was what you wanted, if not, just remove the >sign in the selector.
4
var files = $('#sortable img').map(function(){
     return this.src.split('/').pop();
}).get();

http://jsfiddle.net/uyQXP/

1 Comment

There can be only one.... answer. But take solace in the fact that when multiple minds arrive independently at the same conclusion; it's lends credit to it's accuracy.
1

jQuery each() is most likely the answer you are looking for.

var theImageOrder = "";
$('#sortable > li > img').each(function(index, element){
    theImageOrder += element.attr('src').howeverYouWantToModifyThisString();
});

Comments

1

I put together a vanilla JS recursive example in ES6 that may help future onlookers:

let images = [];

const processChildrenNodes = (node, getNodeChildren) => {
  const nodeChildren = [...node.childNodes];

  for (const thisNode of nodeChildren) {
    if (getNodeChildren)
      processChildrenNodes(thisNode, true);

    if (thisNode.nodeName === 'IMG') {
      images.push(
        thisNode.getAttribute('src')
        .replace('.jpg', '')
        .split('/')
        .filter(item => item !== 'images')
      );
    }
  }
};

processChildrenNodes(document.getElementById('sortable'), true);

This will allow for you to look through all nodes children for an IMG, and then parse the images into an "images" array. This could be compacted even more using reduce, but I figured this would give you an easy option without Jquery.

The example above was tested on JSFIDDLE

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.