Ładowanie skryptów tylko wtedy, gdy występuje określony krótki kod lub widżet

17

Potrzebowałem sposobu na odfiltrowanie zawartości strony / postów przed jej załadowaniem, aby móc dodać skrypty do nagłówka, jeśli występuje określony krótki kod. Po wielu poszukiwaniach natknąłem się na to na http://wpengineer.com

function has_my_shortcode($posts) {
    if ( empty($posts) )
        return $posts;

    $found = false;

    foreach ($posts as $post) {
        if ( stripos($post->post_content, '[my_shortcode') )
            $found = true;
            break;
        }

    if ($found){
        $urljs = get_bloginfo( 'template_directory' ).IMP_JS;

    wp_register_script('my_script', $urljs.'myscript.js' );

    wp_print_scripts('my_script');
}
    return $posts;
}
add_action('the_posts', 'has_my_shortcode');

co jest absolutnie genialne i zrobiło dokładnie to, czego potrzebowałem.

Teraz muszę go trochę rozszerzyć i zrobić to samo dla pasków bocznych. Może to być określony typ widżetu, krótki kod, fragment kodu lub cokolwiek innego, co działałoby w celu zidentyfikowania, kiedy skrypt musi zostać załadowany.

Problem polega na tym, że nie mogę dowiedzieć się, jak uzyskać dostęp do zawartości pasków bocznych przed załadowaniem paska bocznego (dany motyw będzie miał kilka pasków bocznych)

Ashley G.
źródło
Czy skrypty w nagłówku są twardym wymogiem w Twojej sytuacji? Skrypty na końcu strony łatwiej poradzić sobie z warunkową i zalecaną praktyką dotyczącą wydajności.
Rarst
Najpierw spróbowałem w wp_footer, co ładnie eliminuje potrzebę wstępnego filtrowania zawartości, ale chociaż skrypty ładowały się dobrze, nie działały. Te skrypty muszą znajdować się w wp_head, aby robić to, co muszą.
Ashley G,

Odpowiedzi:

20

Możesz użyć funkcji is_active_widget . Na przykład:

function check_widget() {
    if( is_active_widget( '', '', 'search' ) ) { // check if search widget is used
        wp_enqueue_script('my-script');
    }
}

add_action( 'init', 'check_widget' );

Aby załadować skrypt tylko na stronę, na której widżet jest ładowany, musisz dodać kod is_active_widget () do klasy widżetu. Np. Zobacz domyślny widżet ostatnich komentarzy (wp-zawiera / domyślny-widgets.php, wiersz 602):

class WP_Widget_Recent_Comments extends WP_Widget {

