Agregar atributos adicionales en la etiqueta de script para JS de terceros

20

Me encontré con esto al intentar integrar la caída de Dropbox en la API del selector en un complemento que estoy escribiendo.

La documentación de la API le indica que coloque la siguiente scriptetiqueta en la parte superior de su 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 en realidad funciona cuando lo pego directamente en la página que se llama en la sección de administración. Pero, me gustaría usar alguna variación de wp_register_script (), wp_enqueue_script () y wp_localize_script () para pasar la identificación necesaria y la clave de aplicación de datos.

He probado un par de variaciones diferentes de esto:

add_action('admin_enqueue_scripts', 'add_dropbox_stuff');
function add_dropbox_js() {
    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() {
        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 se reemplaza con la clave de aplicación apropiada en mi código. Agradecería cualquier dirección. Gracias.

EDITAR: También intenté hacerlo con un poco de jquery, pero fue en vano. Probé con la carga del documento y con el documento listo Me devuelve un {"error": "clave_aplicación no válida"}.

$('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');
Andrew Bartel
fuente
2
Lo wp_localize_scriptque debe hacer es imprimir un objeto codificado con json en la salida html de la página. El script reconoce este objeto, por lo que puede usarlo. Lo que necesita es agregar algunos atributos a la etiqueta del script, por wp_localize_scriptlo que no puede ayudarlo.
gmazzap
2
GM es correcto wp_localize_scripty no crea atributos de script. Pero, ¿es posible pasar la clave de la aplicación directamente a dropbox.js? Solo una suposición, pero ¿lo has intentado array('appKey'=>"MY_APP_KEY")? Este es el código que toma la clave del atributoif(!Dropbox.appKey){Dropbox.appKey=(e=document.getElementById("dropboxjs"))!=null?e.getAttribute("data-app-key"):void 0}
epilektric
Hola @epilektric ¿Podrías poner eso en una respuesta? No estoy siguiendo exactamente cómo implementarlo.
Andrew Bartel
@epilektric con wp_localize_scriptseguridad de que puede pasar atributos al script. Realmente no sé si esto funcionará o no, sin embargo, no es un asunto relacionado con Worpress.
gmazzap
@ AndrewBartel No estoy realmente seguro de cómo tampoco. Tal vez esto ayude. pippinsplugins.com/use-wp_localize_script-it-is-awesome
epilektric

Respuestas:

18

puede intentar usar el script_loader_srcgancho de filtro, 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";
}

Actualizar

Acabo de darme cuenta de que esc_url escapa al src, así que busqué un poco más y encontré el clean_urlfiltro que puede usar para devolver el valor con su identificación y datos clave de la aplicación:

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;
}
Bainternet
fuente
No funciona Antes de imprimirse, el resultado de 'script_loader_src' se escapa, por lo que las comillas se eliminan y lo que se genera se reconoce como parte del atributo 'src' y no como atributos separados. Este código colocará en el marcado html algo así 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
Sí, actualicé mi respuesta.
Bainternet
3
He probado el código después de mi edición y funciona. Gracias por enseñarme algo con esto.
gmazzap
1
Creo que OP será más feliz que tú y yo. ;)
gmazzap
1
Gracias @Bainternet por tu ayuda, lo hice funcionar usando tu respuesta.
Andrew Bartel
14

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

script_loader_tag

Úselo 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="MY_APP_KEY"></script>';
    }

    return $tag;
}
ClemC
fuente
¿Se ejecuta esto antes de que tenga lugar el almacenamiento en caché de JS?
Joanna Mikalai
3

OK, me parece (a mí) que con wp_enqueque_scripts no es posible imprimir la identificación y la clave de la aplicación como atributos de etiqueta de script.

Estoy seguro al 90%, porque WP_Dependenciesno es una clase que conozco bien, pero mirando el código no me parece posible.

Pero estoy seguro al 100% de que usar wp_localize_scriptes no útil para su alcance .

Como dije en mi comentario anterior:

Lo que hace wp_localize_script es imprimir un objeto codificado con json en la salida html de la página. El script reconoce este objeto, por lo que puede usarlo.

Lo que no he dicho en el comentario es que el objeto codificado con json como un nombre arbitrario que usted decide, de hecho, mirando la sintaxis:

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

El objeto llamado $object_name podría ser utilizado por el guión porque es en el ámbito global e impreso en el código HTML de la página.

Pero el $object_namees un nombre que usted decide, por lo que puede ser todo .

Entonces pregúntate a ti mismo:

¿Cómo el script en el servidor remoto de Dropbox puede hacer uso de una variable que no saben cómo se llama?

