Condicionalmente cargando JavaScript / CSS para códigos cortos

36

He lanzado un complemento que crea un shortcode y requiere un archivo JavaScript y un archivo CSS para cargar en cualquier página que contenga ese shortcode. Podría hacer que el script / estilo se cargue en todas las páginas, pero esa no es la mejor práctica. Solo quiero cargar los archivos en las páginas que llaman al shortcode. He encontrado dos métodos para hacer esto, pero ambos tienen problemas.

Método 1 establece un indicador en verdadero dentro de la función del manejador de código corto y luego verifica ese valor dentro una devolución de llamada wp_footer . Si es cierto, usa wp_print_scripts() para cargar el JavaScript. El problema con esto es que solo funciona con JavaScript y no con CSS, porque CSS debe declararse dentro de <head> , lo que solo puede hacer durante un primer enlace como init o wp_head .

Method 2 se activa temprano y" mira hacia adelante "para ver si existe el código corto en el contenido de la página actual. Me gusta este método mucho mejor que el primero, pero el problema no detectará si la plantilla llama do_shortcode() .

Por lo tanto, me inclino por utilizar el segundo método y luego trato de detectar si una plantilla está asignada, y si es así, analícela para el código corto. Antes de hacer eso, sin embargo, quería comprobar si alguien conoce un método mejor.

Actualización: He integrado la solución en mi complemento. Si alguien tiene curiosidad por verlo desarrollado en un entorno en vivo, puede descargarlo o navegue por él .

Actualización 2: a partir de WordPress 3.3, ahora es posible call wp_enqueue_script() directamente dentro de una devolución de llamada de shortcode , y el archivo JavaScript se llamará dentro del pie de página del documento. Esto también es técnicamente posible para los archivos CSS, pero debe considerarse una mala práctica porque la salida de CSS fuera de la etiqueta <head> infringe las especificaciones de W3C, puede incluir FOUC y puede forzar al navegador a volver a renderizar la página.

    
pregunta Ian Dunn 23.06.2011 - 17:07

8 respuestas

10

Basado en mi propia experiencia, he usado una combinación del método 1 & 2: los scripts de arquitectura y pie de página de 1, y la técnica de "anticipación" de 2.

Sin embargo, para el look-ahead, uso expresiones regulares en lugar de stripos ; preferencia personal, más rápido, y puede verificar el shortcode 'malformado';

preg_match( '#\[ *shortcode([^\]])*\]#i', $content );

Si le preocupa que los autores utilicen do_shortcode manualmente, optaré por indicarles que utilicen una llamada de acción para poner en cola su estilo preinscrito manualmente.

ACTUALIZACIÓN : para el autor perezoso que nunca realiza RTFM, emita un mensaje para resaltar el error de sus formas;)

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;
}
    
respondido por el TheDeadMedic 23.06.2011 - 20:23
8

Llegué tarde a esta pregunta, pero desde que Ian comenzó a este hilo en la lista de wp-hackers de hoy me hizo pensar que vale la pena responder, especialmente teniendo en cuenta que he estado planeando agregar una característica de este tipo a algunos complementos en los que he estado trabajando.

Un enfoque a considerar es verificar la carga de la primera página para ver si realmente se usa el shortcode y luego guardar el estado de uso del shortcode en una clave de metadatos posterior. Aquí es cómo:

Instrucciones paso a paso

  1. Establezca un indicador $shortcode_used en 'no' .
  2. En la propia función de código abreviado, establece el indicador $shortcode_used en 'yes' .
  3. Establezca una prioridad de enganche 'the_content' 12 después de que WordPress haya procesado los códigos cortos y verifique el meta del post para un '' usando la clave "_has_{$shortcode_name}_shortcode" . (se devuelve un valor de '' cuando no existe una clave de metadatos de publicación para la ID de publicación).
  4. Use un gancho 'save_post' para eliminar el meta de publicación que borra la marca persistente para esa publicación en caso de que el usuario cambie el uso de shortcode.
  5. También en el enganche 'save_post' use wp_remote_request() para enviar un GET HTTP sin bloqueo al enlace permanente de la publicación para activar la carga de la primera página y la configuración del indicador persistente.
  6. Por último, establezca un 'wp_print_styles' y verifique el metadatos para un valor de 'yes' , 'no' o '' usando la clave "_has_{$shortcode_name}_shortcode" . Si el valor es 'no' no sirve el externo. Si el valor es 'yes' o '' , siga adelante y sirva al externo.

