Come aggiungere fogli di stile solo alle pagine con uno shortcode specifico?

31 lug 2013, 12:42:21
Visualizzazioni: 14.6K
Voti: 9

Sto eseguendo una funzione nelle pagine dove viene utilizzato lo shortcode [make-me-a-map]. Carica javascript nella pagina e crea una mappa. Questa parte funziona bene (evviva!) ma ho problemi con l'aggiunta dei fogli di stile solo a quelle pagine in modo simile.

functions.php (Attuale)

add_shortcode("make-me-a-map", "create_new_map");
add_action("wp_head", "style_my_new_map");

function create_new_map () {
    global $new_map_called_for;
    $map_called_for = true;

    wp_register_script('make-a-new-map', get_template_directory_uri() . '/js/new-map.js', array('jquery'), '0.1', true);
    wp_enqueue_script('make-a-new-map');
    }

function style_my_new_map() {
    global $new_map_called_for;
    if ($new_map_called_for == true) {
        $tDir = get_template_directory_uri();

        // Stampo i fogli di stile perché wp_register_style & wp_enqueue_style non funzionano al momento
        // E add_action('wp_enqueue_script', 'style_my_new_maps') con quelle funzioni aggiungerebbe lo stile a tutte le pagine
        // Non solo a quelle con lo shortcode [make-me-a-map]
        echo "<link rel='stylesheet' href='", $tDir, "/css/new-map.css' />", PHP_EOL;

        // Stampo Javascript direttamente nella pagina (non riuscivo a farlo con wp_enqueue_script) per far conoscere al codice js la directory del template
        echo '<script type="text/javascript">var templateDir = "', get_template_directory_uri(), '";</script>', PHP_EOL;
        $map_called_for = false;
    }
}

Purtroppo questo non sembra funzionare. Gli stili vengono aggiunti a tutte le pagine.

Non ho usato wp_register_style & wp_enqueue_style perché questo bug sta ancora aggiungendo tag <Link /> al footer da quelle funzioni.

Avrei potuto usare add_action("wp_enqueue_scripts", "style_my_new_map") invece di add_action('wp-head', "style_my_new_map") ma per quanto ho visto e verificato, non c'è differenza? Aggiunge comunque i fogli di stile a tutte le pagine.

Quindi la mia domanda è in realtà divisa in due parti: :)

  1. Perché l'attuale functions.php non funziona e aggiunge stili a tutte le pagine? Non sono sicuro se è la chiamata global o l'istruzione if...
  2. Qual è il modo migliore per aggiungere i fogli di stile all'header solo delle pagine che utilizzano lo shortcode sopra citato, supponendo che non conosca gli id delle pagine, ecc?

Grazie in anticipo! P

1
Tutte le risposte alla domanda 8
3
11

Caricamento Dinamico di Script e Stili Utilizzando Shortcode

Vantaggi

  • Non cerca attraverso tutti i post ogni volta che lo shortcode viene chiamato.
  • Permette di aggiungere dinamicamente stili e script solo quando lo shortcode è presente nella pagina.
  • Non utilizza regex poiché tendono a essere più lente rispetto a strstr() o strpos(). Puoi passare alle regex se hai bisogno di accettare argomenti.
  • Riduce le chiamate ai file

Spiegazione del Codice

  1. Trova gli shortcode nella pagina utilizzando l'hook save_post solo quando il post non è una revisione e corrisponde al post_type specificato.

  2. Salva gli ID dei post trovati come un array utilizzando add_option() con autoload impostato su "yes" a meno che l'entry non sia già presente. In tal caso, utilizzerà update_option().

  3. Utilizza l'hook wp_enqueue_scripts per chiamare la nostra funzione add_scripts_and_styles().

  4. Questa funzione poi chiama get_option() per recuperare il nostro array di ID di pagina. Se l'attuale $page_id è presente nell'array $option_id_array, allora aggiunge gli script e gli stili.

Nota: Ho convertito il codice da classi OOP con namespace, quindi potrei aver tralasciato qualcosa. Fatemelo sapere nei commenti se è così.

Esempio di Codice: Trovare le Occorrenze dello Shortcode

function find_shortcode_occurences($shortcode, $post_type = 'page')
{
    $found_ids = array();
    $args         = array(
        'post_type'   => $post_type,
        'post_status' => 'publish',
        'posts_per_page' => -1,
    );
    $query_result = new \WP_Query($args);
    foreach ($query_result->posts as $post) {
        if (false !== strpos($post->post_content, $shortcode)) {
            $found_ids[] = $post->ID;
        }
    }
    return $found_ids;
}

function save_option_shortcode_post_id_array( $post_id ) {
    if ( wp_is_post_revision( $post_id ) OR 'page' != get_post_type( $post_id )) {
        return;
    }
    $option_name = 'yourprefix-yourshortcode';
    $id_array = find_shortcode_occurences($option_name);
    $autoload = 'yes';
    if (false == add_option($option_name, $id_array, '', 'yes')) update_option($option_name, $id_array);
}

