짧은 코드에 대한 조건부로 JavaScript / CSS로드


37

짧은 코드를 만드는 플러그인을 출시했으며 해당 짧은 코드가 포함 된 모든 페이지에 JavaScript 파일과 CSS 파일을로드해야합니다. 모든 페이지에 스크립트 / 스타일을로드 할 수는 있지만 최선의 방법은 아닙니다. 단축 코드를 호출하는 페이지에만 파일을로드하고 싶습니다. 이 작업을 수행하는 두 가지 방법을 찾았지만 두 가지 모두 문제가 있습니다.

방법 1 은 단축 코드 처리기 함수 내에서 플래그를 true로 설정 한 다음 wp_footer콜백 내에서 해당 값을 확인합니다 . true 인 경우 wp_print_scripts()JavaScript를로드하는 데 사용 됩니다. 이 문제는 CSS가 내부에 선언해야하기 때문에 그것은 단지, 자바 스크립트, CSS하지 작동한다는 것입니다 <head>만 같은 초기 후크에서 수행 할 수있는, init또는 wp_head.

방법 2 가 일찍 실행되고 "앞으로 엿보기"하여 현재 페이지 내용에 단축 코드가 있는지 확인합니다. 이 방법은 첫 번째 방법보다 훨씬 좋지만 템플릿의 호출 여부를 감지하지 못합니다 do_shortcode().

그래서 두 번째 방법을 사용하고 템플릿이 할당되었는지 감지하려고 시도하고 있다면 코드를 구문 분석합니다. 그러나 그렇게하기 전에 누군가 더 나은 방법을 알고 있는지 확인하고 싶었습니다.

업데이트 : 솔루션을 플러그인에 통합했습니다. 누군가 실제 환경에서이 기능을보고 싶어하는 경우 다운로드 하거나 찾아 볼 수 있습니다.

업데이트 2 : WordPress 3.3부터는 단축 코드 콜백 내에서 직접 호출wp_enqueue_script() 할 수 있으며 JavaScript 파일은 문서의 바닥 글 내에서 호출됩니다. CSS 파일에서도 기술적으로 가능하지만 <head>태그 외부에서 CSS를 출력하면 W3C 사양을 위반하고 FOUC를 발생시킬 수 있으며 브라우저가 페이지를 다시 렌더링 해야하기 때문에 나쁜 습관으로 간주해야합니다 .


과거에는 방법 1의 변형을 사용했습니다. 바닥 글에 단축 코드 용 JS를로드하고 단축 코드 용 CSS를 인라인으로로드하십시오. 작동하지만 해킹 적입니다. 더 나은 솔루션을 기대합니다.
— EAMann

인라인 CSS의 주요 문제점은 다른 스타일로 대체하기가 어렵고 wp_enqueue_styles () 메소드를 사용하지 않는다는 것입니다.
— Ian Dunn

CSS는 얼마입니까?
— mfields 2016 년

자바 스크립트는 몇 줄입니까?
— mfields 2016 년

2
자바 스크립트는 쉬운 부분입니다. 이 작업을 수행하는 가장 좋은 와트는 여기에 "제다이"아래 : scribu.net/wordpress/optimal-script-loading.html
— mfields

답변:


11

내 경험을 바탕으로 방법 1과 2의 방법-1의 아키텍처 및 바닥 글 스크립트와 2의 '예측'기술의 조합을 사용했습니다.

예를 들어, 대신 정규식을 사용합니다 stripos. 개인 취향은 더 빠르며 '잘못된'단축 코드를 확인할 수 있습니다.

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

저자가 do_shortcode수동으로 사용하는 것을 염려한다면 사전 등록 된 스타일을 수동으로 대기열에 넣는 액션 콜 을 사용 하도록 지시합니다 .

업데이트 : RTFM을 전혀 겪지 않은 게으른 저자의 경우 , 오류 를 강조하는 메시지를 출력하십시오 .)

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

