Cum să adaugi fișiere CSS doar pe paginile cu un shortcode specific?

31 iul. 2013, 12:42:21
Vizualizări: 14.6K
Voturi: 9

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

  1. 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țiunea if...
  2. 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

1
Toate răspunsurile la întrebare 8
3
11

Î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() sau strpos(). 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

  1. Găsește shortcode-urile pe pagină folosind hook-ul save_post doar când articolul nu este o revizie și se potrivește cu post_type specificat.

  2. 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 folosi update_option().

  3. Folosește hook-ul wp_enqueue_scripts pentru a apela funcția noastră add_scripts_and_styles().

  4. 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');
21 feb. 2014 21:10:56
Comentarii

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

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

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

CommandZ CommandZ
4 mai 2017 06:17:22

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.

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

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/

16 iul. 2015 13:36:37
Comentarii

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

fuxia fuxia
16 iul. 2015 14:23:29

Problema aici este că stilurile vor fi legate în subsol. Este probabil că va funcționa. Dar este 'greșit' și nu este garantat că va funcționa.

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

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

  1. 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ă.
  2. 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).
31 iul. 2013 13:05:45
Comentarii

Da, varianta #2 ar putea fi mai puțin eficientă, dar cu siguranță mai elegantă decât inline =) Am reușit să o fac să funcționeze acum, mulțumesc!

Padraic Padraic
3 aug. 2013 11:46:20
0

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

    }

}

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.

26 mai 2017 15:16:43
0

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

8 nov. 2014 17:26:44
0

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

25 feb. 2015 20:03:15
0

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

26 mai 2017 12:47:02