Pull to refresh

Comments 131

… на <script extsrc="..."> или <script extsrc="..."> (есть разница!)
Точно?
на минуту застрял на этой строке
Пардон ;) второе — «asyncsrc».
                document.write = function(i) {
                    var txt = document.createTextNode(i); 
                    span.appendChild(txt);
                };

1. innerHTML
2. document.write хорошо бы после исполнения скрипта на место вернуть

а хром разве поддерживает @defer?
* а хром разве не поддерживает @defer?
defer разве работает document.write?
> Используйте <script asyncsrc="..."></script> если уверены что в данном конкретном скрипте нет document.write
зачем придумывать то что, что уже есть? т.е. чем самописный @asyncsrc отличается от @defer? // хром вылез из старого варианта статьи
А сколько браузеров реально поддерживают «defer»?
IE 4+, FF 3.5+, в вебките скоро должна появится поддержка. Про оперу ничего не известно. Опера вообще по загрузке скриптов на последнем месте сейчас (так как даже не умеет параллельно грузить скрипты). Это конечно можно исправить, если грузить через XHR, но тогда отпадает кроссдоменность.
под «скоро должна появиться» имеется ввиду, что в ночных сборках уже есть и скоро появится в стабильных.
В Opera что-то похожее есть уже довольно давно (~ года 2), но пока почему-то в обычные настройки не вынесено:

opera:config#Extensions|DelayedscriptExecution
Можно попробовать отследить наличие поддержки @async и @defer, и в случае отсутствия оной эмулировать соответствующее поведение скриптами. Так правильнее точно будет.
Как раз недавно читал что многие браузеры имеют это свойство и отчитываются о его наличии, хотя и не реализуют его.
Ну, попробовать по браузерам/их версиям отслеживать, суть не в этом, а в том, что правильнее не добавлять свою альтернативную функциональность для того, что стандартизировано, а попробовать реализовать существующие стандарты там, где они не реализованы. Ну да ладно, это придирки уже =)
1. Про innerHTML я думал, но будет медленнее мне кажется. Есть какие-то аргументы в пользу?
2. Верно — надо бы, сделаю.
2. Сделано — document.write возвращается на место.
медленней, но верней. ибо такой код отобразиться простым текстом

   document.write('\<script\>alert("bu")\<\/script\>')

а надо что бы срабатывало, тогда я яндексовские и гугловские рекламы нормально будут срабатывать
О! Верно! Это очень даже правильно. Плюс Вам в карму за помощь. Исправлено.
WinXP Opera 10.62
После «script3:» пустота…
IE 678 такая же штука и ошибки ещё выпадают.
А можно копию того что выдает IE и желательно из оперы тоже — есть ли что-то в Error Console?
А можете выложить что IE пишет и есть ли что-то в Error Console у Opera?
В Opera нет ничего. Только жалуется на отсутствующий скрипт 404…
В IE — не знаю поможет ли это :)
Строка 69 Символ 1 Предполагается наличие объекта
Строка 852 Символ 6 Предполагается наличие идентификатора, строки или числа
Это по ходу ошибки в другом скрипте, в extsrc.js там до 852 строки не доходит дело :)
Вы просто мало смотрели на «отладчик» js, встроенный в IE :). Это может означать что угодно.
Opera 10.62/Ubuntu все ОК. Может кто-то еще с оперой подтвердить баг?
А не, вижу баг. Все правильно. Буду искать.
Проблема в .onerror у IE/Opera… точнее в том, что его нет :) Думаю как обойти.
Вроде бы фикс нашелся — проверьте в IE/Opera.
Сейчас в Opera 9.6+ работает.
а что будет если встретится конструкция

document.write('<script src=«s.js» type=«text/javascript») + document.write('></script>')
Скорее всего проблемы не будет.
Хотя смотря ГДЕ. В коде страницы? Во внешнем скрипте?

Проблемы в любом случае не возникнет, скорее всего. Единственное что будет работать медленнее (как обычный скрипт), но в любом случае после рендера страницы.
                
document.write = function(i) {
  var txt = document.createElement('span'); 
  txt.innerHTML = i;
  span.appendChild(txt);
};

исходя из этой реализации, проблемы будут, скрипт не подключится.
разве innerHTML = '<script></script>' не работает?
или в чем проблема?
1) работает, не во всех браузерах
2) проблема не в этом, а в

innerHTML = '<script src=«s.js» type=«text/javascript»';
innerHTML = '></script>';

