Carga de scripts solo si hay un shortcode o widget en particular

17

Necesitaba una forma de filtrar el contenido de una página / publicación antes de que se cargara para poder agregar scripts al encabezado si hubiera un shortcode específico. Después de mucho buscar me encontré con esto en 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');

que es absolutamente brillante e hizo exactamente lo que necesitaba.

Ahora necesito extenderlo un poco más y hacer lo mismo para las barras laterales. Puede ser por un tipo de widget en particular, código corto, fragmento de código o cualquier otra cosa que funcione para identificar cuándo se necesita cargar el script.

El problema es que no puedo entender cómo acceder al contenido de las barras laterales antes de cargar la barra lateral (el tema en cuestión tendrá varias barras laterales)

Ashley G
fuente
¿Son los scripts en el encabezado un requisito difícil para su situación? Las secuencias de comandos al final de la página son más fáciles de manejar con condicionalidad y la práctica recomendada para el rendimiento.
Rarst
Lo probé primero en wp_footer, lo que elimina muy bien la necesidad de prefiltrar el contenido, pero aunque los scripts se cargaron bien, no funcionaron. Estos scripts deben estar en wp_head para hacer lo que necesitan.
Ashley G

Respuestas:

20

Puede usar la función is_active_widget . P.ej:

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

add_action( 'init', 'check_widget' );

Para cargar el script en la página donde solo se carga el widget, deberá agregar el código is_active_widget () en su clase de widget. Por ejemplo, vea el widget predeterminado de comentarios recientes (wp-includes / default-widgets.php, línea 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
fuente
Se puede llamar ANTES de que se carguen los widgets. Para que quede claro, esto tiene que ocurrir antes de que la página se cargue. Mi código de muestra usa the_posts para filtrar el contenido de la página, pero eso no obtiene las barras laterales / widgets.
Ashley G
Sí, vea el ejemplo que agregué a mi respuesta.
sorich87
Tu ejemplo en realidad no funciona. ¿Me estoy perdiendo algo obvio?
Ashley G
En realidad lo estaba. wp_enqueue_script no parece funcionar cuando se aplica a wp_head, pero wp_print_scripts sí. wp_enqueue_script funciona si se aplica a init así: add_action ('init', 'check_widget');
Ashley G
Sin embargo, carga los scripts en cada página del sitio, incluso si el widget solo está activo en una barra lateral. por ejemplo si tengo una barra lateral para páginas de blog y otra barra lateral para otras páginas. Agrego el widget de búsqueda a la barra lateral del blog y los scripts se cargan, pero también se cargan en páginas que no tienen la barra lateral del blog. Necesito poder cargar el script solo si el widget está presente en esa página.
Ashley G
3

Solo quería compartir una solución en la que trabajé que me permitió ser un poco más versátil con mi implementación. En lugar de hacer que la función verifique una variedad de códigos cortos, la modifiqué para buscar un código corto único que haga referencia a una función de secuencia de comandos / estilo que necesita ser puesta en cola. Esto funcionará para ambos métodos en otras clases (como complementos que pueden no hacerlo por sí mismos) y funciones dentro del alcance. Simplemente suelte el código a continuación en functions.php y agregue la siguiente sintaxis a cualquier página / publicación donde desee CSS y JS específicos.

Sintaxis de página / publicación: [loadCSSandJS function = "(class-> method / function name)"]

código de functions.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;
}

Esto también le permitirá agregar tantos como desee en una página. Tenga en cuenta que necesita un método / función para cargar.

Nick Caporin
fuente
1

¡Gracias por compartir este consejo! Me dio un poco de dolor de cabeza, porque al principio no estaba funcionando. Creo que hay un par de errores (quizás errores tipográficos) en el código anterior has_my_shortcodey reescribí la función de la siguiente manera:

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

Creo que hubo dos problemas principales: el breakno estaba en el alcance de la declaración if, y eso causó que el ciclo siempre se rompiera en la primera iteración. El otro problema fue más sutil y difícil de descubrir. El código anterior no funciona si el shortcode es lo primero que se escribe en una publicación. Tuve que usar el ===operador para resolver esto.

De todos modos, muchas gracias por compartir esta técnica, me ayudó mucho.

jekbau
fuente
1

con Wordpress 4.7 hay otra forma de lograr esto en su functions.phparchivo,

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

primero registras tu script , que en realidad no se imprime en tu página a menos que lo pongas en cola si se llama a tu 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;
}

el do_shortcode_tagfue introducido en WP 4.7 y se pueden encontrar en los nuevos desarrolladores de documentación páginas.

Aurovrata
fuente