Verwenden Sie AJAX im Shortcode

9

Ich habe den folgenden Code zum Shortcode, um ein zufälliges Zitat anzuzeigen. Frage: Wie kann eine Schaltfläche ein neues zufälliges Zitat anzeigen? Ich meine, das würde den Knopf drücken und Ihnen ein neues Zitat zeigen (natürlich ohne die Seite zu aktualisieren).

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

Ich bin daran interessiert, wie Sie den Inhalt der Seite mit Ajax in WordPress aktualisieren können. In meiner Situation, weil in der Tat genau das sein.

Entschuldigung für mein schlechtes Englisch. Ich hoffe du verstehst mich. Vielen Dank!

user23769
quelle

Antworten:

4

Zunächst einmal ist dies im Rahmen von WPSE überhaupt sehr grenzwertig .
Abgesehen von dem Shortcode zum Auslösen der anfänglichen HTML-Ausgabe ist dies wirklich nur AJAX.

Trotzdem wird es so gemacht:

Das PHP

Angenommen, das oben angegebene PHP-Snippet ist funktionsfähig, platzieren Sie Folgendes in einer PHP-Datei für den Ajax-Aufruf:

/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>';
 ?>

Zum späteren Nachschlagen und um diese Antwort für andere nützlich zu machen: Beachten Sie, dass wp-load.phpdies enthalten sein muss, um die native WordPress-Funktionalität nutzen zu können. Der häufigste Fall ist wahrscheinlich entweder die Notwendigkeit von WP_Queryoder $wpdb.

Die HTML-Struktur

In einem Seiteninhalt, einem Widget oder einer Vorlagendatei:

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

Dies können Sie natürlich nach Ihren Wünschen anpassen, aber für dieses Beispiel gehen wir so vor.
Wir werden das oben genannte später über einen Shortcode generieren.

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

Zusammenstellen in functions.php

Fügen Sie unter Ihrem obigen Snippet (das Sie unten modifiziert finden) Folgendes ein:

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

Optional: Das CSS für den Ladebildschirm

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

Ressourcen / Lesen

Johannes Pille
quelle
1
Gibt es einen Grund, die integrierte AJAX-API nicht zu verwenden?
Fuxia
@toscho Ehrlich gesagt - nicht zu vertraut damit. Eine Lektüre wert?
Johannes Pille
Ja absolut. :) Ich werde eine Alternative hinzufügen.
Fuxia
Perfekt! Vielen Dank! <br/> Ein Skript funktioniert, wenn Sie das Funktionsargument setzen? Zum Beispiel im Shortcode sein, um einen Link zu einer Textdatei bereitzustellen? <br/> function random_quote ($path) {      $ array = file ("$ path");<br/> ... [randomquote file = "http://exampe.com/file.txt"]<br/> Also wird es funktionieren? Ich bin nicht sehr versiert in der Programmierung.
user23769
Ich habe die Antwort aktualisiert. Es enthält jetzt einen Dateipfad, der durch den Shortcode festgelegt [randomquotes path="path/to/file.txt"], an js und von dort an das PHP-Skript weitergegeben wird.
Johannes Pille
7

Sie können ein Skript in einem Shortcode registrieren. Es wird in die Fußzeile gedruckt, sofern das Thema enthält wp_footer().

Wie es funktioniert:

  1. Registrieren Sie den Shortcode-Rückruf bei add_shortcode().
  2. Registrieren Sie im Shortcode-Rückruf das Skript und geben Sie die Ausgabe zurück.
  3. Fügen Sie im Skript eine Schaltfläche zum Aktualisieren hinzu, senden Sie eine POST-Anforderung an admin_url( 'admin-ajax.php' )und rufen Sie neue Daten ab. Fügen Sie die zurückgegebenen Daten mit dem Shortcode in das Element ein.

Hier ist ein Beispielskript, das das macht. Zwei Dateien: eine PHP-Klasse und eine JavaScript-Datei. Beide sollten sich beispielsweise im selben Verzeichnis befinden 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 );
});

Ergebnis in einem Blogbeitrag:

Geben Sie hier die Bildbeschreibung ein

Fuxia
quelle
+1 & Danke für das oben Gesagte. Sieht definitiv lesenswert aus. Ich glaube, ich bekomme das meiste von dem, was oben vor sich geht, die Codex-Seiten stehen auf meiner Lese-Agenda und ich werde wahrscheinlich trotzdem die Quelle überprüfen. Erlauben Sie mir dennoch, zwei kurze Fragen zu beantworten: Ich kann sehen, dass die Verwendung der API für mich, den Programmierer, von Vorteil ist (sauber, präzise, ​​an die Umgebung gebunden (dh WP)). 1. Wie wäre es mit Leistung? Irgendwelche Vorteile oder Nachteile im Vergleich zur direkten Verwendung von jQuery (sind Sie sich der Leistungslücke zu Straight Js bewusst)? 2. Ist es so flexibel? Dh kann ich dieselben Rückrufe und Argumente verwenden?
Johannes Pille
@JohannesPille Leistung ist nicht perfekt . Auf der anderen Seite agieren Sie jetzt in einer vorhersehbaren Umgebung, andere Plugins können Ihren Code (Hooks, Funktionen) wiederverwenden und Sie müssen nicht wissen, wo WP installiert ist (das Plugin-Verzeichnis / die URL könnte sich auf einer anderen befinden Server). Abgesehen davon ist es das gleiche wie eine benutzerdefinierte Lösung.
Fuxia
@toscho Als ich die define('WP_DEBUG', true);in meiner wp-config.php aktiviert habe, hat diese Lösung einen Fehler generiert : 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. Ist das kritisch? Ich habe es ein wenig geändert: wordpress.stackexchange.com/q/196332/25187
Iurie Malai
1
@Iurie Ja, diese Methode muss als deklariert werden static. Ich habe meinen Beitrag dafür bearbeitet. Danke für die Anmerkung. Ich würde den Code nicht mehr so ​​schreiben. :)
Fuxia