그건 좋은 지적이야. 이상적으로는 별도의 조치를 취하지 않아도 작동하고 싶습니다. 왜냐하면 절반의 시간이 FAQ를 먼저 읽지 않을 것이기 때문에 문제가 있다고 가정 할 것입니다. 그러나 결국 그렇게 할 수 있습니다. 모든 페이지에 스크립트를 등록 할 수 있지만 단축 코드를 감지 한 경우에만 대기열에 넣습니다. 그런 다음 사용자는 init에 연결하고 해당 시점에서 실행이 너무 늦지 않다고 가정하고 필요한 경우 특정 템플릿에서 enqueue 함수를 호출 할 수 있습니다. 또한 WP에는 get_shortcode_regex ()가 내장되어 있습니다.
— Ian Dunn

3
사용자가 구현 do_shortcode()에 능숙하다면, 단축 코드 스타일을 대기열에 넣기위한 지침을 따르는 것도 마찬가지로 가정하는 것이 합리적이지 않습니까?
— Chip Bennett

1
사실, 그것은 당신의 것이 아닌 모든 단축 코드에 대한 정규 표현식을 얻을 것입니다.;) "모든 페이지에 스크립트를 등록 할 수 있습니다"아마도 더 좋은 방법 일 것입니다! init이전에 어디서나 에 연결할 필요가 없습니다 wp_head. 게으른 개발자의 경우 wp_style_is( 'my_style_handle', 'done' )단축 코드 내부를 확인 하십시오. False이면 눈에 보이는 오류를 인쇄하여 수행 할 작업을 지시합니다.
— TheDeadMedic

@Chip는 - 나는 그들이하지 않은 것을 걱정하고 있지 않다 수있는 그들은 당신이 아무것도 추가 할 필요가 없습니다 시간의 99 % 이후, 그들은 거 야 알 수 없습니다 단지, 지침에 따라의.
— Ian Dunn

1
@Ian 내 생각은 do_shortcode()템플릿에 추가 하는 것이 이미 "추가적인 일을하고있다"는 것입니다. 그리고 그 일을하는 사용자는 이미 스타일을 큐에 넣을 필요성에 대해 알고 있거나 더 기꺼이 할 것입니다. 특별한 지침을 따르십시오.
— Chip Bennett

8

나는이 질문에 늦게 대답하고 있지만 Ian 이 오늘 wp-hackers 목록 에서이 스레드 를 시작한 이래로 내가 작업 한 일부 플러그인에 이러한 기능을 추가 할 계획을 고려할 때 특히 대답 할 가치가 있다고 생각했습니다.

고려해야 할 방법은 첫 페이지로드를 점검하여 단축 코드가 실제로 사용되는지 확인한 다음 단축 코드 사용 상태를 사후 메타 키에 저장하는 것입니다. 방법은 다음과 같습니다.

단계별 사용법

  1. $shortcode_used플래그를로 설정하십시오 'no'.
  2. 단축 코드 기능 자체에서 $shortcode_used플래그를로 설정하십시오 'yes'.
  3. WordPress가 단축 코드를 처리 한 후 'the_content'후크 우선 순위 12를 설정 ''하고 키를 사용하여 포스트 메타를 점검하십시오 "_has_{$shortcode_name}_shortcode". 게시물 ID에 대해 게시 메타 키가 없으면 값 ''이 반환됩니다.
  4. 'save_post'사용자가 단축 코드 사용법을 변경하는 경우 후크를 사용하여 해당 게시물에 대한 지속 플래그를 지우는 게시물 메타를 삭제하십시오.
  5. 또한 'save_post'후크 wp_remote_request()에서 비 차단 HTTP GET을 게시물의 퍼머 링크로 전송하여 첫 페이지로드 및 지속적 플래그 설정을 트리거합니다.
  6. 마지막으로을 설정 'wp_print_styles'하고의 값을 포스트 메타를 확인 'yes', 'no'또는 ''키를 사용하여 "_has_{$shortcode_name}_shortcode". 값이 'no'외부를 제공하지 않으면 값이 'yes'아니면 ''계속해서 외부 서비스를 제공하십시오.

그리고 그렇게해야합니다. 이 플러그인이 어떻게 작동하는지 보여주는 플러그인 예제를 작성하고 테스트했습니다.

플러그인 코드 예

플러그인 은 페이지 [trigger-css]의 <h2>요소를 흰색에서 빨간색으로 설정하여 작동하는 것을 쉽게 볼 수 있는 짧은 코드 에서 깨어납니다 . 이 CSS 파일을 css포함 하는 서브 디렉토리를 가정 style.css합니다.

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

