Условная загрузка JavaScript и CSS для шорткодов в WordPress

23 июн. 2011 г., 18:07:29
Просмотры: 17.8K
Голосов: 41

Я выпустил плагин, который создает шорткод и требует загрузки JavaScript и CSS файлов на страницах, содержащих этот шорткод. Я мог бы просто загружать скрипты и стили на всех страницах, но это не лучшая практика. Мне нужно загружать файлы только на страницах, где вызывается шорткод. Я нашел два метода, но у обоих есть проблемы.

Метод 1 устанавливает флаг в true внутри функции обработки шорткода, а затем проверяет это значение внутри коллбэка wp_footer. Если флаг true, он использует wp_print_scripts() для загрузки JavaScript. Проблема в том, что это работает только для JavaScript, но не для CSS, так как CSS должен объявляться внутри <head>, что можно сделать только на ранних хуках типа init или wp_head.

Метод 2 срабатывает раньше и "заглядывает вперед", чтобы проверить, есть ли шорткод в контенте текущей страницы. Этот метод мне нравится больше, но проблема в том, что он не обнаруживает случаи, когда шаблон вызывает do_shortcode().

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

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

Обновление 2: Начиная с WordPress 3.3, можно вызывать wp_enqueue_script() прямо внутри коллбэка шорткода, и JavaScript файл будет загружен в футере документа. Технически это возможно и для CSS файлов, но это плохая практика, так как вывод CSS вне тега <head> нарушает спецификации W3C, может вызвать FOUC и заставить браузер перерисовывать страницу.

10
Комментарии

В прошлом я использовал вариацию Метода 1. Загружал JS для шорткода в подвале, а CSS для шорткода встроенным. Это работает, но выглядит костыльно. Жду более элегантного решения.

EAMann EAMann
23 июн. 2011 г. 18:14:52

Основные проблемы встроенного CSS в том, что его сложно переопределить другими стилями, и он не использует метод wp_enqueue_styles().

Ian Dunn Ian Dunn
23 июн. 2011 г. 19:05:16

Сколько у тебя CSS?

mfields mfields
23 июн. 2011 г. 19:35:32

Сколько строк JavaScript?

mfields mfields
23 июн. 2011 г. 19:36:42

Это примерно 30 строк CSS и 100 строк JavaScript, но это не имеет значения. Их нужно подключать ПРАВИЛЬНО, независимо от размера. Смотрите комментарии к ответам, чтобы понять почему.

Ian Dunn Ian Dunn
23 июн. 2011 г. 19:45:43

JavaScript - это самая простая часть. Лучший способ сделать это описан в разделе "Jedi" здесь: http://scribu.net/wordpress/optimal-script-loading.html

mfields mfields
23 июн. 2011 г. 19:55:27

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

mfields mfields
23 июн. 2011 г. 19:59:12

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

Ian Dunn Ian Dunn
23 июн. 2011 г. 21:02:10

Тогда вы уже знаете ЛУЧШИЙ способ обработки javascript ;) ЛУЧШИЙ способ, по моему мнению, для работы с CSS — это "30 строк — это не так уж много, я бы минифицировал их и вывел в head в теге style во всех представлениях. Предусмотреть фильтр и/или настройку, позволяющую пользователю отключить стили при необходимости." Если вам нужно использовать wp_enqueue_script() — пожалуйста, я не считаю это необходимым, так как это добавляет еще один HTTP-запрос. Минификация -> вывод в wp_head() -> разрешение другим расширениям фильтровать вывод.

mfields mfields
23 июн. 2011 г. 21:14:52

Я считаю, что разделение на отдельные файлы делает код чище и лучше организован. Минификацию можно выполнять на сервере во время выполнения.

Ian Dunn Ian Dunn
23 июн. 2011 г. 21:40:56
Показать остальные 5 комментариев
Все ответы на вопрос 7
9
11

Основываясь на собственном опыте, я использовал комбинацию методов 1 и 2 - архитектуру и скрипты в подвале из первого метода и технику "опережающего просмотра" из второго.

Что касается "опережающего просмотра", я использую регулярные выражения вместо stripos; личное предпочтение, быстрее и позволяет проверять на "некорректные" шорткоды:

preg_match( '#\[ *shortcode([^\]])*\]#i', $content );

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

ОБНОВЛЕНИЕ: Для ленивых авторов, которые никогда не читают документацию, можно вывести сообщение, чтобы подчеркнуть ошибку их подхода ;)

