Koşullu Olarak Kısa Kodlar için JavaScript / CSS Yükleme


37

Bir kısa kod oluşturan ve bu kısa kodu içeren herhangi bir sayfaya yüklemek için bir JavaScript dosyası ve bir CSS dosyası gerektiren bir eklenti yayınladım. Komut dosyası / stilin tüm sayfalara yüklenmesini sağlayabilirim, ancak bu en iyi uygulama değil. Dosyaları yalnızca kısa kodu çağıran sayfalara yüklemek istiyorum. Bunu yapmanın iki yöntemini buldum, ancak her ikisinin de sorunları var.

Yöntem 1 , bir kısa kod işleyici işlevi içinde bir bayrağı true olarak ayarlar ve sonra bir wp_footergeri çağırma içindeki bu değeri denetler . Eğer doğruysa, kullandığı wp_print_scripts()JavaScript yüklemek için. Bu sorun CSS içine beyan edilmelidir çünkü sadece, JavaScript ve CSS değil çalışır olmasıdır <head>yalnızca gibi erken bir kanca sırasında yapabileceğiniz, initya wp_head.

Yöntem 2 erken ateş eder ve kısa sayfanın geçerli sayfa içeriğinde olup olmadığını görmek için "ileriye göz atar". Bu yöntemi ilkinden daha çok seviyorum, ancak şablonun aradığını algılayamaz do_shortcode().

Böylece, ikinci yöntemi kullanmaya ve daha sonra bir şablonun atanıp atanmayacağını saptamaya çalışıyorum ve öyleyse kısa kod için ayrıştırmaya çalışıyorum. Bunu yapmadan önce, daha iyi bir yöntem bilen var mı kontrol etmek istedim.

Güncelleme: Çözümü eklentime ekledim. Herkes canlı bir ortamda fışkıran olduğunu merak ediyorsa, indirebilir veya göz atabilirsiniz .

Güncelleme 2: WordPress 3.3'ten itibaren, doğrudan bir kısa kod geri çağrısı wp_enqueue_script()içinden arama yapmak mümkündür ve JavaScript dosyası belgenin altbilgisinde çağrılır. Bu, CSS dosyaları için de teknik olarak mümkündür, ancak CSS'nin <head>etiket dışına çıkması W3C özelliklerini ihlal ettiğinden, FOUC'yi ihlal edebileceğinden ve tarayıcıyı sayfayı yeniden oluşturmaya zorlayabileceğinden kötü bir uygulama olarak düşünülmelidir .


Geçmişte Yöntem 1'in bir varyasyonunu kullandım. Kısa kod için JS'yi altbilgiye yükleyin, kısa kod için satır içi CSS'yi yükleyin. Çalışıyor, ama hackish. Daha iyi bir çözüm için bekliyorum.
EAMann

Satır içi CSS ile ilgili temel sorunlar, diğer stillerle geçersiz kılmanın zor olması ve wp_enqueue_styles () yöntemini kullanmamasıdır.
Ian Dunn

Ne kadar css'ınız var?
mfields

Javascript kaç satır?
mfields

2
Javascript kolay kısmıdır. Bunu yapmak için en iyi su burada "Jedi" altında: scribu.net/wordpress/optimal-script-loading.html
mfields

Yanıtlar:


11

Kendi tecrübelerime dayanarak, 1 ve 2 yöntemlerinin bir birleşimini kullandım - 1'in mimarisi ve altbilgisi kodları ve 2'nin 'ileriye dönük' tekniği.

İleriye dönük olsa da, yerine regex kullanıyorum stripos; kişisel tercih, daha hızlı ve 'hatalı biçimlendirilmiş' kısa kodları kontrol edebilir;

preg_match( '#\[ *shortcode([^\]])*\]#i', $content );

Yazarları do_shortcodemanuel olarak kullanma konusunda endişeleriniz varsa , önceden kaydedilmiş tarzınızı manuel olarak biçimlendirmek için bir eylem çağrısı kullanmalarını söylemeyi tercih ederim .

GÜNCELLEME : Hiç RTFM olmayan tembel yazar için , kendi yollarının hatasını vurgulamak için bir mesaj çıktı ;)

function my_shortcode()
{
    static $enqueued;
    if ( ! isset( $enqueued ) )
        $enqueued = wp_style_is( 'my_style', 'done' ); // cache it so we don't repeat if called over and over

    // do shortcode
    $output = '';

    if ( ! $enqueued )
        // you can output the message on first occurence only by wrapping it in the previous if
        $output .= <<<HTML
<p>Attention! You must enqueue the shortcode stylesheet yourself if calling <code>do_shortcode()</code> directly!</p>
<p>Use <code>wp_enqueue_style( 'my_style' );</code> before your <code>get_header()</code> call inside your template.</p>
HTML;

    return $output;
}

