Accoda script / stili quando è presente lo shortcode


54

Qual è il modo idea per registrare / accodare script e / o stili da usare nei plugin?

Di recente ho creato un semplice plugin per aggiungere l'utente avatar / gravatar con uno shortcode. Ho diverse opzioni di stile per visualizzare l'avatar (quadrato, rotondo, ecc.) E ho deciso di inserire il CSS direttamente nello shortcode stesso.

Tuttavia, mi rendo conto ora che questo non è un buon approccio poiché ripeterà i CSS ogni volta che lo shortcode viene utilizzato su una pagina. Ho visto molti altri approcci su questo sito e il codice wp ha anche due esempi propri, quindi è difficile sapere quale approccio sia il più coerente e veloce.

Ecco i metodi di cui sono attualmente a conoscenza:

Metodo 1: Includi direttamente nello shortcode - Questo è ciò che sto facendo attualmente nel plugin, ma non sembra buono poiché ripete il codice.

class My_Shortcode {
function handle_shortcode( $atts, $content="" ) {
/* simply enqueue or print the scripts/styles in the shortcode itself */
?>
<style type="text/css">

</style>
<?php
    return "$content";
     }
}
add_shortcode( 'myshortcode', array( 'My_Shortcode', 'handle_shortcode' ) );

Metodo 2: utilizzare la classe per accodare script o stili in modo condizionale

class My_Shortcode {
    static $add_script;
    static function init() {
        add_shortcode('myshortcode', array(__CLASS__, 'handle_shortcode'));
        add_action('init', array(__CLASS__, 'register_script'));
        add_action('wp_footer', array(__CLASS__, 'print_script'));
    }
    static function handle_shortcode($atts) {
        self::$add_script = true;
        // shortcode handling here
    }
    static function register_script() {
        wp_register_script('my-script', plugins_url('my-script.js', __FILE__), array('jquery'), '1.0', true);
    }
    static function print_script() {
        if ( ! self::$add_script )
            return;
        wp_print_scripts('my-script');
    }
}
My_Shortcode::init();

Metodo 3: Utilizzo get_shortcode_regex();

function your_prefix_detect_shortcode() {

    global $wp_query;   
    $posts = $wp_query->posts;
    $pattern = get_shortcode_regex();

    foreach ($posts as $post){
        if (   preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
            && array_key_exists( 2, $matches )
            && in_array( 'myshortcode', $matches[2] ) )
        {
            // css/js 
            break;  
        }    
    }
}
add_action( 'wp', 'your_prefix_detect_shortcode' );

Metodo 4: Utilizzo has_shortcode();

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'myshortcode') ) {
        wp_enqueue_script( 'my-script');
    }
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');

Penso che Method 4: Using has_shortcode();sia meglio perché assicurerà che gli script e gli stili vengano caricati una volta se i contenuti dei post hanno shortcode indipendentemente dagli usi multipli di shortcode. Anche se potrebbe non funzionare per gli shortcode nei widget o nella barra laterale, non sono sicuro. Se è per un plug-in, non ti consiglierei di legare gli script con shortcode perché alcuni potrebbero chiamare la tua funzione anziché shortcode per ottenere l'output desiderato.
Robert hue,

Risposte:


45

Ho trovato un altro modo che funziona bene per me:

Ecco un plug-in di esempio che utilizza questo metodo che ti consente di utilizzare get_avatar come shortcode. Il foglio di stile è accodato solo quando è presente lo shortcode.

