Cum să adaugi fișiere CSS doar pe paginile cu un shortcode specific?
Rulez o funcție pe paginile unde este folosit shortcode-ul [make-me-a-map]
. Aceasta încarcă JavaScript pe pagină și creează o hartă. Partea aceasta funcționează bine (ura!) dar am probleme cu adăugarea fișierelor CSS doar pe acele pagini într-un mod similar.
functions.php (Current)
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();
// Afișează fișierele CSS pentru că wp_register_style & wp_enqueue_style nu funcționează momentan
// Și add_action('wp_enqueue_script', 'style_my_new_maps') cu acele funcții ar adăuga stilurile pe toate paginile
// Nu doar pe cele cu shortcode-ul [make-me-a-map]
echo "<link rel='stylesheet' href='", $tDir, "/css/new-map.css' />", PHP_EOL;
// Afișează JavaScript direct pe pagină (nu am putut face asta cu wp_enqueue_script) pentru a permite codului JS să cunoască directorul template-ului
echo '<script type="text/javascript">var templateDir = "', get_template_directory_uri(), '";</script>', PHP_EOL;
$map_called_for = false;
}
}
Din păcate, acest lucru nu pare să funcționeze. Stilurile sunt adăugate pe toate paginile.
Nu am folosit wp_register_style & wp_enqueue_style pentru că acest bug încă adaugă tag-uri <Link />
în footer din acele funcții.
Aș fi putut folosi add_action("wp_enqueue_scripts", "style_my_new_map")
în loc de add_action('wp-head', "style_my_new_map")
dar din câte văd și am verificat, nu este nicio diferență? Tot adaugă fișierele CSS pe toate paginile.
Deci întrebarea mea are de fapt două părți: :)
- De ce nu funcționează fișierul functions.php curent și adaugă stilurile pe toate paginile? Nu sunt sigur dacă este vorba despre apelul
global
sau despre instrucțiuneaif
... - Care este cea mai bună metodă pentru a adăuga fișierele CSS în header-ul doar al paginilor unde este folosit shortcode-ul menționat mai sus, presupunând că nu voi cunoaște ID-urile paginilor, etc?
Mulțumesc anticipat! P

Încărcarea Dinamică a Scripturilor și Stilurilor folosind Shortcode
Avantaje
- Nu caută prin toate articolele de fiecare dată când este apelat shortcode-ul.
- Permite adăugarea dinamică a stilurilor și scripturilor doar când shortcode-ul este prezent pe pagină.
- Nu utilizează expresii regulate (regex) deoarece acestea tind să fie mai lente decât
strstr()
saustrpos()
. Puteți trece la regex dacă aveți nevoie să acceptați argumente. - Reduce numărul de apeluri către fișiere
Explicația Codului
Găsește shortcode-urile pe pagină folosind hook-ul
save_post
doar când articolul nu este o revizie și se potrivește cupost_type
specificat.Salvează ID-urile posturilor găsite ca un array folosind
add_option()
cu autoload setat la da, cu excepția cazului în care intrarea există deja. În acest caz, va folosiupdate_option()
.Folosește hook-ul
wp_enqueue_scripts
pentru a apela funcția noastrăadd_scripts_and_styles()
.Această funcție apelează
get_option()
pentru a prelua array-ul nostru cu ID-uri de pagini. Dacă$page_id
curent se află în$option_id_array
, atunci adaugă scripturile și stilurile.
Notă importantă: Am convertit codul din clase OOP Namespaced, așa că este posibil să fi ratat ceva. Anunțați-mă în comentarii dacă am făcut-o.
Exemplu de Cod: Găsirea Aparițiilor Shortcode-ului
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' );
Exemplu de Cod: Shortcode pentru Includerea Dinamică a Scripturilor și Stilurilor
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');

Nu am testat acest lucru încă, dar acesta este răspunsul pe care îl căutam. Pare să aibă un dezavantaj minim.

@JacobRaccuia Am testat acest lucru acum ceva timp și a funcționat. Nu știu cum se comportă cu versiunile mai noi de WP, dar mă îndoiesc că s-au schimbat multe având în vedere natura platformei.

așa că am petrecut mult timp încercând să perfecționez acest lucru. Are dezavantaje serioase dacă utilizatorul introduce shortcode-ul în mod non-traditional în WP. Am scris un hook pentru a verifica toate câmpurile personalizate, care ar putea ajuta la acoperirea acestei probleme.

Aceasta funcționează pentru mine:
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__));
}
// încarcă scripturile / stilurile doar când shortcode-ul este apelat
function do_my_shortcode () {
wp_enqueue_style('my-style');
wp_enqueue_script('my-script');
// logica shortcode-ului...
}
// înregistrează CSS
add_action('wp_enqueue_scripts', 'register_my_css');
// înregistrează JavaScript
add_action('wp_enqueue_scripts', 'register_my_scripts');
// înregistrează shortcode
add_shortcode('my-shortcode', 'do_my_shortcode');
Mai multe informații aici: http://mikejolley.com/2013/12/sensible-script-enqueuing-shortcodes/

