Soluciones para generar javascript / CSS dinámico

13

Supongamos que necesita generar código javascript o CSS que depende del contexto actual.

Por ejemplo, tiene un formulario en la página de inicio que activa una solicitud ajax en el envío, y un formulario diferente en la página única. O en el caso de CSS, desea crear un tema que permita a sus usuarios crear su propio diseño, cambiar colores, etc.

Soluciones que veo hasta ahora:

  1. Incluya el código en la sección principal del documento (o al final en el caso de JS)

  2. Realice una solicitud especial que genere el código, como site.com?get_assets . Esto es lento porque WP se carga dos veces.

  3. Guárdelo en archivos temporales durante un período de tiempo determinado y cárguelo desde allí. No es muy confiable para temas públicos o complementos.

  4. Solo Javascript: haga que sea estático colocándolo en un archivo normal que se carga cada vez. En este caso, tendría que hacer que su código maneje cualquier situación

¿Conoces a otros? ¿Qué camino irías?

    
pregunta onetrickpony 29.10.2011 - 16:56

5 respuestas

8

Una opción adicional, dependiendo del tipo de parámetros que necesita pasar. Llamémoslo (2a). También puede crear scripts PHP que generen text/css o text/javascript generados dinámicamente en lugar de text/html , y proporcionarles los datos que necesitan utilizando parámetros GET en lugar de cargar WordPress. Por supuesto, esto solo funciona si necesita pasar un número relativamente pequeño de parámetros relativamente compactos. Entonces, por ejemplo, digamos que necesita pasar solo la URL de una publicación o el directorio de un archivo o similar, puede hacer algo como esto:

En header.php:

 <script type="text/javascript" src="<?php print get_stylesheet_directory_uri(); 
 ?>/fancy-js.php?foo=bar&amp;url=<?php print urlencode(get_permalink($post->ID)); ?>"></script>

En fancy-js.php:

 <?php
 header("Content-type: text/javascript");
 ?>
 foo = <?php print json_encode($_GET['foo']); ?>;
 url = <?php print json_encode($_GET['url']); ?>;

etc.

Pero esto solo le permite acceder a los datos directamente pasados en los parámetros GET; y solo funcionará si el número de cosas que necesita pasar es relativamente pequeño, y la representación de esas cosas es relativamente compacta. (Básicamente, un puñado de valores numéricos o de cadena: un nombre de usuario, por ejemplo, o un directorio; no una lista de todas las publicaciones recientes de un usuario o algo así).

En cuanto a cuál de estas opciones es la mejor, no lo sé; Eso depende de tu caso de uso. La opción (1) tiene el mérito de ser simple, y le permite claramente acceder a cualquier información de WordPress que pueda necesitar, sin el impacto en el rendimiento de cargar WordPress dos veces. Es casi seguro que deberías hacer lo que quieras, a menos que tengas una buena razón para no hacerlo (por ejemplo, debido al tamaño de la hoja de estilo o secuencia de comandos que necesitas usar).

Si el tamaño es lo suficientemente grande como para causar un problema en términos del peso de su página, entonces puede probar (2) o (2a).

O bien, esta es probablemente la mejor idea: puede intentar separar las partes del script o la hoja de estilo que realmente hace uso de los datos dinámicos de las partes que se pueden especificar de forma estática. Dice que tienes una hoja de estilo que necesita pasar un directorio de WordPress para establecer un parámetro de fondo para el elemento # my-fancy. Podrías poner todo esto en el elemento principal:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */
 </style>

¿Pero por qué necesitarías hacer eso? Aquí solo hay una línea que depende de los datos de WordPress. Es mejor dividir solo las líneas que dependen de WordPress:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
 }
 </style>

Coloque todo lo demás en una hoja de estilo estática que carga con un elemento de enlace estándar (style.css o lo que sea):

 #my-fancy-element {
      /* background-image provided dynamically */
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */

Y deja que la cascada haga el trabajo.

