Добавление дополнительных атрибутов в тег скрипта для стороннего JS

20

Я столкнулся с этим, когда пытался интегрировать Dropbox Drop Chooser API в плагин, который я пишу.

Документация по API предписывает вам разместить следующий scriptтег в верхней части вашего файла:

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

Все хорошо, и это действительно работает, когда я непосредственно вставляю его в страницу, которая вызывается в разделе администратора. Но я хотел бы использовать некоторые варианты wp_register_script (), wp_enqueue_script () и wp_localize_script () для передачи необходимого идентификатора и data-app-key.

Я пробовал пару разных вариантов этого:

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

И:

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 заменен соответствующим ключом приложения в моем коде. Был бы признателен за любое направление. Благодарю.

РЕДАКТИРОВАТЬ: Также пытался сделать это с некоторыми jquery, но безрезультатно. Попробовал его при загрузке документа и при готовности документа. Я получаю {"error": "Invalid app_key"} return.

$('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');
Эндрю Бартел
источник
2
Что wp_localize_scriptнужно сделать, это напечатать json-кодированный объект в html-выводе страницы. Этот объект распознается сценарием, и вы можете использовать его. То, что вам нужно, это добавить некоторые атрибуты в тег скрипта, и поэтому wp_localize_scriptне может помочь вам.
gmazzap
2
GM правильно, что wp_localize_scriptне создает атрибуты сценария. Но можно ли передать ключ приложения прямо в dropbox.js? Просто предположение, но вы пробовали array('appKey'=>"MY_APP_KEY")? Это код, который получает ключ от атрибутаif(!Dropbox.appKey){Dropbox.appKey=(e=document.getElementById("dropboxjs"))!=null?e.getAttribute("data-app-key"):void 0}
epilektric
Эй, @epilektric. Не могли бы вы добавить это в ответ? Я не совсем понимаю, как это реализовать.
Эндрю Бартел
@epilektric с wp_localize_scriptуверенностью вы можете передать атрибуты в сценарий. Я действительно не знаю, сработает ли это или нет, однако это не связано с проблемами.
gmazzap
@ AndrewBartel Я тоже не совсем уверен, как. Может быть, это поможет. pippinsplugins.com/use-wp_localize_script-it-is-awesome
эпилектрик

Ответы:

18

Вы можете попытаться использовать script_loader_srcфильтр, например:

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

Обновить

Я сам понял, что src избежал esc_url, поэтому, посмотрев немного больше, я нашел clean_urlфильтр, который вы можете использовать для возврата значения с вашим идентификатором и данными ключа приложения:

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
источник
Не работает Перед печатью результат 'script_loader_src' экранируется, поэтому кавычки удаляются, и то, что вы выводите, распознается как часть атрибута 'src', а не как отдельные атрибуты. Этот код поместит в html-разметку что-то вроде<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
да, я обновил свой ответ.
Bainternet
3
Я протестировал код после редактирования, и он работает. Спасибо, что научил меня чему-то этому.
gmazzap
1
Я думаю, что OP будет счастливее, чем вы меня. ;)
gmazzap
1
Спасибо @Bainternet за вашу помощь, получил его, используя ваш ответ.
Эндрю Бартел
14

Начиная с WP 4.1.0, для достижения этой цели легко доступен новый фильтр-хук:

script_loader_tag

Используйте это так:

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
источник
выполняется ли это до того, как произойдет кэширование JS?
Джоанна Микалай
3

Хорошо, кажется (мне) , что с wp_enqueque_scriptsне возможно печатать идентификатор и ключ приложения в качестве атрибутов тега скрипта.

Я уверен на 90%, потому что WP_Dependenciesэто не тот класс, который я хорошо знаю, но, глядя на код, мне это кажется невозможным.

Но я уверен на 100% , что , используя wp_localize_scriptэто не полезно для вашего объема .

Как я уже сказал в моем комментарии выше:

Что делает wp_localize_script - это печатать json-кодированный объект в html-выводе страницы. Этот объект распознается сценарием, и вы можете использовать его.

Что я не сказал в комментарии, так это то, что json-кодированный объект - это произвольное имя, которое вы решаете, фактически, глядя на синтаксис:

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

Именованный объект $object_name может использоваться сценарием, потому что он находится в глобальной области видимости и печатается в html-странице.

Но $object_nameэто имя, которое вы решаете, так что это может быть что угодно .

Так что спросите себя:

как скрипт на удаленном сервере Dropbox может использовать переменную, которую они не знают, как она называется?

Так что нет никакой причины передавать идентификатор и / или ключ приложения в скрипт wp_localize_script: вам нужно просто напечатать их как атрибуты тега скрипта, как сказано в документации Dropbox API.

Я не являюсь разработчиком js, но я думаю, что скрипт dropbox:

  1. получить все <script>элементы HTML на странице
  2. перебирайте их в поисках одного с id '==' dropboxjs '
  3. если этот скрипт найден, посмотрите на «data-app-key» этого скрипта
  4. проверьте, является ли этот ключ приложения (если имеется) действительным, и авторизуйте вас, если так

Пожалуйста, обратите внимание, что я не знаю это наверняка, я просто догадываюсь .

Таким образом, скрипт, загруженный с сервера Dropbox, может проверить ключ вашего приложения так, чтобы он был легким для них и простым для реализации.

Потому что в первом предложении я сказал , что это не возможно , чтобы напечатать идентификатор и ключ приложения в сценарии с использованием wp_enqueque_scripts, мораль этой истории является то , что вы должны напечатать их в разметке и по - другому.

Способ, который не пахнет слишком много (когда нет альтернатив), состоит в том, чтобы использовать wp_print_scriptsловушку, чтобы напечатать тег сценария:

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
источник
Спасибо GM, я получил его на работу, используя это. Мне интересно посмотреть, есть ли альтернативные решения, использующие хуки enqueue, но я ценю все мысли, которые вы вложили в ответ.
Эндрю Бартел
@ AndrewBartel Я думаю, что нет способа использовать wp_enqueque_scripts в вашем случае, но если вы найдете один, дайте нам знать! :)
gmazzap
Ваше решение может увеличить нагрузку на сервер, так как вы делаете еще один http-запрос, выполняя echo. Решение хорошее, но не оптимизированное.
Фейсал Шейх
@FaisalShaikh хочешь объяснить? echoЗаявление не любой запрос HTTP, насколько я могу судить, и WordPress wp_enqueue_scriptделает эхо , а также (см core.trac.wordpress.org/browser/tags/4.9/src/wp-includes/... ) Конечно , вы могли бы уменьшить количество запросов путем объединения сценария с некоторым другим имеющимся сценарием, но: 1) сценарии существуют на стороннем сервере в этом случае 2) с HTTP 2 в настоящее время объединение сценария приведет к снижению производительности, а не к их увеличению. Так может я что-то упустил?
gmazzap
@ gmazzap ты прав. на самом деле, у меня есть другой способ сделать это. Мы можем сохранить эту третью часть js на нашем сервере, и я действительно не чувствую, что комбинирующий скрипт может увеличить нагрузку на сервер.
Фейсал Шейх
1

От Bainternet ответ выше. Этот код работал для меня.

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

Изменить: Единственное отличие от кода Bainternet заключается в том, что я добавил условие, чтобы проверить, является ли URL-адрес сценария dropbox и является ли он файлом .js.

Я игнорирую все остальные URL-адреса и переписываю URL-адрес dropbox.

user2914440
источник
2
Пожалуйста, добавьте некоторые пояснения относительно того, что вы изменили и почему вы его изменили (или должны были изменить).
tfrommen
Я знаю, что это старый ответ, но в приведенном выше коде вы имели в виду возвращать $ original_url внутри оператора IF вместо просто $ url?
Leromt
1

Я сделал некоторые проверки в коде dropbox.js (v2), чтобы увидеть, что происходит и как лучше всего это решить. Как оказалось, data-app-key используется только для установки переменной Dropbox.appKey. Я смог установить переменную со следующей дополнительной строкой.

Использование примера JavaScript на странице 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>

В моем коде я установил Dropbox.appKey в каждом месте, где я ссылаюсь на подпрограммы JavaScript Dropbox. Это позволило мне использовать wp_enqueue_script () без дополнительных параметров.

Michaelkay
источник
0

Я сделал это с моим плагином eCards, и это действительно просто.

Вот прямая копия / вставка из плагина:

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

Обратите внимание, что ключ API передается через опцию.

Киприан
источник
Как используется $ output? Вторит? Добавить в wp_print_scripts ()?
Эндрю Бартел
Он либо возвращается, либо отображается, в зависимости от вашей функции.
Ciprian
0

Есть более простой способ сделать это

 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 );
Макс Кондрачук
источник
0

Синтаксис Wordpress для script_loader_tag :

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

Чтобы добавить любой атрибут, вы можете изменить свой тег $ следующим образом:

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

Который будет правильно экранировать URL.

JackLinkers
источник
0

Спасибо за все сообщения, они действительно помогли. Я сделал свою собственную версию, чтобы придать ей некоторую структуру и облегчить ее чтение и обновление. Используйте enqueue как обычно, используйте скрипт для CSS-файлов с ложным тегом в конце, чтобы он загружался вверху. Хотя, возможно, это можно несколько упростить.

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
источник