add_action('save_post', 'save_option_shortcode_id_array' );

Esempio di Codice: Shortcode per Includere Dinamicamente Script e Stili

function yourshortcode_add_scripts_and_styles() {
    $page_id = get_the_ID();
    $option_id_array = get_option('yourprefix-yourshortcode');
    if (in_array($page_id, $option_id_array)) {
        wp_enqueue_script( $handle, $src, $deps, $ver, $footer = true );
        wp_enqueue_style( $handle, $src , $deps);
    }
}

add_action('wp_enqueue_scripts', 'yourshortcode_add_scripts_and_styles');
21 feb 2014 21:10:56
Commenti

Non l'ho ancora testato, ma questa è la risposta che stavo cercando. Sembra avere un impatto minimo.

Jacob Raccuia Jacob Raccuia
21 apr 2017 16:33:53

@JacobRaccuia L'ho testato qualche tempo fa e ha funzionato. Non so come si comporti con le versioni più recenti di WP, ma dubito che sia cambiato molto data la natura della piattaforma.

CommandZ CommandZ
4 mag 2017 06:17:22

ho passato molto tempo a cercare di perfezionare questo aspetto. Ha seri inconvenienti se l'utente inserisce lo shortcode in ambienti WP non tradizionali. Ho scritto un hook per verificare tutti i campi personalizzati, che potrebbe potenzialmente aiutare a coprire questo problema.

Jacob Raccuia Jacob Raccuia
4 mag 2017 08:36:53
2

Questo funziona per me:

function register_my_css () {
    wp_register_style('my-style', plugins_url('styles.css', __FILE__));
}

function register_my_scripts () {
    wp_register_script('my-script', plugins_url('scripts.js', __FILE__));
}

// carica gli script / stili solo quando viene chiamato lo shortcode
function do_my_shortcode () {
    wp_enqueue_style('my-style');
    wp_enqueue_script('my-script');

    // fai le operazioni dello shortcode...
}

// registra il css
add_action('wp_enqueue_scripts', 'register_my_css');

// registra javascript
add_action('wp_enqueue_scripts', 'register_my_scripts');

// registra shortcode
add_shortcode('my-shortcode', 'do_my_shortcode');

Maggiori informazioni qui: http://mikejolley.com/2013/12/sensible-script-enqueuing-shortcodes/

16 lug 2015 13:36:37
Commenti

No, questo mostrerà lo shortcode sopra il contenuto.

fuxia fuxia
16 lug 2015 14:23:29

Il problema qui è che gli stili verranno collegati nel footer. Probabilmente funzionerà, ma è "sbagliato" e non è garantito che funzioni.

Doug Cassidy Doug Cassidy
11 mar 2016 18:16:17
1

2 domande quindi 2 risposte :)

Perché l'attuale functions.php non funziona e aggiunge gli stili a tutte le pagine? Non sono sicuro se sia la chiamata globale o l'istruzione if...

Non funziona a causa dell'ordine in cui queste funzioni vengono chiamate. La tua callback dello shortcode viene chiamata durante il rendering del contenuto del post (molto probabilmente la chiamata alla funzione the_content).

Sia wp_enqueue_scripts che wp_head vengono chiamati molto prima: wp_head da qualche parte nel file header.php del tuo tema e wp_enqueue_scripts durante la chiamata a wp_head.

Qual è il modo migliore per aggiungere i fogli di stile all'header solo delle pagine in cui viene utilizzato lo shortcode sopra, supponendo che non conosca gli ID delle pagine, ecc?

Non penso esista un modo "migliore" in assoluto. Non è affatto una buona idea. I browser memorizzano nella cache i file CSS. Quindi se hai lo stesso CSS su tutte le pagine, il browser lo scaricherà solo una volta. Se ci sono molti file CSS per pagine diverse, il browser dovrà scaricarli tutti. Quindi non lo farei affatto e includerei questi stili CSS nel file CSS globale.

Sebbene se devi includerlo solo nelle pagine che utilizzano questo shortcode, allora (2 soluzioni, la scelta di quale è migliore è tua; penso che la seconda sia più carina)...

  1. Puoi aggiungere questi stili come stili inline. Fai solo attenzione a non includerli più volte. Quindi stampali con il tuo shortcode e assicurati che vengano stampati solo una volta.
  2. Poiché i post sono già selezionati quando viene chiamato wp_head/wp_enqueue_scripts, puoi aggiungere una funzione a questo hook, scorrere i post selezionati, verificare se contengono il tuo shortcode e includere il tuo CSS se necessario. (Ovviamente non sarà molto efficiente).
31 lug 2013 13:05:45
Commenti

Sì, l'opzione #2 potrebbe essere meno efficiente ma decisamente più elegante rispetto allo stile inline =) Ora funziona perfettamente, grazie!

Padraic Padraic
3 ago 2013 11:46:20
0

Puoi agganciarti a un'azione dopo che la query principale è stata eseguita e determinare se è necessario caricare i tuoi stili e script.