아래는 작동하는 플러그인의 코드입니다.

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

스크린 샷 예

다음은 일련의 스크린 샷입니다.

기본 게시물 편집기, 내용 없음

게시물 표시, 내용 없음

[trigger-css]단축 코드가있는 기본 포스트 편집기

[trigger-css]단축 코드가있는 포스트 디스플레이

100 %이면 확실하지 않습니다

위의 내용은 거의 모든 경우에 작동해야한다고 생각하지만이 코드를 작성했을 때 100 % 확신 할 수는 없습니다. 작동하지 않는 상황을 찾을 수 있다면 정말로 알고 싶습니다. 방금 추가 한 일부 플러그인에서 코드를 수정할 수 있습니다. 미리 감사드립니다.


따라서 접근 방식을 사용하는 5 개의 플러그인은 게시물을 저장할 때마다 5 개의 원격 요청을 트리거합니까? 오히려에 정규식을 사용하고 싶습니다 post_content. 위젯의 단축 코드는 어떻습니까?
— fuxia

@toscho 포스트 로딩의 트리거링은 실제로 선택 사항입니다. 사용자가 외부 장치가로드 된 첫 페이지로드를 볼 필요가 없도록하기 위해서만 있습니다. 또한 비 차단 통화이므로 이론적으로는 알 수 없습니다. 코드의 경우 기본 클래스에서 수행하므로 기본 클래스는 한 번만 처리 할 수 ​​있습니다. 우리는 후크 수 'pre_http_request'그동안 같은 URL에 후크와 비활성화를 여러 번 호출을 'save_post'후크가 활성화되어있는,하지만 난 정말 아니, 그 필요를 보았다 w 때까지 기다려야 싶어? 위젯에 관해서는 처리하도록 향상 될 수 있지만 아직 살펴본 유스 케이스는 아닙니다.
— MikeSchinkel

1
@toscho-또 다른 후크가 지울 수 있으므로 단축 코드가 있는지 확신 할 수 없습니다. 단축 코드 기능이 실제로 실행되는지 확인하는 유일한 방법입니다. 따라서 정규식 접근 방식은 100 % 신뢰할 수 없습니다.
— MikeSchinkel

알아. 짧은 코드에 CSS를 삽입하는 방탄 방법 은 없습니다 (을 사용하는 것을 제외 <style>).
— fuxia

이 솔루션을 기반으로 한 구현을 사용하고 있으며이 방법으로 게시물 / 페이지 미리보기를 대기열에 넣지 않을 것이라고 지적하고 싶었습니다.
— mor7ifer

5

인터넷 검색으로 잠재적 인 답을 찾았습니다 . 나는 "잠재적"이라고 말하면 좋을 것 같지만 작동해야하지만 100 %가 최선의 방법이라고 확신하지는 않습니다.

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

현재 게시물이 짧은 코드를 사용하고 있는지 확인하고 스타일 시트를 <head>요소에 적절하게 추가 할 수 있어야합니다 . 그러나 인덱스 (예 : 루프의 여러 게시물) 페이지에서는 작동하지 않는다고 생각합니다 ... 2 년 된 블로그 게시물에서 온 것이므로 WP 3.1.X에서도 작동하는지 확실하지 않습니다. .


단축 코드에 인수가 있으면 작동하지 않습니다. 이 방법으로 천천히 가고 싶다면 천천히 WP를 사용하십시오 get_shortcode_regex().
— onetrickpony

내가 말했듯이, 아직 테스트하지 않은 "잠재적"답변 ... :-)
— EAMann

기본적으로 방법 2와 동일하지만 여전히 템플릿에서 do_shortcode () 호출을 확인하지 않습니다.
— Ian Dunn

왜 그렇게해야합니까? do_shortcode()템플릿에서 수동으로 호출 하면 이미 단축 코드를 실행할 것임을 알고 있습니다.
— onetrickpony

나는 단축 코드를 부르는 사람이 아니며, 사용자입니다. 전용 플러그인이 아닌 분산 플러그인 용입니다.
— Ian Dunn

2

