Añadir Atributos Adicionales en la Etiqueta Script para JS de Terceros

20 ago 2013, 22:39:36
Vistas: 29.6K
Votos: 29

Me encontré con esto al intentar integrar la API del selector de Dropbox en un plugin que estoy desarrollando.

La documentación de la API indica que debes colocar la siguiente etiqueta script en la parte superior de tu archivo:

<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropins.js" id="dropboxjs" data-app-key="MY_APP_KEY"></script>

Todo bien, y de hecho funciona cuando lo pego directamente en la página que se llama en la sección de administración. Sin embargo, me gustaría usar alguna variación de wp_register_script(), wp_enqueue_script() y wp_localize_script() para pasar el id y data-app-key necesarios.

He probado diferentes variaciones de esto:

add_action('admin_enqueue_scripts', 'add_dropbox_stuff');
function add_dropbox_js() {
    // Registrar y cargar el script de Dropbox
    wp_register_script('dropbox.js','https://www.dropbox.com/static/api/1/dropins.js');
    wp_enqueue_script('dropbox.js');
    wp_localize_script('dropbox.js','dropboxdata',array('id'=>"dropboxjs",'data-app-key'=>"MY_APP_KEY"));
}

Y:

add_action('admin_enqueue_scripts', 'add_dropbox_stuff');
function add_dropbox_stuff() {
        // Registrar y cargar el script de Dropbox con múltiples atributos
        wp_register_script('dropbox.js','https://www.dropbox.com/static/api/1/dropins.js');
        wp_enqueue_script('dropbox.js');
        wp_localize_script('dropbox.js','dropboxdata',array(array('id'=>"dropboxjs"),array('data-app-key'=>"MY_APP_KEY")));
    }

MY_APP_KEY está reemplazado con la clave de aplicación apropiada en mi código. Agradecería cualquier orientación. Gracias.

EDICIÓN: También intenté hacerlo con jQuery, pero sin éxito. Lo probé tanto en document load como en document ready. Recibo un retorno {"error": "Invalid app_key"}.

$('script[src="https://www.dropbox.com/static/api/1/dropins.js?ver=3.6"]').attr('id','dropboxjs').attr('data-multiselect','true').attr('data-app-key','MY_APP_KEY');
7
Comentarios

Lo que hace wp_localize_script es imprimir un objeto codificado en json en el html de salida de la página. Este objeto es reconocido por el script y así puedes utilizarlo. Lo que necesitas es añadir algunos atributos a la etiqueta script, por lo que wp_localize_script no puede ayudarte.

gmazzap gmazzap
20 ago 2013 23:10:40

G. M. tiene razón en que wp_localize_script no crea atributos de script. Pero, ¿es posible pasar directamente la clave de la aplicación a dropbox.js? Solo una suposición, pero ¿has probado array('appKey'=>"MI_CLAVE_APP")? Este es el código que obtiene la clave del atributo if(!Dropbox.appKey){Dropbox.appKey=(e=document.getElementById("dropboxjs"))!=null?e.getAttribute("data-app-key"):void 0}

epilektric epilektric
20 ago 2013 23:21:21

Hola @epilektric ¿Podrías poner eso en una respuesta? No termino de entender cómo implementarlo.

Andrew Bartel Andrew Bartel
21 ago 2013 00:40:57

@epilektric con wp_localize_script seguro que puedes pasar atributos al script. Realmente no sé si esto funcionará o no, sin embargo no es un asunto relacionado con WordPress.

gmazzap gmazzap
21 ago 2013 01:00:44

@AndrewBartel No estoy realmente seguro de cómo hacerlo tampoco. Tal vez esto ayude. http://pippinsplugins.com/use-wp_localize_script-it-is-awesome/

epilektric epilektric
21 ago 2013 02:39:07

Duplicado ... o al menos muy parecido a uno. Actualmente no se puede cerrar debido a la recompensa abierta.

kaiser kaiser
28 ago 2013 14:34:00

Creo que esto es un duplicado de esta pregunta.

fuxia fuxia
28 ago 2013 20:55:52
Mostrar los 2 comentarios restantes
Todas las respuestas a la pregunta 9
1
29

Desde WP 4.1.0, está disponible un nuevo filtro para lograr esto fácilmente:

script_loader_tag

Úsalo de esta manera:

