Laden von Skripten nur, wenn ein bestimmter Shortcode oder ein bestimmtes Widget vorhanden ist

17

Ich brauchte eine Möglichkeit, um den Inhalt einer Seite / eines Beitrags zu filtern, bevor er geladen wurde, damit ich dem Header Skripte hinzufügen konnte, wenn ein bestimmter Shortcode vorhanden war. Nach langem Suchen bin ich auf http://wpengineer.com gestoßen

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

Das ist absolut genial und hat genau das getan, was ich brauchte.

Jetzt muss ich es ein bisschen weiter ausbauen und das Gleiche für Sidebars tun. Es kann sich um einen bestimmten Widget-Typ, einen Shortcode, ein Code-Snippet oder irgendetwas anderes handeln, um zu identifizieren, wann das Skript geladen werden muss.

Das Problem ist, dass ich nicht herausfinden kann, wie ich auf den Inhalt der Seitenleiste zugreifen kann, bevor die Seitenleiste geladen wird (das betreffende Thema hat mehrere Seitenleisten).

Ashley G
quelle
Sind Skripte im Header für Ihre Situation eine harte Anforderung? Skripte am Ende der Seite sind leichter zu handhaben und werden für die Leistung empfohlen.
Rarst
Ich habe es zuerst in wp_footer ausprobiert, wodurch das Vorfiltern des Inhalts entfällt, aber obwohl die Skripte gut geladen waren, funktionierten sie nicht. Diese Skripte müssen sich in wp_head befinden, um das zu tun, was sie brauchen.
Ashley G

Antworten:

20

Sie können die Funktion is_active_widget verwenden . Z.B:

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

add_action( 'init', 'check_widget' );

Um das Skript auf der Seite zu laden, auf der nur das Widget geladen wird, müssen Sie in Ihrer Widget-Klasse den Code is_active_widget () hinzufügen. Siehe z. B. das Standard-Widget für aktuelle Kommentare (wp-includes / default-widgets.php, Zeile 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
quelle
Kann das aufgerufen werden, bevor die Widgets geladen werden. Um klar zu sein, muss dies geschehen, bevor die Seite überhaupt geladen wird. Mein Beispielcode verwendet the_posts, um den Inhalt der Seite zu filtern, aber die Seitenleisten / Widgets werden nicht angezeigt.
Ashley G
Ja, siehe das Beispiel, das ich meiner Antwort hinzugefügt habe.
Sorich87
Ihr Beispiel funktioniert nicht wirklich. Vermisse ich etwas Offensichtliches?
Ashley G
Eigentlich war ich. wp_enqueue_script scheint nicht zu funktionieren, wenn es auf wp_head angewendet wird, wp_print_scripts jedoch. wp_enqueue_script funktioniert jedoch, wenn es wie folgt auf init angewendet wird: add_action ('init', 'check_widget');
Ashley G
Es lädt jedoch die Skripte auf jeder Seite der Site, auch wenn das Widget nur in einer Seitenleiste aktiv ist. Zum Beispiel, wenn ich eine Seitenleiste für Blogseiten und eine andere Seitenleiste für andere Seiten habe. Ich füge das Such-Widget der Blog-Seitenleiste hinzu und das Skript wird geladen, aber es wird auch auf Seiten geladen, die keine Blog-Seitenleiste haben. Ich muss das Skript nur laden können, wenn das Widget auf dieser Seite vorhanden ist.
Ashley G
3

Ich wollte nur eine Lösung vorstellen, an der ich gearbeitet habe und die es mir ermöglichte, meine Implementierung etwas vielseitiger zu gestalten. Anstatt die Funktion auf eine Vielzahl von Shortcodes prüfen zu lassen, habe ich sie geändert, um einen einzelnen Shortcode zu suchen, der auf eine Skript- / Stilfunktion verweist, die in die Warteschlange gestellt werden muss. Dies funktioniert sowohl für Methoden in anderen Klassen (z. B. Plugins, die dies möglicherweise nicht selbst ausführen) als auch für Funktionen im Gültigkeitsbereich. Legen Sie einfach den folgenden Code in functions.php ab und fügen Sie die folgende Syntax zu jeder Seite / jedem Post hinzu, auf der Sie spezifisches CSS und JS wünschen.

Page / Post-Syntax: [loadCSSandJS function = "(class-> method / function name)"]

functions.php code:

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

Auf diese Weise können Sie auf einer Seite so viele hinzufügen, wie Sie möchten. Denken Sie daran, dass Sie zum Laden eine Methode / Funktion benötigen.

Nick Caporin
quelle
1

Vielen Dank für diesen Tipp! Es bereitete mir ein bisschen Kopfschmerzen, weil es zuerst nicht funktionierte. Ich denke, es gibt ein paar Fehler (vielleicht Tippfehler) im obigen Code has_my_shortcodeund ich habe die Funktion wie folgt umgeschrieben:

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

Ich denke, es gab zwei Hauptprobleme: Das breakwar nicht im Umfang der if-Anweisung, und das verursachte, dass die Schleife immer bei der ersten Iteration unterbrochen wurde. Das andere Problem war subtiler und schwieriger zu entdecken. Der obige Code funktioniert nicht, wenn der Shortcode das allererste ist, was in einem Beitrag geschrieben wird. Ich musste den ===Operator verwenden, um dies zu lösen.

Wie auch immer, vielen Dank, dass Sie diese Technik geteilt haben, sie hat mir sehr geholfen.

jekbau
quelle
1

mit Wordpress 4.7 gibt es eine andere Möglichkeit, dies in Ihrer functions.phpDatei zu erreichen ,

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

Zuerst registrieren Sie Ihr Skript , das nicht auf Ihrer Seite gedruckt wird, es sei denn, Sie stellen es in eine Warteschlange, wenn Ihr Shortcode aufgerufen wird.

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

Das do_shortcode_tagwurde in WP 4.7 eingeführt und ist auf den Dokumentationsseiten der neuen Entwickler zu finden .

Aurovrata
quelle