вообщем, проблема в том, что частями != целиком
хммммм… да, проблемка… есть идеи как ее решить?
есть, просмотрите реализацию document.write в fullajax.ru, можно сделать как-то подобным образом.
А по-точнее можно?

Я тут свою идею уже придумал ) но она требует доработки. Идея, в общем-то — буфферизация в случае если document.write обнаруживает, что пишется <script до момента пока </script не обнаружится… Только сказать проще чем отладить ))
ну мысль примерно в нужном направлении… ищем начало любых тегов и ждем их окончания. Проблемы могут быть не только со script, а также с коментами и другими тегами.
Вроде бы пофиксил в 0.007. whiteposts.com/extsrc_js/extsrc.js (переменная buffer)

Буфферизируется все, что выдает скрипт, пока не сработает следующий скрипт (или скрипты не закончатся). Затем один раз создается SPAN с этим содержимым (для каждого скрипта).

Если только кто-то не делает doc.write чего-то и ждет в скрипте результатов этого (мне даже трудно представить возможно ли такое) — то должно работать для всех тэгов скриптов и т.п. Есть идеи где такое возможно?

Спасибо за подсказку :)
не прокатит. интерпретация частями != интерпретации одного целого
document.write('<script src=«s.js» type=«text/javascript») + document.write('></script>')

тут тоже интерпретация частями
Хром по-моему это не поддерживает. Это вообще первое что я попробовал :)
по идее не может он такого не поддерживать, потому что
node.innerHTML += "</div";
тоже самое, что
node.innerHTML = node.innerHTML + "</div";
Так на всякий случай, в FF4 b7 (и в ночных сборках тоже), не работает («script3:» и пустота). Какая-то проблема с динамической вставкой элементов script у них, не вызывается onload и onerror тоже.
ff4b6
 "With document.write" (loads seq-ly, BUT AFTER document renders)
 script1:             [dw1.document.write]
 script2 (not found, must be empty line): 
 script3:             
А сейчас та же фигня?
FF 3.6.10 — также «script3:» и пустота
Пардон, отображается — только секунд через 20 после обновления странички.
кому и зачем так сильно нужен тот document.write?
информеры новостных обменников, к примеру
дак они асинхронно загружаются
A если в черновики убираешь (мне пауза нужна была чтобы не высказать все что я думаю по поводу internet explorer :)) ) — комменты временно пропадают до первого нового.
А нифига вы молодец какой! (:
Спасибо :) признаю, это было непросто и в какой-то момент IE довел меня до желания все бросить и что работать это никак не будет :)
А реально ли оформить extsrc.js в виде юзерскрипта, который будет подменять все «src» на «extsrc»?
Не все src можно заменять на extsrc — в том-то и проблема. Пока это только моя интуиция, но есть подозрения… Поэтому и рекомендуется руками заменять.

Кроме того этот userjs должен будет срабатывать до того как браузер обработает DOM. Я не знаю насколько это возможно. Не настолько я спец в Javascripte :)
Жаль. Было бы полезно. В принципе, можно было бы составить базу данных скриптов-исключений, но возни много и риск остаётся.
для оперы, может также как расширение в хроме.
в файрфоксе userjs срабатывает после того как документ загружен
ну это то да, opera:config#Extensions|DelayedscriptExecution
но хочется во всех браузерах
Спасибо за наводку. Включил, походил по разным сайтам. Глюков не заметил.
Тем кто вешает на более-менее посещаемый сайт внешний скрипт — вроде виджета вконтата, фейбука или твиттера — я бы отрывал руки. Ну не должен ваш сайт зависеть от того — работает некий другой сайт или нет!
Самое правильное решение — хранить копии js файлов для виджетов у себя на сервере, и просто обновлять версию при необходимости.
Да, я бы тоже уши-то пооткрутил — но ведь ДЕЛАЮТ люди и многие. Так пусть хоть может так делают, хоть чуть быстрее будет все.
да, в jquery(ui), есть такая штуковина $.getscript — api.jquery.com/jQuery.getscript/. оно то делает? или я чего то не понял.
но в любом случае, он использует некий фреймворк, а ваш скрипт, как я понял — нет.
а extsrc атрибут в теге script валидный с точки зрения html?
Конечно в спецификации от W3C нет такого атрибута для script. Встречный вопрос – зачем вам W3C-валидность html-кода?
Вот я и спрашиваю – зачем вам эта плашка? Пользователям абсолютно до фонаря W3C-валидность (они даже не знают, что это), им надо чтобы сайт/сервис работал.
Я слышал что Google обращает на это внимание при ранжировании
1m39s: «Мы не даем никаких привелегий(boost) страницам, которые валидны»
Ок, спасибо, что развеяли заблуждение!
Для самоудовлетворения, этого мало?
Пользователям до фонаря, пока сервис работает как они ожидают.

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

