Utiliser AJAX en shortcode

9

J'ai le code suivant dans le shortcode pour afficher un devis aléatoire. Question: comment faire afficher à un bouton un nouveau devis aléatoire? Je veux dire, cela frapperait le bouton et vous montrerait une nouvelle citation (sans rafraîchir la page bien sûr).

function random_quote() {

    // quotes file
     $array = file("/path to txt file");

    // generate a random number between 0 and the total count of $array minus 1
    // we minus 1 from the total quotes because array indices start at 0 rather than 1 by default
    $r = rand(0,count($array)-1);

    // return the quote in the array with an indices of $r - our random number
    return $array[rand(0,count($array)-1)];
}

add_shortcode( 'randomquotes', 'random_quote');

Je voudrais savoir comment mettre à jour le contenu de la page en utilisant ajax dans WordPress? Dans ma situation, car en fait être exactement cela.

Désolé pour mon mauvais anglais. J'espère que tu me comprends. Merci!

user23769
la source

Réponses:

4

Tout d'abord, c'est très limite dans le cadre de WPSE, c'est tout.
Mis à part le shortcode pour déclencher la sortie HTML initiale, c'est vraiment juste AJAX.

Quoi qu'il en soit, cela étant dit, voici comment cela se fait:

Le PHP

En supposant que l'extrait PHP ci-dessus que vous avez fourni soit fonctionnel, placez ce qui suit dans un fichier php pour l'appel ajax:

/wp-content/themes/%your_theme%/js/ajax-load-quote.php

 <?php
 /* uncomment the below, if you want to use native WP functions in this file */
// require_once('../../../../wp-load.php');

 $array = file( $_POST['file_path'] ); // file path in $_POST, as from the js
 $r = rand( 0, count($array) - 1 );

 return '<p>' . $array[$r] . '</p>';
 ?>

Pour référence future et afin de rendre cette réponse utile aux autres: Notez que cela wp-load.phpdoit être inclus afin d'utiliser la fonctionnalité native de WordPress. Le cas le plus courant est probablement le besoin de WP_Queryou $wpdb.

La structure HTML

Dans un contenu de page, un widget ou un fichier modèle:

<div id="randomquotes">
    <p>I would rather have my ignorance than another man’s knowledge,
       because I have so much more of it.<br />
       -- Mark Twain, American author & Playwright</p>
</div>
<a id="newquote" class="button" href="#" title="Gimme a new one!">New Quote</a>

Vous pouvez évidemment ajuster cela à votre guise, mais pour cet exemple, c'est ce que nous allons faire.
Nous générerons ce qui précède via un shortcode plus tard.

La jQuery

/wp-content/themes/%your_theme%/js/ajax-load-quote.js

function ajaxQuote() {
    var theQuote = jQuery.ajax({
        type: 'POST',
        url: ajaxParams.themeURI+'js/ajax-load-quote.php',
        /* supplying the file path to the ajax loaded php as a $_POST variable */
        data: { file_path: ajaxParams.filePath },
        beforeSend: function() {
            ajaxLoadingScreen(true,'#randomquotes');
        },
        success: function(data) {
            jQuery('#randomquotes').find('p').remove();
            jQuery('#randomquotes').prepend(data);
        },
        complete: function() {
            ajaxLoadingScreen(false,'#randomquotes');
        }
    });
    return theQuote;
}
/* Loading screen to be displayed during the process, optional */
function ajaxLoadingScreen(switchOn,element) {
    /* show loading screen */
    if (switchOn) {
        jQuery(''+element).css({
            'position': 'relative'
        });
        var appendHTML = '<div class="ajax-loading-screen appended">
            <img src="'+ajaxParams.themeURI+'images/ajax-loader.gif"
                alt="Loading ..." width="16" height="16" /></div>';
        if( jQuery(''+element).children('.ajax-loading-screen').length === 0 ) {
            jQuery(''+element).append(appendHTML);
        }
        jQuery(''+element).children('.ajax-loading-screen').first().css({
            'display': 'block',
            'visibility': 'visible',
            'filter': 'alpha(opacity=100)',
            '-ms-filter': '"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"',
            'opacity': '1'
        });
    } else {
        /* hide the loading screen */
        jQuery(''+element).children('.ajax-loading-screen').css({
            'display': '',
            'visibility': '',
            'filter': '',
            '-ms-filter': '',
            'opacity': ''
        });
        jQuery(''+element).css({
            'position': ''
        });
    }
}
/* triggering the above via the click event */
jQuery('#newquotes').click( function() {
    var theQuote = ajaxQuote();
    return false;
});

L'assemblage dans functions.php

