Особенности подключения JS скриптов в WordPress

Владимир | | JavaScript, PHP, Web разработка, WordPress.

wordpress scripts

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

Один из таких примеров – подключение JavaScript кода в WordPress.

Этот движок предоставляет удобную функцию wp_enqueue_script. С её помощью можно обеспечить необходимый порядок подключения скриптов и, при этом, гарантируется, что один и тот же скрипт будет подключён только один раз.

Кстати, аналогичные возможности есть и в различных фреймворках, например, Yii.

Но разница между фреймворком и WordPress в том, что с помощью последнего можно создать сайт, не читая документацию, во всяком случае, ту часть, которая касается API. В этом нет ничего плохого, но можно столкнуться с некоторыми нюансами. О них речь пойдет ниже.

Основные проблемы и причины их появления


Возьмем самую распространённую ситуацию. Есть сайт на WP, и есть готовый JS скрипт, который нужно к этому сайту подключить.

Что написано в инструкции по установке скрипта?

«Вставьте тег <script…> в заголовок страницы (между <head> и </head>)».

Тут все правильно. Разработчик пишет инструкцию на общий случай, а не конкретно под WP.

Следующий вопрос. Где находятся теги <head> и </head> в WP?

Обычно в файле header.php текущей темы.

Т.е. если делать строго по инструкции, то нужно добавить теги <script…> в header.php.

Именно здесь и возникают проблемы.

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

Проблема 1. Многократная загрузка JS файлов.

Возникает если подключить JS скрипт в файле темы, а затем использовать плагин, которому нужен этот же скрипт. Чаще всего такое происходит с JavaScript библиотеками.

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

В результате один раз JavaScript файл подключается вашим тегом, второй – тегом, который добавит плагин. Это приводит к увеличению веса страницы, времени её загрузки, росту трафика сервера.

Проблема 2. «Неработающие» плагины.

Вытекает из первой.

Рассмотрим небольшой пример. Допустим скрипты подключены в header.php следующим образом.

<head>
	...
	<script src="...jquery.js" ...></script>
	<script src="...jquery.my-plugin.js" ...></script>
	<?php wp_head(); ?>
</head>

Что произойдет если какой-то из плагинов WP подключит jQuery?

Функция wp_enqueue_script добавит теги script там, где находится вызов wp_head(). А это, помимо повторной загрузки jquery, означает, что и объект jQuery будет создан заново. И он будет использоваться вместо первого объекта, к которому подключили плагин.

В принципе, проблему можно решить так.

<head>
	...
	<?php wp_head(); ?>
	<script src="...jquery.my-plugin.js" ...></script>
</head>

Но если вы в админке WP отключите плагин, который использует jQuery, то my-plugin.js также перестанет работать. Т.к. jQuery будет не подключена.

Как избежать этих проблем?

Просто не трогайте header.php. В папке с темой есть файл functions.php в который нужно добавить следующий код.

<?php
if ( !is_admin() ) {
	function register_my_js() {
		wp_enqueue_script( 'my-script', get_bloginfo( 'template_directory' ).'/my-script.js', array( 'jquery' ), '1.0', true );
	}
	add_action('init', 'register_my_js');
}
?>

Этот код подключит скрипт на всех страницах сайта, кроме админки. Если нужно подключать скрипт только на части страниц, можно в условие проверки добавить is_single(), is_home() и т.д.

Кроме того, библиотеку jQuery явно подключать не нужно, т.к. она указана в массиве зависимостей (третий параметр wp_enqueue_script). WordPress подключит её сам до вашего плагина.

Для справки

Функция wp_enqueue_script подключает JS файл если он не был подключен ранее. Т.е. можно вызвать её несколько раз для одного и того же скрипта и, при этом, скрипт будет вставлен только один раз.

Параметры.

wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );

$handle – название скрипта, должно быть уникальным.

$src – URL скрипта. Если скрипт был предварительно зарегистрирован с помощью wp_register_script, то его указывать не обязательно.

$deps – массив зависимостей (нужно перечислить названия JS скриптов, которые должны быть загружены перед данным).

$ver – версия скрипта (необязательный).

$in_footer – если равен true, скрипт будет подключен в конце страницы, там где находится wp_footer(). Обычно в файле footer.php перед </body>.

Заключение

Очень советую почитать статью Function Reference/wp enqueue script. Она небольшая, но в ней вы найдёте несколько интересных примеров. Например, объясняющих как заменить версию библиотеки jQuery, которая идёт в дистрибутиве WP.

Интересное в сети.

Возможно, самый оригинальный подарок:фруктовые корзины с доставкой по Москве.