Nu, asta va afișa shortcode-ul deasupra conținutului.

2 întrebări deci 2 răspunsuri :)
De ce nu funcționează functions.php curent și adaugă stiluri la toate paginile? Nu sunt sigur dacă este vorba de apelul global sau de instrucțiunea if...
Nu funcționează din cauza ordinii în care aceste funcții sunt apelate. Callback-ul shortcode-ului tău este apelat în timpul randării conținutului postării (cel mai probabil apelul funcției the_content
).
Atât wp_enqueue_scripts
cât și wp_head
sunt apelate mult mai devreme: wp_head
undeva în fișierul header.php
al temei tale și wp_enqueue_scripts
în timpul apelului wp_head
.
Care este cea mai bună metodă pentru a adăuga fișierele de stil în header-ul doar al paginilor pe care este folosit shortcode-ul de mai sus, presupunând că nu voi cunoaște ID-urile paginilor, etc?
Nu cred că există o metodă "cea mai bună". Nu este o idee bună deloc. Browser-ele cache-ază fișierele CSS. Deci dacă ai același CSS pe toate paginile, browser-ul îl va prelua doar o dată. Dacă sunt multe fișiere CSS pentru diferite pagini, browser-ul va trebui să le preia pe toate. Așa că nu aș face asta deloc și aș include aceste stiluri CSS în fișierul CSS global.
Totuși, dacă trebuie să le incluzi doar pe paginile care folosesc acest shortcode, atunci (2 soluții, alegerea care este mai bună este a ta; cred că a 2-a este mai elegantă)...
- Poți adăuga aceste stiluri ca stiluri inline. Doar ai grijă să nu le incluzi de mai multe ori. Deci afișează-le cu shortcode-ul tău și asigură-te că vor fi tipărite doar o dată.
- Deoarece postările sunt deja selectate când
wp_head
/wp_enqueue_scripts
este apelat, poți adăuga o funcție la acest hook, parcurge postările selectate, verifica dacă conțin shortcode-ul tău și încărca CSS-ul tău dacă este necesar. (Desigur, nu va fi foarte eficient).

Poți folosi un hook pentru a acționa după ce interogarea principală a rulat și a determina dacă este necesar să încarci stilurile și scripturile tale.
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() {
//Încarcă aici resursele tale (stiluri/scripturi).
}

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' );
}
}
Aș folosi has_shortcode
pentru a verifica conținutul $post și a încărca scripturile folosind wp_enqueue_scripts, dar depinde de locul în care sunt încorporate shortcode-urile tale.
Înlocuiește $tag cu tag-ul shortcode-ului tău în codul de mai sus.
Adaugă în fișierul functions al temei child și modifică condițiile dacă este necesar.

O soluție mult mai simplă care a funcționat pentru mine a fost să înregistrez scriptul în afara funcției shortcode și apoi să încarc scriptul în interiorul funcției. Astfel, scriptul se încarcă doar pe paginile care folosesc shortcode-ul tău.
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;
}
O descriere a acestei metode poate fi găsită aici: http://mikejolley.com/2013/12/sensible-script-enqueuing-shortcodes/
Rețineți că această metodă încarcă CSS-ul în subsolul paginii, ceea ce poate să nu fie de dorit sau conform standardelor W3C. În cazul meu, acest lucru nu a fost o problemă.

Poți să faci asta simplu în felul următor:
// hook pentru shortcode
add_shortcode("make-me-a-map", "create_new_map");
// callback pentru 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');
// restul codurilor tale
}
}
Funcționează și pentru fișierele de stil. Pentru a-ți încărca fișierul de stil ultimul, adaugă numere la hook-ul shortcode-ului, astfel:
add_shortcode("make-me-a-map", "create_new_map", 9999);
Am testat și funcționează.

Încărcarea Dinamică a Scripturilor și Stilurilor Folosind Shortcode-uri
Acesta este codul extins pentru soluția oferită de Commandz mai sus.
Am constatat că metoda sa este cea mai bună și mai fezabilă, deoarece opțiunea de bază de date este disponibilă la aproape toate hook-urile.
S-a modificat pentru a găsi aparițiile shortcode-urilor doar pentru conținutul postării curente, în loc să parcurgă toate postările - ceea ce poate fi mai lent atunci când numărul de postări este mare.
S-au modificat aici două linii după transmiterea unei alte variabile $post_id din acțiunea save_post către funcția find_shortcode_occurences()
if( !empty($post_id) ) {
$args['posts__in'] = $post_id;
}
Cod modificat pentru ambele funcții
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);
}
}
De asemenea, a fost adăugată o altă variabilă, astfel încât să puteți avea denumiri diferite pentru opțiunea din baza de date și numele shortcode-ului.