Sous votre extrait ci-dessus (que vous trouverez inclus modifié ci-dessous), collez ce qui suit:

function random_quote( $atts ) {
    /* extracts the value of shortcode argument path */
    extract( shortcode_atts( array(
        'path' => get_template_directory_uri() . '/quotes.txt' // default, if not set
    ), $atts ) );
    $array = file( $path );
    $r = rand( 0, count($array) - 1 );
    $output = '<div id="randomquotes">' .
            '<p>' . $array[$r] . '</p>' .
        '</div>' .
        '<a id="newquote" class="button" href="#" title="Gimme a new one!">New Quote</a>';
    /* enqueue the below registered script, if needed */
    wp_enqueue_script( 'ajax-quote' );
    /* supplying the file path to the script */
    wp_localize_script(
        'ajax-quote',
        'ajaxParams',
        array(
            'filePath' => $path,
            'themeURI' => get_template_directory_uri() . '/'
        )
    );
    return $output;
}
add_shortcode( 'randomquotes', 'random_quote');
/* register the js */
function wpse72974_load_scripts() {
    if ( ! is_admin() ) {
        wp_register_script(
           'ajax-quote', 
            get_template_directory_uri() . '/js/ajax-load-quote.js',
            array( 'jquery' ),
            '1.0',
            true
        );
    }
}
add_action ( 'init', 'wpse72974_load_scripts' );

Facultatif: le css pour l'écran de chargement

.ajax-loading-screen {
    display: none;
    visibility: hidden;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    background: #ffffff; /* the background of your site or the container of the quote */
    filter: alpha(opacity=0);
    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
    opacity: 0;
    -webkit-transition:  opacity .1s;
    -moz-transition:  opacity .1s;
    -ms-transition:  opacity .1s;
    -o-transition: opacity .1s;
    transition: opacity .1s;
    z-index: 9999;
}
.ajax-loading-screen img {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -8px 0 0 -8px;
}

Ressources / Lecture

Johannes Pille
la source
1
Une raison de ne pas utiliser l'API AJAX intégrée?
fuxia
@toscho Honnêtement - pas trop familier avec ça. Vaut la peine d'être lu?
Johannes Pille
Oui absolument. :) Je vais ajouter une alternative.
fuxia
Parfait! Merci! <br/> Un script fonctionnera, si vous définissez l'argument de la fonction? Par exemple, être dans le shortcode pour fournir un lien vers un fichier texte? <br/> function random_quote ($path) {      $ array = file ("$ path");<br/> ... [randomquote file = "http://exampe.com/file.txt"]<br/> Alors ça va marcher? Je ne connais pas trop la programmation.
user23769
J'ai mis à jour la réponse. Il inclut maintenant un chemin de fichier défini par le shortcode [randomquotes path="path/to/file.txt"], transmis au js et de là au script php.
Johannes Pille
7

Vous pouvez enregistrer un script dans un shortcode. Il sera imprimé dans le pied de page, étant donné que le thème contient wp_footer().

Comment ça fonctionne:

  1. Enregistrez le rappel de shortcode avec add_shortcode().
  2. Dans le rappel de shortcode, enregistrez le script, puis renvoyez la sortie.
  3. Dans le script, ajoutez un bouton de mise à jour, envoyez une demande POST à admin_url( 'admin-ajax.php' )et récupérez de nouvelles données. Insérez les données retournées dans l'élément avec le shortcode.

Voici un exemple de script faisant cela. Deux fichiers: une classe PHP et un fichier JavaScript. Les deux devraient par exemple se trouver dans le même répertoire ajax-shortcode-demo.

ajax-shortcode-demo.php

<?php
/**
 * Plugin Name: AJAX Shortcode Demo
 * Description: How to use AJAX from a shortcode handler named <code>[ajaxdemo]</code>.
 */

add_action( 'wp_loaded', array ( 'Ajax_Shortcode_Demo', 'get_instance' ) );

class Ajax_Shortcode_Demo
{
    /**
     * Current plugin instance
     *
     * @type NULL|object
     */
    protected static $instance = NULL;

    /**
     * Unique action name to trigger our callback
     *
     * @type string
     */
    protected $ajax_action = 'load_demo_data';

    /**
     * CSS class for the shortcode, reused as JavaScript handle.
     *
     * Must be unique too.
     *
     * @type string
     */
    protected $shortcode_class = 'ajaxdemo';

    /**
     * Remeber if we had regsitered a script on a page already.
     *
     * @type boolean
     */
    protected $script_registered = FALSE;

