prettyPrint() не вызывается при загрузке страницы

Я пытаюсь улучшить свой код в Blogger. Я связал файлы Google JS и CSS со своим шаблоном. Проблема в том, что я хочу, чтобы код был предварительно обработан при загрузке страницы, поэтому я добавляю prettyPrint(); к событию загрузки страницы в шаблоне.

<body onload="prettyPrint();">

Этот код не выполняется. Однако, если я наберу в консоли prettyPrint() вручную, мои коды будут корректно обработаны. Блокирует ли шаблон blogger вызов функций JS вручную?

РЕДАКТИРОВАТЬ Я заставляю это работать, вручную вызывая функцию в каждом сообщении, код которого мне нужно украсить (см. ниже). Тем не менее, я хочу знать, почему я не могу сделать это на шаблоне.

<pre class="prettyprint linenums lang-js">
function testCode(){

}
</pre>
// I have to do this in every post :-s
<script type="text/javascript">
prettyPrint();
</script>

EDIT 2 В README сказано, что мне не следует использовать prettyPrint() непосредственно как обработчик, но вместо этого оберните его замыканием. Поэтому я добавил этот код, похожий на пример в README, в свой <head>, но безрезультатно.

<script type='text/javascript'>
window.addEventListener('load', function (event) { prettyPrint() }, false); 
</script>

ИЛИ

<script type='text/javascript'>
document.addEventListener('DOMContentLoaded',function() {
    prettyPrint();
});
</script>

РЕДАКТИРОВАНИЕ 3 HTML-код моего шаблона — это просто шаблон Dynamics View (классический) по умолчанию с библиотекой prettify, добавленной, как описано выше.

EDIT 4 Вот ссылка, демонстрирующая проблему: http://testprettyprint.blogspot.com/2013/02/blog-post.html -- блок кода не претифицируется автоматически, но если вы откроете консоль Chrome и наберете prettyPrint(), коды будут правильно выделены.

EDIT 5 Причина, по которой я думаю, что это моя проблема, а не проблема блоггера, потому что этот парень все еще имеет свой код, предварительно обработанный с использованием той же техники: http://errorbuster.blogspot.com/2012/07/prettify-syntax-highlighter-for-blogger.html

EDIT 6 Как указал Джеффри То в своем ответе, представление Dynamics View загружает содержимое блога с помощью AJAX, поэтому любой вызов JS при загрузке документа будет выполняться ДО загрузки фактического содержимого. Таким образом, любой код JavaScript, выполненный с фактическим содержимым блога, а не с документом, недействителен. Итак, я предполагаю, что теперь вопрос заключается в том, как подключиться к событию Dynamics View ajax:complete, если такое существует, но я сомневаюсь, что это так. Спасибо всем, кто ответил. Я не уверен, что это можно считать ошибкой, но я сообщу о проблеме блоггеру.

ЗАКЛЮЧЕНИЕ Пожалуйста, прочитайте ответ Джеффри То. Он нашел событие для вызова функции.


person Lim H.    schedule 26.01.2013    source источник
comment
какой аргумент вы даете prettyPrint ()?   -  person    schedule 26.01.2013
comment
Где это определено в упомянутом вами Google JS?   -  person    schedule 26.01.2013
comment
Это JS: google-code-prettify.googlecode.com. /svn/trunk/src/prettify.js. А вот и CSS: google-code-prettify.googlecode. com/svn/trunk/styles/. Они добавляются в ‹head› моего шаблона.   -  person Lim H.    schedule 26.01.2013
comment
Видите ли вы какие-либо сообщения об ошибках в консоли отладки? Если вы замените вызов prettyPrint() на alert('onload happened'), появится ли всплывающее предупреждение, когда вы ожидаете?   -  person Mike Samuel    schedule 27.01.2013
comment
@MikeSamuel Да, все в порядке. Собственно, что я и сделал :)   -  person Lim H.    schedule 28.01.2013
comment
Сообщений об ошибках тоже нет? Можете ли вы сократить свой HTML-код до одного примера и добавить его в вопрос или опубликовать в украсить трекер ошибок?   -  person Mike Samuel    schedule 28.01.2013
comment
@MikeSamuel Спасибо. Пожалуйста, смотрите редактирование. Если вы не заметите какой-либо аномалии, думаю, я опубликую ее в системе отслеживания проблем.   -  person Lim H.    schedule 28.01.2013
comment
Это довольно сложно, потому что я не уверен, являются ли входные данные XHTML/HTML и как они предварительно обрабатываются перед обслуживанием. Если бы вы могли curl свою страницу и показать фактический HTML-код, поступающий по сети, это могло бы помочь. Однако я заметил одну вещь: скрипт document.addEventListener(&#39;DOMContentLoaded&#39;,...) выглядит как XHTML? Если Blogger использует XHTML для внутреннего хранения, но отправляет HTML, то он искажает кавычки. Возможно, если есть некоторая путаница XHTML/HTML, может помочь добавление раздела /*<[!CDATA[*/...//]]> вокруг тела скрипта.   -  person Mike Samuel    schedule 28.01.2013
comment
Привет, результат скручивания - HTML. Просто хочу сообщить вам и сказать спасибо за диагностику. Я попробую CDATA, когда у меня будет время сегодня.   -  person Lim H.    schedule 29.01.2013
comment
Можете ли вы опубликовать ссылку или Fiddle, демонстрирующие проблему?   -  person Jeffery To    schedule 01.02.2013
comment
@JefferyTo я добавил ссылку :)   -  person Lim H.    schedule 01.02.2013