function my_shortcode()
{
    static $enqueued;
    if ( ! isset( $enqueued ) )
        $enqueued = wp_style_is( 'my_style', 'done' ); // кэшируем, чтобы не повторять при многократном вызове

    // выполняем шорткод
    $output = '';

    if ( ! $enqueued )
        // можно вывести сообщение только при первом появлении, обернув его в предыдущее условие
        $output .= <<<HTML
<p>Внимание! Вы должны самостоятельно добавить таблицу стилей шорткода, если вызываете <code>do_shortcode()</code> напрямую!</p>
<p>Используйте <code>wp_enqueue_style( 'my_style' );</code> перед вызовом <code>get_header()</code> в вашем шаблоне.</p>
HTML;

    return $output;
}
23 июн. 2011 г. 21:23:00
Комментарии

Хорошее замечание. В идеале мне хотелось бы, чтобы это работало без необходимости дополнительных действий с их стороны — потому что в половине случаев они, скорее всего, не прочитают FAQ заранее и просто решат, что что-то сломалось. Но, возможно, мне придется пойти этим путем. Я могу регистрировать скрипты на каждой странице, но подключать их только при обнаружении шорткода. Тогда пользователи смогут подключиться к хуку init и вызывать функции enqueue в конкретных шаблонах, где это необходимо, если к тому моменту выполнение еще не зашло слишком далеко. Кроме того, в WP уже есть встроенная функция get_shortcode_regex().

Ian Dunn Ian Dunn
23 июн. 2011 г. 21:54:54

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

Chip Bennett Chip Bennett
23 июн. 2011 г. 22:16:03

Верно, но regex будет получен для всех шорткодов, а не только для вашего ;) "Я могу регистрировать скрипты на каждой странице" — вероятно, это тоже более правильный метод! Заметьте, им не обязательно подключаться к хуку init, достаточно сделать это до wp_head. Для ленивых разработчиков: проверьте wp_style_is( 'my_style_handle', 'done' ) внутри вашего шорткода. Если вернется false, выведите видимую ошибку с инструкциями, что делать.

TheDeadMedic TheDeadMedic
23 июн. 2011 г. 22:17:52

@Chip - Я не беспокоюсь, что они не способны следовать инструкциям, просто они могут не знать, что должны это делать, поскольку в 99% случаев не требуется делать ничего дополнительного.

Ian Dunn Ian Dunn
24 июн. 2011 г. 01:05:05

@Ian - Я думал, что добавление do_shortcode() в шаблон уже является "деланием чего-то дополнительного" — и пользователи, которые сделают это что-то дополнительное, либо уже будут знать о необходимости подключить стили, либо будут более готовы/склонны следовать особым инструкциям.

Chip Bennett Chip Bennett
24 июн. 2011 г. 02:03:16

@TheDeadMedic - Я интегрировал это со своим кодом и обновил вопрос ссылками на него, на случай если кто-то захочет увидеть реализацию. Ещё раз спасибо за помощь :)

Ian Dunn Ian Dunn
26 июн. 2011 г. 08:27:34

@Ian Отлично! Спасибо, что вернулись с обновлением, как для нас, так и для гуглеров, которые наткнутся на это позже ;)

TheDeadMedic TheDeadMedic
26 июн. 2011 г. 08:41:34

Хорошо, но я должен не согласиться, что preg_match быстрее, чем strpos http://lzone.de/articles/php-string-search.htm

Bainternet Bainternet
5 февр. 2012 г. 19:57:30

@Bainternet Не обязательно - preg_match против stripos (без учета регистра) - в любом случае, мы говорим о незначительных временных затратах. Оглядываясь назад, думаю, мне следовало избегать термина "быстрее" - на самом деле я хотел сказать, что это более эффективно для данной задачи (в отличие от множественных вызовов stripos для обработки различных форматов шорткодов).

TheDeadMedic TheDeadMedic
9 февр. 2012 г. 20:35:16
Показать остальные 4 комментариев
6

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

Один из подходов, который стоит рассмотреть, — это проверка при первой загрузке страницы, используется ли шорткод, а затем сохранение статуса использования шорткода в мета-ключе записи. Вот как это можно сделать:

Пошаговое руководство

  1. Установите флаг $shortcode_used в значение 'no'.
  2. В самой функции шорткода установите флаг $shortcode_used в значение 'yes'.
  3. Установите хук для 'the_content' с приоритетом 12 (после того, как WordPress обработает шорткоды) и проверьте метаданные записи на наличие пустого значения '' с ключом "_has_{$shortcode_name}_shortcode". (Значение '' возвращается, если мета-ключ не существует для ID записи.)
  4. Используйте хук 'save_post' для удаления метаданных записи, сбрасывая флаг на случай, если пользователь изменит использование шорткода.
  5. Также в хуке 'save_post' используйте wp_remote_request() для отправки неблокирующего HTTP GET запроса на постоянную ссылку записи, чтобы активировать первую загрузку страницы и установку флага.
  6. Наконец, установите хук 'wp_print_styles' и проверьте метаданные записи на значения 'yes', 'no' или '' с ключом "_has_{$shortcode_name}_shortcode". Если значение 'no' — не загружайте внешние ресурсы. Если значение 'yes' или '' — загружайте их.

И это должно сработать. Я написал и протестировал пример плагина, чтобы показать, как это работает.

Пример кода плагина

Плагин активируется при использовании шорткода [trigger-css], который устанавливает стиль элементов <h2> на странице как белый текст на красном фоне, чтобы было легко увидеть его работу. Он предполагает наличие подкаталога css с файлом style.css, содержащим следующий CSS:

/*
 * Filename: css/style.css
 */
h2 {
  color: white;
  background: red;
}

А ниже приведен код работающего плагина:

<?php
/**
 * Plugin Name: CSS on Shortcode
 * Description: Shows how to conditionally load a shortcode
 * Author: Mike Schinkel <mike@newclarity.net>
 */
class CSS_On_Shortcode {

  /**
   * @var CSS_On_Shortcode
   */
  private static $_this;

  /**
   * @var string 'yes'/'no' vs. true/false as get_post_meta() returns '' for false and not found.
   */
  var $shortcode_used = 'no';

  /**
   * @var string
   */
  var $HAS_SHORTCODE_KEY = '_has_trigger-css_shortcode';
  /**
   *
   */
  function __construct() {
    self::$_this = $this;
    add_shortcode( 'trigger-css', array( $this, 'do_shortcode' ) );
    add_filter( 'the_content', array( $this, 'the_content' ), 12 ); // AFTER WordPress' do_shortcode()
    add_action( 'save_post', array( $this, 'save_post' ) );
    add_action( 'wp_print_styles', array( $this, 'wp_print_styles' ) );
  }

  /**
   * @return CSS_On_Shortcode
   */
  function this() {
    return self::$_this;
  }

  /**
   * @param array $arguments
   * @param string $content
   * @return string
   */
  function do_shortcode( $arguments, $content ) {
    /**
     * If this shortcode is being used, capture the value so we can save to post_meta in the 'the_content' filter.
     */
    $this->shortcode_used = 'yes';
    return '<h2>THIS POST WILL ADD CSS TO MAKE H2 TAGS WHITE ON RED</h2>';
  }

  /**
   * Delete the 'has_shortcode' meta value so that it can be regenerated
   * on first page load in case shortcode use has changed.
   *
   * @param int $post_id
   */
  function save_post( $post_id ) {
    delete_post_meta( $post_id, $this->HAS_SHORTCODE_KEY );
    /**
     * Now load the post asynchronously via HTTP to pre-set the meta value for $this->HAS_SHORTCODE_KEY.
     */
    wp_remote_request( get_permalink( $post_id ), array( 'blocking' => false ) );
  }

  /**
   * @param array $args
   *
   * @return array
   */
  function wp_print_styles( $args ) {
    global $post;
    if ( 'no' != get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * Only bypass if set to 'no' as '' is unknown.
       */
      wp_enqueue_style( 'css-on-shortcode', plugins_url( 'css/style.css', __FILE__ ) );
    }
   }

  /**
   * @param string $content
   * @return string
   */
  function the_content( $content ) {
    global $post;
    if ( '' === get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * This is the first time the shortcode has ever been seen for this post.
       * Save a post_meta key so that next time we'll know this post uses this shortcode
       */
      update_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, $this->shortcode_used );
    }
    /**
     * Remove this filter now. We don't need it for this post again.
     */
    remove_filter( 'the_content', array( $this, 'the_content' ), 12 );
    return $content;
  }

}
new CSS_On_Shortcode();

Примеры скриншотов

Вот серия скриншотов:

Базовый редактор записи, без контента