    /**
     * Create a new instance.
     *
     * @wp-hook wp_loaded
     * @return  object $this
     */
    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }

    /**
     * Constructor. Register shortcode and AJAX callback handlers.
     */
    public function __construct()
    {
        add_shortcode( 'ajaxdemo', array ( $this, 'shortcode_handler' ) );

        // register the AJAX callback
        $callback = array ( $this, 'ajax_callback' );
        // user who are logged in
        add_action( "wp_ajax_$this->ajax_action", $callback );
        // anonymous users
        add_action( "wp_ajax_nopriv_$this->ajax_action", $callback );
    }

    /**
     * Render the shortcode.
     */
    public function shortcode_handler()
    {
        $this->register_scripts();

        return sprintf(
            '<div class="%1$s"><b>%2$s</b></div>',
            $this->shortcode_class,
            $this->get_rand()
        );
    }

    /**
     * Return AJAX result.
     *
     * Must 'echo' and 'die'.
     *
     * @wp-hook wp_ajax_$this->ajax_action
     * @wp-hook wp_ajax_nopriv_$this->ajax_action
     * @return int
     */
    public function ajax_callback()
    {
        echo $this->get_rand();
        exit;
    }

    /**
     * Random number.
     *
     * @return int
     */
    protected function get_rand()
    {
        return rand( 1, 1000 );
    }

    /**
     * Register script and global data object.
     *
     * The data will be printent before the linked script.
     */
    protected function register_scripts()
    {
        if ( $this->script_registered )
            return;

        $this->script_registered = TRUE;

        wp_register_script(
            // unique handle
            $this->shortcode_class,
            // script URL
            plugin_dir_url( __FILE__ ) . '/jquery-ajax-demo.js',
            // dependencies
            array ( 'jquery'),
            // version
            'v1',
            // print in footer
            TRUE
        );

        wp_enqueue_script( $this->shortcode_class );

        $data = array (
            // URL address for AJAX request
            'ajaxUrl'   => admin_url( 'admin-ajax.php' ),
            // action to trigger our callback
            'action'    => $this->ajax_action,
            // selector for jQuery
            'democlass' => $this->shortcode_class
        );

        wp_localize_script( $this->shortcode_class, 'AjaxDemo', $data );
    }
}

jquery-ajax-demo.js

jQuery( function( $ ) {

    var buttonClass = AjaxDemo.democlass + 'Button',
        // insert AJAX result into the shortcode element
        updateDemo = function( response ){          
            $( '.' + AjaxDemo.democlass ).find( 'b' ).html( response );
        },
        // fetch AJAX data
        loadDemo = function() {
            $.post( AjaxDemo.ajaxUrl, { action: AjaxDemo.action }, updateDemo );
        };

    // add an update button
    $( '.' + AjaxDemo.democlass )
        .append( ' <button class="' + buttonClass + '">New</button>' );

    // assign the clock handler to the button
    $( '.' + buttonClass ).click( loadDemo );
});

Résultat dans un article de blog:

entrez la description de l'image ici

fuxia
la source
+1 et merci pour ce qui précède. Ça vaut vraiment la peine d'être lu. Je pense que je comprends la plupart de ce qui se passe ci-dessus, les pages du codex sont à mon agenda de lecture et je vais probablement vérifier la source de toute façon. Néanmoins, permettez-moi de poser 2 questions de suivi rapides: je peux voir que l'utilisation de l'API sera avantageuse pour moi, le programmeur (propre, concis, lié à l'environnement (c'est-à-dire WP)). 1. Qu'en est-il des performances? Y a-t-il des gains ou des inconvénients par rapport à l'utilisation directe de jQuery (je suis conscient de l'écart de performance avec les js droits)? 2. Est-il aussi flexible? Est-ce que je peux utiliser les mêmes rappels et arguments?
Johannes Pille
@JohannesPille La performance n'est pas parfaite . D'un autre côté, vous agissez maintenant dans un environnement prévisible, d'autres plugins peuvent réutiliser votre code (hooks, fonctions), et vous n'avez pas besoin de savoir où WP est installé (le répertoire / URL du plugin pourrait être sur un autre serveur). En plus de cela, c'est la même chose qu'une solution personnalisée.
fuxia
@toscho Quand je le permis define('WP_DEBUG', true);dans mon wp-config.php cette solution a généré une erreur: Strict Standards: call_user_func_array() expects parameter 1 to be a valid callback, non-static method Ajax_Shortcode_Demo::get_instance() should not be called statically in /var/www/.../public_html/wp-includes/plugin.php on line 496. Est-ce critique? Je l'ai un peu changé: wordpress.stackexchange.com/q/196332/25187
Iurie Malai
1
@Iurie Oui, cette méthode doit être déclarée comme static. J'ai fait une modification à mon message pour cela. Merci pour l'avis. Je n'écrirais plus le code comme ça. :)
fuxia