программирование
Быстрый trim для JavaScript
Самый быстрый trim на JavaScript выглядит странно:
function trim12 (str) {
var str = str.replace(/^\s\s*/, ''),
ws = /\s/,
i = str.length;
while (ws.test(str.charAt(--i)));
return str.slice(0, i + 1);
}Код взят из блога Flagrant Badassery. Цикл с регуляркой быстрее, чем простое регулярное выражение /\s+$/, а кроме того, \s\s* быстрее, чем \s+? OMG!
Dialupass: если пароль от диалапа утерян
Потерял я на днях свой пароль
Программа работает под Windows 2000, XP, 2003, Vista, 2008, для Windows 9x и ME есть более старая версия. В случае чего — рекомендую.
Canvas в разных браузерах
Сегодня с утра, порадовавшись выходу Mozilla Firefox 3.5beta4, решил погонять её на

Плохо то, что Firefox, как оказывается, сильно размывает Canvas. Когда я играл на эмуляторе в одну из игр, мне казалось, что у меня
Получаем ещё один «стандарт», который ведёт себя во всех браузерах
Почему разработчики браузеров не внедряют CSS3?
Лично для меня очевиден ответ на вопрос, вынесенный в заголовок. Но умница pepelsbey расписал всё настолько хорошо, что грех не процитировать:
Чтобы чётко понимать чем стандарт отличается от черновика, прочитайте черновик CSS 3, а особенно места, помеченные красным. Фразы там звучат примерно такие:
— А может назовём свойство
blah-blah иначе? Напримерfoo-foo! — А давайте возьмём свойства a, b и с и… объединим их в одно с именем abc? — …и так далее.И что в итоге? Каким образом производителям браузеров внедрять свойства, которые ещё до конца не описаны? Нет, конечно есть модули, которые близки к статусу рекомендаций, но над большинством вещей ещё думать и думать. В частности, на мой вопрос
про border-radius, разработчики Opera ответили, что оно уже реализовано в экспериментальных билдах, но вокруг него крутится столько нюансов, а Mozilla делает так, а Webkit иначе… как же поступать Opera? Вот и тормозит внедрение новых классных фич…Поэтом заявление MS о том, что, мол, мы не поддерживаем CSS 3, пока черновик не превратится в финальную спецификацию, звучат вполне резонно. Как бы это ни было грустно.
В общем, меньше фанатизма и больше читайте спецификации ;)
Знаете ли вы JavaScript
У Дмитрия Барановского (это автор Raphaël —
Итак, что выведет каждый кусок кода?
if (!("a" in window)) {
var a = 1;
}
alert(a);var b = function a(x) {
x && a(--x);
};
alert(a);function a(x) {
return x * 2;
}
var a;
alert(a);function b(x, y, a) {
arguments[2] = 10;
alert(a);
}
b(1, 2, 3);function a() {
alert(this);
}
a.call(null);Доступ по паролю
Большое заблуждение, считать, что http://user:password@example.org/ и http://example.org/user/password/ сильно различаются. Ничего подобного. Единственное различие между ними, что если набрать второй адрес руками, то он останется в истории браузера. Для AJAX’а более пригоден второй путь — «logout» делать сильно проще.
Необходимое замечание: речь, конечно же, идёт
Итак http://example.org/jfdhfjhrtjktjkfhdjht/ это вполне себе парольный доступ.
Opera и document.all
«Опера» в одно время пыталась притворяться Internet Explorer’ом — копировала его
var isIE = document.all && self.operaВпрочем, на Западе «Опера» не популярна, поэтому «Оперу» не исключают и считают её разновидностью IE.
Так вот, в последние годы «Опера» пытается открестится от своего «иешного» прошлого, например,
В новых «Операх» конструкция alert(document.all ? 1 : 0) выдаст «0», тогда как alert(document.all) — «[object HTMLCollection]». Сделано понятно для чего: обратная совместимость не ломается, но проверка «не IE ли» теперь уже выдаёт false.
О5 25: JavaScript — не Java!
Ллео, +1, зачетно обосрал JS ))) Ненавижу javascript, а еще заточку на кроссбраузерность, где код JS вырастает раза в 3
из-за разных браузеров. Говно это. Кастрат Java. Долой JS!
Пишет у Каганова в блоге
Ну и про «заточку на кроссбраузерность». Так уже давно никто не делает (если не считать
«//» в ссылках
Как известно, в вебе, в подавляющем большинстве случаев, для адресации ресурсов применяются HTTP или HTTPS протоколы. Как вы понимаете, я не Капитан Очевидность, так что за этим последует
Бывает так, что одна и так же страница должна быть видна по обоим протоколам (например, у нас в интранетах такое бывает часто). В зависимости от того как пользователь зайдёт.
То, что я скажу дальше NDA не является, например, об этом рассказывал Олег Оболенский
В итоге, когда человек заходит на страницу, ему грузится ещё и CSS с другого сайта, внутри которых могут быть абсолютные (с протоколом) пути, которые подгружают картинки. Если человек зашёл по HTTPS, то и всё остальное должно отдаться по HTTPS (иначе, например, Internet Explorer заругается), если он зашёл по HTTP, то всё должно отдаваться по HTTP (HTTPS нагружает сервер и вообще отдаётся по шифрованному протоколу всё заметно медленее).
Как это реализовать? Как менять протокол, в зависимости от протокола страницы, если CSS, который грузится статичен и менять пути внутри него не получится? Делать два отдельных CSS?
Есть способ проще.
Откуда я о нём узнал, я не помню.
Способ заключается в том, чтобы не указывать протокол. Выглядит такой URL вот так: «//example.net/picture.jpg» и описан в RFC 1738 как «Common Internet Scheme Syntax»:
While the syntax for the rest of the URL may vary depending on the particular scheme selected, URL schemes that involve the direct use
of an IP-based protocol to a specified host on the Internet use a common syntaxfor the scheme-specific data://<user>:<password>@<host>:<port>/<url-path>
Смысл в том, что в таком указания без протокола должен использоваться текущий тип протокола. Таким образом, хорошее решение — просто всегда указывать полный URL в таком виде.
CSS sprites, data URI
CSS sprites, data URI+mhtml, склейка CSS с JavaScript. Что ещё придумают
Например, в FireFox есть прекрасно подходящий для этого протокол «jar» (а в Internet Explorer немного похожие на него «mhtml» и «res»). Этот протокол стал известен массам в основном благодаря уязвимости, которая работала через него.
URL выглядит как «jar:http://sample.org/file.jar/folder/file.png», где «http://sample.org/file.jar» — путь
К сожалению, FireFox сейчас сделать так не позволит, а жаль (так они залатали уязвимость).
Opera и GeoIP
В конце
В JavaScript это выглядит примерно так:
function showMap(position) {
// Show a map centered at (position.coords.latitude, position.coords.longitude).
}
// One-shot position request.
navigator.geolocation.getCurrentPosition(showMap);Тем, кто видел Google Gears это уже знакомо. Причём, в момент, когда клиентское приложение в первый раз пытается получить координаты, браузер задаёт пользовалю вопрос, разрешает ли пользователь узнать приложению его координаты.
К чему это я всё вёл. Вчера появился специальный билд «Оперы», поддерживающий GeoIP. Что, правда, ничего не говорит о сроках внедрения технологии в стабильную версию. Например, тег VIDEO появился в эксперементальном билде аж в конце
Браузеры: порядок загрузки и количество одновременных соединений
Для интереса написал на PHP небольшой скрипт для анализа сколько соединений открывают браузеры и в каком порядке они грузят данные. Создал
Вот что получилось (считаются одновременные соединения):
- Opera 10 alpha (build 1355) — 4 соединения к серверу, порядок загрузки: js, ico, css, gif; особенности: 0.css
почему-то загружен два раза.
— Internet Explorer 8 — 6 соединений к серверу, порядок загрузки: js, css, gif, ico
— Internet Explorer 5.5 и 6 — 2 соединения к серверу, порядок загрузки: js, css, gif
— Google Chrome 1.0.154.53 — 6 соединений к серверу, порядок загрузки: js, css, gif, ico
— FireFox 3.0.7 — 6 соединений, порядок загрузки: js, ico, css и gif вперемешку; особенности:почему-то ico загружен два раза, gif и css грузились вперемешку
— Safari 4 beta (528.16) — 4 соединения, порядок загрузки: js и css вперемешку, gif; особенности: js и css грузились вперемешку
— Safari 3 (526.27.1) под Maкинтош — 3 соединения, порядок: js и css вперемешку, gif; особенности: js и css грузились вперемешку
— FireFox 2.0.0.20 под Макинтош — 2 соединения, порядок: js, ico, css, gif; особенности: ico загружен три раза
Раскрашивание прокрутки в WebKit
Я помню многие ругали Microsoft за то, что в IE
Как бы то ни было, WebKit в свою новую сборку включил селекторы для очередных измывательств над полосой прокрутки (причём, отдельно для ресайзера, горизонтальной и вертикальной прокрутки).
Стилей там добрый мешок, лучше сходить на сайт «ВебКита» и посмотреть, а мне же нравится, что появился новый
noindex::-webkit-scrollbar, .someclass {
color: red;
}
Кроссбраузерный data URI в CSS-файлах (многабукв)
Прелюдия
Некоторое время назад, я нашёл способ, использования data URI в Internet Explorer. Data URI — специальный вид URL, который включает в себя код самого объекта. Например, таким образом можно внедрять изображения прямо в код
Выглядит такой HTML вот так:
<img src="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP…и так далее" />Где «data» — это протокол URI, image/gif — тип объекта (картинка GIF), base64 — тип кодирования, после запятой идёт сам код картинки.
Такой вид URI понимают сейчас все современные браузеры, включая Internet Explorer 8 (правда, со многими ограничениями). Плохо то, что Internet Explorer 7 и ниже этого не поддерживает, а доля этих версий настолько велика (около 50% на данный момент по данным LiveInternet), что до недавнего времени data URI использовалась крайне редко.
Я, увлёкшись исследованием малодокументированного протокола mhtml (MIME HTML), поддерживаемого в браузерах Microsoft с пятой версии, в одном из экспериментов разобрался как внедрить объект в тело
Вообще mhtml был придумал для адресации внутри так называемых
Типичный
mhtml:http://example.net/index.html!fhhryregdy4gereГде после «mhtml» идёт обычный
В итоге, когда мне пришла эта идея, я совместил оба способа так, чтобы Internet Explorer видел файл как
Специфика HTML допускает переносы, в том числе и внутри data URI, поэтому мне удалось задуманное относительно быстро. В CSS всё сложнее, а тема использования data URI в CSS, как оказалось, актуальнее, чем для HTML. Например, в книге Николая Мациевского «Разгони свой сайт» сделана попытка расширения моего способа на CSS, к сожалению, менее удачная, чем хотелось бы: требуется включение закодированного объекта два раза.
Фуга
Итак, мне захотелось посмотреть, не получится ли расширить мой способ на CSS, не прибегая к включению закодированного файла два раза. Причём, сфера тут уже, подключаемый к CSS объект это, в 99,99% — картинка.
После немногочисленных экспериментов, оказалось, что оторвать закодированный объект от начала data URI не представляется возможным, что мешает использованить mhtml — там заголовок и кодированный объект должны отделяться пустой строкой.
Тем не менее, других способов побороть IE я не видел и потому продолжал эксперименты. Несколько слов о том, что такое base64. Base64, по сути, анахронизм, доставшийся нам от электронной почты на заре её зарождения. Письма тогда ходили исключительно в латинице и все почтовые системы полагали, что никаких других символов в письмах не бывает.
Таким образом, когда встала задача передавать в письмах
Хорошие новости, заключаются в том, что браузеры игнорируют в кодированной строке символы, которые не входят в упомянутые 64. Можно было ожидать, что браузеры вообще откажутся разбирать такую строку.
Итак, строка data URI начинается
Из вышесказанного следует, что нужно
Оставим в покое XBM, BMP, ART, WMF/EMF, JPEG200 и прочую экзотику, поддерживаемую браузерами, и остановимся на триплете JPEG, GIF, PNG. Честно сказать с форматом GIF я знаком плохо, а JPEG и PNG исследовал несколько лет назад довольно подробно.
JPEG и PNG состоят из секций. В общих чертах, сначала идёт заголовок файла, потом сами секции, в формате (с некоторыми вариациями) «имя секции», «длина секции», «конец секции». И у JPEG, и у PNG есть секции для произвольного содержимого. У JPEG это COM и APPn, у PNG — iTXt, tEXt и zTXt. Кстати, и у GIF тоже есть похожее место — Application Extension.
Отсюда идея: Internet Explorer, декодировав файл с начала строки, получает заголовок с секцией из содержимого, куда помещается заголовок для остальных браузеров и мусор, оставшийся от декодирования начала data URI, остальные браузеры должны пропустить заголовок для IE и начать декодирование с data URI.
Получаем, на примере JPEG:
FF D8 — заголовок JPEG для IE FF E0 xx xx — секция APP0, куда прячется всё до данных изображения, «;background-color:url(data:image/jpeg;base64,» — это видят остальные браузеры FF D8 — начало JPEG для остальных браузеров «данные изображения» — это место видят уже все браузеры
Все бинарные данные выравниваются и кодируются (строка начала
В моём примере такой CSS выглядит вот так:
/9j/4AAs;background-image:url(data:image/jpeg;base64;BOLKNOTE.RU,/9j/4AAC…Легко увидеть, как видит этот стиль браузер: «/9j/4AAs» кажется ему ошибочным атрибутом (его, кстати, можно взять в комментарий), а «;» — разделителем атрибутов. И хорошо просматривается («/9j/AA») двойной старт заголовка
Остальное должно быть понятно из примера («!ie» — CSS hack, делающий стиль видимым только для IE), как это выглядит в браузере, можно увидеть в разделе «Храню» у меня на сайте.
IE8 быстрее всех?

Microsoft опубликовала смешной документ, в которым утвержается, что IE8 самый быстрый браузер in da world. Методика тестирования — время загрузки 25 сайтов (а почему нет «Оперы», кстати?):
For the Internet Explorer 8 performance video we published, we chose the Top 25 websites in the world as measured by comScore to reflect the sites users are most likely to visit on the web. The following table shows results from the benchmark testing process for those 25 websites tested on the following browsers: Google Chrome, Mozilla Firefox, and Internet Explorer 8.
Ха. Ха.
PHP: библиотека SPL
На сайте Blue Parabola появилась очень хорошая статья, объясняющая чем хороша библиотека SPL (Standard PHP Library). Даже если вы не читаете на английском, всё равно взгляните — там есть примеры кода.
А мужики-то и не знают!
Сергей Чикуенок из студии Лебедева сделал потрясающее открытие: чем сложнее структура документа, тем больше тормозит браузер.
Libmapi писали индусы?
Есть ощущение, что некоторые части libmapi писали индусы. Напоминаю, что libmapi — библиотека для общения с Microsoft Exchange Server, к которой я пишу биндинг в Python с использованием ctypes.
Некоторые вызовы я предпочёл переписать на Python, так как код содержит баги и глупости. Например, мне приходит (в терминах Python) массив событий. Приходят два «слова», два числа, которые содержат дату/время старта и окончания. Числа приходят в минутах, например, чтобы узнать какой там указан день, нужно нацело разделить число на 1440 (количество минут в сутках) и прибавить один.
В итоге, я вычисляю всё вот так (часовой пояс я ещё не умею определять):
last = event_end - event_start
day = event_start // 1440
hour = (event_start - day * 1440) // 60
minute = event_start % 60
day += 1Авторы libmapi делают куда затейлевее:
for (hour = 0; hour < 24; hour++) {
if (!((event_start - (60 * hour)) % 1440)) {
// значит мы нашли час, который указан в событии
day = ((event_start - (60 * hour)) / 1440) + 1;
last = event_end - event_start;
}
}Эпопея с MAPI
Все эти пляски с ctypes — следствие одной большой задачи, с которой мы столкнулись в группе внутренних сервисов. Интеграция нашего интранета с Microsoft Exchange Server — это сервер для обмена сообщениями и совместной работы. Основной протокол, по которому этот сервер работает — MAPI.
После небольшого исследования выяснилось, что направлений для дальнейшего исследования три: можно попытаться работать с MAPI через RPC, можно использовать библиотеки, которые
Последний вариант,
Я долго не мог выяснить что за RPC применяет Microsoft, пока не начал перебирать всё, что приходит на ум. Оказалось, что Microsoft, в основном, использует диалект
Документации на него — кот наплакал, чуть примеров и в Сети есть несколько эксплоитов, написанных при помощи этого модуля. Этого хватило, чтобы понять как примерно им пользоваться и несколько дней и я пытался сделать прототип для общения с Exchange на нём.
Довольно быстро оказалось, что задача очень трудоёмкая. Даже для того, чтоб описать только вызовы верхнего уровня, ушёл бы не один день, а описывать
Готовых библиотек для работы с MAPI немного. Бесплатная, кажется, так и вовсе одна — libmapi. Сейчас стабильной версией считается 0.7, поскольку библиотека требует присутствия Samba4, то решено было ставить её из исходников. Оказалось, дело это очень непростое, так как база пакетов на машине, куда пришлось её ставить была разрушена, «Пайтонов» было два, от чего у исталлятора уносило крышу и имелась собственная Samba3, которая используется в работе.
Наши админы попробовали её поставить, но после нескольких проблем, сказали, что это очень сыро и ставить не получается. Я их понимаю — работы у них масса, слишком много времени на исталляцию недописанного софта они выделять не в состоянии. Поэтому библиотеку я ставил сам. В рунете я не смог найти никаких описаний того, что это
Для начала, лучше всего ставить версию из транка. Встаёт она значительно проще, чем стабильная. Далее. Сначала надо поставить Samba4, для этого в каталоге «script» есть специальный скрипт, который выкачивает её и ставит. Посколько API Samba меняется очень часто (это «альфа»), выкачивать нужно определённую ревизию, скрипт это умеет, но ему нужен git. Git — это распределённая система контроля версий, это пакет в Debian называется
Как оказалось, Samba4 в памяти не нужна. Всё что он неё надо, чтобы она была скомпилена со всеми библиотеками и небольшой конфиг, образец которого есть в дебрях libmapi. Не забудьте правильно выставить язык в конфиге, в небольшой инструкции по установке есть описание того, как это делается. В установочных файлах конфига проследите, чтобы все пути были указаны правильно. Например, мне пришлось поправить пути до исходников Samba с «samba4» на «samba4/source4», а так же руками добавлять PKG_CONFIG_DIR в файлы configure.
Дайте libmapi и Samba4 весь софт, который она попросит. Даже опциональный. И самый свежий (к Python это не относится, у меня взлетело с 2.4). Это важно. Некоторые файлы нужно будет перенести вручную, например, библиотеки для Python. После компиляции создайте профиль (в wiki libmapi есть инструкция) и запустите openchangeclient, чтобы проверить соединение. Если у вас домен, то не забудьте про утилиту provision (описание можно найти в инете, важно пускать её именно так как в примерах — чтобы текущей была указанная в примерах папка).
Если openchangeclient выдаёт
Кажется, это всё. Да, если у вас несколько «Пайтонов» на машине, удалите все, кроме одного, или перепишите место, где в конфигах определяется версия «Пайтона» руками (я так и сделал), иначе часть модулей, возможно, встанет не туда, куда ожидается. Python нужен для работы provision (кстати, некоторые утилиты написаны на Perl, но с ним проблем у меня не было).
После всех боданий, из Си удалось подключиться к Exchange и получить данные. Из Python пока удаётся только залогиниться, но это дело времени — нужно описать нужные структуры и понять что куда передавать. В документации, кстати, есть неточности, лучше читать исходники.
JavaScript: два синтаксиса определения функции
A function statement is shorthand for a var statement with a function value.
The statement:
function foo() {}
means about the same thing as:
var foo = function () {}
Мне кажется, что поведение, описанное мною под заголовком «JavaScript: баг с замыканием в FireFox», является хаком браузеров, для того, чтобы все функции, описанные ниже, можно было вызывать из вышестоящих функций.
Дополнение. Надо было вчера дочитать главу, прежде чем спать ложиться. Ниже описывается отличие этих конструкций, упоминается то, что я назвал «хаком браузеров» и даже есть намёк на различное поведение function под if в разных браузерах:
function statement is hoisting. This means that regardless of where a function a placed, it is moved to the top of the scope in which it is defined. This relaxes the requirement that function should be declared before used, which I think leads to sloppiness. It also prohibits the use of function statement in if statement, but they vary in how that should be interpreted. That creates portability problems.