Технология кейс-стади: отлично работает при продаже услуг.

  • Annsar

    полезная статья. спасибо

  • Гость

    Не работает из шорткодов.

    • Шорткоды обрабатываются после того, как часть страницы уже создана.
      Используйте события вроде init или wp_print_scripts.

  • Установил Disqus, активировал его перестал работать nivo slider, в чем может быть беда?
    Отключаю Дискус, слайдер опять работает.
    Как выглядит проблема. У меня слайдер стоит на главной странице, после того, при автивированном дискусе, открывается сайт нормально, но слайдер вместо показа картинок, показывает крутящееся колесо, якобы что-то он пытается загрузить.
    Просто не знаю даже куда обратиться, решил туда, где хоть немного речь идет о дискусе и джикверри.
    Помогите разобраться, а то уже день сижу не могу исправить положение(

    • Прежде всего, посмотрите, выводит ли ошибки firebug при включенных nivo slider и Дискусе. Затем проверьте какие JS файлы загружаются когда включены оба плагина и по отдельности (вкладка Сеть).

      Дальше — в зависимости от результатов.

      • При активированном плагине дискуса пишет:
        Невозможно загрузить исходный код для:…includes/js/jquery/jquery.js?ver=1.4.4

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

        • Добрый день, так решили проблему? Я тоже столкнулся с этим.

        • Сам разобрался:)
          Nevermind, I checked the Woothemes forum and the solution is to go to the Disqus admin in WordPress, click Advanced Settings in the upper right (On my widescreen I never even saw this option until it was pointed out) and check «Output JavaScript in footer».

          Voila.

  • Gooz

    Функции is_single, is_admin, is_home в functions.php всегда возвращают false! Для того, чтобы определить где пользователь находится нужно использовать хук:

    add_action('wp', 'имя_функции');

    Например, чтобы подключить скрипт только на страницах с одиночным постом нужен вот такой код в function.php

    function register_js() { if(is_single()) {wp_enqueue_script( 'my-script', get_bloginfo     ( 'template_directory' ).'/ajax.js'); } add_action('init', 'register_js');}

    Вот тут подробнее:
    http://codex.wordpress.org/Conditional_Tags/

    обратите внимание:

    Warning: You can only use conditional query tags after the init action hook in WordPress. For themes, this means the conditional tag will never work properly if you are using it in the body of functions.php, i.e. outside of a function.

    • Вы правы, фактически вообще нельзя использовать встроенные функции WP вне хуков. Если только вы не хотите полностью перехватить управление в момент загрузки functions.php.

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

      • Код должен быть примерно такой:

        add_action('wp_enqueue_scripts', 'add_js_function_name');
        function add_js_function_name() {
        wp_enqueue_script('script_id', get_template_directory_uri().'/main.js', ...);
        }

        • но в таком случае скрипт будет добавлен абсолютно на все страницы сайта, а нужно только в single. дело в том, что этот скрипт нужен для индексации страниц сервисом Relap, который поставляет мне виджет рекомендованных записей. но в рекомендованные попадают и home и archive и taxonomy

        • попробуйте перед вызовом

          wp_enqueue_script
          сделать проверку
          if (is_single()) { ….

        • спасибо, уже получилось. но все равно поменял Relap на Addthis, намного более продуманный сервис с точки зрения API

  • Привет! Признаюсь, для меня коды, как китайская грамота.

    Установил плагин All-in-One-Shortcodes на свой вордпресс. Штука весьма интересная, но при этом вылетел встроенный в шаблон слайдер контента. Частично проблема решилась удалением другого плагина (Commenluv), слайдер появился, но крутит без картинок, они как бы непрерывно загружаются.

    Почему я тут пишу? В описании плагина написано вставить хук wp_head(); в header.php между тегами неаd и wp_footer(); в footer.php

    Я посмотрел, такие функции там изначально имеются. Не подскажите, ка решить проблему?

    • В описании All-in-One-Shortcodes указано, что он поддерживает Nivo Slider. Может быть имеет смысл использовать его?

      А для того, чтобы определить причину конфликта нужно сравнить шорткоды, которые регистрирует шаблон и плагин. Если есть с одинаковыми названиями — это однозначно проблема. Чтобы найти шорткоды, ищите

      add_shortcode

      • Спасибо за ответ. Я не могу использовать Nivo, точнее могу, но где-нибудь в виджете, либо на странице, при этом мне надо будет прописывать адреса ссылок и пути к картинкам.
        Встроенный же слайдер вставлен в страницу журнального типа, она же главная. Да и зачем, когда встроенный слайдер делает все на автомате? Плюс имеется виджет, полностью дублирующий слайдер, все настройки прописываются в админке.
        Как бы мне нужен функционал плагина, уж очень там много наворотов, но без слайдера.
        А где искать шорткоды? Я пытался убирать из редактора плагина какие-то куски с упоминанием Nivo, но это ничего не дало.

        • Да, вот сейчас попробовал отключить встроенный слайдер, загрузил Nivo, а он-то как раз картинки не показывает, крутится колечко в центре и все.

          Можно ли в принципе убрать из плагина шорткод Nivo?

        • Владимир, я временно решил проблему, правда по-тупому, вот хочу посоветоваться:
          значит, в файле aio-shortcodes/style.css
          я удалил вот этот кусок:
          #slider-wrapper { background: url(images/slider.png) no-repeat; margin: 0 0 50px 0; }

          #slider { position: relative; background: url(images/nivo/loading.gif) no-repeat 50% 50%; }

          #slider img { position: absolute; top: 0px; left: 0px; display: none; }

          #slider a { border: 0; display: block; }

          Видимо, в шаблоне тоже есть операторы такие же.
          Теперь встроенный слайдер заработал, а слайдер от Nivo показывает первую картинку, не крутит…
          Что посоветуете? Может вот эти операторы переназвать как-нибудь? Но тогда где-то ещё надо менять

        • Если у вас встроенный слайдер работает, то Nivo вам не нужен? Правильно?

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

          Сначала поищите шорткоды. Для этого в любом текстовом редакторе, который поддерживает поиск по файлам, поищите строку «add_shortcode» (без кавычек). Эта функция подключает шорткод и в её втором параметре передаётся имя функции, которая формирует разметку. Т.е. чтобы отключить шорткод достаточно закомментировать строку в которой вызывается add_shortcode.

          Если можете, покажите ваш сайт, тогда я смогу firebug'ом посмотреть что происходит со слайдером.

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

        • ОК, тогда успехов 😉

      • А нет, извиняюсь, Nivo в виджет не вставить, только в запись или страницу, это я приукрасил.

  • Михаил

    А как подключить js/css в админку (пишу свой плагин)?

    • Принцип тот же.

      Я приведу пример из одного из моих плагинов.

      class TD_Admin_Tools {

      public function admin_menu() {
      $this->page = add_submenu_page( TD_TEXTDOMAIN, __( 'Tools', TD_TEXTDOMAIN)
      , __( 'Tools', TD_TEXTDOMAIN), 'manage_options', 'td-tools'
      , array( $this, 'tools_page' ));
      add_action( 'admin_print_styles-' . $this->page, array( $this, 'load_styles' ) );
      }

      /**
      * This method includes CSS file
      */
      public function load_styles() {
      wp_enqueue_style( 'td_css', TD_URL . '/css/td_styles.css' );
      }

      }

  • Евгений Антипов

    Спасибо за статью.
    Нашел тут сайт с русским сервером скриптов
    http://salat-production.ru/interactive-jquery-mootools-cdn.php

  • greench

    у меня партнёрка и там такой код

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

    • Нужна документация к коду. Вы привели тег script, который загружает основной JS код. Размещение баннеров, скорее всего, нужно указать отдельно.

  • неважно

    Сплошная вода

  • А как быть с скриптами в пару строчек, например для прокрутки страницы вверх, как правильно вставить?

    • Если это действительно единственный скрипт на странице, можете в шаблоне (обычно footer.php) добавить тег script перед закрывающим body.

  • Алексей Спесивцев

    Приветствую, коллеги! у меня вордпресс никак не желает принять &, который прописан в js-скрипте. Пробовал и как & и как & ругается так: Uncaught SyntaxError: Unexpected token &

    • Алексей Спесивцев

      здесь мнемоники «рубятся» & и &

      • Алексей Спесивцев

        никак… ну вы знаете как выглядят аналоги

    • А куда вы js-код вставляете? В шаблон или в текст поста?
      Попробуйте использовать функцию esc_js

  • Даниил

    Такая проблема я в

    functions.php добавил свой скрипт wp_enqueue_script( 'stry_nes-skip-link-focus-fix', get_template_directory_uri() . '/js/script.js', array(), '20151215', true ); а дальше что не пойму?

    Что нужно прописать в

    footer.php перед ?

    • Ничего не нужно прописывать. Главное, чтобы в footer.php был вызов

      wp_footer();

  • masha_18

    Добрый вечер!

    В файле темы functions.php было прописано require_once('lib/scripts.php'); // CSS and JS includes goes here

    Код

    был вставлен в файл lib/scripts.php

    Далее в файл header.php темы было вставлено:

    var map;

    function initialize() {
    //создаем объект для работы с картой
    map = new GMap2(document.getElementById(«map_canvas»));
    if (GBrowserIsCompatible()) {
    //устанавливаем координаты и начальное приближение
    map.setCenter(new GLatLng(50.453629, 30.502838), 13);
    //добавляем шкалу зума
    map.addControl(new GLargeMapControl());
    //добавляем переключатель типа карт (Карта, Спутник, Гибрид)
    map.addControl(new GMapTypeControl());
    //указываем тип карты по-умолчанию (Спутник)
    map.setMapType(G_SATELLITE_MAP);
    }
    }

    (вместо ваш ключ был добавен ключ)
    На сайте стала отображаться лишь пустая область, без карты. Подскажите, пожалуйста, что не так?


    • должен быть после открвающего тега

      В вашем случае, скорее всего, код нужно вставить в какой-то из файлов вроде index.php, page.php, single.php (зависит от того как сделана тема WP и на какой странице вы хотите показывать карту).

      • masha_18

        Спасибо за ответ. В выбранной теме нет вообще тега в перечисленных файлах (т.к почти во всех файлах этой темы вызываются функции php). Тема Jolene. Подскажите, куда там можно еще вставить вызов карты?

        • В файлы index.php, archive.php, category.php (после 10-ой строки), в файл single.php, в файлы content-….php.