TheDeadMedic의 답변과 get_shortcode_regex () 문서 (실제로 내 단축 코드를 찾지 못함)의 조합을 사용하여 여러 단축 코드의 스크립트를 대기열에 넣는 데 사용되는 간단한 함수를 만들었습니다. 짧은 코드의 wp_enqueue_script ()는 바닥 글에만 추가되므로 헤더 및 바닥 글 스크립트를 모두 처리 할 수 ​​있으므로 도움이 될 수 있습니다.


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

마지막으로 플러그인 www.mapsmarker.com에서 작동하는 조건부 CSS 로딩에 대한 솔루션을 찾았 으며 귀하와 공유하고 싶습니다. 현재 템플릿 파일과 header / footer.php 내에서 짧은 코드가 사용되는지 확인하고 필요한 경우 헤더에 필요한 스타일 시트를 큐에 넣습니다.

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

조금 제쳐두고 있지만 사람들이 header.php와 footer.php를 사용하고 있다고 가정하지는 않습니다. scribu.net/wordpress/theme-wrappers.html에서 설명한 것과 같은 테마 줄 바꿈 방법은 어떻 습니까? 또는 템플릿 부분을 다른 곳에 보관하는 루트와 같은 테마?
— orionrush 2016 년

1

내 플러그인의 경우 사용자에게 간혹 메타 데이터에 저장된 단축 코드가있는 테마 빌더가 있음을 발견했습니다 . 플러그인 단축 코드가 현재 게시물 또는 게시물 메타 데이터에 있는지 여부를 감지하는 데 사용하는 내용은 다음과 같습니다 .

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

CSS는 내부에 선언되어야하기 때문에 <head>

CSS 파일의 경우 짧은 코드 출력 내에 해당 파일을로드 할 수 있습니다.

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

다음과 같이 상수 또는 무언가를 설정하십시오 MY_CSS_LOADED(상수가 설정되지 않은 경우에만 CSS 포함).

두 가지 방법 모두이 방법보다 느립니다.

JS 파일의 경우로드하는 스크립트가 고유하고 외부 종속성이없는 경우에도 동일한 작업을 수행 할 수 있습니다. 그렇지 않은 경우 바닥 글 안에로드하지만 상수를 사용하여로드해야하는지 여부를 결정하십시오.


3
<head>요소 외부에 CSS를로드하는 것은 올바른 마크 업이 아닙니다. 사실, 유효성 검사는 지침 일 뿐이지 만이 지침을 따르려고하면 짧은 코드 출력 내에 스타일 시트를로드하는 것이 좋지 않습니다.
— EAMann 2016 년

인라인 CSS 블록은 XHTML에서도 내가 기억하는 것으로부터 유효한 마크 업입니다. 다른 적절한 대안이 없을 때 그것들을 사용하지 않을 이유가 없습니다
— onetrickpony

1
W3C의 검증 도구에 따르면 : <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". 따라서 인라인 스타일 ( <element style="..."></element>)은 유효하지만 인라인 <style>요소는 유효 하지 않습니다.
— EAMann 2016 년

1
필터링 할 수 있고 다른 플러그인이나 테마는 원하는대로 할 수 있습니다. 빈 문자열을 반환하도록 필터를 구성하면 아무 것도 인쇄되지 않습니다.
— mfields

1
이 관행에 대한 객관적인 이유는 언급하지 않았습니다. 어쨌든 그것은 중요하지 않습니다. 여기에는 두 가지 옵션 만 있습니다. 항상 CSS / 스크립트로드 (크기에 맞게 최적화) 또는 조건부 인라인 스타일
— onetrickpony

0

Script Logic은 모든 JavaScript 및 CSS 파일을 완벽하게 제어 할 수있는 WordPress 플러그인입니다. 이 플러그인을 사용하면 필요한 페이지에만 CSS 및 JS 파일을 조건부로로드 할 수 있습니다.

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


그것은 플러그인 자체 내에서 큐잉을 제어하는 ​​것에 관한이 질문과 관련이 없습니다. 접근하려면 사용자에게 다른 플러그인을 설치하도록 요청한 다음 올바르게 구성하는 방법을 이해해야합니다.
— Ian Dunn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.