Иначе — никто не гарантирует что в IE13 (в соответствии с современным ему стандартом) у <script> не появится атрибут extjs=, который будет форматировать диск ц вести себя как-то несоответственно текущим ожиданиям.

— Как выход из положения, для валидности кода я бы предложил добавить JS-интерфейс для подгрузки скриптов асинхронно, ну то есть добавлять скрипты в очередь подгрузки с помощью инлайн-жаваскрипта.
В статье автора "… поэтому все внешние скрипты отдайте extjs..." — я уже вижу как неудачное название может вызвать путаницу (ExtJS — ru.wikipedia.org/wiki/Extjs)
Лучше было бы назвать по-другому…
Верная мысль… есть идеи про название?
«Валидность гарантирует, что в каком-то новом браузере, соответствующем стандартам, ваш сайт будет отображаться точно также, как отображается в нынешних.»

Единственное что хоть немного(чуть-чуть) это обещает — это ACID тесты… Гарантировать тут вообще никто ничего не гарантирует. Код может быть валидным и отображаться черт-те-как в разных браузерах.
Если верстальщик не очень уж криворукий, то сегодня, соблюдая стандарты, уже можно корректно отображающуюся во всех полноценно поддерживающих стандарт браузерах делать. И гарантировать на некоторое ближайшее будущее корректное отображение с большой вероятностью.

То есть плохое отображение может быть по 3 причинам:
1. Использование устаревших браузеров, не поддерживающих стандрат (ие6, гыгы)
2. Использование будущего стандарта — html5/css3 например.
3. Использование криворуких верстальщиков (да, валидный код таки может отображаться по-разному, за счет использования допустимых, но четко не оговоренных в стандарте средств)
Поддержку сегодняшних стандартов завтра вам никто и ничто не гарантирует, я даже не удивлюсь, если в течение ближайших лет HTML вообще выйдет из применения. Валидность не заставит ваш сайт простоять столько же, сколько пирамиды.
Ну это уже вообще крайности. Если не получится сделать сайт, который простоит 1000 лет, то не стоит и париться — так выходит? :) С таким подходом не стоит и пытаться что-то делать правильно. Все равно пирамиды не переживет.

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

См. мой комментарий выше к yoihj.
Ваш сайт устареет целиком – и по дизайну, и по серверной стороне – и потребует переделки быстрее, чем стандарт изменится. Менять дизайн → перевёрстывать и писать JS, используя новые возможности браузеров. Так что лучше сегодня я сделаю у input невалидные атрибуты pattern и required, а когда появится поддержка WebForms 2.0 нужно будет только отключить часть JS-кода.

Хотя бывают, конечно, исключения. Популярная Лента.ру уже 6 лет не меняет оформления. При этом валидатор W3C о её главной говорит «1198 errors, 263 warnings». Ещё, кстати, невалидный HTML у главных страниц Google, Яндекс, Youtube, Twitter, Facebook, Википедии, сайтов Microsoft, Apple. Хабр тоже валидацию не проходит :)
Вот ключевой момент:

> нужно будет только отключить часть JS-кода
Кто это будет делать? Заказчик? Когда он заметит, что у некоторых пользователей что-то не работает?
Я так понял, в скрипте пересоздаётся новый тег script, но при этом тогда теряются другие аттрибуты типа charset. Хорошо бы переносить туда же.
Мысль интересная, но у меня как-то ни одной мысли как найти все атрибуты у тэга…
current_script.attributes, только работайте как с массивом, а то у ие с for in по этому св-ву проблемы
что характерно… при попытке добавить это

 var attrs = current_script.attributes;
 for(var i = 0; i < attrs.length; i++) {};


в ту часть где asyncsrc — IE6 напрочь отказывается что-либо грузить и правильно работать…

код whiteposts.com/extsrc_js/extsrc-004.js

разгадки?..
проще тогда не новый создавать, а клонировать старый, и потом с ним работать
node.cloneNode(true);
krook.org/jsdom/Node.html
Мысль интересная, надо будет попробовать.
>но нельзя использовать inline javascript

