Enqueue Scripts / Styles ketika shortcode hadir

54

Apa cara ide untuk mendaftar / membuat skrip dan / atau gaya untuk digunakan dalam plugin?

Baru-baru ini saya membuat plugin plugin sederhana untuk menambahkan pengguna avatar / gravatar dengan kode pendek. Saya memiliki opsi gaya yang berbeda untuk menampilkan avatar (persegi, bulat, dll.) Dan memutuskan untuk meletakkan css langsung di shortcode itu sendiri.

Namun, saya menyadari sekarang ini bukan pendekatan yang baik karena akan mengulangi css setiap kali kode pendek digunakan pada halaman. Saya telah melihat beberapa pendekatan lain di situs ini dan wp codex bahkan memiliki dua contoh sendiri sehingga sulit untuk mengetahui pendekatan apa yang paling konsisten dan tercepat.

Berikut adalah metode yang saat ini saya ketahui:

Metode 1: Sertakan langsung dalam kode pendek - Ini adalah apa yang saya lakukan saat ini di plugin, tetapi sepertinya tidak bagus karena ini mengulangi kode.

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

Metode 2: Gunakan kelas untuk skrip enqueueing atau gaya kondisional

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();

Metode 3: Menggunakan 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' );

Metode 4: Menggunakan 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');
Bryan Willis
sumber
Saya pikir Method 4: Using has_shortcode();yang terbaik karena akan memastikan bahwa skrip dan gaya akan memuat sekali jika konten posting memiliki kode pendek terlepas dari beberapa penggunaan kode pendek. Meskipun mungkin tidak berfungsi untuk penggunaan kode pendek di widget atau di bilah sisi, tidak yakin sekalipun. Jika itu untuk sebuah plugin maka saya tidak akan merekomendasikan Anda untuk mengikat skrip dengan shortcode karena beberapa orang mungkin memanggil fungsi Anda alih-alih shortcode untuk mendapatkan output yang diinginkan.
Robert hue

Jawaban:

45

Saya menemukan cara lain yang berfungsi baik untuk saya:

Berikut adalah contoh plugin menggunakan metode ini yang memungkinkan Anda menggunakan getugu sebagai kode pendek. Lembar gaya hanya enqueued ketika shortcode hadir.

Penggunaan (id default untuk pengguna saat ini):

[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' );
}
Jblanche
sumber
Lupa saya mengajukan pertanyaan ini tahun lalu, tetapi saya sebenarnya sudah mulai melakukannya dengan cara ini juga dalam banyak kasus. Ini seperti menggabungkan metode 1 dan 2.
Bryan Willis
4
Metode ini memuat CSS di footer, yang tentunya memiliki keterbatasan?
Jacob Raccuia
1
Ini benar-benar cara yang tepat untuk melakukan ini. Gunakan metode ini kapan saja Anda perlu memuat skrip atau stylesheet secara kondisional ketika wp_enqueue_scriptskail sudah terjadi. (Kode singkat diuraikan the_contentyang merupakan bagian dari the_posthook, artinya enqueueing ketika diuraikan sudah terlambat kecuali Anda sudah mendaftarkan skrip)
JRad the Bad
26

Sebelum memulai jawaban saya harus mengatakan bahwa mengenai topik ini css dan js tidak sama.

Alasannya sederhana: sementara menambahkan js ke badan halaman (di footer) adalah cara yang umum dan valid untuk pergi, css perlu ditempatkan di <head>bagian halaman: bahkan jika mayoritas browser dapat membuat rss css di halaman tubuh, itu bukan kode HTML yang valid.

Ketika kode pendek diberikan, <head>bagian sudah dicetak, itu berarti bahwa js dapat ditambahkan tanpa masalah pada footer, tetapi css harus ditambahkan sebelum kode pendek diberikan.

Skrip

Jika kode pendek Anda hanya memerlukan js, Anda beruntung dan hanya dapat digunakan wp_enqueue_scriptdalam isi panggilan kode pendek:

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

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

Melakukan hal itu skrip Anda ditambahkan ke footer dan hanya sekali, bahkan jika kode pendek digunakan lebih dari satu kali di halaman.

Gaya

Jika kode Anda memerlukan gaya, maka Anda harus bertindak sebelum kode pendek benar-benar ditampilkan.

Ada berbagai cara untuk melakukan ini:

  1. lihat semua posting di kueri saat ini dan tambahkan gaya kode pendek jika diperlukan. Ini adalah apa yang Anda lakukan di kedua metode # 3 dan # 4 di OP. Sebenarnya, kedua metode melakukan hal yang sama, tetapi has_shortcodeditambahkan di WP 3.6, sementara get_shortcode_regextersedia sejak versi 2.5, jadi gunakan get_shortcode_regexhanya jika Anda ingin membuat plugin Anda kompatibel dengan versi yang lebih lama.

  2. selalu tambahkan gaya kode pendek, di semua halaman

Masalah

Masalah dengan # 1 adalah kinerja. Regex adalah operasi yang sangat lambat dan meluncurkan regex dalam satu lingkaran dari semua posting dapat memperlambat halaman secara konsisten. Selain itu, itu adalah tugas yang cukup umum dalam tema untuk hanya menampilkan kutipan posting di arsip dan menampilkan konten lengkap dengan kode pendek hanya dalam tampilan tunggal. Jika itu terjadi, ketika arsip ditampilkan, plugin Anda akan meluncurkan pencocokan regex dalam satu lingkaran dengan tujuan untuk menambahkan gaya yang tidak akan pernah digunakan: dampak kinerja ganda yang tidak perlu: memperlambat pembuatan halaman + permintaan HTTP tambahan yang tidak perlu

