Cómo añadir hojas de estilo solo a páginas con shortcodes específicos

31 jul 2013, 12:42:21
Vistas: 14.6K
Votos: 9

Estoy ejecutando una función en páginas donde se usa el shortcode [make-me-a-map]. Este añade JavaScript a la página y crea un mapa. Eso funciona bien (¡bien!), pero estoy teniendo problemas para añadir las hojas de estilo solo a esas páginas de manera similar.

functions.php (Actual)

add_shortcode("make-me-a-map", "create_new_map");
add_action("wp_head", "style_my_new_map");

function create_new_map () {
    global $new_map_called_for;
    $map_called_for = true;

    wp_register_script('make-a-new-map', get_template_directory_uri() . '/js/new-map.js', array('jquery'), '0.1', true);
    wp_enqueue_script('make-a-new-map');
    }

function style_my_new_map() {
    global $new_map_called_for;
    if ($new_map_called_for == true) {
        $tDir = get_template_directory_uri();

        // Echo de hojas de estilo porque wp_register_style & wp_enqueue_style no funcionan actualmente
        // Y add_action('wp_enqueue_script', 'style_my_new_maps') con esas funciones añadiría estilos a todas las páginas
        // No solo a las que tienen el shortcode [make-me-a-map]
        echo "<link rel='stylesheet' href='", $tDir, "/css/new-map.css' />", PHP_EOL;

        // Echo de JavaScript directamente a la página (no se pudo hacer con wp_enqueue_script) para que el código JS conozca el directorio de la plantilla
        echo '<script type="text/javascript">var templateDir = "', get_template_directory_uri(), '";</script>', PHP_EOL;
        $map_called_for = false;
    }
}

Esto no parece estar funcionando, desafortunadamente. Los estilos se están añadiendo a todas las páginas.

No usé wp_register_style & wp_enqueue_style porque este error sigue añadiendo etiquetas <Link /> al pie de página con esas funciones.

Podría haber usado add_action("wp_enqueue_scripts", "style_my_new_map") en lugar de add_action('wp-head', "style_my_new_map") pero hasta donde puedo ver y he comprobado, ¿no hay diferencia? Aún así añade las hojas de estilo a todas las páginas.

Así que mi pregunta es en realidad en dos partes: :)

  1. ¿Por qué el functions.php actual no funciona y añade estilos a todas las páginas? No estoy seguro si es por la llamada global o por la declaración if...
  2. ¿Cuál es la mejor manera de añadir las hojas de estilo al encabezado solo de las páginas donde se usa el shortcode mencionado, asumiendo que no conoceré los IDs de las páginas, etc.?

¡Gracias de antemano! P

1
Todas las respuestas a la pregunta 8
3
11

Cargar Scripts y Estilos Dinámicamente Usando Shortcodes

Ventajas

  • No busca en todas las publicaciones cada vez que se llama al shortcode.
  • Capaz de añadir estilos y scripts dinámicamente solo cuando el shortcode está en la página.
  • No usa expresiones regulares ya que tienden a ser más lentas que strstr() o strpos(). Podrías cambiarlas por regex si necesitas aceptar argumentos.
  • Reduce las llamadas a archivos

Explicación del Código

  1. Encuentra los shortcodes en la página usando el hook save_post solo cuando la publicación no es una revisión y coincide con el post_type especificado.

  2. Guarda los IDs de las publicaciones encontradas como un array usando add_option() con autoload configurado como 'yes' a menos que la entrada ya exista. En ese caso usará update_option().

  3. Usa el hook wp_enqueue_scripts para llamar a nuestra función add_scripts_and_styles().

  4. Esa función entonces llama a get_option() para recuperar nuestro array de IDs de página. Si el $page_id actual está en el $option_id_array, añade los scripts y estilos.

Nota importante: Convertí el código de clases OOP con Namespaces, así que puede que haya omitido algo. Avísame en los comentarios si es así.

Ejemplo de Código: Encontrar Ocurrencias de Shortcodes

function find_shortcode_occurences($shortcode, $post_type = 'page')
{
    $found_ids = array();
    $args         = array(
        'post_type'   => $post_type,
        'post_status' => 'publish',
        'posts_per_page' => -1,
    );
    $query_result = new \WP_Query($args);
    foreach ($query_result->posts as $post) {
        if (false !== strpos($post->post_content, $shortcode)) {
            $found_ids[] = $post->ID;
        }
    }
    return $found_ids;
}

function save_option_shortcode_post_id_array( $post_id ) {
    if ( wp_is_post_revision( $post_id ) OR 'page' != get_post_type( $post_id )) {
        return;
    }
    $option_name = 'yourprefix-yourshortcode';
    $id_array = find_shortcode_occurences($option_name);
    $autoload = 'yes';
    if (false == add_option($option_name, $id_array, '', 'yes')) update_option($option_name, $id_array);
}