İyi bir noktaya değindin. İdeal olarak, fazladan bir şey yapmak zorunda kalmadan çalışmalarını istiyorum - çünkü muhtemelen ilk önce SSS'yi okumazlar, bu yüzden kırıldığını varsayarlar - ama bununla sonuçlanabilirim. Komut dosyalarını her sayfaya kaydedebilirim, ancak yalnızca bir kısa kod algıladığımda onları sıkıştırabilirim. Daha sonra, kullanıcılar, bu noktada yürütmede çok geç olmadığını varsayarak, gerektiğinde belirli şablonlarda enqueue işlevlerini arayabilir ve çağırabilir. Ayrıca, WP yerleşik get_shortcode_regex () özelliğine sahiptir.
Ian Dunn

3
Kullanıcılar uygulamada do_shortcode()ustaca davranıyorlarsa, aynı şekilde kısa kod stilini biçimlendirmek için aşağıdaki talimatlarda usta olduklarını varsaymak mantıklı değil midir?
Chip Bennett

1
Doğru, ancak tüm kısa kodların regex'ini alır, sadece sizinki değil;) "Komut dosyalarını her sayfaya kaydedebilirim" Muhtemelen daha iyi bir yöntem! Dikkat etmeleri gerek init, daha önce herhangi bir yerde wp_head. Tembel geliştirici wp_style_is( 'my_style_handle', 'done' )için kısa kodunuzu kontrol edin . Yanlışsa, ne yapmaları gerektiğini söyleyen görünür bir hata yazdırın.
TheDeadMedic

@Chip - Herkesin olduğundan endişeli değilim yetenekli onlar şey fazladan yapmak gerekmez zaman% 99 yana, onlar zannediyorsunuz bilmez sadece, talimatları uygulamak.
Ian Dunn

1
@ Düşünceme göre do_shortcode(), şablona eklemenin zaten "fazladan bir şey yapması" - ve bunu fazladan yapan bir şey, ya stili daha da zorlama gereği olduğunu zaten bilen ya da daha istekli / muhtemel olacağını söyleyebilirim. özel talimatları takip etmek için.
Chip Bennett

8

Bu soruyu cevaplamaya geç kaldım, ancak Ian bu konuya wp-hacker'lar listesinde bugün başladığından beri , özellikle üzerinde çalıştığım bazı eklentilere böyle bir özellik eklemeyi planladığımı düşünerek cevap vermeye değer olduğunu düşünmeme neden oldu.

Dikkate alınacak bir yaklaşım, kısa kodun gerçekten kullanılıp kullanılmadığını görmek için ilk sayfa yükünü kontrol etmek ve ardından kısa kod kullanım durumunu bir post meta anahtarına kaydetmektir. İşte nasıl:

Adım Adım Nasıl Yapılır

  1. Bir $shortcode_usedbayrak olarak ayarlayın 'no'.
  2. Kısa kod işlevinde kendisi $shortcode_usedbayrağı ayarlar 'yes'.
  3. WordPress kısa kodları işledikten sonra bir 'the_content'kanca önceliği 12belirleyin ''ve tuşu kullanarak post meta kontrol edin "_has_{$shortcode_name}_shortcode". ( ''Posta kimliği için bir yazı meta anahtarı bulunmadığında değeri döndürülür.)
  4. 'save_post'Kullanıcının kısa kod kullanımını değiştirmesi durumunda, söz konusu yazının kalıcı bayrağını temizleyerek post metasını silmek için bir kanca kullanın .
  5. Ayrıca 'save_post'kancada wp_remote_request(), ilk sayfa yükünü ve kalıcı bayrağın ayarını tetiklemek için yazının kendi kalıcı bağlantısına engelleyici olmayan bir HTTP GET göndermek için kullanın .
  6. Son olarak bir set 'wp_print_styles've bir değeri için yazılan meta kontrol 'yes', 'no'veya ''tuşunu kullanarak "_has_{$shortcode_name}_shortcode". Eğer değer 'no'harici değilse. Değer ise 'yes'veya ''devam edip dış hizmet etmek.

Ve bu yapmalı. Bunun nasıl çalıştığını göstermek için bir örnek eklenti yazdım ve test ettim.