Базовый редактор записи без контента

Отображение записи без контента

Отображение записи без контента

Базовый редактор записи с шорткодом [trigger-css]

Редактор записи с шорткодом trigger-css

Отображение записи с шорткодом [trigger-css]

Отображение записи с шорткодом trigger-css

Не уверен на 100%

Я считаю, что вышеописанное должно работать практически во всех случаях, но так как я только что написал этот код, я не могу быть уверен на 100%. Если вы найдете ситуации, когда он не работает, я был бы рад узнать об этом, чтобы исправить код в плагинах, куда я это добавил. Заранее спасибо.

2 янв. 2013 г. 08:57:23
Комментарии

Значит, пять плагинов, использующих ваш подход, будут вызывать пять удалённых запросов каждый раз при сохранении записи? Я бы предпочёл использовать регулярное выражение для post_content. А как насчёт шорткодов в виджетах?

fuxia fuxia
2 янв. 2013 г. 09:02:29

@toscho На самом деле загрузка поста по триггеру опциональна; она нужна только для того, чтобы пользователь не увидел первый загруженный страницу с внешними ресурсами. Кроме того, это неблокирующий вызов, так что теоретически вы его не заметите. В нашем коде мы делаем это в базовом классе, чтобы он мог обрабатывать вызов только один раз. Мы могли бы использовать хук 'pre_http_request' и отключить множественные вызовы к одному и тому же URL, пока активен хук 'save_post', но я бы хотел подождать, пока действительно увижу в этом необходимость, согласны? Что касается виджетов, это можно доработать, но я пока не рассматривал этот кейс.

MikeSchinkel MikeSchinkel
2 янв. 2013 г. 09:59:16

@toscho - Кроме того, вы не можете быть уверены, что шорткод останется, так как другой хук может его очистить. Единственный способ убедиться — это если функция шорткода действительно сработает. Так что подход с регулярными выражениями не на 100% надёжен.

MikeSchinkel MikeSchinkel
2 янв. 2013 г. 10:03:28

Я знаю. Не существует абсолютно надежного способа вставки CSS для шорткодов (кроме использования <style>).

fuxia fuxia
2 янв. 2013 г. 10:05:39

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

mor7ifer mor7ifer
2 авг. 2015 г. 17:45:38

Мое решение проблемы с предпросмотром: https://gist.github.com/mor7ifer/e50a9864a372a05b4a3b

mor7ifer mor7ifer
2 авг. 2015 г. 18:42:24
Показать остальные 1 комментариев
11

Поиск в Google подсказал мне потенциальный ответ. Я говорю "потенциальный", потому что он выглядит рабочим, но я не на 100% уверен, что это лучший способ:

add_action( 'wp_print_styles', 'yourplugin_include_css' );
function yourplugin_include_css() {
    // Проверяем, есть ли шорткод в контенте страницы или записи
    global $post;

    // Убрал закрывающую скобку ' ] '... чтобы можно было передавать аргументы.
    if ( strstr( $post->post_content, '[yourshortcode ' ) ) {
        echo $csslink;
    }
}

Этот код должен проверять, использует ли текущая запись шорткод, и соответственно добавлять таблицу стилей в элемент <head>. Но я не думаю, что он будет работать на страницах архива (где выводится несколько записей в цикле)... Также этот код из двухлетней записи в блоге, так что я не уверен, будет ли он работать с WP 3.1.X.

23 июн. 2011 г. 18:34:45
Комментарии

Это не будет работать, если шорткод имеет аргументы. Если вы действительно хотите пойти этим путем, что медленно, используйте функцию WordPress get_shortcode_regex() для поиска.

onetrickpony onetrickpony
23 июн. 2011 г. 18:39:14

Как я и сказал, это "потенциальный" ответ, который я еще не тестировал ... :-)

EAMann EAMann
23 июн. 2011 г. 18:39:56

Это, по сути, то же самое, что и метод 2, но он все равно не проверяет шаблон на вызовы do_shortcode().

Ian Dunn Ian Dunn
23 июн. 2011 г. 18:45:17

Зачем это нужно? Если вы вручную вызываете do_shortcode() в шаблоне, вы уже знаете, что будете выполнять шорткод

onetrickpony onetrickpony
23 июн. 2011 г. 18:50:08

Я не тот, кто вызывает шорткод, это делает пользователь. Это плагин для распространения, а не приватный.

Ian Dunn Ian Dunn
23 июн. 2011 г. 19:06:51

