web-dev-qa-db-fra.com

Site à une seule page + PushState?

J'ai un site d'une seule page avec des articles qui sont chargés via Ajax sur la même page via slide down div. Lorsqu'un message est "activé", je souhaite que cet état soit défini de manière à ce que, lorsque je visite directement l'URL, il se connecte à ce message spécifique qui apparaît déjà dans le div.

Ma question est:

Est-ce que je crée les articles dans single.php et les appelle moins l'en-tête et le pied de page? Ou dois-je créer le modèle dans le cadre de la fonction Ajax? N'oubliez pas que ma prochaine tâche serait de trouver comment implémenter history.js afin que les états soient définis dans l'url, la pile d'historique, etc.

Voici ma fonction Ajax:

function my_load_ajax_content () {

    $args = array(
        'p' => $_POST['post_id'],
        'post_type' => 'projects'
        );

    $post_query = new WP_Query( $args );
    while( $post_query->have_posts() ) : $post_query->the_post(); ?>

    <div class="post-container">
        <div id="project-left-content">
            <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
            <?php the_content(); ?>

            <!-- If there is a URL -->
            <?php if( get_field('url') ): ?>
                <a href="http://<?php the_field('url'); ?>" target="_blank"><?php the_field('url'); ?></a>
            <?php endif; ?>
        </div>
        <div id="project-right-content">

            <?php if( have_rows('slides') ): ?>

                <div id="slider">

                    <!-- Slider Setup -->
                    <?php if( have_rows('slides') ):
                        $slideNumber = 0;
                        while ( have_rows('slides') ) : the_row();
                        $slideNumber++;
                    ?>

                        <input type="radio" name="slider" id="slide<?php echo $slideNumber; ?>">

                    <?php endwhile;endif; ?>

                    <!-- Slide -->
                    <?php if( have_rows('slides') ): ?>
                        <div id="slides">
                            <div id="overflow">
                                <div class="inner">

                                    <?php if( have_rows('slides') ):
                                    while ( have_rows('slides') ) : the_row();

                                        $slideImage = get_sub_field('slide_image');
                                    ?>

                                    <article>
                                        <img src="<?php echo $slideImage; ?>" alt="<?php the_title(); ?>">
                                    </article>

                                    <?php endwhile;endif; ?>

                                </div><!-- #inner -->
                            </div><!-- #overflow -->
                        </div><!-- #slides -->

                    <?php endif; ?>

                    <!-- Controls -->
                    <?php if( have_rows('slides') ):
                        $slideNumber = 0;
                    ?>
                        <div id="active">

                            <?php while ( have_rows('slides') ) : the_row();
                                $slideNumber++;
                            ?>
                                <label for="slide<?php echo $slideNumber; ?>"></label>
                            <?php endwhile; ?>

                        </div><!-- #active -->
                    <?php endif; ?>
                </div><!-- #slider -->
            <?php endif; ?>
        </div><!-- #project-right-content -->
    </div><!-- .post-container -->

    <?php
    endwhile;
    wp_die();
}

add_action ( 'wp_ajax_nopriv_load-content', 'my_load_ajax_content' );
add_action ( 'wp_ajax_load-content', 'my_load_ajax_content' );

Voici une version simplifiée de mon appel Ajax:

$('.post-link').on('click', function(e) {
    e.preventDefault();

    var post_id = $(this).data('id'),
        projectTitle = $(this).data('title'),
        ajaxURL = site.ajaxurl;

    $.ajax({
        type: 'POST',
        url: ajaxURL,
        context: this,
        data: {'action': 'load-content', post_id: post_id },
        success: function(response) {
            $('#project-container').html(response); // response
            return false;
        }
    });
});

Voici mon HTML:

