Utilizzare AJAX in shortcode


9

Ho il seguente codice allo shortcode per visualizzare un preventivo casuale. Domanda: come fare in modo che un pulsante visualizzi una nuova citazione casuale? Voglio dire, ciò premerebbe il pulsante e ti mostrerebbe una nuova citazione (senza aggiornare la pagina ovviamente).

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');

Sono interessato a come è possibile aggiornare il contenuto della pagina utilizzando Ajax in WordPress? Nella mia situazione, perché in realtà è esattamente quello.

Scusa per il mio cattivo inglese. Spero tu mi capisca. Grazie!

Risposte:


4

Prima di tutto, questo è molto borderline nell'ambito del WPSE.
Oltre allo shortcode per attivare l'output HTML iniziale, questo è davvero solo AJAX.

Comunque, detto questo, è così che si fa:

Il PHP

Supponendo che lo snippet PHP sopra indicato sia funzionale, inserire quanto segue in un file php per la chiamata 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>';
 ?>

Per riferimento futuro e in modo da rendere questa risposta utile ad altri: Nota che wp-load.phpdeve essere incluso per utilizzare la funzionalità nativa di WordPress. Il caso più comune è probabilmente la necessità WP_Queryo $wpdb.

La struttura HTML

In un contenuto della pagina, un widget o un file modello:

<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>

Questo è ovviamente possibile adattarlo a proprio piacimento, ma per il bene di questo esempio, questo è ciò con cui stiamo andando.
Genereremo quanto sopra tramite un codice breve in seguito.

Il 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;
});

Mettendolo insieme in Functions.php

Sotto lo snippet di cui sopra (che troverai incluso modificato di seguito), incolla quanto segue:

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' );

Opzionale: CSS per la schermata di caricamento

.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;
}

Risorse / Lettura


1
Qualche motivo per non utilizzare l'API AJAX integrata?
fuxia

@toscho Onestamente - non troppo familiare. Vale la pena leggere?
Johannes Pille,

Si assolutamente. :) Aggiungerò un'alternativa.
fuxia

Perfetto! Grazie! <br/> Uno script funzionerà se imposti l'argomento della funzione? Ad esempio, essere nello shortcode per fornire un collegamento a un file di testo? <br/> function random_quote ($path) {      $ array = file ("$ path");<br/> ... [randomquote file = "http://exampe.com/file.txt"]<br/> Quindi funzionerà? Non sono troppo esperto in programmazione.
user23769

Ho aggiornato la risposta. Ora include un percorso file impostato dal codice funzione [randomquotes path="path/to/file.txt"], trasmesso a js e da lì allo script php.
Johannes Pille,

7

È possibile registrare uno script in un shortcode. Sarà stampato nel piè di pagina, dato che il tema contiene wp_footer().

Come funziona:

  1. Registrare il callback dello shortcode con add_shortcode().
  2. Nel callback dello shortcode, registrare lo script, quindi restituire l'output.
  3. Nello script aggiungi un pulsante di aggiornamento, invia una richiesta POST a admin_url( 'admin-ajax.php' )e recupera nuovi dati. Inserire i dati restituiti nell'elemento con lo shortcode.

Ecco uno script di esempio che lo fa. Due file: una classe PHP e un file JavaScript. Entrambi dovrebbero trovarsi nella stessa directory, per esempio 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 );
});

Risultato in un post sul blog:

inserisci qui la descrizione dell'immagine


+1 e grazie per quanto sopra. Sembra sicuramente degno di nota. Penso di avere la maggior parte di ciò che sta succedendo sopra, le pagine del codice sono nel mio programma di lettura e probabilmente controllerò comunque la fonte. Tuttavia, consentitemi di rispondere a 2 domande di follow-up: posso vedere che l'utilizzo dell'API sarà vantaggioso per me, il programmatore (pulito, conciso, legato all'ambiente (cioè WP)). 1. Che ne dici di prestazioni? Qualche vantaggio o svantaggio rispetto all'utilizzo diretto di jQuery (sono consapevole del gap prestazionale rispetto a js straight)? 2. È flessibile? Cioè posso usare gli stessi callback e argomenti?
Johannes Pille,

@JohannesPille Le prestazioni non sono perfette . D'altra parte, ora agisci in un ambiente prevedibile, altri plug-in possono riutilizzare il tuo codice (hook, funzioni) e non devi sapere dove è installato WP (la directory / URL del plug-in potrebbe trovarsi in un altro server). Inoltre è uguale a una soluzione personalizzata.
fuxia

@toscho Quando ho attivato il define('WP_DEBUG', true);mio wp-config.php questa soluzione ha generato un errore: 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. È critico? L'ho cambiato un po ': wordpress.stackexchange.com/q/196332/25187
Iurie Malai

1
@Iurie Sì, quel metodo deve essere dichiarato come static. Ho fatto una modifica al mio post per questo. Grazie per l'avviso. Non scriverei più il codice in questo modo. :)
fuxia
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.