Utilizzo (ID predefinito per l'utente corrente):

[get_avatar id="" size="32" default="mystery" alt="Profile Photo" class="round"]

function wpse_165754_avatar_shortcode_wp_enqueue_scripts() {
    wp_register_style( 'get-avatar-style', plugins_url( '/css/style.css', __FILE__ ), array(), '1.0.0', 'all' );
}

add_action( 'wp_enqueue_scripts', 'wpse_165754_avatar_shortcode_wp_enqueue_scripts' );
if ( function_exists( 'get_avatar' ) ) {
    function wpse_165754_user_avatar_shortcode( $attributes ) {

        global $current_user;
        get_currentuserinfo();

        extract( shortcode_atts(
                     array(
                         "id"      => $current_user->ID,
                         "size"    => 32,
                         "default" => 'mystery',
                         "alt"     => '',
                         "class"   => '',
                     ), $attributes, 'get_avatar' ) );

        $get_avatar = get_avatar( $id, $size, $default, $alt );

        wp_enqueue_style( 'get-avatar-style' );

        return '<span class="get_avatar ' . $class . '">' . $get_avatar . '</span>';
    }

    add_shortcode( 'get_avatar', wpse_165754_user_avatar_shortcode' );
}

Ho dimenticato di fare questa domanda l'anno scorso, ma in realtà ho iniziato a farlo anche in molti casi. È un po 'come combinare il metodo 1 e 2.
Bryan Willis l'

4
Questo metodo carica il CSS nel piè di pagina, che sicuramente ha dei limiti?
Jacob Raccuia,

1
Questo è assolutamente il modo giusto per farlo. Utilizzare questo metodo ogni volta che è necessario caricare in modo condizionale uno script o un foglio di stile quando si wp_enqueue_scriptsè già verificato l' hook. (Gli shortcode vengono analizzati durante i the_contentquali fa parte the_postdell'hook, il che significa che accodarsi quando viene analizzato è troppo tardi a meno che tu non abbia già registrato la sceneggiatura)
JRad the Bad

26

Prima di iniziare la risposta devo dire che riguardo a questo argomento css e js non sono gli stessi.

Il motivo è semplice: mentre l'aggiunta di js al corpo della pagina (a piè di pagina) è un modo comune e valido per andare, i CSS devono essere collocati nella <head>sezione della pagina: anche se la maggior parte dei browser può eseguire correttamente il rendering dei CSS nella pagina body, non è un codice HTML valido.

Quando viene eseguito il rendering di uno shortcode, la <head>sezione è già stata stampata, significa che js può essere aggiunto senza alcun problema a piè di pagina, ma è necessario aggiungere CSS prima di renderizzare lo shortcode.

Script

Se il tuo shortcode ha bisogno solo di js sei fortunato e puoi semplicemente utilizzarlo wp_enqueue_scriptnel corpo del callback shortcode:

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

function my_handle_shortcode() {
  wp_enqueue_script( 'myshortcodejs', '/path/to/js/file.js' );
  // rest of code here...
}

In questo modo lo script viene aggiunto al piè di pagina e solo una volta, anche se lo shortcode viene utilizzato più di una volta nella pagina.

stili

Se il codice ha bisogno di stili, è necessario agire prima che lo shortcode sia effettivamente visualizzato.

Esistono diversi modi per farlo:

  1. guarda tutti i post nella query corrente e aggiungi gli stili di shortcode se necessario. Questo è ciò che fai in entrambi i metodi n. 3 e n. 4 in OP. In effetti, entrambi i due metodi fanno la stessa cosa, ma è has_shortcodestato aggiunto in WP 3.6, mentre get_shortcode_regexè disponibile dalla versione 2.5, quindi usa get_shortcode_regexsolo se vuoi rendere il tuo plugin compatibile con le versioni precedenti.

  2. aggiungi sempre lo stile shortcode, in tutte le pagine

Problemi

Il problema con il n. 1 è rappresentato dalle prestazioni. Regex sono operazioni piuttosto lente e l'avvio di regex in un ciclo di tutti i post può rallentare la pagina in modo coerente. Inoltre, è un compito abbastanza comune nei temi mostrare solo estratto di post negli archivi e mostrare il contenuto completo con codici brevi solo in visualizzazioni singole. Se ciò accade, quando viene mostrato un archivio, il tuo plugin avvierà una regex matching in un ciclo con l'obiettivo di aggiungere uno stile che non sarà mai usato: un impatto doppiamente non necessario delle prestazioni: rallenta la generazione della pagina + richiesta HTTP aggiuntiva non necessaria

Il problema con # 2 è di nuovo la performance. Aggiungere stile a tutte le pagine significa aggiungere un'ulteriore richiesta HTTP per tutte le pagine, anche quando non è necessario. Anche se il tempo di generazione della pagina laterale del server non è influenzato, il tempo di rendering della pagina totale sarà e per tutte le pagine del sito.

Quindi, cosa dovrebbe fare uno sviluppatore di plug-in?

Penso che la cosa migliore da fare sia aggiungere una pagina di opzioni al plug-in, in cui gli utenti possono scegliere se gestire lo shortcode solo in vista singolare o anche negli archivi. In entrambi i casi è meglio fornire un'altra opzione per scegliere per quali tipi di post abilitare lo shortcode.

In questo modo è possibile agganciare "template_redirect"per verificare se la query corrente soddisfa i requisiti e in tal caso aggiungere lo stile.

Se l'utente sceglie di utilizzare lo shortcode solo in visualizzazioni di post singolari, è una buona idea controllare se il post ha shortcode o meno: una volta che è necessaria una sola regex, non dovrebbe rallentare così tanto la pagina.

Se l'utente sceglie di utilizzare lo shortcode anche negli archivi, eviterei di eseguire regex per tutti i post se il numero di post è elevato e accodare lo stile se i requisiti di query soddisfano.

Che cosa da considerare "alto" a questo proposito dovrebbe essere ottenere alcuni test delle prestazioni o, in alternativa, aggiungere un'altra opzione e dare la scelta agli utenti.


2
Vale la pena notare qui che i <style>tag nel corpo del documento sono ora validi secondo le specifiche W3C. w3.org/TR/html52/document-metadata.html#the-style-element
Isaac Lubow

5

Per il mio plugin ho scoperto che a volte gli utenti hanno un generatore di temi che ha shortcode memorizzati nei metadati post . Ecco cosa sto usando per rilevare se il mio shortcode plug-in è presente nel post corrente o post meta dati :

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // determine whether this page contains "my_shortcode" shortcode
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );

2

Io faccio così:

class My_Shortcode {