add_filter( 'script_loader_tag', 'add_id_to_script', 10, 3 );

function add_id_to_script( $tag, $handle, $source ) {
    if ( 'dropbox.js' === $handle ) {
        $tag = '<script type="text/javascript" src="' . $source . '" id="dropboxjs" data-app-key="MI_CLAVE_DE_APP"></script>';
    }

    return $tag;
}
1 nov 2016 01:17:16
Comentarios

¿esto se ejecuta antes de que ocurra cualquier almacenamiento en caché de JS?

JoaMika JoaMika
22 ago 2018 14:16:14
7
19

Puedes intentar usar el gancho de filtro script_loader_src, por ejemplo:

add_filter('script_loader_src','add_id_to_script',10,2);
function add_id_to_script($src, $handle){
    if ($handle != 'dropbox.js') 
            return $src;
    return $src."' id='dropboxjs' data-app-key='MY_APP_KEY";
}

Actualización

Acabo de descubrir por mí mismo que el src es escapado por esc_url, así que investigando un poco más encontré el filtro clean_url que puedes usar para devolver el valor con tu id y datos de app key:

add_filter('clean_url','unclean_url',10,3);
function unclean_url( $good_protocol_url, $original_url, $_context){
    if (false !== strpos($original_url, 'data-app-key')){
      remove_filter('clean_url','unclean_url',10,3);
      $url_parts = parse_url($good_protocol_url);
      return $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . "' id='dropboxjs' data-app-key='MY_APP_KEY";
    }
    return $good_protocol_url;
}
28 ago 2013 00:57:21
Comentarios

No funciona. Antes de ser impreso, el resultado de 'script_loader_src' es escapado, por lo que las comillas son eliminadas y lo que muestras es reconocido como parte del atributo 'src' y no como atributos separados. Este código generará en el marcado HTML algo como <script type='text/javascript' src='https://www.dropbox.com/static/api/1/dropins.js?ver=3.6&#039;id=&#039;dropboxjs&#039;data-app-key=&#039;MY_APP_KEY'></script>

gmazzap gmazzap
28 ago 2013 10:21:02

Sí, actualicé mi respuesta.

Bainternet Bainternet
28 ago 2013 10:29:41

¡Genial! +1, pero todavía no funciona... Aunque creo que un pequeño ajuste lo hará funcionar.

gmazzap gmazzap
28 ago 2013 10:42:20

He probado el código después de mi edición y funciona. Gracias por enseñarme algo con esto.

gmazzap gmazzap
28 ago 2013 10:45:30

me alegra que lo hayas conseguido :)

Bainternet Bainternet
28 ago 2013 10:45:58

Creo que el OP estará más feliz que tú y yo. ;)

gmazzap gmazzap
28 ago 2013 10:49:28

Gracias @Bainternet por tu ayuda, lo conseguí funcionar usando tu respuesta.

Andrew Bartel Andrew Bartel
30 ago 2013 02:40:47
Mostrar los 2 comentarios restantes
5

OK, parece (para mí) que con wp_enqueque_scripts no es posible imprimir el id y la app key como atributos del tag script.

Estoy seguro al 90%, porque WP_Dependencies no es una clase que conozca bien, pero al mirar el código me parece que no es posible.

Pero estoy seguro al 100% que usar wp_localize_script es inútil para tu propósito.

Como dije en mi comentario anterior:

Lo que hace wp_localize_script es imprimir un objeto codificado en json en el html de la página. Este objeto es reconocido por el script y así puedes usarlo.

Lo que no mencioné en el comentario es que el objeto codificado en json tiene un nombre arbitrario que tú decides, de hecho, mirando la sintaxis:

wp_localize_script( $handle, $object_name, $l10n );

El objeto llamado $object_name podría ser usado por el script porque está en el ámbito global e impreso en el html de la página.

Pero el $object_name es un nombre que decides, así que puede ser cualquier cosa.

Así que pregúntate:

¿cómo puede el script en el servidor remoto de Dropbox hacer uso de una variable cuyo nombre desconocen?

Así que no hay ninguna razón para pasar el id y/o app key al script con wp_localize_script: simplemente tienes que imprimirlos como atributos del tag script como se indica en la documentación de la API de Dropbox.