Y eso debería hacerlo. He escrito y probado un complemento de ejemplo para mostrar cómo funciona todo esto.

Código de complemento de ejemplo

El complemento se activa con un código corto [trigger-css] que establece los elementos <h2> en la página en blanco sobre rojo para que pueda verlo fácilmente. Asume un subdirectorio css que contiene el archivo style.css con este CSS en él:

/*
 * Filename: css/style.css
 */
h2 {
  color: white;
  background: red;
}

Y debajo está el código en un complemento de trabajo:

<?php
/**
 * Plugin Name: CSS on Shortcode
 * Description: Shows how to conditionally load a shortcode
 * Author: Mike Schinkel <[email protected]>
 */
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();

Capturas de pantalla de ejemplo

Aquí hay una serie de capturas de pantalla

Editor de publicaciones básico, sin contenido

Visualizacióndepublicaciones,sincontenido

Editor de publicaciones básico con [trigger-css] Shortcode

Visualizacióndepublicacióncon[trigger-css]Shortcode

No estoy seguro de que sea 100%

Creo que lo anterior debería funcionar en casi todos los casos, pero como acabo de escribir este código no puedo estar 100% seguro. Si puede encontrar situaciones en las que no funciona, me gustaría saberlo para poder corregir el código en algunos complementos a los que acabo de agregar esto. Gracias de antemano.

    
respondido por el MikeSchinkel 02.01.2013 - 07:57
5

Google me encontró un potencial respuesta . Digo "potencial" porque parece bueno, debería funcionar, pero no estoy 100% convencido de que sea la mejor manera de hacerlo:

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

Esto debería poder verificar si la publicación actual está usando un shortcode y agregar una hoja de estilo al elemento <head> de manera apropiada. Pero no creo que funcione para una página de índice (es decir, varias publicaciones en el bucle) ... También es de una publicación de blog de 2 años, así que ni siquiera estoy seguro de que funcione con WP 3.1.X .

    
respondido por el EAMann 23.06.2011 - 17:34
2

Usando una combinación de la respuesta de TheDeadMedic y get_shortcode_regex () documentación (que en realidad no encontré mis códigos cortos) Creé una función simple que se usa para poner en cola los scripts para varios códigos cortos. Dado que wp_enqueue_script () en códigos cortos solo se agrega al pie de página, esto puede ser útil, ya que puede manejar los scripts de encabezado y pie de página.


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' );
    
respondido por el Sean Michaud 30.11.2013 - 20:52
1

Finalmente, también encontré una solución para la carga de CSS condicional que funciona para mi complemento www.mapsmarker.com y me gustaría compartir con usted. Comprueba si mi shortcode se usa dentro del archivo de plantilla actual y header / footer.php y, en caso afirmativo, encola la hoja de estilo necesaria en el encabezado:

  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' );
    
respondido por el robertharm 12.12.2012 - 22:29
1

Para mi complemento, encontré que a veces los usuarios tienen un generador de temas que tiene un código corto almacenado en metadatos de publicación . Esto es lo que estoy usando para detectar si el código abreviado de mi complemento está presente en la publicación actual o en la metadatos de la publicación :

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' );
    
respondido por el zdenekca 06.11.2015 - 01:24
0
  

porque CSS debe declararse dentro de <head>

Para los archivos CSS, puede cargarlos dentro de su salida de código corto:

<style type="text/css">
  @import "path/to/your.css"; 
</style>

Establece una constante o algo después de esto, como MY_CSS_LOADED (solo incluye el CSS si la constante no está establecida).

Ambos métodos son más lentos que ir de esta manera.

Para los archivos JS, puede hacer lo mismo si el script que está cargando es único y no tiene dependencias externas. Si este no es el caso, cárguelo dentro del pie de página, pero use la constante para determinar si necesita cargarse o no ...

    
respondido por el onetrickpony 23.06.2011 - 17:22
0

Script Logic es un complemento de WordPress que le brinda control total sobre todos los archivos JavaScript y CSS. Usando este complemento, puede cargar condicionalmente archivos CSS y JS solo en páginas donde sea necesario.

enlace

    
respondido por el Tahir Yasin 17.06.2014 - 09:44

Lea otras preguntas en las etiquetas