Masalah dengan # 2 adalah kinerja, lagi. Menambahkan gaya ke semua halaman berarti menambahkan permintaan HTTP tambahan untuk semua halaman, bahkan ketika tidak diperlukan. Bahkan jika waktu pembuatan halaman sisi server tidak terpengaruh, total waktu rendering halaman akan, dan untuk semua halaman situs.

Jadi, apa yang harus dilakukan oleh pengembang plugin?

Saya pikir hal terbaik yang harus dilakukan adalah menambahkan halaman opsi ke plugin, di mana pengguna dapat memilih apakah kode pendek harus ditangani hanya dalam tampilan tunggal atau bahkan dalam arsip. Dalam kedua kasus lebih baik untuk memberikan opsi lain untuk memilih jenis posting mana yang mengaktifkan kode pendek.

Dengan cara itu dimungkinkan untuk menghubungkan "template_redirect"untuk memeriksa apakah permintaan saat ini memenuhi persyaratan dan dalam hal itu menambahkan gaya.

Jika pengguna memilih untuk menggunakan kode pendek hanya dalam tampilan posting tunggal, adalah ide yang bagus untuk memeriksa apakah posting memiliki kode pendek atau tidak: sekali hanya diperlukan satu regex, seharusnya tidak terlalu memperlambat halaman.

Jika pengguna memilih untuk menggunakan kode pendek bahkan dalam arsip, maka saya akan menghindari menjalankan regex untuk semua posting jika jumlah posting tinggi dan hanya gaya enqueue jika permintaan sesuai persyaratan.

Apa yang dianggap "tinggi" dalam hal ini harus menggunakan beberapa tes kinerja atau, sebagai alternatif, tambahkan opsi lain dan berikan pilihan kepada pengguna.

gmazzap
sumber
2
Perlu dicatat di sini bahwa <style>tag dalam badan dokumen sekarang valid sesuai spesifikasi W3C. w3.org/TR/html52/document-metadata.html#the-style-element
Isaac Lubow
5

Untuk plugin saya, saya menemukan bahwa kadang-kadang pengguna memiliki pembuat tema yang memiliki kode pendek yang disimpan dalam data meta pos . Inilah yang saya gunakan untuk mendeteksi apakah kode pendek plugin saya ada di pos saat ini atau data meta pos :

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' );
zdenekca
sumber
2

Saya melakukannya:

class My_Shortcode {

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

dan menangkap hook di fungsi lain (atau plugin lain):

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

Saya menemukan plugin saya sendiri, jika ada kode pendek di widget teks.

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');
Gino
sumber
1

WordPress memiliki fungsi bawaan untuk melakukan sesuatu berdasarkan status penyajian Shortcode tertentu. Nama fungsinya adalah has_shortcode(). Anda dapat menggunakan kode berikut untuk mengubah gaya dan skrip Anda.

Di sini saya menggunakan is_a( $post, 'WP_Post' )untuk memeriksa apakah $postobjek dari WP_Postkelas dan saya digunakan $post->post_contentuntuk memeriksa konten posting.

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' );
}
Arif Rahman
sumber
0

Saya membuat kombinasi kode contoh dari halaman Wordpress untuk has_shortcode () dan jawaban yang diberikan zndencka . Saya memang memperhatikan bahwa fungsi kode has_short ditambahkan di Wordpress 3.6, jadi itu sebabnya saya pertama kali memeriksa apakah fungsi tersebut ada. Mungkin cek itu agak usang, karena tidak ada banyak pengguna dari bawah wordpress 3.6 lagi menurut wordpress statistik mereka sendiri.

// 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');
Vasco
sumber
0

Kami memang dapat memuat file CSS dan JS secara kondisional melalui shortcode tanpa menggunakan fungsi yang terlalu rumit :

Pertama, mari kita asumsikan kita telah mendaftarkan semua file CSS / JS kami sebelumnya (mungkin ketika wp_enqueue_scriptsdijalankan)

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

Selanjutnya, mari kita periksa fungsi kode pendek kami:

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

Sederhana. Selesai. Ergo: kita dapat "memuat secara kondisional" file css / js, (hanya ketika [shortcode] berjalan).

Mari pertimbangkan ideologi berikut:

  • Kami ingin memuat file CSS / JS tertentu (tetapi hanya ketika kode pendek dipicu)
  • Mungkin kita tidak ingin file-file itu dimuat di setiap halaman, atau sama sekali jika kode pendek tidak digunakan pada halaman / posting. (ringan)
  • Kita dapat melakukan ini dengan memastikan WP mendaftarkan SEMUA file css / js sebelum memanggil kode pendek dan sebelum enqueue.
  • IE: Mungkin selama prep_css_and_js()fungsi saya, saya memuat SEMUA file .css / .js yang ada di folder tertentu ...

Sekarang WP melihatnya sebagai skrip terdaftar, kita memang dapat memanggil mereka, secara kondisional, berdasarkan kejujuran situasi, termasuk tetapi tidak terbatas pada my_shortcode_func()

Manfaat: (tanpa MySQL, tidak ada fungsi lanjutan dan tidak perlu filter)

  • ini adalah "WP orthodix", elegan, pemuatan cepat, mudah dan sederhana
  • memungkinkan kompiler / penggubah untuk mendeteksi skrip tersebut
  • menggunakan fungsi WP (wp_register_style / wp_register_script)
  • kompatibel dengan lebih banyak tema / plugin yang mungkin ingin membatalkan pendaftaran skrip tersebut untuk alasan yang jelas.
  • tidak akan memicu beberapa kali
  • sangat sedikit pemrosesan atau kode yang terlibat

Referensi:

Žagarskas Kristen
sumber