No soy desarrollador js, pero creo que lo que hace el script de Dropbox es:

  1. Obtener todos los elementos <script> html en la página
  2. Ciclar a través de ellos buscando el que tenga 'id' == 'dropboxjs'
  3. Si ese script se encuentra, mirar el 'data-app-key' de ese script
  4. Verificar si esa app key (si está presente) es válida y autorizarte si es así

Por favor, ten en cuenta que no sé esto con seguridad, solo estoy adivinando.

De esta manera, el script cargado desde el servidor de Dropbox puede verificar tu app key de una manera fácil para ellos y fácil de implementar para ti.

Como en la primera frase dije que es no posible imprimir el id y la app key en el script usando wp_enqueque_scripts, la moraleja es que tienes que imprimirlos en el markup de otra manera.

Una manera que no huela demasiado mal (cuando no hay alternativas) es usar el hook wp_print_scripts para imprimir el tag script:

add_action('wp_print_scripts', 'do_dropbox_stuff');

function do_dropbox_stuff() {

  if ( ! is_admin() ) return; // solo para el área de administración

  $app_key = 'MY_APP_KEY';

  // ¿por qué no crear una opción para ello?
  // $app_key = get_option('dropbox_app_key');

  if ( empty($app_key) ) return;

  echo '<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropins.js" id="dropboxjs" data-app-key="' . esc_attr($app_key) . '"></script>';

}
24 ago 2013 04:14:29
Comentarios

Gracias G.M., logré que funcione usando esto. Estoy interesado en ver si hay soluciones alternativas usando los hooks de enqueue pero agradezco todo el pensamiento que pusiste en la respuesta.

Andrew Bartel Andrew Bartel
27 ago 2013 00:59:10

@AndrewBartel Creo que no hay forma de usar wp_enqueque_scripts en tu caso, pero si encuentras una, ¡avísanos! :)

gmazzap gmazzap
27 ago 2013 03:37:53

tu solución puede aumentar la carga en el servidor ya que estás haciendo directamente 1 solicitud http más al usar echo. La solución es buena pero no está optimizada.

Faisal Shaikh Faisal Shaikh
17 jul 2018 00:19:46