Хорошо, поэтому вам нужна валидная разметка :) Вы говорите, что ваш плагин инструктирует пользователя редактировать файлы шаблонов и вызывать эту функцию? Тогда, если вы не создадите собственный PHP-парсер, нет способа узнать, где и когда вызывается эта функция...

onetrickpony onetrickpony
23 июн. 2011 г. 19:12:24

Мне всегда нужна валидная разметка, независимо от обстоятельств... Плагин не говорит пользователю вызывать функцию, но это всегда вариант. Пользователь всегда может вызвать любой шорткод, либо введя его в область содержимого записи/страницы, либо просто вызвав do_shortcode() в шаблоне, поэтому обе ситуации должны обрабатываться. И я не думаю, что мне нужно писать собственный PHP-парсер, мне просто нужно разобрать файл шаблона, назначенный текущей странице (если он есть), чтобы проверить, содержится ли в нем шорткод.

Ian Dunn Ian Dunn
23 июн. 2011 г. 19:38:02

Предполагая, что ты сможешь узнать, какой файл шаблона используется текущей страницей (в чем я сомневаюсь), как ты собираешься его разбирать без парсера? Регулярные выражения? А если строка с кодом закомментирована? Существуют десятки способов комментирования PHP-кода

onetrickpony onetrickpony
23 июн. 2011 г. 19:59:30

Назначенный шаблон просто хранится в таблице post_meta, что сложного в его определении? Можно подключиться к хуку the_posts, чтобы получить доступ к текущему $post до вывода чего-либо. Под "PHP-парсером" я предполагал весь движок, а не просто функцию strpos или регулярное выражение. Закомментированные строки — это крайний случай, о котором я особо не беспокоюсь.

Ian Dunn Ian Dunn
23 июн. 2011 г. 21:06:22

вы путаете шаблоны страниц (как в случае с типом записи page) с файлами темы, используемыми в качестве шаблонов

onetrickpony onetrickpony
23 июн. 2011 г. 21:20:18

А, вы говорите о стандартных шаблонах (например, single.php, home.php) в отличие от кастомного шаблона, созданного специально для страницы (например, map.php), верно? Это хорошее замечание. Держу пари, что есть способ определить, какой именно используется, но я не помню его сходу.

Ian Dunn Ian Dunn
23 июн. 2011 г. 21:44:48
Показать остальные 6 комментариев
0

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


function add_shortcode_scripts() {
    global $wp_query;   
    $posts = $wp_query->posts;
    $scripts = array(
        array(
            'handle' => 'map',
            'src' => 'http://maps.googleapis.com/maps/api/js?sensor=false',
            'deps' => '',
            'ver' => '3.0',
            'footer' => false
        ),
        array(
            'handle' => 'contact-form',
            'src' => get_template_directory_uri() . '/library/js/jquery.validate.min.js',
            'deps' => array( 'jquery' ),
            'ver' => '1.11.1',
            'footer' => true
        )   
    );

    foreach ( $posts as $post ) {
        foreach ( $scripts as $script ) {
            if ( preg_match( '#\[ *' . $script['handle'] . '([^\]])*\]#i', $post->post_content ) ) {
                // подключаем css и/или js
                if ( wp_script_is( $script['handle'], 'registered' ) ) {
                    return;
                } else {
                    wp_register_script( $script['handle'], $script['src'], $script['deps'], $script['ver'], $script['footer'] );
                    wp_enqueue_script( $script['handle'] );
                }
            }
        }
    }
}
add_action( 'wp', 'add_shortcode_scripts' );
30 нояб. 2013 г. 21:52:06
1

Наконец я нашел решение для условной загрузки CSS, которое работает для моего плагина www.mapsmarker.com, и хочу поделиться им с вами. Оно проверяет, используется ли мой шорткод в текущем файле шаблона и в header.php/footer.php, и если да, подключает необходимую таблицу стилей в заголовке:

  function prefix_template_check_shortcode( $template ) {
    $searchterm = '[mapsmarker';
    $files = array( $template, get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'header.php', get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'footer.php' );
    foreach( $files as $file ) {
        if( file_exists($file) ) {
            $contents = file_get_contents($file);
            if( strpos( $contents, $searchterm )  ) {
                wp_enqueue_style('
leafletmapsmarker', LEAFLET_PLUGIN_URL . 'leaflet-dist/leaflet.css');
                  break; 
            }
        }
    }
  return $template;
  }  
  add_action('template_include','prefix_template_check_shortcode' );
12 дек. 2012 г. 23:29:42
Комментарии

Небольшое отступление, но разве это не предполагает, что люди используют header.php и footer.php? А как насчёт методов обёртывания тем, таких как описанные в http://scribu.net/wordpress/theme-wrappers.html? Или тем вроде Roots, где шаблонные части хранятся в других местах?

orionrush orionrush
3 мар. 2013 г. 14:32:51
0

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

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // определяем, содержит ли страница шорткод "my_shortcode"
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );
6 нояб. 2015 г. 02:24:01
14