заранее прошу прощения, если спрошу бред.
А разве нельзя вашим-же скриптом обработать inline скрипты?
ну хорошо, если они пытаются отработать сразу, то к примеру засунуть их в коммент, ваш скриптик их бы собирал и выполнял апосля.
К сожалению, в том-то и беда, что нельзя… Допустим мой скрипт загрузился первым — inline script еще не загрузился — я не могу его обработать… как только браузер его загрузит — он его исполнит — я его опять же не могу обработать…
Мда, вообще-то проблема не в том.

Во первых количество потоков браузера ограничено, IE — 2, остальные 4-6, при чем больше 2 не разрешено :). Дополнительно браузер отдает приоритет скриптам перед остальными элементами.

Исходя из этого надо все скрипты слить в один поток — слить и сжать, и поставить в конце страницы и собственно проблема задержки рендеринга страницы из-за скриптов пропадает как факт, но при этом отлично работают inline jQuery и прочие фишки.

Дполнительно не плохо было бы layout прописать так что бы ни скрипты ни отдельные элементы не влияли на рендеринг — приписать размеры или минимальные размеры, прописать начальное состояние и прочие заморочки. Если надо вынести основные стили в страницу.

Думаю что данная библиотека интересная, но поскольку требует иногда значительной переделки скриптов, вынос inline и прочее — в принципе бесполезная. А для данной технологии было бы полезнее сделать библиотеку поддержки для нового тега отложенной загрузки — не помню какой именно — недавно была статья тут на эту тему.
Вы живете в мире фантастики.

Вот вы вебмастер сайта, вот вам дают какой-нибудь информер, который шеф обязательно хочет видеть прямо вот в начале страницы. И использует она document.write()… При этом скрипт генерится на удаленной серверной стороне… Давайте, дерзайте, слейте ее в один файл и всуньте в конец. Посмотрю я как это у вас получится.

Проблема как раз в том, что туча всякого дурдома до сих пор использует document.write… туча всякого дурдома не позволяет вам хранить их скрипт на вашем сервере.

Те же Google Maps API — давайте, слейте в один со своими скриптами.
Я такие вещи просто впишу по onload и они никак не повлияют на рендеринг страницы. Конечно принцип такой-же как в библиотеке.

Google API как раз document.write использует для линка на загрузчик.
Или вот еще интереснее задачка — есть у вас 10 счетчиков, которые выдали вам код с <script src — попробуйте-ка слить их в один файл у себя на стороне (учитывая что счетчики срабатывают именно при этом вызове того самого URL, который в src="" прописан).
Смотрим на то как прописывается google analytics и делаем также :)
чтобы юзер не пялился в пустую страницу 10 секунд достаточно слить все скрипты в один. а вот выдавать ему страницу с неработающими 10 секунд кнопками — не стоит.
Отличная библиотека! А вы не думали о том, чтобы выложить её на Google Code? Будет очень досадно, если такое добро пропадёт, ну и возможно тем кто будет ей пользоваться было бы полезно подписаться на уведомления об обновлениях в коде.
Да, выложу. Просто ей еще 12 часов нет, надо было хоть немного отладить :)
Идея по поводу inline-скриптов. Может вызывать какое-нибудь событие, после загрузки всех скриптов? Что-то вроде следующего:

<script src=«extsrc.js»></script>
<script extsrc=«jquery.js»></script>
<script>
extscr.ready(function() {
$(document).ready(....)
})
</script>
Думаю это плохая идея, потому что когда его вызывать — когда загрузились все скрипты? Долго ждать придется. Лучше уж все же выносить во внешние файлы. И на самом деле JQuery лучше держать локально и не вызывать через extsrc, а использовать extsrc для всяких виджетов, информеров, API — всего того, что нельзя локально скопировать.
Да, именно, вызывать когда загрузились все скрипты через extsrc.
JQuery здесь лишь только для примера. Вместо него может быть любой другой внешний api.
Плохая это идея для JQuery, представьте такую ситуацию:

extsrc jquery
extsrc 20 социальных виджетов
extsrc ваш скрипт

«ваш скрипт» не запустится пока все 20 виджетов не загрузится — куда лучше

зараза хабр при ctrl+v отправил комментарий

src=jquery + ее плагины (все в одном файле)
extsrc=20 виджетов
inline=ваш скрипт

