1

I'm trying to implement this feature request in SOUP, but I'm having trouble figuring out a good way to actually load the answers.

  • I can just load the full question page (like this one, for example) and extract the answers off of it with jQuery. However, this gives me a bunch on non-functional UI elements (like tabs and vote buttons) that I don't really want, and it also ends up re-running any scripts embedded on the page. Surprisingly, despite those issues, it still seems to more or less work, but I really don't like it.

  • I can use an API /questions/{ids}/answers query with filter=withbody to get the answer bodies in a JSON wrapper (example). This has kind of the opposite problem — I only get the HTML for the answer body, and would have to manually reconstruct all the surrounding "wrapper" HTML based on the metadata in the JSON response. I don't really like this option either, if only because I don't like my user scripts full of hardcoded HTML code.

  • Finally, the undocumented(?) URL used to fetch the question previews for the close-as-duplicate popup, /posts/popup/close/search-originals/1?q=/questions/{id}, gives me almost exactly the kind of HTML I want (example). Alas, it seems to only work for questions that are actually eligible for being marked as duplicates, i.e. those that have at least one accepted or upvoted answer.

So, does anyone know of a convenient way (officially documented or not) to load the full answers to a question, including an HTML wrapper similar to what would normally be shown on the close vote review page (example)?

1 Answer 1

1

The method I ended up using in SOUP 1.10 is the first one listed above — loading the full question page and stripping it down to match the review interface. Here's the core of the actual code:

var injectAnswers = function ( html ) {
    // new cleaner parsing!
    var parser = new DOMParser();
    var doc = parser.parseFromString( html, 'text/html' );
    var rawAnswers = doc.querySelectorAll('.answer');  // XXX: don't use .getElementsByClassName(), loop below needs a static NodeList!
    var answers = $('<div>'), n = 0;
    for (var i = 0; i < rawAnswers.length; i++) {
        if ( document.getElementById( rawAnswers[i].id ) ) continue;
        answers[0].appendChild( rawAnswers[i] );
        n++;
    }
    answers = answers.children();

    // mangle the answer wrappers to look like the review page before injecting them
    answers.find('.votecell button, .post-menu > *, .comments, .comments-link').remove();
    answers.find('.votecell .js-vote-count').after( function () {
        return '<div class="fs-caption fc-black-500 ta-center">vote' + ( this.textContent.trim() == 1 ? '' : 's' ) + '</div>';
    } );

    // inject answers into the review page
    var header = $('<div id="answers-header"><div class="subheader answers-subheader"><h2></h2></div></div>');
    header.find('h2').text( n + ( shown ? ' Other' : '') + ' Answer' + ( n == 1 ? '' : 's' ) );
    header.insertAfter( question );
    answers.insertAfter( header );
};

Here, url is the normal URL of the question (obtained from the link in the question title), question is the question div (with class "question") on the review page DOM and shown is the number of answers already shown on the review page (e.g. when reviewing an answer).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .