Adăugarea atributelor suplimentare în tag-ul Script pentru JavaScript third-party
Am întâmpinat această problemă când am încercat să integrez API-ul Dropbox chooser într-un plugin pe care îl dezvolt.
Documentația API-ului te instruiește să plasezi următorul tag script
în partea de sus a fișierului tău:
<script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropins.js" id="dropboxjs" data-app-key="MY_APP_KEY"></script>
Totul e în regulă și funcționează când îl lipesc direct în pagina care este apelată în secțiunea de administrare. Dar, aș dori să folosesc o variație a funcțiilor wp_register_script(), wp_enqueue_script() și wp_localize_script() pentru a transmite id-ul și data-app-key necesare.
Am încercat câteva variante diferite de acest gen:
add_action('admin_enqueue_scripts', 'add_dropbox_stuff');
function add_dropbox_js() {
// Înregistrăm scriptul 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"));
}
Și:
add_action('admin_enqueue_scripts', 'add_dropbox_stuff');
function add_dropbox_stuff() {
// Înregistrăm și încărcăm scriptul
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 este înlocuit cu cheia de aplicație corespunzătoare în codul meu. Aș aprecia orice îndrumare. Mulțumesc.
EDIT: Am încercat și cu jQuery, dar fără succes. Am încercat atât la încărcarea documentului cât și la document ready. Primesc eroarea {"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');

Începând cu WP 4.1.0, un nou filtru hook este disponibil pentru a realiza acest lucru într-un mod simplu:
Folosiți-l în felul următor:
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;
}

poți încerca să folosești hook-ul de filtrare script_loader_src
, de exemplu:
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";
}
Actualizare
tocmai am realizat că src este escapuit de esc_url, așa că am căutat puțin și am găsit filtrul clean_url
pe care îl poți folosi pentru a returna valoarea cu id-ul și datele cheii aplicației:
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;
}

Nu funcționează. Înainte de a fi afișat, rezultatul 'script_loader_src' este escapat, astfel încât ghilimelele sunt eliminate și ceea ce afișați este recunoscut ca parte a atributului 'src' și nu ca atribute separate. Acest cod va introduce în markup-ul HTML ceva de genul <script type='text/javascript' src='https://www.dropbox.com/static/api/1/dropins.js?ver=3.6'id='dropboxjs'data-app-key='MY_APP_KEY'></script>

Excelent! +1, dar încă nu funcționează... Cred însă că o mică modificare ar rezolva problema.

Am testat codul după editare și funcționează. Mulțumesc că m-ai învățat ceva nou prin asta.

OK, se pare (după mine) că cu wp_enqueque_scripts
nu este posibil să afișezi id-ul și cheia aplicației ca atribute ale tag-ului script.
Sunt sigur în proporție de 90%, deoarece WP_Dependencies
nu este o clasă pe care o cunosc foarte bine, dar uitându-mă la cod mi se pare că nu este posibil.
Dar sunt sigur în proporție de 100% că utilizarea wp_localize_script
este nefolositoare pentru scopul tău.
După cum am spus în comentariul meu de mai sus:
Ceea ce face wp_localize_script este să afișeze un obiect codificat json în html-ul paginii. Acest obiect este recunoscut de script și astfel îl poți utiliza.
Ceea ce nu am spus în comentariu este că obiectul codificat json are un nume arbitrar pe care tu îl decizi, de fapt, uitându-ne la sintaxă:
wp_localize_script( $handle, $object_name, $l10n );
Obiectul numit $object_name
ar putea fi utilizat de script deoarece se află în scope-ul global și este afișat în html-ul paginii.
Dar $object_name
este un nume pe care tu îl decizi, deci poate fi orice.
Așadar, întreabă-te:
cum poate scriptul de pe serverul remote dropbox să folosească o variabilă despre care nu știe cum se numește?
Deci nu există niciun motiv să transmiți id-ul și/sau cheia aplicației către script cu wp_localize_script
: trebuie doar să le afișezi ca atribute ale tag-ului script așa cum este menționat în documentația Dropbox API.
Nu sunt dezvoltator js, dar cred că scriptul dropbox face următoarele:
- obține toate elementele
<script>
html din pagină - iterează prin ele căutându-l pe cel cu 'id' == 'dropboxjs'
- dacă acel script este găsit, verifică 'data-app-key' al acelui script
- verifică dacă cheia aplicației (dacă există) este una validă și te autorizează dacă da
Te rog, notează că nu știu asta sigur, doar presupun.
În acest fel, scriptul încărcat de pe serverul dropbox poate verifica cheia ta de aplicație într-un mod ușor pentru ei și ușor de implementat pentru tine.
Deoarece în prima propoziție am spus că este imposibil să afișezi id-ul și cheia aplicației în script folosind wp_enqueque_scripts
, concluzia este că trebuie să le afișezi în markup într-un alt mod.
O metodă care nu miroase prea rău (când nu există alternative) este să folosești hook-ul wp_print_scripts
pentru a afișa tag-ul script:
add_action('wp_print_scripts', 'do_dropbox_stuff');
function do_dropbox_stuff() {
if ( ! is_admin() ) return; // doar pentru zona de administrare
$app_key = 'CHEIA_MEA_DE_APLICAȚIE';
// de ce să nu creezi o opțiune pentru asta?
// $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>';
}