Lo mismo ocurre con JavaScript: en lugar de hacer esto:

 <script type="text/javascript">
 // Here comes a huge function that uses WordPress data:
 function my_huge_function () {
     // Do a million things ...

     jQuery('#my-fancy').append('<a href="'+<?php json_encode(get_permalink($GLOBALS['post']->ID)); ?>+'">foo</a>);

     // Do a million more things ...

     my_other_function(<?php print json_encode(get_userdata($GLOBALS['post']->post_author); ?>);
 }

 function my_other_function (user) {
     // Do a million things ...
 }
 </script>

En su lugar, coloca algo como esto en el elemento principal:

 <script type="text/javascript">
 var WordPressPostData = {
 url: <?php print json_encode(get_permalink($GLOBALS['post']->ID)); ?>,
 author: <?php print json_encode(get_userdata($GLOBALS['post']->post_author)); ?>
 }
 </script>

Y luego coloque el resto en un archivo JavaScript estático, reescribiendo my_huge_function () y my_other_function () para hacer uso de los globales WordPressPostData.url y WordPressPostData.author.

40K de CSS o 40K de JS casi siempre se pueden dividir en < 1K que realmente depende de datos dinámicos, y el resto, que se puede especificar en un archivo externo estático y luego se puede combinar usando la cascada (para CSS) o variables accesibles globalmente (globales, elementos DOM o cualquier otro agujero de cubículo que prefiera, para JS).

    
respondido por el radgeek 30.10.2011 - 16:05
5

El caso de CSS dinámico es bastante simple.

Simplemente cree una función que genere las definiciones de CSS dinámicas dentro de las etiquetas <style type="text/css"></style> , y luego enganche esa función en wp_print_styles . por ejemplo

<?php
function mytheme_dynamic_css() {
    $options = get_option( 'mytheme_options' );
    ?>
    <style type="text/css">
    /* Dynamic H1 font family */
    h1 { font-family: <?php echo $options['h1_font_family']; ?>;
    </style>
    <?php
}
add_action( 'wp_print_styles', 'mytheme_dynamic_css' );
?>

O, digamos que tiene esquemas de color preconfigurados; puede poner en la cola la hoja de estilo apropiada de acuerdo con la configuración actual del usuario:

<?php
function mytheme_enqueue_colorscheme_stylesheet() {
    $options = get_option( 'mytheme_options' );
    $color_scheme = $options['color_scheme'];
    wp_enqueue_style( $colorscheme, get_template_directory_uri() . '/css/' . $color_scheme . '.css' );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_colorscheme_stylesheet' );
?>

Tenga en cuenta que, en este caso, la función se enlaza con wp_enqueue_scripts , ya que WordPress no tiene un gancho de acción wp_enqueue_styles .

    
respondido por el Chip Bennett 29.10.2011 - 18:44
2

Estaba pensando eso por un tiempo ahora. Tu pregunta me hace volver a ella. No estoy seguro de que sea una buena idea o no, por lo que me gustaría que los expertos comenten sobre eso.

¿Qué pasa si i escribo el archivo javascript / css a través de php cuando el administrador guarda los datos. Será una escritura de una sola vez hasta que el usuario vuelva a cambiar el diseño (lo que el usuario no puede hacer con demasiada frecuencia). De esa manera, accedemos a la base de datos para la configuración del usuario solo una vez cuando el usuario guarda datos.

Después de escribir el archivo, será un archivo regular de javascript / css, por lo que no tenemos que llamar a la base de datos cada vez que se cargue el tema.

Una pregunta que debe responderse: ¿Qué pasará cuando un visitante intente acceder al sitio en el instante en que PHP escribe el archivo?

Déjame saber lo que piensas.

    
respondido por el Sisir 31.10.2011 - 12:27
1

Para pequeños fragmentos de scripts, que tal vez no quiera incluir en un archivo separado, por ejemplo, porque se generan dinámicamente, WordPress 4.5 y otras ofertas wp_add_inline_script . Esta función básicamente bloquea el script a otro script. Digamos, por ejemplo, que está desarrollando un tema y desea que su cliente pueda insertar sus propios scripts (como Google Analytics o AddThis) a través de la página de opciones. Ejemplo .

Para los estilos hay wp_add_inline_style , que básicamente funciona de la misma manera. Lo usaría, por ejemplo, para recorrer todos los mods de su personalizador y reunirlos en una cadena llamada $all_mods , que luego agregaría así a su hoja de estilo principal:

if (!empty($all_mods)) wp_add_inline_style ('main-style', $all_mods);
    
respondido por el cjbj 31.10.2016 - 10:09
-2

Cree un archivo JS.php dinámico y aliméntele a él las consultas importantes. Esas variables en $_GET ayudarán al archivo a determinar el contexto y en él puede almacenar en caché y usar readfile() para futuras solicitudes ... haz lo que quieras.

Solo asegúrate de que el archivo cargue wp-load.php antes que nada, para que tengas acceso a las funciones WP. Use la ruta relativa a la carpeta actual (dirname(__FILE__)) o simplemente digg descendente en la estructura de la carpeta para ubicar wp-load.php independientemente de la ubicación del complemento.

Código para buscar wp-load.php desde cualquier lugar

// Ensure single declaration of function!
if(!function_exists('wp_locate_loader')):
    /**
     * Locates wp-load.php looking backwards on the directory structure.
     * It start from this file's folder.
     * Returns NULL on failure or wp-load.php path if found.
     * 
     * @author EarnestoDev
     * @return string|null
     */
    function wp_locate_loader(){
        $increments = preg_split('~[\\/]+~', dirname(__FILE__));
        $increments_paths = array();
        foreach($increments as $increments_offset => $increments_slice){
            $increments_chunk = array_slice($increments, 0, $increments_offset + 1);
            $increments_paths[] = implode(DIRECTORY_SEPARATOR, $increments_chunk);
        }
        $increments_paths = array_reverse($increments_paths);
        foreach($increments_paths as $increments_path){
            if(is_file($wp_load = $increments_path.DIRECTORY_SEPARATOR.'wp-load.php')){
                return $wp_load;
            }
        }
        return null;
    }
endif;
// Now try to load wp-load.php and pull it in
$mt = microtime(true);
if(!is_file($wp_loader = wp_locate_loader())){
    header("{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden");
    header("Status: 403 Forbidden");
    echo 'Access denied!'; // Or whatever
    die;
}
require_once($wp_loader); // Pull it in
unset($wp_loader); // Cleanup variables

¡Salud, Scribu!

PS : para estructuras complicadas donde las carpetas no siguen la estructura decreciente de WP normal, los complementos principales pueden compartir información con archivos accesibles directamente. Un complemento principal que viene con un archivo PHP dinámico que procesa CSS / JS puede escribir en un archivo el realpath() del wp-load.php y el archivo independiente puede usar eso. Esto sería un problema para el 0.1% de los usuarios de WP. Creo que aquellos que mueven carpetas y no siguen la estructura normal saben lo que están haciendo y probablemente pueden los complementos PIMP que necesitan cargar wp-load.php directamente.

    
respondido por el EarnestoDev 29.10.2011 - 17:51

Lea otras preguntas en las etiquetas