views:

343

answers:

1

Related to my earlier question (thanks for your response Cryo), I have a further question for the javaScript mavens here.

Given an html structure like this:

<content>
    <div entry>
        <div rubric>
            <a name>
        </div>
        <div content block>
            <p>
            <a links>
        </div>
    </div entry>
    .
    .
    . multiple identical entry divs

</content>

Using jQuery I wanted to find a given anchor name, and return the whole html markup of its containing entry div, with a new classname, as a string that can be passed to shadowbox's html player like this:

"""
<div newclassname>
    <div rubric>
        <a name>
    </div>
    <div content block>
        <p>
        <a links>
    </div>
</div>
"""

The following code does this, but with one wrinkle, it reverses the document order of <div rubric> and <div content block>.

var $pageEntry = null;

jQuery.get('thatPage.html', function(data){
    $pageEntry = jQuery(data).find("#content");
});

function displayEntry(entry){
    html = $pageEntry.find("a[name='" + entry + "']")
        .parent()
        .siblings()
        .andSelf()
        .wrapAll('<div class="newclassname"></div')
        .parent()
        .parent()
        .html()

    Shadowbox.open({
        options: {
            enableKeys: false
        },
        player: 'html',
        content: html
    });
};

Can anyone suggest a less verbose jQuery chain that retains the document order of the elements in the returned string? Any helpful suggestions or observations would be welcome. If there's a more straightforward way to do this in straight js, I'd love to know that too.

Thanks,

jjon

update: the answer thanks to comments from Pointy:

elem = $("#content")
.find("a[name=entry]")
.parent()
.parent()
.wrapAll('<div class="new"></div')
.parent()
.html()
A: 

Well, the simplest thing to me would be to make sure that the pairs of rubric and content blocks shared some sort of class marker. Then you could go up from the links all the way to the outer container and find the 2 divs of interest.

[edit] oh wait - they're already inside an "entry" div, is that right? Well if there's always a container around each rubric/content div pair, then why not go up from the "a" tag to that level and then get the children divs?

// ...
html = $pageEntry.find('a ... ')
  .parent().parent()
  .children()
  .wrapAll('<div class="newclassname"/>')
  // ...
Pointy
Right, if all I needed was the child elements of the entry div, that would work fine, but I need to return the html string of the whole of entry div, not just its contents. Another way to put the problem might be: How can I return the html of the element containing the named anchor?
jjon
Sorry to be dense, but "the whole of entry div, not just its contents" doesn't make sense to me. What is the whole of entry div besides its contents? Or why not just change the class name on entry div to the new name, grab the html, and then change the class name back?
Pointy
Pointy, thanks, I'm the one being dense. "the whole of entry div", that is:"<entry><rubric><content></entry>" not just"<rubric><content>", its the string I need, not the contained elements.but your comment was a big help actually. Now I have this chain which, though still long, is more compact and does what I want:elem = $("#content").find("a[name=entry]").parent().parent().wrapAll('<div class="new"></div').parent().html()it dawned on me that after wrapping <entry>, the context was the newly created div. So I only had to go up one level and then call .html()Many thanks
jjon