потому что CSS должен объявляться внутри <head>

Для CSS файлов вы можете загружать их прямо в выводе шорткода:

<style type="text/css">
  @import "путь/к/вашему.css"; 
</style>

Установите константу или что-то подобное после этого, например MY_CSS_LOADED (включать CSS только если константа не установлена).

Оба ваших метода медленнее, чем этот подход.

Для JS файлов вы можете сделать то же самое, если загружаемый скрипт уникален и не имеет внешних зависимостей. Если это не так, загружайте его в подвале (футере), но используйте константу для определения необходимости загрузки...

23 июн. 2011 г. 18:22:16
Комментарии

Загрузка CSS вне элемента <head> не является правильной разметкой. Действительно, валидация — это всего лишь рекомендация, но если мы пытаемся следовать этим рекомендациям, то загрузка таблицы стилей внутри вывода шорткода — плохая идея.

EAMann EAMann
23 июн. 2011 г. 18:29:09

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

onetrickpony onetrickpony
23 июн. 2011 г. 18:32:37

Согласно инструменту валидации W3C: <style type="text/css"> Указанный выше элемент был найден в контексте, где он не разрешён. Это может означать, что вы неправильно вложили элементы — например, элемент "style" в разделе "body" вместо "head". Таким образом, встроенные стили (<element style="..."></element>) являются валидными, но встроенные элементы <style> — нет.

EAMann EAMann
23 июн. 2011 г. 18:36:59

Да, я знаю, что такой вариант возможен, но это считается плохой практикой. Это может вызвать FOUC (мигание нестилизованного контента), заставить браузер перерисовывать страницу и не пройти валидацию W3C. Также это не будет работать с wp_enqueue_style(), что лишит других разработчиков тем/плагинов возможности легко подменить свои собственные скрипты/стили.

Ian Dunn Ian Dunn
23 июн. 2011 г. 18:41:04

@EAMann. Верно, моя ошибка, я думал что это пройдет валидацию. Хотя, впрочем, валидация W3C ничего не значит...

onetrickpony onetrickpony
23 июн. 2011 г. 18:43:17

@One Trick Pony Эм-м... Для меня это кое-что значит. И для всех остальных разработчиков, которых я уважаю, тоже. Я не следую этому слепо, но редко когда считаю приемлемым решение, которое нарушает стандарты.

Ian Dunn Ian Dunn
23 июн. 2011 г. 18:49:06

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

onetrickpony onetrickpony
23 июн. 2011 г. 18:51:00

Я привел 4 причины в своем комментарии выше...

Ian Dunn Ian Dunn
23 июн. 2011 г. 19:11:02

Это считается плохой практикой, но именно так работает шорткод галереи в ядре WordPress: выводит CSS блок прямо в коде. Это немного лучше, чем использование атрибута style, и работает. Мой плагин со шорткодом просто выводит CSS в head на каждой странице. Его не так много :)

mfields mfields
23 июн. 2011 г. 19:42:13

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

Ian Dunn Ian Dunn
23 июн. 2011 г. 19:47:29

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

mfields mfields
23 июн. 2011 г. 19:51:50

Ты не привёл никаких объективных причин против такой практики. В любом случае это не важно; я вижу только два варианта: всегда загружать CSS/скрипты (оптимизировав их по размеру) или условные инлайн-стили.

onetrickpony onetrickpony
23 июн. 2011 г. 20:01:08

@mfields, это хорошее замечание, но я предпочитаю подход с enqueue_style.

Ian Dunn Ian Dunn
23 июн. 2011 г. 21:09:49

@One Trick Pony, я думаю, ты ошибаешься, но мне надоело спорить об этом.

Ian Dunn Ian Dunn
23 июн. 2011 г. 21:10:02
Показать остальные 9 комментариев