    function WP_Widget_Recent_Comments() {
        $widget_ops = array('classname' => 'widget_recent_comments', 'description' => __( 'The most recent comments' ) );
        $this->WP_Widget('recent-comments', __('Recent Comments'), $widget_ops);
        $this->alt_option_name = 'widget_recent_comments';

        if ( is_active_widget(false, false, $this->id_base) )
            add_action( 'wp_head', array(&$this, 'recent_comments_style') );

        add_action( 'comment_post', array(&$this, 'flush_widget_cache') );
        add_action( 'transition_comment_status', array(&$this, 'flush_widget_cache') );
    }
sorich87
źródło
Czy można to nazwać PRZED załadowaniem widżetów. Aby to wyjaśnić, musi to nastąpić, zanim strona się załaduje. Mój przykładowy kod używa post_posts do filtrowania treści na stronie, ale to nie wyświetla pasków bocznych / widżetów.
Ashley G,
Tak, zobacz przykład dodany do mojej odpowiedzi.
sorich87
Twój przykład tak naprawdę nie działa. Czy brakuje mi czegoś oczywistego?
Ashley G
Właściwie to byłem. wp_enqueue_script nie wydaje się działać po zastosowaniu do wp_head, ale wp_print_scripts działa. wp_enqueue_script działa jednak, jeśli zastosuje się go do init w ten sposób: add activity ('init', 'check_widget');
Ashley G
Jednak ładuje skrypty na każdej stronie witryny, nawet jeśli widżet jest aktywny tylko na jednym pasku bocznym. na przykład, jeśli mam pasek boczny dla stron blogu i inny pasek boczny dla innych stron. Dodam widżet wyszukiwania do paska bocznego blogu, a skrypty ładują się, ale ładują się również na stronach, które nie mają paska bocznego blogu. Muszę być w stanie załadować skrypt tylko wtedy, gdy widżet jest obecny na tej stronie.
Ashley G
3

Chciałem tylko udostępnić rozwiązanie, nad którym pracowałem, dzięki czemu mogłem być nieco bardziej wszechstronny przy wdrażaniu. Zamiast sprawdzania funkcji pod kątem różnych skrótów, zmodyfikowałem go, aby znaleźć pojedynczy skrót, który odwołuje się do funkcji skryptu / stylu, która wymaga kolejkowania. Będzie to działać dla obu metod w innych klasach (takich jak wtyczki, które same tego nie mogą zrobić) i funkcji w zakresie. Po prostu upuść poniższy kod w functions.php i dodaj następującą składnię do dowolnej strony / postu, w której chcesz mieć określony CSS i JS.

Składnia strony / postu: [loadCSSandJS function = "(class-> method / function name)"]

kod funkcji.php:

function page_specific_CSSandJS( $posts ) {
  if ( empty( $posts ) )
    return $posts;

  foreach ($posts as $post) {

    $returnValue = preg_match_all('#\[loadCSSandJS function="([A-z\-\>]+)"\]#i', $post->post_content, $types);

    foreach($types[1] as $type) {
      $items = explode("->",$type);
      if (count($items) == 2) {
        global $$items[0];      
        if( method_exists( $$items[0], $items[1] ))
          add_action( 'wp_enqueue_scripts', array(&$$items[0], $items[1]) );
      }
      else if( !empty( $type ) && function_exists( $type ))
        add_action( 'wp_enqueue_scripts', $type );
    }
  }

  return $posts;
}

Umożliwi to również dodanie dowolnej liczby stron na stronie. Pamiętaj, że do załadowania potrzebujesz metody / funkcji.

Nick Caporin
źródło
1

Dziękujemy za udostępnienie tej wskazówki! Sprawiało mi to ból głowy, ponieważ na początku nie działało. Wydaje mi się, że w powyższym kodzie jest kilka błędów (być może literówek) has_my_shortcodei przepisałem funkcję jak poniżej:

function has_my_shortcode( $posts ) {

        if ( empty($posts) )
            return $posts;

        $shortcode_found = false;

        foreach ($posts as $post) {

            if ( !( stripos($post->post_content, '[my-shortcode') === false ) ) {
                $shortcode_found = true;
                break;
            }
        }

        if ( $shortcode_found ) {
            $this->add_scripts();
            $this->add_styles();
        }
        return $posts;
    }

Myślę, że były dwa główne problemy: breaknie było to w zakresie instrukcji if, a to spowodowało, że pętla zawsze przerywała się przy pierwszej iteracji. Drugi problem był bardziej subtelny i trudny do wykrycia. Powyższy kod nie działa, jeśli krótki kod jest pierwszą rzeczą napisaną w poście. Musiałem użyć ===operatora, aby rozwiązać ten problem.

W każdym razie bardzo dziękuję za udostępnienie tej techniki, bardzo pomogła.

jekbau
źródło
1

w Wordpress 4.7 istnieje inny sposób na osiągnięcie tego w twoim functions.phppliku,

add_action( 'wp_enqueue_scripts', 'register_my_script');
function register_my_script(){
  wp_register_script('my-shortcode-js',$src, $dependency, $version, $inFooter);
}

najpierw zarejestruj swój skrypt , który tak naprawdę nie zostanie wydrukowany na twojej stronie, chyba że umieścisz go w kolejce, jeśli zostanie wywołany Twój shortcode,

add_filter( 'do_shortcode_tag','enqueue_my_script',10,3);
function enqueue_my_script($output, $tag, $attr){
  if('myShortcode' != $tag){ //make sure it is the right shortcode
    return $output;
  }
  if(!isset($attr['id'])){ //you can even check for specific attributes
    return $output;
  }
  wp_enqueue_script('my-shortcode-js'); //enqueue your script for printing
  return $output;
}

do_shortcode_tagzostał wprowadzony w WP 4.7 i można je znaleźć w nowej dokumentacji programiści stron.

Aurovrata
źródło