add_action('save_post', 'save_option_shortcode_id_array' );

Ejemplo de Código: Shortcode para Incluir Scripts y Estilos Dinámicamente

function yourshortcode_add_scripts_and_styles() {
    $page_id = get_the_ID();
    $option_id_array = get_option('yourprefix-yourshortcode');
    if (in_array($page_id, $option_id_array)) {
        wp_enqueue_script( $handle, $src, $deps, $ver, $footer = true );
        wp_enqueue_style( $handle, $src , $deps);
    }
}

add_action('wp_enqueue_scripts', 'yourshortcode_add_scripts_and_styles');
21 feb 2014 21:10:56
Comentarios

Aún no lo he probado, pero esta es la respuesta que estaba buscando. Parece tener un inconveniente mínimo.

Jacob Raccuia Jacob Raccuia
21 abr 2017 16:33:53

@JacobRaccuia Probé esto hace un tiempo y funcionó. No sé cómo funciona con versiones más nuevas de WP, pero dudo que haya cambiado mucho dada la naturaleza de la plataforma.

CommandZ CommandZ
4 may 2017 06:17:22

He pasado mucho tiempo intentando perfeccionar esto. Tiene serios inconvenientes si el usuario introduce el shortcode en entornos no tradicionales de WP. Escribí un hook para verificar todos los campos personalizados, lo que podría ayudar a cubrir este problema.

Jacob Raccuia Jacob Raccuia
4 may 2017 08:36:53
2

Esto funciona para mí:

function register_my_css () {
    wp_register_style('my-style', plugins_url('styles.css', __FILE__));
}

function register_my_scripts () {
    wp_register_script('my-script', plugins_url('scripts.js', __FILE__));
}

// solo encola los scripts/estilos cuando se llama al shortcode
function do_my_shortcode () {
    wp_enqueue_style('my-style');
    wp_enqueue_script('my-script');

    // hacer cosas del shortcode...
}

// registrar css
add_action('wp_enqueue_scripts', 'register_my_css');

// registrar javascript
add_action('wp_enqueue_scripts', 'register_my_scripts');

// registrar shortcode
add_shortcode('my-shortcode', 'do_my_shortcode');

Más información aquí: http://mikejolley.com/2013/12/sensible-script-enqueuing-shortcodes/

16 jul 2015 13:36:37
Comentarios

No, eso mostrará el shortcode encima del contenido.

fuxia fuxia
16 jul 2015 14:23:29

El problema aquí es que los estilos se vincularán en el pie de página. Probablemente funcionará. Pero es 'incorrecto' y no está garantizado que funcione.

Doug Cassidy Doug Cassidy
11 mar 2016 18:16:17
1

2 preguntas así que 2 respuestas :)

¿Por qué el functions.php actual no funciona y agrega estilos a todas las páginas? No estoy seguro si es la llamada global o la sentencia if...

No funciona debido al orden en que se llaman estas funciones. Tu callback del shortcode se ejecuta durante el renderizado del contenido del post (muy probablemente durante la llamada a the_content).

Tanto wp_enqueue_scripts como wp_head se llaman mucho antes: wp_head en algún lugar de tu archivo header.php del tema y wp_enqueue_scripts durante la llamada a wp_head.

¿Cuál es la mejor manera de agregar las hojas de estilo solo al encabezado de las páginas donde se usa el shortcode anterior, asumiendo que no conoceré los IDs de página, etc.?

No creo que exista una forma "mejor". No es una buena idea en absoluto. Los navegadores almacenan en caché los archivos CSS. Así que si tienes el mismo CSS en todas las páginas, el navegador solo lo cargará una vez. Si hay muchos archivos CSS para diferentes páginas, el navegador tendrá que cargarlos todos. Por eso no lo haría en absoluto, e incluiría estos estilos CSS en el archivo CSS global.

Aunque si tienes que incluirlo solo en las páginas que usan este shortcode, entonces (2 soluciones, la elección de cuál es mejor es tuya; creo que la 2ª es más elegante)...

  1. Puedes agregar estos estilos como estilos en línea. Solo ten cuidado de no incluirlos muchas veces. Así que imprímelos con tu shortcode y asegúrate de que solo se muestren una vez.
  2. Como los posts ya están seleccionados cuando se llama a wp_head/wp_enqueue_scripts, puedes agregar alguna función a este hook, recorrer los posts seleccionados, verificar si contienen tu shortcode y encolar tu CSS si es necesario. (Por supuesto, no será muy eficiente).
31 jul 2013 13:05:45
Comentarios

Sí, la opción #2 podría ser menos eficiente pero definitivamente más agradable que en línea =) Ya lo tengo funcionando, ¡gracias!

Padraic Padraic
3 ago 2013 11:46:20
0

Puedes engancharte a una acción después de que la consulta principal se haya ejecutado y determinar si necesitas cargar tus estilos y scripts.

