Добавление onload к тегу body
Сейчас я разрабатываю плагин, который будет встраивать тур по Google Earth в запись или страницу WordPress через шорткод.
Проблема, с которой я столкнулся, заключается в том, что для загрузки тура необходимо добавить атрибут onload="init()" в тег <body>.
Я могу изменить конкретный файл шаблона, но поскольку это для релиза, мне нужно добавить его динамически через хук. Есть идеи?
А вот решение на jQuery (как предложил Майк в своем первом комментарии).
function add_my_scripts() {
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'my_init_script', SCRIPTSRC, 'jquery', '1.0' );
}
add_action( 'init', 'add_my_scripts' );
Затем добавьте скрипт в ваш плагин, который делает следующее:
jQuery.noConflict();
jQuery(document).ready(function($) {
init();
});
Это запустит jQuery в режиме без конфликтов (если он еще не в этом режиме) и добавит вызов метода init(), когда документ будет готов. Это более безопасный метод, чем использование body onready(), потому что функция onready() может вызывать только одну вещь... так что никто другой не сможет подключить что-либо к этому или добавить собственный скрипт. Лучше сделать ваш плагин как можно менее навязчивым, чтобы другие плагины не мешали ему или наоборот.
Я считаю, что ваш метод один из предпочтительных. Думаю, jQuery-код можно даже сократить, потому что jQuery предлагает сокращение для функции ready.
hakre
@EAMann - Не могли бы вы подробнее объяснить jQuery.noConflict()? Я никогда не использовал эту функцию, и документация мне не совсем понятна.
MikeSchinkel
По умолчанию jQuery использует символ $ как синоним для jQuery... это может нарушить работу других библиотек (Prototype, Scriptaculous и т.д.), а также пользовательских функций $. Использование jQuery.noConflict() отключает это поведение по умолчанию, но вы по-прежнему можете использовать функцию $ в своём коде, если передадите её... так что функция, которую я определил выше, может использовать $.ajax и другие нативные вызовы внутри объявленной функции.
EAMann
@MikeSchinkel: http://hakre.wordpress.com/2010/08/11/selekturz-they-iz-serius-bizniss/
hakre
@EAMann - Спасибо. Я знал про использование внутри функции ready(), но не осознавал, что будет конфликт, если просто никогда не использовать $ за пределами замыкания. Я до сих пор не понимаю, что это делает. Возможно, мне стоит просто поизучать этот вопрос подробнее...
MikeSchinkel
@MikeSchinkel - По умолчанию jQuery устанавливает глобальный $ как псевдоним объекта jQuery. Вызов jQuery в режиме noConflict() переопределяет это поведение по умолчанию.
EAMann
Вот один из подходов. Вы должны добавить вызов add_action() внутри вашего хука, как я полагаю. Предполагается, что функция init уже определена в приведённом JavaScript коде. Если это не так, то данный код не сработает, но подключение скрипта, кажется, это проблема, которую вы уже решили, если я правильно вас понял. Обратите внимание, что вам не обязательно добавлять его в wp_foot, вы так же легко можете добавить его в wp_head:
<?php
function mypluginprefix_onload_init() { ?>
<script language="text/javascript">
// проверяем стандартный способ добавления событий onload
if ( typeof(window.addEventListener) !== 'undefined' )
window.addEventListener( "load", init, false );
// или старый нестандартный способ для msie
else if ( typeof(window.attachEvent) !== 'undefined' ) {
window.attachEvent( "onload", init );
}
</script>
<?php }
// это помещается в ваш хук
add_action('wp_foot', 'mypluginprefix_onload_event');
?>
Почему чистый JavaScript, а не jQuery? jQuery обрабатывает все крайние случаи, когда код может выполниться до полной загрузки страницы.
MikeSchinkel
Для простого события onload, я считаю jQuery избыточным. Просто прикрепите обработчик и всё. jQuery создает дополнительную нагрузку в плане загрузки. Я люблю jQuery, но это не решение для всего. Если бы jQuery уже был подключен, тогда я бы сказал использовать его, но мой ответ обходится без него.
artlung
Игнорируя возможность сделать это с помощью jQuery, одним из вариантов является использование хука template_include вместе с ob_start() и callback-функцией. Ваша callback-функция может выполнить поиск строки '<body' и заменить её на '<body onload="init()"', как показано в следующем коде. Вы можете использовать его напрямую в своем плагине, просто убедитесь, что изменили названия в соответствии с вашими соглашениями об именовании:
<?php
add_filter('template_include','start_buffer_capture',1);
function start_buffer_capture($template) {
ob_start('end_buffer_capture'); // Запускаем буферизацию вывода
return $template;
}
function end_buffer_capture($buffer) {
return str_replace('<body','<body onload="init()"',$buffer);
}
Обратите внимание, что я бы не считал приведенный выше код полностью надежным. Сомневаюсь, что он обработает все крайние случаи, так как я просто быстро его написал для ответа на ваш вопрос. Тем не менее, он показывает, как решить задачу в стандартном случае, и после тестирования вы сможете доработать его для обработки важных крайних случаев (например, что делать, если '<BODY' написан в верхнем регистре и т.д.).
Вот JavaScript для динамического добавления callback при загрузке страницы, с jQuery или без него:
function add_onload() {
?>
<script type="text/javascript">
my_onload_callback = function() { alert('Привет!'); }; // тестовая функция
if( typeof jQuery == "function" ) {
jQuery(my_onload_callback); // document.ready
} else {
document.getElementsByTagName('body')[0].onload = my_onload_callback; // body.onload
}
</script>
<?php
}
add_action( 'wp_footer', 'add_onload' );
В вашем случае вам нужно просто заменить my_onload_callback на ваш метод инициализации.
Покопался ещё немного и нашёл «лучший» способ заставить это работать (Google усложняет встраивание своих туров по Земле, и их гаджет не работает).
В итоге я создал плагин, который использует комбинацию шорткода и произвольного поля.
Если у вас есть возможность, я бы рекомендовал опубликовать код для пользы других пользователей, которые найдут этот пост.
User
Да, это помогло бы лучше понять, о чем вы изначально спрашивали. Вопрос и ответ должны идти вместе.
hakre
Для тех, кто может захотеть, вот плагин. Он размещен в репозитории WP http://wordpress.org/extend/plugins/google-earth-tours/
Norcross