Come aggiungere fogli di stile solo alle pagine con uno shortcode specifico?
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: :)
- Perché l'attuale functions.php non funziona e aggiunge stili a tutte le pagine? Non sono sicuro se è la chiamata
global
o l'istruzioneif
... - 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

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()
ostrpos()
. Puoi passare alle regex se hai bisogno di accettare argomenti. - Riduce le chiamate ai file
Spiegazione del Codice
Trova gli shortcode nella pagina utilizzando l'hook
save_post
solo quando il post non è una revisione e corrisponde alpost_type
specificato.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()
.Utilizza l'hook
wp_enqueue_scripts
per chiamare la nostra funzioneadd_scripts_and_styles()
.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');

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

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

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.

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/

No, questo mostrerà lo shortcode sopra il contenuto.

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

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
}

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.

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.

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.

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.
