move markup after wp_query loop


Hi, I need to reconstruct DOM after the wp_query loop. The initial DOM's data-markup-ids are:

beans_main_grid
    first_news
    beans_primary
        article_0
        article_1

I need to bring article_0 up inside first_news, like this:

beans_main_grid
    first_news
        article_0
    beans_primary
        article_1

I alreay tried to set this after the loop:

beans_modify_action_hook( 'article_0', 'first_news_append_markup' );

but nothing happens. What am I doing wrong? Thanks!


Note: You cannot move a markup, you can only wrap/remove/modify it.

With beans you can do this structure:

[div] beans_main_grid
    [div] beans_primary
        [div] first_news
            [article] beans_post
        [article] beans_post
        [article] beans_post
        ...

Article's markup ID does not have any number on it to detect the first one, but there's a trick:

// wraps every article with 'first_news' markup.
beans_wrap_markup( 'beans_post', 'first_news', 'div', array(
    'class' => 'first-news',
) );

// removes 'first_news' markup for articles except the first one.
do_action( 'first_news_after_markup', function() {
    beans_remove_markup( 'first_news' );
} );

well, first of all thank you for answering! this is a huge mistake for me and I need to find a solution. I already tought about wrapping but this doesn't seem to be a valid option in this project.

I try explaining the "plot" in a more detailed way, hoping you can help me as best as possible. I'm working on this project as manteiner and I'm forced to keep the same structure. Until now the DOM replacement was done throught javascript on page load and CSS adjustments. This produces a unacceptable loading effect hugely visible in slow internet connections where the first article is loaded before the other elements that overlap it and, only at page load, get moved down to their place. I absolutely need to solve this behavior keeping the structure constraint.

The page is built through a custom template with a three columns layout:

'grid' => 10,
'sidebar_primary' => 3,
'sidebar_secondary' => 2

Then the new wp_query loop is generated and starts the population of the "beans_primary" grid assigning to each article the respective classes and attributes considering their order. Deactivating all the javascript and CSS stuff that produces the loading misbehaviors I get the following result:

<div class="uk-grid" data-uk-grid-margin="" data-markup-id="beans_main_grid">
    <div class="tm-primary uk-width-medium-5-10 uk-row-first" data-markup-id="beans_primary">
        <div class="uk-width-1-1 uk-width-medium-7-10" id="first-news" data-markup-id="first_news">
            <article id="post-32155" class="loop breaking-news " data-markup-id="article_0">
                <div class="meta-row">[...]</div>
                <a class="featured_image"><img src="..."></a>
                <a class="title"><h2>[...]</h2></a>
                <div class="excerpt">[...]</div>
                <div class="social-row">[...]</div>
            </article>
        </div>
        <div id="loop-wrapper" data-markup-id="loop_wrapper">
            <article id="post-32150" class="loop hot-news " data-markup-id="article_1">
                <div class="meta-row">[...]</div>
                <a class="featured_image"><img src="..."></a>
                <a class="title"><h2>[...]</h2></a>
                <div class="excerpt">[...]</div>
                <div class="social-row">[...]</div>
            </article>
            <article id="post-32148" class="loop hot-news " data-markup-id="article-32148">
                <div class="meta-row">[...]</div>
                <a class="featured_image"><img src="..."></a>
                <a class="title"><h2>[...]</h2></a>
                <div class="excerpt">[...]</div>
                <div class="social-row">[...]</div>
            </article>
            <article id="post-32136" class="loop four-loop " data-markup-id="article-32136">
                <div class="meta-row">[...]</div>
                <a class="featured_image"><img src="..."></a>
                <a class="title"><h2>[...]</h2></a>
                <div class="excerpt">[...]</div>
                <div class="social-row">[...]</div>
            </article>
            <article id="post-32134" class="loop four-loop " data-markup-id="article-32134">
                <div class="meta-row">[...]</div>
                <a class="featured_image"><img src="..."></a>
                <a class="title"><h2>[...]</h2></a>
                <div class="excerpt">[...]</div>
                <div class="social-row">[...]</div>
            </article>
            <article id="post-32131" class="loop four-loop " data-markup-id="article-32131">
                <div class="meta-row">[...]</div>
                <a class="featured_image"><img src="..."></a>
                <a class="title"><h2>[...]</h2></a>
                <div class="excerpt">[...]</div>
                <div class="social-row">[...]</div>
            </article>
            <article id="post-32129" class="loop four-loop " data-markup-id="article-32129">
                <div class="meta-row">[...]</div>
                <a class="featured_image"><img src="..."></a>
                <a class="title"><h2>[...]</h2></a>
                <div class="excerpt">[...]</div>
                <div class="social-row">[...]</div>
            </article>
        </div>
    </div>
    <aside class="tm-tertiary uk-width-medium-2-10 uk-width-small-4-10 uk-width-1-1" id="beans-secondary-sidebar" role="complementary" itemscope="itemscope" itemtype="https://schema.org/WPSideBar" tabindex="-1" data-markup-id="beans_sidebar_secondary">[...]</aside>
    <aside class="tm-secondary uk-width-medium-3-10 uk-width-small-6-10 uk-width-1-1" id="beans-primary-sidebar" role="complementary" itemscope="itemscope" itemtype="https://schema.org/WPSideBar" tabindex="-1" data-markup-id="beans_sidebar_primary">[...]</aside>