Örnek Eklenti Kodu

Eklenti , sayfadaki öğeleri kırmızıya beyaza [trigger-css]ayarlayan bir kısa kodla uyanır, <h2>böylece çalışmasını kolayca görebilirsiniz. İçinde bu CSS bulunan dosyayı cssiçeren bir alt dizini varsayar style.css:

/*
 * Filename: css/style.css
 */
h2 {
  color: white;
  background: red;
}

Ve aşağıda çalışan bir eklenti kodudur:

<?php
/**
 * Plugin Name: CSS on Shortcode
 * Description: Shows how to conditionally load a shortcode
 * Author: Mike Schinkel <mike@newclarity.net>
 */
class CSS_On_Shortcode {

  /**
   * @var CSS_On_Shortcode
   */
  private static $_this;

  /**
   * @var string 'yes'/'no' vs. true/false as get_post_meta() returns '' for false and not found.
   */
  var $shortcode_used = 'no';

  /**
   * @var string
   */
  var $HAS_SHORTCODE_KEY = '_has_trigger-css_shortcode';
  /**
   *
   */
  function __construct() {
    self::$_this = $this;
    add_shortcode( 'trigger-css', array( $this, 'do_shortcode' ) );
    add_filter( 'the_content', array( $this, 'the_content' ), 12 ); // AFTER WordPress' do_shortcode()
    add_action( 'save_post', array( $this, 'save_post' ) );
    add_action( 'wp_print_styles', array( $this, 'wp_print_styles' ) );
  }

  /**
   * @return CSS_On_Shortcode
   */
  function this() {
    return self::$_this;
  }

  /**
   * @param array $arguments
   * @param string $content
   * @return string
   */
  function do_shortcode( $arguments, $content ) {
    /**
     * If this shortcode is being used, capture the value so we can save to post_meta in the 'the_content' filter.
     */
    $this->shortcode_used = 'yes';
    return '<h2>THIS POST WILL ADD CSS TO MAKE H2 TAGS WHITE ON RED</h2>';
  }

  /**
   * Delete the 'has_shortcode' meta value so that it can be regenerated
   * on first page load in case shortcode use has changed.
   *
   * @param int $post_id
   */
  function save_post( $post_id ) {
    delete_post_meta( $post_id, $this->HAS_SHORTCODE_KEY );
    /**
     * Now load the post asynchronously via HTTP to pre-set the meta value for $this->HAS_SHORTCODE_KEY.
     */
    wp_remote_request( get_permalink( $post_id ), array( 'blocking' => false ) );
  }

  /**
   * @param array $args
   *
   * @return array
   */
  function wp_print_styles( $args ) {
    global $post;
    if ( 'no' != get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * Only bypass if set to 'no' as '' is unknown.
       */
      wp_enqueue_style( 'css-on-shortcode', plugins_url( 'css/style.css', __FILE__ ) );
    }
   }

  /**
   * @param string $content
   * @return string
   */
  function the_content( $content ) {
    global $post;
    if ( '' === get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * This is the first time the shortcode has ever been seen for this post.
       * Save a post_meta key so that next time we'll know this post uses this shortcode
       */
      update_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, $this->shortcode_used );
    }
    /**
     * Remove this filter now. We don't need it for this post again.
     */
    remove_filter( 'the_content', array( $this, 'the_content' ), 12 );
    return $content;
  }

}
new CSS_On_Shortcode();

Örnek Ekran Görüntüleri

İşte bir dizi ekran görüntüsü

Temel Yazı Düzenleyicisi, İçerik Yok

Mesaj Görüntüleme, İçerik Yok

[trigger-css]Kısa Kodlu Temel Yazı Düzenleyicisi

[trigger-css]Kısa Kodlu Mesaj Görüntüleme

% 100 olup olmadığından emin değil

Yukarıdakilerin hemen hemen tüm durumlarda çalışması gerektiğine inanıyorum, ancak bu kodu henüz yazdığım için% 100 emin olamam. İşe yaramadığı durumları bulabilirseniz gerçekten bilmek isterim, bu yüzden kodu yeni eklentilere ekledim. Şimdiden teşekkürler.


Yani yaklaşımınızı kullanan beş eklenti, her kayıt kaydedildiğinde beş uzak isteği tetikleyecektir? Üzerinde regex kullanmayı tercih ederim post_content. Peki ya widget'lardaki kısa kodlar?
fuxia