<div id="project-container"></div>
<div id="projects-list">

    <!-- Start the loop -->
    <?php $home_query = new WP_Query('post_type=projects');

    while($home_query->have_posts()) : $home_query->the_post(); ?>

    <article class="project">
        <?php the_post_thumbnail( 'home-thumb' ); ?>
        <div class="overlay">
            <a class="post-link" href="<?php the_permalink(); ?>" data-id="<?php the_ID(); ?>" data-title="<?php the_title(); ?>">+</a>
        </div>
    </article>

    <?php endwhile; ?>
    <?php wp_reset_postdata(); // reset the query ?>

</div><!-- #projects-list -->

Si quelqu'un pouvait me montrer le chemin, je l'apprécierais vraiment. Il semble que je ne trouve pas beaucoup d’informations sur des sites WordPress d’une page et sur l’historique HTML5.

Edit: Mise à jour de la fonction Ajax vers la version complète (auparavant simplifiée).

1
Desi

J'ai fait quelque chose de similaire sur einsteinworld.com .

La façon dont je l'ai fait était d'utiliser une fonction dans functions.php pour obtenir et restituer le contenu, puis j'ai appelé la même fonction depuis single.php ou via ajax selon le scénario.

Ainsi, vous pouvez soit utiliser le $ post global pour accéder directement à la page, ou simplement transmettre l'identifiant du post via ajax et une requête pour $ post. N'oubliez pas de wp_localize_script et ajoutez votre fonction à utiliser avec ajax

Utilisez History.pushState pour pousser le lien permanent du message lorsqu'il est appelé via ajax.

Voici le code squelette

/* In $(document).ready... */

History.pushState(null, [next-page-title], [next-page-url]);

$().update_content({
  post_id   : [next-page-id]
});


/* js function */

$.fn.update_content = function(args){

  var data = {
    action  : 'my_function',// in functions.php
    post_id : args['post_id']
  };

  $.post( MyAjax.ajaxurl, data, function(response) {
    if( response != 0 ){
      // put the returned content in the DOM
    }else{
      // Do something else      
    }
  });
};

/* in functions.php */

function my_function(){
  if( isset( $_POST['post_id'] ) ){
    $post = get_post( $_POST['post_id'] );
    $ajax = true;
  }else{
    $ajax = false;
  }

  echo [html-to-display-the-post-content]

  // if this is ajax'd stop the output
  if( $ajax )
    die();
}

Update Le site référencé ci-dessus n'est plus actif, mais la réponse fonctionne toujours :)

0
shahar

Je dirais que cela dépend principalement de la complexité des messages que vous chargez.

S'ils sont aussi simples que ...

<div class="post-container">
        <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
        <?php the_content(); ?>
</div><!-- .post-container -->

... Je viens de mettre cela dans le AJAX gestionnaire et en finir avec cela.

Si les articles sont plus complexes, vous voudrez peut-être simplement utiliser les données nues sous forme de fichier JSON via AJAX et en créer le code HTML côté client, en utilisant peut-être même un framework frontal.

history.js devrait être facile à mettre en œuvre (et serait probablement mieux aussi en tant que question distincte). En tous cas:

History.pushState({post_id:1}

History.Adapter.bind(window,'statechange',function(){
    var State = History.getState(); // {"post_id":1}
    //AJAX Call
});

... devrait vous apporter la majeure partie du chemin.

Si vous développez un peu plus sur les détails, je peux améliorer cette réponse.

0
kraftner

Deux manières assez simples auxquelles je peux penser:

  1. Utilisez le résultat de votre fonction my_load_ajax_content pour dessiner <div id="project-container"></div> lors du premier rendu de la page.
  2. Lorsque la page se charge, déclenchez votre bouton de clic.
$(window).on('load', function(){
    $('.post-link').first().trigger('click');
});

Tant que jQuery est chargé et que vous affichez les publications les plus récentes en haut, les informations ci-dessus devraient automatiquement déclencher votre code lors de votre première visite sur la page.

Si vous ne souhaitez pas publier le message le plus récent dans la div et le haut de la page, vous pouvez ajuster votre modèle de page de manière à ne pas dessiner le message le plus récent (par exemple, le premier de la liste) en le sautant, en utilisant filtre pré-get-posts, etc.

0
Privateer