add_action('template_include', 'custom_template_include');
function custom_template_include($template) {
    if (is_single() || is_page()) {
          global $post;
          if (has_shortcode($post->post_content, 'your_short_code')) {
              add_action('wp_enqueue_scripts', 'custom_enqueue_scripts');
          }
    } 
    return $template;
}

function custom_enqueue_scripts() {
    // Encuela tus scripts y estilos aquí.
}
1 abr 2015 15:50:55
0
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_styles', 1 );
function enqueue_shortcode_styles() {

    global $post;

    if ( isset($post->post_content) && is_singular(array( 'post','page' ) ) && ! has_shortcode( $post->post_content, '$tag' ) ) {

    wp_enqueue_style( 'shortcode-styles', get_stylesheet_directory_uri() . '/style.css' );

    }

}

Yo usaría has_shortcode para verificar el contenido de $post y cargar los scripts usando wp_enqueue_scripts, pero depende de dónde estén incrustados tus shortcodes.

Reemplaza $tag con tu etiqueta de shortcode en el código anterior.

Añade esto al archivo functions.php de tu tema hijo y cambia los condicionales si es necesario.

26 may 2017 15:16:43
0

Una solución mucho más simple que funcionó para mí fue registrar el script fuera de la función del shortcode y luego encolar el script dentro de la función. De esta manera, solo se carga el script en las páginas que utilizan tu shortcode.

wp_register_script('make-a-new-map', get_template_directory_uri() . '/js/new-map.js', array('jquery'), '0.1', true);
wp_register_style('make-a-new-map-style', get_template_directory_uri() . '/css/new-map.css');

add_shortcode("make-me-a-map", "create_new_map");
add_action("wp_head", "style_my_new_map");

function create_new_map () {
   wp_enqueue_script('make-a-new-map');
   wp_enqueue_style('make-a-new-map-style');

   global $new_map_called_for;
   $map_called_for = true;
}

Puedes encontrar una descripción de este método aquí: http://mikejolley.com/2013/12/sensible-script-enqueuing-shortcodes/

Ten en cuenta que esto carga el CSS en el pie de página, lo cual puede no ser deseable o válido según W3C. En mi caso, eso no fue un problema.

8 nov 2014 17:26:44
0

Puedes hacerlo simplemente así:

// hook del shortcode
add_shortcode("make-me-a-map", "create_new_map");

// callback del shortcode
function style_my_new_map() {
    global $new_map_called_for;
    if ($new_map_called_for == true) {
  wp_register_script('make-a-new-map', get_template_directory_uri() . '/js/new-map.js', array('jquery'), '0.1', true);
  wp_enqueue_script('make-a-new-map');

// el resto de tus códigos
    }
}

También funciona para hojas de estilo. Para cargar tu hoja de estilos al final, añade números a tu hook de shortcode, así:

add_shortcode("make-me-a-map", "create_new_map", 9999);

Lo he probado y funciona.

25 feb 2015 20:03:15
0

Cargando Scripts y Estilos Dinámicamente Usando Shortcode

Este es un código extendido para la solución proporcionada por Commandz anteriormente.

He encontrado que su método es el mejor y más factible ya que la opción de base de datos está disponible en casi todos los hooks.

Se ha modificado para encontrar las ocurrencias de shortcodes solo en el contenido del post actual, en lugar de revisar todos los posts - lo cual puede ser más lento cuando el número de posts es grande.

Se ha cambiado aquí en dos líneas después de pasar otra variable $post_id desde la acción save_post a la función find_shortcode_occurences()

if( !empty($post_id) ) {
    $args['posts__in'] = $post_id; 
}

Código modificado para ambas funciones

function find_shortcode_occurences($shortcode, $post_id='', $post_type = 'page') {
    $found_ids = array();
    $args         = array(
        'post_type'   => $post_type,
        'post_status' => 'publish',
        'posts_per_page' => -1,
    );

    if( !empty($post_id) ) {
        $args['posts__in'] = $post_id; 
    }

    $query_result = new WP_Query($args);
    foreach ($query_result->posts as $post) {
        if (false !== strpos($post->post_content, $shortcode)) {
            $found_ids[] = $post->ID;
        }
    }
    return $found_ids;
}

add_action('save_post', 'save_option_for_sppro_pages' );
function save_option_for_sppro_pages( $post_id ) {
    if ( wp_is_post_revision( $post_id ) {
        return;
    }
    $option_name = 'database-option';
    $shortcode = 'shortcode-name';
    $id_array = find_shortcode_occurences($shortcode, $post_id);
    $autoload = 'yes';
    if (false == add_option($option_name, $id_array, '', 'yes')) {
        $current_value = get_option($option_name);
        $new_value = array_merge($current_value, $id_array);
        update_option($option_name, $id_array);
    }
}

Además, se ha añadido otra variable para que puedas tener diferentes nombres para la opción de base de datos y el nombre del shortcode.

26 may 2017 12:47:02