Ответы (2)


Я полагаю, что на вашей тестовой странице используются «шаблоны Ajax» Blogger (не знаю, каково официальное название), тогда как другая размещенная вами ссылка использует классические шаблоны.

Если вы перезагрузите свою тестовую страницу, вы сначала увидите логотип Blogger в середине страницы, а затем отобразится ваш контент. Если вы просмотрите исходный код тестовой страницы, вы увидите много кода, но не ваш контент. Я полагаю, что с шаблонами макета код Blogger сначала запускается, а затем извлекает ваш контент с помощью Ajax. Любой код JavaScript, который выполняется при готовности документа (DOMContentLoaded) или загрузке окна, будет выполняться до того, как ваш контент будет загружен на страницу.

Я считаю, что если вы добавите виджет HTML/Javascript на страницу (после ваш блок контента), затем включите вызов prettyPrint() в этот виджет, он должен вызываться каждый раз, когда отображается сообщение.


Обновление. Официальное название этого шаблона — «Динамические представления», и похоже, что виджет HTML/JavaScript не поддерживается для динамических представлений. Я не могу найти никаких упоминаний об API, позволяющем подключиться к JavaScript Blogger, поэтому я считаю, что ответ (по крайней мере, на данный момент) состоит в том, что невозможно добавить код уровня шаблона, чтобы делать то, что вы хотите. Наиболее практичным способом было бы включать тег script с prettyPrint() в каждый пост :-(


Обновление 2. Я просмотрел код Blogger и нашел подходящее (и привязываемое) событие. Попробуйте включить это после кода Dynamic Views (в элементе head после тегов <script src='//www.blogblog.com/dynamicviews/...'></script>):

<script>
$(window.blogger.ui()).on('viewitem', function (event, post, element) {
    prettyPrint();
});
</script>

Событие viewitem запускается каждый раз, когда пользователь просматривает элемент (что может происходить несколько раз за время существования страницы). Аргумент element — это объект jQuery элемента контейнера элемента, поэтому, если вы хотите сэкономить prettyPrint() немного времени, вы можете сделать это:

<script>
$(window.blogger.ui()).on('viewitem', function (event, post, element) {
    element.each(function () {
        // first argument is a callback function
        // second argument is a root element or document to check
        prettyPrint(null, this);
    });
});
</script>
person Jeffery To    schedule 02.02.2013
comment
Спасибо. Есть ли способ сделать это на шаблоне? Например, можно ли каким-либо образом подключиться к обратному вызову успеха ajax блоггера из самого шаблона? - person Lim H.; 02.02.2013
comment
Наконец, я могу добавить любой пользовательский скрипт на страницу Blogger. Большое Вам спасибо. - person Alex Palcuie; 16.02.2014

С приведенными выше фрагментами могут возникнуть некоторые проблемы. Если вы перехватите событие с помощью <body onload="...">, другие коды javascript могут перезаписать его. Dom.addEventListener не будет работать с Internet Explorer, вам нужно использовать там Dom.attachEvent. В основном, когда я не использую или не могу использовать структуру javascript, например jquery для обработки событий, я использую свой старый код для обработки событий onload:

// window.ready
function register_onload(func){
    var oldOnload = window.onload;
    if(typeof(oldOnload) == 'function'){
        window.onload = function(){
            oldOnload();
            func();
        }
    }else{
        window.onload = function(){
            func();
        }
    }
}

// document.ready
function register_onload(func){
    var old_onload = document.onreadystatechange;
    if(typeof old_onload == 'function'){
        document.onreadystatechange = function(){
            old_onload();
            if(document.readyState == 'complete'){
                func();
            }
        }
    }else{
        document.onreadystatechange = function(){
            if(document.readyState == 'complete'){
                func();
            }
        }
    }
}

Я прилагаю два кода, которые работают немного по-разному. В основном, если вы используете document.ready(2nd snippet), тогда перехваченный код будет запускаться при загрузке страницы и создании всех элементов HTML. Но в document.ready нет гарантии, что все коды javasript и css также будут загружены, поэтому, если вы хотите, чтобы все коды и скрипты были загружены, вам нужно window.ready (1-й фрагмент).

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

// copy 2nd snippet here...
register_onload(function(){
    prettyPrint();
});

Также я рекомендую вам поместить код javacript между символами /*<![CDATA[*/ ... /*]]>*/, чтобы ваш окончательный код выглядел так:

<script type="text/javascript">/*<![CDATA[*/
// shorter version of the 2nd snippet
function register_onload(f){
    var d=document,o=d.onreadystatechange;
    if(typeof(o)=='function'){
        d.onreadystatechange=function(){o();if(d.readyState=='complete')f();}
    }else{
        d.onreadystatechange=function(){if(d.readyState=='complete')f();}
    }
}
register_onload(function(){
    prettyPrint();
});
/*]]>*/</script>

Надеюсь, это поможет вам решить вашу проблему.

person Lajos Mészáros    schedule 01.02.2013
comment
Спасибо за подробный ответ. Однако у меня не получилось :( И я пробовал довольно много подходов к загрузке, включая jQuery. Я также пробовал CDATA, как было предложено в комментарии. Не повезло :( Я воспроизведу проблему и скоро опубликую ссылку. . - person Lim H.; 01.02.2013