add_action('template_include', 'custom_template_include');
function custom_template_include($template) {
    if (is_single() || is_page()) {
          global $post;
          if (has_shortcode($post->post_content, 'your_short_code')) {
              add_action('wp_enqueue_scripts, 'custom_enqueue_scripts');
          }
    } 
}

function custom_enqueue_scripts() {
    //Inserisci qui i tuoi script e stili
}
1 apr 2015 15:50:55
0
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_styles', 1 );
function enqueue_shortcode_styles() {

    global $post;

    if ( isset($post->post_content) && is_singular(array( 'post','page' ) ) && ! has_shortcode( $post->post_content, '$tag' ) ) {

    wp_enqueue_style( 'shortcode-styles', get_stylesheet_directory_uri() . '/style.css' );

    }

}

Userei has_shortcode per verificare il contenuto del $post e caricare gli script usando wp_enqueue_scripts, ma dipende da dove sono incorporati i tuoi shortcode.

Sostituisci $tag con il tag del tuo shortcode nel codice sopra.

Aggiungi al file functions del tuo child theme e modifica i condizionali se necessario.

26 mag 2017 15:16:43
0

Una soluzione molto più semplice che ha funzionato per me è stata registrare lo script al di fuori della funzione dello shortcode e poi accodare lo script all'interno della funzione. In questo modo il script viene caricato solo sulle pagine che utilizzano il tuo shortcode.

wp_register_script('make-a-new-map', get_template_directory_uri() . '/js/new-map.js', array('jquery'), '0.1', true);
wp_register_style('make-a-new-map-style', get_template_directory_uri() . '/css/new-map.css');

add_shortcode("make-me-a-map", "create_new_map");
add_action("wp_head", "style_my_new_map");

function create_new_map () {
   wp_enqueue_script('make-a-new-map');
   wp_enqueue_style('make-a-new-map-style');

   global $new_map_called_for;
   $map_called_for = true;
}

Una descrizione di questo metodo può essere trovata qui: http://mikejolley.com/2013/12/sensible-script-enqueuing-shortcodes/

Nota che questo carica il CSS nel footer, il che potrebbe non essere desiderabile o valido secondo gli standard W3C. Nel mio caso questo non è stato un problema.

8 nov 2014 17:26:44
0

Puoi farlo semplicemente in questo modo:

// hook per lo shortcode
add_shortcode("make-me-a-map", "create_new_map");

// callback dello shortcode
function style_my_new_map() {
    global $new_map_called_for;
    if ($new_map_called_for == true) {
  wp_register_script('make-a-new-map', get_template_directory_uri() . '/js/new-map.js', array('jquery'), '0.1', true);
  wp_enqueue_script('make-a-new-map');

// il resto dei tuoi codici
    }
}

Funziona anche per i fogli di stile. Per caricare il tuo foglio di stile per ultimo, aggiungi dei numeri al tuo hook dello shortcode, così:

add_shortcode("make-me-a-map", "create_new_map", 9999);

L'ho testato e funziona.

25 feb 2015 20:03:15
0

Caricamento Dinamico di Script e Stili Utilizzando Shortcode

Questo è il codice esteso per la soluzione fornita da Commandz sopra.

Ho trovato che il suo metodo sia il migliore e più fattibile poiché l'opzione del database è disponibile in quasi tutti gli hook.

È stato modificato per trovare le occorrenze degli shortcode solo per il contenuto del post corrente, invece di analizzare tutti i post - cosa che potrebbe essere più lenta quando il numero di post è elevato.

È stato modificato qui in due righe dopo aver passato un'altra variabile $post_id dall'azione save_post alla funzione find_shortcode_occurences()

if( !empty($post_id) ) {
    $args['posts__in'] = $post_id; 
}

Codice modificato per entrambe le funzioni

function find_shortcode_occurences($shortcode, $post_id='', $post_type = 'page') {
    $found_ids = array();
    $args         = array(
        'post_type'   => $post_type,
        'post_status' => 'publish',
        'posts_per_page' => -1,
    );

    if( !empty($post_id) ) {
        $args['posts__in'] = $post_id; 
    }

    $query_result = new WP_Query($args);
    foreach ($query_result->posts as $post) {
        if (false !== strpos($post->post_content, $shortcode)) {
            $found_ids[] = $post->ID;
        }
    }
    return $found_ids;
}

add_action('save_post', 'save_option_for_sppro_pages' );
function save_option_for_sppro_pages( $post_id ) {
    if ( wp_is_post_revision( $post_id ) ) {
        return;
    }
    $option_name = 'database-option';
    $shortcode = 'shortcode-name';
    $id_array = find_shortcode_occurences($shortcode, $post_id);
    $autoload = 'yes';
    if (false == add_option($option_name, $id_array, '', 'yes')) {
        $current_value = get_option($option_name);
        $new_value = array_merge($current_value, $id_array);
        update_option($option_name, $id_array);
    }
}

Inoltre, è stata aggiunta un'altra variabile in modo da poter avere nomi diversi per l'opzione del database e il nome dello shortcode.

26 mag 2017 12:47:02