    function __construct() {
        do_action('my_start_shortcode'); // call
....

e catturare il gancio in altre funzioni (o altri plugin):

function wpse_3232_load_script(){
    wp_enqueue_script('js-myjs');
}
add_action('my_start_shortcode','wpse_3232_load_script',10);

1

Ho scoperto il mio plugin, se lo shortcode è presente nel widget di testo.

function check_shortcode($text) {

  $pattern = get_shortcode_regex();

   if (   preg_match_all( '/'. $pattern .'/s', $text, $matches )
        && array_key_exists( 2, $matches )
        && in_array( 'myshortcode', $matches[2] ) )
    {
        // myshortcode is being used

        // enque my css and js
        /****** Enqueu RFNB  ******/
        wp_enqueue_style('css-mycss');
        wp_enqueue_script('js-myjs');

        // OPTIONAL ALLOW SHORTCODE TO WORK IN TEXT WIDGET
        add_filter( 'widget_text', 'shortcode_unautop');
        add_filter( 'widget_text', 'do_shortcode'); 

    }

  return $text;

}
add_filter('widget_text', 'check_shortcode');

1

WordPress ha una funzione integrata per fare qualcosa in base a uno Shortcode specifico che presenta lo stato. Il nome della funzione è has_shortcode(). Puoi usare il seguente codice per accodare il tuo stile e i tuoi script.

Qui ho usato il is_a( $post, 'WP_Post' )per verificare se l' $postoggetto appartiene alla WP_Postclasse e $post->post_contentper controllare il contenuto del post.

if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'shortcode_tag') ) {
    wp_enqueue_style( 'handle', get_template_directory_uri() . '/your_file_filename.css' );
}

0

Ho creato una combinazione del codice di esempio dalla pagina di Wordpress per has_shortcode () e la risposta fornita da zndencka . Ho notato che la funzione has_shortcode è stata aggiunta in Wordpress 3.6, quindi è per questo che per prima cosa controllo se esiste la funzione. Forse quel controllo è un po 'obsoleto, dal momento che non ci sono più molti utenti che usano WordPress 3.6 al di sotto di WordPress secondo le proprie statistiche.

// This makes sure the styling is already enqueued in the header, so before the shortcode loads in the page/post
function enqueue_shortcode_header_script() {
    global $post;
    if ( function_exists( 'has_shortcode' ) ){  // is added in wordpress 3.6
        // Source: https://codex.wordpress.org/Function_Reference/has_shortcode
        if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'my_shortcode') ) {
            wp_enqueue_style( 'shortcode-css' );
        }
    }
    else if ( isset($post->ID) ) { // Small percentage wordpress users are below 3.6 https://wordpress.org/about/stats/
        global $wpdb;
        $result = $wpdb->get_var(
          $wpdb->prepare(
              "SELECT count(*) FROM $wpdb->postmeta " .
              "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'",
               $post->ID )
        );
        if (!empty( $result )) { wp_enqueue_style( 'shortcode-css' ); }
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_header_script');

0

Possiamo infatti caricare in modo condizionale file CSS e JS tramite shortcode senza utilizzare funzioni eccessivamente elaborate :

Innanzitutto, supponiamo di aver registrato tutti i nostri file CSS / JS in precedenza (forse quando wp_enqueue_scriptseseguito)

function prep_css_and_js() {
     wp_register_style('my-css', $_css_url);
     wp_register_script('my-js', $_js_url);
}
add_action( 'wp_enqueue_scripts', 'prep_css_and_js', 5 );

Successivamente, esaminiamo la nostra funzione shortcode:

function my_shortcode_func( $atts, $content = null ) {
  if( ! wp_style_is( "my-css", $list = 'enqueued' ) ) { wp_enqueue_style('my-css'); }
  if( ! wp_script_is( "my-js", $list = 'enqueued' ) ) { wp_enqueue_script('my-js'); }
  ...
}

Semplice. Fatto. Ergo: possiamo "caricare in modo condizionale" i file css / js, (solo quando viene eseguito [shortcode]).

Consideriamo la seguente ideologia:

  • Vogliamo caricare alcuni file CSS / JS (ma solo quando viene attivato lo shortcode)
  • Forse non vogliamo che questi file vengano caricati su ogni pagina, o affatto se lo shortcode non viene utilizzato su una pagina / post. (leggero)
  • Possiamo ottenere ciò assicurandoci che WP registri TUTTI i file css / js prima di chiamare lo shortcode e prima dell'accodamento.
  • IE: Forse durante la mia prep_css_and_js()funzione carico TUTTI i file .css / .js che si trovano in determinate cartelle ...

Ora che WP li vede come script registrati, possiamo davvero chiamarli, condizionatamente, in base a una verità di situazioni, incluso ma non limitato a my_shortcode_func()

Vantaggi: (nessun MySQL, nessuna funzione avanzata e nessun filtro necessario)

  • questo è "WP orthodix", elegante, caricamento rapido, facile e semplice
  • consente ai compilatori / minificatori di rilevare tali script
  • usa le funzioni WP (wp_register_style / wp_register_script)
  • compatibile con più temi / plugin che potrebbero voler annullare la registrazione di tali script per una verità di motivi.
  • non si innescherà più volte
  • l'elaborazione o il codice sono molto limitati

Riferimenti:

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.