@toscho Yükleme sonrası tetikleme aslında isteğe bağlıdır; yalnızca kullanıcının harici yüklenen ilk sayfa yükünü görmesi gerekmediğinden emin olmak için vardır. Aynı zamanda engelleyici olmayan bir çağrı olduğundan teoride bunu farketmemeniz gerekir. Kodumuz için bir temel sınıfta yapıyoruz, böylece temel sınıf bunu yalnızca bir kez yapabilir. Biz kanca olabilir 'pre_http_request'iken aynı URL'ye kanca ve devre dışı çoklu aramaları 'save_post'kanca aktiftir, ama gerçekten hayır, bunun için bir ihtiyaç gördüm w kadar beklemek ister ki? Widget'lara gelince işlemek için geliştirilebilir, ancak henüz baktığım bir kullanım durumu değil.
MikeSchinkel

1
@toscho - Ayrıca kısa kodun orada olduğundan emin olamazsınız, çünkü başka bir kanca onu temizleyebilir. Emin olmanın tek yolu, kısa kod fonksiyonunun gerçekten çalışıp çalışmadığıdır. Yani regex yaklaşımı% 100 güvenilir değil.
MikeSchinkel

Biliyorum. Orada hiçbir (kullanarak hariç kısa kod için CSS enjekte kurşun geçirmez yolu <style>).
fuxia

Bu çözüme dayanan bir uygulama ile çalışıyorum ve bu yöntemin bir yazı / sayfa önizlemesi için geçerli olmayacağını belirtmek istedim.
mor7ifer

5

Googling bana potansiyel bir cevap buldu . İyi göründüğü gibi "potansiyel" diyorum, çalışmalıyım, ama% 100 olmadığına inanıyorum:

add_action( 'wp_print_styles', 'yourplugin_include_css' );
function yourplugin_include_css() {
    // Check if shortcode exists in page or post content
    global $post;

    // I removed the end ' ] '... so it can accept args.
    if ( strstr( $post->post_content, '[yourshortcode ' ) ) {
        echo $csslink;
    }
}

Bu, geçerli gönderinin bir kısa kod kullanıp kullanmadığını kontrol edebilmeli ve <head>öğeye uygun bir stil sayfası ekleyebilmelidir . Ancak bir indeks için çalışacağını sanmıyorum (yani döngüdeki birden fazla mesaj) sayfası ... Ayrıca 2 yıllık bir blog yazısından da geliyor, bu yüzden WP 3.1.X ile çalışacağından bile emin değilim. .


Kısa kod argümanları varsa bu işe yaramaz. Gerçekten bu şekilde gitmek istiyorsanız, ki bu yavaş, get_shortcode_regex()arama için WP'leri kullanın .
onetrickpony

Söylediğim gibi, henüz test etmediğim "potansiyel" cevabı ... :-)
EAMann

Bu temelde yöntem 2 ile aynıdır, ancak yine de do_shortcode () çağrıları için şablonu denetlemez.
Ian Dunn

Bunu neden yapması gerekiyor? Eğer do_shortcode()şablonda manuel olarak
ararsanız

Kısa kod çağıran ben değilim, kullanıcı. Bu dağıtılmış bir eklenti için değil, özel bir eklenti için.
Ian Dunn

2

TheDeadMedic'in cevabı ve get_shortcode_regex () belgesinin (gerçekte kısa kodlarımı bulamadım) belgelerinin bir birleşimini kullanarak , birden çok kısa kod için komut dosyalarını kodlamak için kullanılan basit bir işlev oluşturdum. Kısa kodlardaki wp_enqueue_script () yalnızca altbilgiyi eklediğinden, hem üstbilgi hem de altbilgi komut dosyalarını işleyebileceği için bu yardımcı olabilir.


function add_shortcode_scripts() {
    global $wp_query;   
    $posts = $wp_query->posts;
    $scripts = array(
        array(
            'handle' => 'map',
            'src' => 'http://maps.googleapis.com/maps/api/js?sensor=false',
            'deps' => '',
            'ver' => '3.0',
            'footer' => false
        ),
        array(
            'handle' => 'contact-form',
            'src' => get_template_directory_uri() . '/library/js/jquery.validate.min.js',
            'deps' => array( 'jquery' ),
            'ver' => '1.11.1',
            'footer' => true
        )   
    );

    foreach ( $posts as $post ) {
        foreach ( $scripts as $script ) {
            if ( preg_match( '#\[ *' . $script['handle'] . '([^\]])*\]#i', $post->post_content ) ) {
                // enqueue css and/or js
                if ( wp_script_is( $script['handle'], 'registered' ) ) {
                    return;
                } else {
                    wp_register_script( $script['handle'], $script['src'], $script['deps'], $script['ver'], $script['footer'] );
                    wp_enqueue_script( $script['handle'] );
                }
            }
        }
    }
}
add_action( 'wp', 'add_shortcode_scripts' );