</div>

Which is visually represented by this schema: https://www.faxonline.it/assets/temp/schema_1.jpg While this is what I need to achieve: https://www.faxonline.it/assets/temp/schema_2.jpg Moving up only the primary sidebar in javascript and CSS, or keeping it anchored to the header somehow.

I thought that there must be a solution using beans framework structures instead of rewriting all the code right inside the wp_query while ( $loop->have_posts() ) but I need your help to figure it out...


...then use two WP_Query.

  • Create another loop for the top article.
add_action( 'beans_primary_before_markup', 'prefix_content_head' );
/**
 * This is added before primary.
 * Contains one article and the arrow up as shown in image...
 */
function prefix_content_head() {
    $one_post_query = new WP_Query( array(
        // use the same arguments like the other $loop you use in primary.
        // add this at the end of other arguments, replace with this it if it is set before.
        'post_per_page' => '1',
    ) );
    if ( ! $one_post_query->have_posts() ) {
        return; // no posts found, don't do anything.
    }
    $one_post_query->the_post();

    echo '<div class="uk-width-1-1">';
        echo '<article class="someClass">';
            the_title();
            the_excerpt(); // etc...
        echo '</article>';
        echo '<div class="theArrow">';
            // arrow up.
        echo '</div>';
    echo '</div>';

    wp_reset_postdata(); // reset query.
}
  • Set an offset of 1 after arguments used to the loop used on Primary section.
// find where
$loop = new WP_Query(
    array(
        // some args.
        // add offset after arguments.
        'offset' => '1',
    )
);

Other solution is to use CSS ONLY, but the top article must have a fixed height in pixels, at least on desktop view.

See EXAMPLE in (jsfiddle)


Well, I thought there would be a direct solution with the framework...

I already proposed all the possible wordpress core solutions, but there are constraints also inside the wp_query that must be evaluated considering values retrieved from a plugin. needs long time to tell...

In the end, leaving the "framework move" path, I'm adopting a different point of view approach which moves first article with jquery, again, but then adapts only the primary sidebar. In this way I reached the main goal to avoid graphical glitch of overlap the second sidebar and other articles over the first article and this is enough now.

Anyway... is there a particular reason why beans cannot move a markup? What does prevents you to public this kind of feature? I really think this would be hugely useful for most of us.

Thank you again for your support!


Anyway... is there a particular reason why beans cannot move a markup? What does prevents you to public this kind of feature? I really think this would be hugely useful for most of us.

Because Javascript selects the element itself and everything inside that element, while beans only selects the element. It is a limitation of how PHP & WordPress works.

What about Regex? Put this on top of your custom template (make a backup first) or in functions.php

// Start buffer, make article placement position using a HTML Comment.
add_action( 'beans_primary_before_markup', function() {
    ob_start();
    echo '<!-- article-placement -->';
} );

// Verify if buffer is cleared using first article, if no articles, clean it.
add_action( 'beans_primary_after_markup', function() {
    if ( apply_filters( 'prefix_has_article_buffer', true ) ) {
        ob_clean(); // clean buffer when no articles are displayed.
    }
} );

// Add a HTML comment before article 0 to identify it with Regex.
add_action( 'beans_article_0_before_markup', function() {
    echo '<!-- open-article-0 -->';
} );

// Replace markup using the buffer we started.
add_action( 'beans_article_0_after_markup', function() {
    echo '<!-- close-article-0 -->';
    $markup = ob_get_clean(); // get markup, clean buffer.

    if ( preg_match("/<!-- open-article-0 -->.+<!-- close-article-0 -->/sU", $markup, $match ) ) {
        $search = array( $match[0], '<!-- article-placement -->' );
        $replace =  array( '', $match[0] );

        // print out the new markup.
        echo str_replace( $search, $replace, $markup );
    }
    add_action( 'prefix_has_article_buffer', '__return_false' );
} );

The code is not tested, you should check if, Primary section has an markup ID beans_primary and the first article in loop should have an markup ID beans_article_0, then it will work.


Write a reply

Login or register to write a reply, it's free!