Mulțumesc G.M., am reușit să funcționeze folosind asta. Sunt curios dacă există soluții alternative folosind hook-urile enqueue dar apreciez tot efortul pe care l-ai depus în răspuns.

@AndrewBartel Cred că nu există nicio modalitate de a folosi wp_enqueque_scripts în cazul tău, dar dacă găsești una, anunță-ne! :)

soluția ta poate crește încărcarea pe server deoarece faci direct o cerere http suplimentară prin folosirea echo. Soluția este bună dar nu este optimizată.

@FaisalShaikh poți să explici? Declarația echo
nu face nicio cerere HTTP din câte îmi dau seama, iar funcția WordPress wp_enqueue_script
folosește și ea echo (vezi https://core.trac.wordpress.org/browser/tags/4.9/src/wp-includes/class.wp-scripts.php#L343) Sigur, ai putea reduce numărul de cereri prin combinarea scriptului cu alte scripturi pe care le ai, dar: 1) în acest caz, scriptul există pe un server terț 2) cu HTTP 2 în zilele noastre, combinarea scripturilor ar reduce performanța, nu le-ar îmbunătăți. Poate îmi scapă ceva?

Din răspunsul lui Bainternet de mai sus. Acest cod a funcționat pentru mine.
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";
}
}
Editare: Singura diferență față de codul lui Bainternet este că am adăugat o condiție pentru a verifica dacă URL-ul scriptului este dropbox și este un fișier .js.
Ignor toate celelalte URL-uri și rescriu doar URL-ul dropbox.

Te rog adaugă o explicație despre ce ai modificat și de ce ai făcut modificarea (sau a trebuit să o faci).

Mulțumesc pentru toate postările, au fost cu adevărat folositoare. Am creat propria mea versiune pentru a-i oferi o structură și a o face mai ușor de citit și actualizat. Folosește enqueue ca de obicei, folosește script pentru fișierele CSS cu un tag false la final pentru a se încărca în partea de sus. Deși probabil poate fi simplificat într-o oarecare măsură.
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;
}

Am făcut asta cu plugin-ul meu pentru eCard-uri și este foarte simplu.
Iată o copiere directă din 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ți că cheia API este transmisă printr-o opțiune.

Am făcut o verificare în codul dropbox.js (versiunea 2) pentru a vedea ce se întâmplă și cum să rezolv această problemă în cel mai bun mod. După cum am descoperit, atributul data-app-key este folosit doar pentru a seta variabila Dropbox.appKey. Am reușit să setez variabila cu următoarea linie suplimentară.
Folosind exemplul JavaScript de pe pagina 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>
În codul meu, am setat Dropbox.appKey în fiecare loc în care fac referire la rutinele JavaScript ale Dropbox. Făcând acest lucru, am putut utiliza wp_enqueue_script() fără parametrii suplimentari.

Există o metodă mai simplă de a face acest lucru
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 );

Sintaxă WordPress pentru script_loader_tag:
apply_filters( 'script_loader_tag', string $tag, string $handle, string $src )
Pentru a adăuga orice atribut, puteți modifica $tag astfel:
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;
}
Ceea ce va escapa corect URL-ul.
