Как эхо JS сразу после установленного сценария, чтобы перевести его в режим noConflict?

Я хочу включить и использовать сторонний файл JavaScript ( Bootstrap Tooltip ) в моем плагине. Поскольку Bootstrap – очень популярная структура, а tooltip() – довольно общее имя, я хочу использовать включенную noConflict() чтобы изолировать экземпляр всплывающей подсказки в моей переменной.

Если я правильно понимаю сроки, это нужно сделать сразу после загрузки файла сценария, так что ничто другое не имеет возможности испортить экземпляр (он только что настроил) или перепутаться с ним.

Однако, похоже, нет никакого соглашения в функциональности очереди, чтобы эхо JS в такой момент. $wp_scripts->print_extra_script() вызывается перед скриптом.

Можно ли это выполнить с текущей реализацией очереди?

Solutions Collecting From Web of "Как эхо JS сразу после установленного сценария, чтобы перевести его в режим noConflict?"

Вы должны фильтровать script_loader_src , проверить, есть ли у вас правильный скрипт и добавить одноразовый фильтр для clean_url . Затем добавьте дополнительный скрипт и убедитесь, что вывод синтаксически действителен.

Довольно просто, хотя и довольно хаки.

 class Extra_Script { private $extra = []; private $handle; private $url; private $versioned_url; public function __construct( $handle, $url ) { $this->handle = $handle; $this->url = $url; add_filter( 'script_loader_src', array( $this, 'filter_script_src' ), 10, 2 ); } public function add_script( $script ) { $this->extra[] = $script; } public function filter_script_src( $src, $handle ) { if ( empty ( $this->extra ) ) return $src; if ( $this->handle !== $handle ) return $src; if ( 0 !== strpos( $src, $this->url ) ) return $src; $this->versioned_url = $src; add_filter( 'clean_url', array( $this, 'filter_esc_url' ) ); remove_filter( current_filter(), array( $this, __FUNCTION__ ) ); return $src; } public function filter_esc_url( $url ) { if ( $url !== $this->versioned_url ) return $url; remove_filter( current_filter(), array( $this, __FUNCTION__ ) ); $scripts = join( "\n", $this->extra ); return "$url'></script><script>$scripts</script><script class='"; } } 

Применение

 add_action( 'wp_enqueue_scripts', function() { $handle = 'foo'; $url = plugins_url( '/foo.js', __FILE__ ); wp_enqueue_script( $handle, $url ); $extra = new Extra_Script( $handle, $url ); $extra->add_script( "alert('bar!');" ); }); 

Это добавит встроенный скрипт сразу после вашего установленного сценария.

Альтернативой может быть Пэчворк . Вы можете переопределить код WordPress во время выполнения с этим. Но это было бы не менее хаки.

WordPress> = 4.1

В WordPress 4.1 был добавлен фильтр script_loader_tag для полного HTML-скрипта. Идеально подходит для добавления чего-то сразу после него.


WordPress <4.1

Я попал в wp_print_footer_scripts в приоритет 11 (после завершения очереди) и wp_print_scripts() явно на дескрипторе скрипта, а затем повторил то, что мне нужно.

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

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

Я написал собственный класс, расширяющий WP_Script , примерно так:

 class GM_Scripts extends WP_Scripts { static function buildFromWp( WP_Scripts $scripts ) { $class = get_called_class(); $obj = new $class; foreach ( get_object_vars( $scripts ) as $n => $v ) { $obj->$n = $v; } return $obj; } public function do_item( $handle, $group = false ) { $done = parent::do_item( $handle, $group ); do_action( 'after_script_done', $handle, $done ); } } 

Этот класс наследует все методы из родительского WP-класса, кроме одного, do_item который используется для эффективной печати сценария при разметке.

GM_Scripts::do_item() вызывает тот же метод в WP_Script и сразу же после пожара настраивает действие 'after_script_done' передавая в качестве аргументов дескриптор скрипта и логическое значение, которое истинно, если сценарий эффективно печатается на странице.

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

 add_action( 'wp_print_scripts', function() { if ( is_admin() || did_action('login_head') || ! isset($GLOBALS['wp_scripts']) ) { return; } $GLOBALS[ 'wp_scripts' ] = GM_Scripts::buildFromWp( $GLOBALS[ 'wp_scripts' ] ); }, 0 ); 

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

Кроме того, это происходит только на фронте, чтобы еще больше уменьшить вероятность конфликтов.

Наконец, я добавил действие, которое отразит то, что мне нужно:

 add_action( 'after_script_done', function( $handle, $done ) { if ( $handle === 'myscript' && $done ) { // echo what needed } }, 0, 2 ); 

и ставил мой сценарий как обычно:

 add_action( 'wp_enqueue_script', function() { wp_enqueue_script( 'myscript', $script_url ); } ); 

В чем преимущество такого подхода против принятого?

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

В качестве примера можно использовать еще один фрагмент кода

 add_action( 'wp_enqueue_script', function() { wp_enqueue_script( 'another-script', $another_url, array( 'myscript' ) ); } ); 

Используя принятый подход, в этом случае

  • если мой скрипт уже зарегистрирован до 'wp_head' он будет вставлен на страницу без конфликта или что-то еще, что я хочу напечатать после него

  • если он не зарегистрирован, 'another-script' не будет вставлен, потому что WordPress не сможет решить зависимость