1

Sonunda www.mapsmarker.com eklentim için çalışan koşullu css yükleme için bir çözüm buldum ve sizinle paylaşmak istiyorum. Kısa kodumun mevcut şablon dosyası ve header / footer.php içinde kullanılıp kullanılmadığını kontrol eder ve evet ise, başlıkta gerekli stil sayfasını gerektirir:

  function prefix_template_check_shortcode( $template ) {
    $searchterm = '[mapsmarker';
    $files = array( $template, get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'header.php', get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'footer.php' );
    foreach( $files as $file ) {
        if( file_exists($file) ) {
            $contents = file_get_contents($file);
            if( strpos( $contents, $searchterm )  ) {
                wp_enqueue_style('
leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css');
                  break; 
            }
        }
    }
  return $template;
  }  
  add_action('template_include','prefix_template_check_shortcode' );

bir kenara biraz ama bu insanların header.php ve footer.php kullandığını varsaymaz. Scribu.net/wordpress/theme-wrappers.html tarafından açıklananlar gibi tema sarma yöntemleri ne olacak ? veya şablon parçalarını başka bir yerde tutan kökler gibi temalar?
orionrush

1

Eklentim için bazen kullanıcıların meta verilerde depolanan kısa kodlu bir tema oluşturucusuna sahip olduğunu buldum . Eklenti kısa kodumun geçerli gönderi veya yazı meta verilerinde mevcut olup olmadığını saptamak için kullanıyorum :

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

0

Çünkü CSS içeride bildirilmelidir. <head>

CSS dosyaları için onları kısa kod çıktınıza yükleyebilirsiniz:

<style type="text/css">
  @import "path/to/your.css"; 
</style>

Bundan sonra bir sabit veya başka bir şey belirleyin MY_CSS_LOADED(yalnızca sabit ayarlanmamışsa yalnızca CSS'yi dahil edin).

Her iki yönteminiz de bu yoldan daha yavaş.

JS dosyaları için, yüklediğiniz komut dosyası benzersiz ve dış bağımlılıkları yoksa, aynı işlemi yapabilirsiniz. Bu durumda değilse, altbilgiye yükleyin, ancak yüklenmesi gerekip gerekmediğini belirlemek için sabit kullanın.


3
CSS'nin <head>elemanın dışına yüklenmesi doğru işaretleme değildir. Doğru, doğrulama sadece bir kılavuzdur, ancak bu kılavuza uymaya çalışıyorsak, kısa kod çıktısına stil sayfasını yüklemeyi kötü bir fikir haline getirir.
EAMann

Satır içi CSS blokları, hatırladığımdan XHTML'de bile geçerlidir.
Kabul

1
W3C doğrulama aracı göre: <style type="text/css"> The element named above was found in a context where it is not allowed. This could mean that you have incorrectly nested elements -- such as a "style" element in the "body" section instead of inside "head". Bu nedenle satır içi stilleri ( <element style="..."></element>) geçerlidir, ancak satır içi <style>öğeleri geçerli değildir.
EAMann

1
filtrelemesini sağlayın ve diğer eklentiler veya temalar onlarla istediklerini yapın. Filtreyi boş bir dize döndürecek şekilde yapılandırırlarsa hiçbir şey yazdırılmaz.
mfields

1
Bu uygulamaya karşı nesnel sebeplerden bahsetmediniz. Neyse önemli değil; Burada sadece iki seçenek görüyorum: Her zaman CSS / script (bunları boyut için optimize et) veya koşullu satır içi stilleri
yükle

0

Script Logic, tüm JavaScript ve CSS dosyaları üzerinde tam kontrol sağlayan bir WordPress eklentisidir. Bu eklentiyi kullanarak CSS ve JS dosyasını sadece ihtiyaç duyulan sayfalara koşullu olarak yükleyebilirsiniz.

http://wordpress.org/plugins/script-logic/


Bu, eklentinin kendi içinden gelen kodlamayı kontrol etmekle ilgili olan bu soru ile gerçekten alakalı değil. Yaklaşımınız, kullanıcıdan başka bir eklenti yüklemesini istemeli ve ardından onu nasıl doğru bir şekilde yapılandıracağını anlamalıdır.
Ian Dunn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.