Por lo tanto, no hay ninguna razón para pasar la identificación y / o la clave de la aplicación al script con wp_localize_script: solo debe imprimirlos como atributos de etiqueta de script como se dice en los documentos de la API de Dropbox.

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

  1. obtener toda <script> elementos html en la página
  2. recorrerlos buscando el que tiene el 'id' == 'dropboxjs'
  3. si se encuentra ese script, mirando la 'clave de aplicación de datos' de ese script
  4. comprobar si esa clave de la aplicación (si está presente) es válida y autorizarlo si es así

Tenga en cuenta que no lo sé con certeza, solo estoy adivinando .

De esta manera, el script cargado desde el servidor de Dropbox puede verificar la clave de su aplicación de una manera que sea fácil para ellos y fácil de implementar para usted.

Debido a que en la primera oración dije que no es posible imprimir la identificación y la clave de la aplicación en el guión wp_enqueque_scripts, la moraleja de la historia es que debe imprimirlos en el marcado de otra manera.

Una forma que no huele demasiado (cuando no hay alternativas) es usar wp_print_scriptshook para imprimir la etiqueta del script:

add_action('wp_print_scripts', 'do_dropbox_stuff');

function do_dropbox_stuff() {

  if ( ! is_admin() ) return; // only for admin area

  $app_key = 'MY_APP_KEY';

  // why do not create an option for it?
  // $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>';

}
gmazzap
fuente
Gracias GM, lo puse a trabajar usando esto. Estoy interesado en ver si hay soluciones alternativas usando los ganchos en cola, pero agradezco todo el pensamiento que pusiste en la respuesta.
Andrew Bartel
@ AndrewBartel Creo que no hay forma de usar wp_enqueque_scripts en su caso, pero si encuentra uno, ¡háganoslo saber! :)
gmazzap
su solución puede aumentar la carga en el servidor ya que está haciendo directamente una solicitud http más haciendo echo. La solución es buena pero no optimizada.
Faisal Shaikh
@FaisalShaikh te importa explicar? La echodeclaración no hace ninguna solicitud HTTP por lo que puedo decir, y WordPress también wp_enqueue_scripthace un eco (ver core.trac.wordpress.org/browser/tags/4.9/src/wp-includes/… ) Seguramente podría reducir el número de solicitudes combinando el script con algún otro script que tenga pero: 1) el script existe en un servidor de terceros en este caso 2) con HTTP 2 hoy en día, combinar el script reduciría el rendimiento, no lo aumentaría. ¿Entonces tal vez extraño algo?
gmazzap
@gmazzap tienes razón. En realidad, tengo una forma diferente de hacer esto. Podemos almacenar esta tercera parte js en nuestro servidor y realmente no creo que la combinación de script pueda aumentar la carga en el servidor.
Faisal Shaikh
1

De la respuesta de Bainternet arriba. Este código me funcionó.

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

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

Estoy ignorando todas las otras URL y reescribiendo la URL de Dropbox.

usuario2914440
fuente
2
Agregue alguna explicación sobre lo que cambia y por qué lo cambió (o tuvo que cambiarlo).
tfrommen
Sé que esta es una respuesta anterior, pero en su código anterior, ¿quiso devolver $ original_url dentro de la instrucción IF en lugar de solo $ url?
leromt
1

Hice un poco de comprobación en el código dropbox.js (v2) para ver qué estaba sucediendo y cómo resolverlo mejor. Como resultado, la clave de aplicación de datos 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 = "YOUR-APP-ID";
var button = Dropbox.createChooseButton(options);
document.getElementById("container").appendChild(button);
</script>

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

Michaelkay
fuente
0

Hice esto con mi complemento eCards y es realmente simple.

Aquí hay una copia directa / pegar desde el complemento:

$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>';

Observe que la clave API se pasa a través de una opción.

Ciprian
fuente
¿Cómo se usa $ output? ¿Echoed? Añadir a wp_print_scripts ()?
Andrew Bartel
Se devuelve o se repite, según su función.
Ciprian el
0

Hay una manera más simple 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='MY_APP_KEY";
    }

    return $url;
}

add_filter( 'clean_url', 'load_attributes', 11, 1 );
Max Kondrachuk
fuente
0

Sintaxis de Wordpress para script_loader_tag :

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

Para agregar cualquier atributo, puede modificar su etiqueta $ 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;
}

Que escapará correctamente de la URL.

JackLinkers
fuente
0

Gracias por todas las publicaciones, realmente ayudaron. Hice rodar mi propia versión para darle algo de estructura y facilitar su lectura y actualización. Use en cola como de costumbre, use script para archivos CSS con una etiqueta falsa al final para que se cargue en la parte superior. Aunque probablemente se pueda simplificar un poco.

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