@FaisalShaikh ¿te importaría explicar? La declaración echo no realiza ninguna solicitud HTTP que yo sepa, y el wp_enqueue_script de WordPress también hace un echo (ver https://core.trac.wordpress.org/browser/tags/4.9/src/wp-includes/class.wp-scripts.php#L343). Seguramente podrías reducir el número de solicitudes combinando el script con algún otro que tengas, pero: 1) en este caso, los scripts existen en un servidor de terceros 2) con HTTP/2 hoy en día, combinar los scripts reduciría el rendimiento, no lo aumentaría. ¿Quizás me estoy perdiendo algo?

gmazzap gmazzap
17 jul 2018 17:55:32

@gmazzap tienes razón. En realidad, tengo una forma diferente de hacer esto. Podemos almacenar este JS de terceros en nuestro servidor y realmente no creo que combinar scripts pueda aumentar la carga en el servidor.

Faisal Shaikh Faisal Shaikh
18 jul 2018 14:22:08
2

Según la respuesta de Bainternet anterior. Este código funcionó para mí.

function pmdi_dropbox( $good_protocol_url, $original_url, $_context){
    if ( FALSE === strpos($original_url, 'dropbox') or FALSE === strpos($original_url, '.js')) {
        return $url;
    } else {
        remove_filter('clean_url','pmdi_dropbox',10,3);
        $url_parts = parse_url($good_protocol_url);
        return $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . "' id='dropboxjs' data-app-key='APIKEY";
    }
}

Edición: La única diferencia con el código de Bainternet es que agregué una condición para verificar si la URL del script es de dropbox y si es un archivo .js.

Estoy ignorando todas las demás URL y reescribiendo solo la URL de Dropbox.

17 feb 2014 14:14:16
Comentarios

Por favor agrega alguna explicación sobre qué cambiaste y por qué lo cambiaste (o tuviste que cambiarlo).

tfrommen tfrommen
17 feb 2014 14:42:33

Sé que esta es una respuesta antigua pero en tu código anterior, ¿quisiste retornar $original_url dentro de la declaración IF en lugar de solo $url?

leromt leromt
12 mar 2015 23:01:09
0

Gracias por todas las publicaciones, realmente ayudaron. Creé mi propia versión para darle algo de estructura y hacerla más fácil de leer y actualizar. Usa enqueue como siempre, usa script para archivos CSS con un tag falso al final para que se cargue en la parte superior. Aunque probablemente se podría simplificar un poco más.

add_filter('script_loader_tag', 'add_attributes_to_script', 10, 3); 
function add_attributes_to_script( $tag, $handle, $src ) {

    $scripts_to_load = array (

        (0) => Array
          (
            ('name') => 'bootstrap_min_css',
            ('type') => '<link rel="stylesheet" href="',            
            ('integrity') => 'sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB',
            ('close') => ' type="text/css" media="all">'
          ),

        (1) => Array
          (
            ('name') => 'popper_min_js',
            ('type') => '<script type="text/javascript" src="',         
            ('integrity') => 'sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49',
            ('close') => '></script>'
          ),

         (2) => Array
           (
            ('name') => 'bootstrap_min_js', 
            ('type') => '<script type="text/javascript" src="',
            ('integrity') => 'sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T',
            ('close') => '></script>'
           )
    );  

    $key = array_search($handle, array_column($scripts_to_load, 'name'));

    if ( FALSE !== $key){

        $tag = $scripts_to_load[$key]['type'] . esc_url($src) . '" integrity="' . $scripts_to_load[$key]['integrity'] .'" crossorigin="anonymous"' . $scripts_to_load[$key]['close'] . "\n";

    }
    return $tag;
}
9 may 2018 00:39:10
2

Hice esto con mi plugin de eCards y es realmente simple.

Aquí tienes una copia directa del plugin:

$output .= '<!-- https://www.dropbox.com/developers/chooser -->';
$output .= '<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropbox.js" id="dropboxjs" data-app-key="' . get_option('ecard_dropbox_private') . '"></script>';
$output .= '<p><input type="dropbox-chooser" name="selected-file" style="visibility: hidden;" data-link-type="direct" /></p>';

Observa que la clave API se pasa mediante una opción.

26 ago 2013 16:55:59
Comentarios

¿Cómo se utiliza $output? ¿Se muestra con echo? ¿Se añade a wp_print_scripts()?

Andrew Bartel Andrew Bartel
27 ago 2013 00:57:41

Depende de tu función, puede ser devuelto o mostrado con echo.

Ciprian Ciprian
27 ago 2013 13:23:06
0

Hice algunas verificaciones en el código de dropbox.js (v2) para ver qué estaba sucediendo y cómo solucionarlo de la mejor manera. Resulta que el atributo data-app-key solo se usa para establecer la variable Dropbox.appKey. Pude establecer la variable con la siguiente línea adicional.

Usando el ejemplo de JavaScript en la página de Dropbox https://www.dropbox.com/developers/dropins/chooser/js:

<script>
Dropbox.appKey = "TU-ID-DE-APP";
var button = Dropbox.createChooseButton(options);
document.getElementById("container").appendChild(button);
</script>

En mi código establezco Dropbox.appKey en cada lugar donde hago referencia a las rutinas JavaScript de Dropbox. Hacer esto me permitió usar wp_enqueue_script() sin los parámetros adicionales.

7 abr 2014 22:19:19
0

Hay una forma más sencilla de hacer esto

 function load_attributes( $url ){
    if ( 'https://www.dropbox.com/static/api/1/dropins.js' === $url ){
        return "$url' id='dropboxjs' data-app-key='MI_CLAVE_DE_APLICACION";
    }

    return $url;
}

add_filter( 'clean_url', 'load_attributes', 11, 1 );
8 dic 2015 11:58:44
0

Sintaxis de WordPress para script_loader_tag:

apply_filters( 'script_loader_tag', string $tag, string $handle, string $src )

Para agregar cualquier atributo, puedes modificar tu $tag de esta manera:

add_filter('script_loader_tag', 'add_attributes_to_script', 10, 3); 
function add_attributes_to_script( $tag, $handle, $src ) {
    if ( 'dropbox.js' === $handle ) {
        $tag = '<script type="text/javascript" src="' . esc_url( $src ) . '" id="dropboxjs" data-app-key="MY_APP_KEY"></script>';
    } 
    return $tag;
}

Lo cual escapará correctamente la URL.

28 ene 2018 12:57:09