짧은 코드에 대한 조건부로 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.