software simian's typewritings

mx310, 6 buttons в линухе

— что в постновогодние каникулы делал?

— настроил мышь и клаву...

дисклеймер: пишу на самом деле больше для себя, чтоб не забыть : )

есть у меня любимая мыша Logitech mx310. Удобная, с 6 кнопками. Очень удобно на одну из них вешать Backspace, он же забой (забей : ), а на другую — F5. Хождение по интернету тогда становится буквально волшебным, а забой вообще часто пригождается.

по приходу © на линух я сравнительно быстро повесил забой на привычное место. А вот с f5 не задалось. И так, и этак пристраивался — не выходит каменный цветок. В конце концов надежно установил, что с точки зрения линукса у меня на мыше две левые кнопки. А зачем мне столько — то ему неведомо.

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

/etc/X11/xorg.conf

Section "InputDevice"
Identifier "Configured Mouse"
Driver "evdev"
Option "CorePointer"
Option "Device" "/dev/input/by-id/usb-Logitech_USB-PS.2_Optical_Mouse-event-mouse"
EndSection

/etc/X11/imwheel/imwheelrc

".*"
None, Up, BackSpace
None, Down, F5

и в автозапуск

imwheel -k -b "68"

якоря и window.location = url

полезняшка, которая может сэкономить время поиска трудновоспроизводимого бага:

якоря в адресе — зло для яваскрипта. Вернее, они, конечно, хороши для многих вещей, но если в адресе есть якорь, то window.location.reload() не сделает того, чего вы ожидаете, а редирект браузера на ту же страницу (после логина, например) не сработает. Вам поможет .replace(/#.*$/, '')

кстати, писать document.location = url — глупо по вполне очевидной причине : )

gzip, статика и graceful degradation*

Придумал мазу. Если что, она из области «создать себе проблему и героически её забороть».

Кратко:

для приближения к нирване достаточно рядом с js|css контентом класть его .gz-копии и этот .htaccess

RewriteEngine on
RewriteRule ^(.*\.gz)$ $1 [L]
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteRule ^(.*)$ $1.gz
AddEncoding x-gzip .gz
AddType application/x-javascript .js
AddType text/css .css

Длинно:

Если вебмастер хочет экономить трафик свой и клиента, обычно он включает в своём апаче сжатие. То есть, берет moddeflate или modgzip, и они сами всё за него делают: смотрят, умеет ли клиент gzip, если умеет, то сжимают данные и подставляют нужные заголовки. Все довольны, все смеются.

Но у такого подхода есть парочка минусов. Первый: сжатие производится динамически. То есть, каждый раз, когда сервер отдает, например, prototype.js, сжималка заново выполняет свою работу. Не то, чтобы это чрезмерно грузит сервер, но неаккуратненько как-то ©

Второй минус заключается в том, что в moddeflate нельзя отключить режим передачи chunked (disclaimer: точнее, я пока что не нашел, как это сделать). Modgzip это как будто умеет, но он не так проверен временем. Чем грозен режим chunked? Да особенно ничем, кроме того, что всенародно нелюбимый браузер™ не всегда его понимает. Если протокол https, данные сжаты, а режим передачи chunked, IE может попытаться использовать файл, не разжимая его.

Первый вариант, который приходит в голову для решения проблемы — при отдаче грамотно сжимать данные скриптом так, чтобы аццкий режим не включался. Собственно, первые полчаса я именно так и бился. Однако, каюсь, ниасилил. При запросе самого файла он прекрасно открывается, но если он подключен к документу — фиг! Даже в опере. Скорее всего, я где-то неоднократно слажал, но это неважно, потому что я придумал способ получше.

Натолкнула меня на идею вот эта статейка. Именно там я увидел фразу «Here since the Javascript is static, which is true for most AJAX applications these days, we can pre-compress which will reduce latency and CPU overhead.» То есть, мы радостно отдаём браузеру уже готовый .gz файл и идём готовить что-то изысканное из двух зайцев.

Но как быть с теми клиентами, которые не понимают сжатия? Естественно, для них нужен свой, несжатый файл, который нужно отдавать убогим. Только непонятно, когда который из двух файлов подключать. Смотреть в шаблоне на заголовки HTTP? Не, так мешать уровень протокола и уровень отображения я не согласен : ) Разбираться с заголовками — это работа скорее апача. Конкретнее, modrewrite. Он, правда, не слышал о HTTPACCEPT_ENCODING, зато спокойно скушает такую конструкцию: %{HTTP:Accept-Encoding}. Немного мучений, и имеем на выходе такую конструкцию для .htaccess:

RewriteEngine on
RewriteRule ^(.*\.gz)$ $1 [L]
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteRule ^(.*)$ $1.gz

Человеческим языком говоря: при запросе не .gz файла приписывать к имени запрашиваемого .gz, если клиент понимает gzip.

Тут встает другая проблема: апач честно говорит клиенту, что отдает не яваскрипт и даже не css, а гзип. IE, конечно, заголовки Content-Type игнорирует, но это не повод расслабляться. Кроме того, откуда браузеру знать, что отправленные ему байты перед употреблением нужно разжать? («Сжатый файл» и «сжато при передаче» — разные вещи все-таки.) Тут нас выручит mod_mime:

AddEncoding x-gzip .gz
AddType application/x-javascript .js
AddType text/css .css

Небольшое пояснение: если вы не знали, в представлении апача у файла может быть несколько расширений. Например, у prototype.js.gz их два: js и gz. Этим мы и пользуемся: если у файла есть расширение gz, то отправляем заголовок Content-Encoding: gzip. А две другие строчки нужны для того, чтобы перекрыть апачевское умолчание «отдавать для .gz файлов Content-Type: application/x-gzip». Мы укажем верный Content-Type.

Естественно, удобнее всего будет, если вы автоматизируете процесс создания .gz-копий. Заодно очень полезно склеивать все однотипные файлы в один (значительно уменьшается число запросов к серверу), и вырезать оттуда всё лишнее: пробелы, комментарии и т.п. Это несложно, jsmin и Vitamin вам в руки.

В результате всех мучений имеем в пять раз меньший объём css+js.

*graceful degradation ~ нормальная работа в том случае, если клиент туп; например, не видит он картинок, но сайтом пользоваться может, или нет у него яваскрипта, но это ему почти не мешает.

,

Cross-domain XMLHttpRequest

собственно, сабж

суть: ифрейм на другой домен, данные передаются через document::postMessage(), который работает, как известно, не везде : )

xml tree (opera user js)

хотя штука узкоспецифическая, не могу не поделиться : )

знаете, когда в ie или ff открывается голый xml, браузеры отрисовывают его таким клевым деревом, которое можно удобно сворачивать-разворачивать для анализа. Опера этого не умеет. По крайней мере, от рождения. Но один умелец нарисовал для неё user javascript, который ровно этим и занимается. Брать его можно здесь

обсуждение в жж