тогда он запустится еще до того как соц.виджеты начнут грузится (подгрузка jquery чуть подтормозит страницу)
Не спорю про виджеты и jquery, но давайте оставим их в покое. Думаю, что я не сумел донести идею.
Хотелось бы иметь возможность гарантированно выполнить inline скрипт после загрузки всех extscr и asyncsrc скриптов. Это могло бы быть полезным для отложенной загрузки некоего большого функционала приложения на страницу (допустим >500kb) и его инициализации.
Да мне не жалко. Единственное назову ее extsrc.complete(), чтобы не путались люди с jquery.ready(). Просто если назову ready — будут думать что она при рендеринге запустится (как в jquery).

В репозитории:
code.google.com/p/extsrcjs/
extsrcjs.googlecode.com/svn/trunk/extsrc.js

Изменения:
code.google.com/p/extsrcjs/source/diff?spec=svn8&r=8&format=side&path=/trunk/extsrc.js
document.write не совсем честный получается. Ситуации достаточно специфичные, но всё же.

1. То, что пишет document.write не приводится к нормализованному html. Например, мы можем написать document.write('<a href="#">') и всё, что дальше, будет считаться ссылкой, пока не встретиться </a>
В случае innerHTML текст сначала нормализуется в правильный html, потом вставляется в документ.

2. В случае, если внешний скрипт с extsrc с помощью document.write создаст ещё один внешний скрипт, а тот, в свою очередь, тоже вызовет document.write, то всё сломается, т.к. к моменту вызова последнего document.write он (document.write) уже родной, а не ваш переопределённый. По крайней мере в Firefox так, в остальных не смотрел.

Ну и несущественное замечание: генерируемый с помощью document.write контент добавляется после текущего script, а не перед. Это не важно, но так, для справки.
Про 1. не очень понял. Там же как бы буфферизация идет — каждый document.write собирается в длинную строку, а затем innerHTML делается один раз по окончании работы каждого загруженного скрипта (а не на каждый вызов d.wr)

2. На самом деле да, document.write(<script) — это вообще проблема (к счастью, все же, многие так не делают). Но на этот случай просто надо такие плохие оставлять обычным src, ибо я не вижу как это решить. Есть идеи?

3. Да, я думал про это — просто insertBefore понадежнее, чем самоделка insertAfter :) не хочу понижать надежность из-за академичности.

Спасибо за комментарии.
1. После document.write('<a href="#">') никаких document.write не будет. Просто текст после тега script станет ссылкой. Поэтому в буфере будет лежать битый html.

3. Можно просто current_script.parentNode.insertBefore(span, current_script.nextSibling).
Ну вот я ж про надежность тут и говорю — а всегда ли будет parentNode и всегда ли nextSibling будет?
parentNode будет, вы же скрипт из дерева взяли.
Если не будет nextSibling, то insertBefore будет работать как appendChild, т.е. добавит в конец.
все же я лучше оставлю insertBefore — надежнее, а разницы во внешнем виде никакой не будет.
Ну я и сказал — несущественное замечание :)
А вот 1. все же не понял. То есть я понимаю, я никак отличия понять не могу — в чем разница того, что произойдет при применении extsrc и просто src при таком d.wr?
document.write('<a href="#">') напишет в документ <a href="#">, тег a закрыт не будет.

el.innerHTML = '<a href="#">' «напишет» в элемент el '<a href="#">'</a>, т.е. тег a автоматически закроется.
разница и правда интересная :) правда extsrc выглядит в этом случае даже лучше.
спасибо за замечание — все равно, мне, кажется, это «исправить» на незакрытый тэг не удастся. :)
> правда extsrc выглядит в этом случае даже лучше.
Не лучше, у document.write своя семантика, у innerHTML — своя.
Просто нужно описать этот нюанс в документации.
Я придумал кстати как побороть 2 хотя бы частично — буду возвращать настоящий d.wr перед тем как делать innerHTML =.
Я для таких целей, с недавних пор, стал использовать labjs.com/ — небольшой вес библиотеки, есть возможность конструкций типа
$LAB
.script("/js/live.js")
.wait(function(){alert('First one loaded');})
.script('/js/additional.js');
Выглядит интересно, но опять же задам глупый вопрос — поддержка document.write у скриптов загружаемых таким образом? :) Это именно та проблема, которую я и решал — document.write. Загрузить скрипт асинхронно — проблемы нет. Загрузить скрипт чтобы он писал куда надо — вот это проблема! (была :) )
Sign up to leave a comment.

Articles