Cargar scripts solo si un shortcode o widget específico está presente

28 sept 2010, 08:21:48
Vistas: 16.1K
Votos: 17

Necesitaba una forma de filtrar el contenido de una página/entrada antes de que se cargara para poder añadir scripts al encabezado si estaba presente un shortcode específico. Después de mucha búsqueda encontré esto en http://wpengineer.com

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

    $encontrado = false;

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

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

    wp_register_script('mi_script', $urljs.'miscript.js' );

    wp_print_scripts('mi_script');
}
    return $posts;
}
add_action('the_posts', 'tiene_mi_shortcode');

lo cual 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 específico, shortcode, 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 descubrir cómo acceder al contenido de las barras laterales antes de que se cargue la barra lateral (el tema en cuestión tendrá varias barras laterales)

2
Comentarios

¿Los scripts en el encabezado son un requisito indispensable para tu situación? Los scripts al final de la página son más fáciles de manejar de forma condicional y son una práctica recomendada para el rendimiento.

Rarst Rarst
28 sept 2010 08:36:31

Probé primero colocarlos en wp_footer, lo cual elimina elegantemente la necesidad de prefiltrar el contenido, pero aunque los scripts se cargaron correctamente, no funcionaron. Estos scripts deben estar en wp_head para hacer lo que necesitan.

Lemon Bacon Lemon Bacon
28 sept 2010 09:12:31
Todas las respuestas a la pregunta 4
9
20

Puedes usar la función is_active_widget. Por ejemplo:

function check_widget() {
    if( is_active_widget( '', '', 'search' ) ) { // comprueba si se usa el widget de búsqueda
        wp_enqueue_script('my-script');
    }
}

add_action( 'init', 'check_widget' );

Para cargar el script solo en la página donde se carga el widget, tendrás que agregar el código is_active_widget() en tu clase de widget. Por ejemplo, mira 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' => __( 'Los comentarios más recientes' ) );
        $this->WP_Widget('recent-comments', __('Comentarios recientes'), $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') );
    }
28 sept 2010 09:03:27
Comentarios

¿Se puede llamar ANTES de que se carguen los widgets? Para ser claro, esto debe ocurrir antes de que la página incluso se cargue. Mi código de ejemplo usa the_posts para filtrar el contenido en la página, pero eso no afecta las barras laterales/widgets.

Lemon Bacon Lemon Bacon
28 sept 2010 09:14:01

Sí, mira el ejemplo que agregué a mi respuesta.

sorich87 sorich87
28 sept 2010 09:24:42

Tu ejemplo en realidad no funciona. ¿Estoy pasando por alto algo obvio?

Lemon Bacon Lemon Bacon
29 sept 2010 04:10:18

En realidad lo estaba. wp_enqueue_script no parece funcionar cuando se aplica a wp_head, pero wp_print_scripts sí. wp_enqueue_script sí funciona si se aplica a init de esta manera: add_action( 'init', 'check_widget' );

Lemon Bacon Lemon Bacon
29 sept 2010 04:25:57

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.

Lemon Bacon Lemon Bacon
29 sept 2010 04:49:34

Edité mi respuesta

sorich87 sorich87
29 sept 2010 06:11:11

¡Eres el mejor! ¡Salud!

Lemon Bacon Lemon Bacon
29 sept 2010 13:52:53

Muy buena solución :)

Anh Tran Anh Tran
25 dic 2011 06:51:48

Es mejor usar wp_enqueue_scripts en lugar de wp_head. Gran respuesta, gracias.

wesamly wesamly
6 mar 2017 07:38:35
Mostrar los 4 comentarios restantes
0

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 shortcodes, la modifiqué para que busque un único shortcode que haga referencia a una función de script/estilo que necesite ser encolada. Esto funcionará tanto para métodos en otras clases (como plugins que podrían no hacer esto por sí mismos) como para funciones dentro del alcance. Solo coloca el siguiente código en functions.php y añade la siguiente sintaxis a cualquier página/post donde quieras CSS y JS específicos.

Sintaxis para Página/Post: [loadCSSandJS function="(clase->método/nombre de función)"]

Código para 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 te permitirá añadir tantos como quieras en una página. Ten en cuenta que necesitas un método/función para cargar.

25 sept 2012 22:14:40
0

Con WordPress 4.7 existe otra forma de lograr esto en tu archivo functions.php,

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

primero registras tu script, que en realidad no se imprime en tu página a menos que lo encoles si se llama a tu shortcode,

add_filter( 'do_shortcode_tag','encolar_mi_script',10,3);
function encolar_mi_script($output, $tag, $attr){
  if('myShortcode' != $tag){ //asegúrate de que es el shortcode correcto
    return $output;
  }
  if(!isset($attr['id'])){ //incluso puedes verificar atributos específicos
    return $output;
  }
  wp_enqueue_script('mi-shortcode-js'); //encola tu script para imprimirlo
  return $output;
}

el do_shortcode_tag fue introducido en WP 4.7 y se puede encontrar en las páginas de la nueva documentación para desarrolladores.

31 ene 2017 05:33:03
0

¡Gracias por compartir este consejo! Me dio un poco de dolor de cabeza, porque al principio no funcionaba. Creo que hay un par de errores (quizás errores tipográficos) en el código anterior has_my_shortcode y reescribí la función como se muestra a continuación:

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 había dos problemas principales: el break no estaba dentro del alcance de la sentencia if, y eso hacía que el bucle siempre se interrumpiera en la primera iteración. El otro problema era 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, ayudó mucho.

22 dic 2011 09:48:39