суббота, 14 сентября 2013 г.

Как узнать ширину скроллбара браузера?

Не так часто, но все же случаются ситуации, когда веб-разработчику необходимо определить ширину браузерного скроллбара (например, чтобы не было скачков контента при переключении свойства overflow и т.д.). Дэвид Уолш (David Walsh - http://davidwalsh.name/) предложил очень изящное решение, код которого можно увидеть ниже.

CSS-код:

/* Убираем данный элемент подальше от глаз пользователя */
.scrollbar-measure {
     width: 100px;
     height: 100px;
     overflow: scroll;
     position: absolute;
     top: -9999px;
}

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

JavaScript-код:

// Создаем элемент и вставляем его в тело страницы
var scrollDiv = document.createElement("div");
scrollDiv.className = "scrollbar-measure";
document.body.appendChild(scrollDiv);

// Получаем ширину скроллбара
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
console.warn(scrollbarWidth); // Mac: 15

// Удаляем элемент
document.body.removeChild(scrollDiv);

Данный подход очень прост и не нуждается в излишних комментариях.

четверг, 28 февраля 2013 г.

Демонизируй это или как запустить Node.js-приложение в виде сервиса при помощи forever

В этой заметке будет рассказано о том, как при помощи замечательного модуля forever для Node.js можно запустить ваше приложение в виде демона на Debian. Модуль Forever нужен для того, чтобы запускать приложение в виде демона, проверять его доступность и перезапускать в случае чего.

Что понадобится

  • Собственно, Node.js;
  • Менеджер пакетов npm.

Устанавливаем Node.js

Рискну предположить, что Node.js у вас уже установлен (а если все-таки нет, то лучшим вариантом будет установка из исходников - https://github.com/joyent/node/wiki/Installation).

Устанавливаем forever

forever - модуль разработанный nodejitsu, - нужен для того, чтобы запускать приложения в виде демона (режиме постоянного выполнения - отсюда и название модуля). Если приложение по каким-то причинам прекращает свое выполнение, то forever его перезапускает. Также, данный модуль имеет API, так что вы можете использовать его в коде своих проектов.

forver может быть установлен при помощи npm:

sudo npm -g install forever

Запускаем тестовое приложение

Давайте создадим тестовое микро-приложение test.js, на котором будем отрабатывать навык работы с forever:

var http = require('http');

http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('testing. . .\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

Запустим созданное приложение, чтобы убедиться в его работоспособности:

node test.js

Примечание: возможно, придется выполнить в консоли следующие две строки:

export PATH=$PATH:/usr/local/bin
export NODE_PATH=$NODE_PATH:/usr/local/lib/node_modules

Открываем в браузере адрес http://localhost:8124. Если все ок, то вы должны увидеть надпись "testing..." на странице.

Ок! Теперь нужно переключиться в консоль и завершить выполнение запущенного приложения - пришло время forever! Выполняем команду:

forever start test.js

Примечание: Если вы выполняли установку этого модуля из-под обычного пользователя или без ключа -g, то установка могла произойти в текущую рабочую директорию или в домашнюю директорию вашего пользователя. В таком случае, чтобы запустить forever нужно выполнить команду:

~/node_modules/.bin/forever start test.js

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

Итак, запустившись, forever должен вывести в консоль что-то типа этого:

info: Running action: stop
info: Forever stopped process:
data: uid command script forever pid logfile uptime 
[0] Bce7 node test.js 33483 33484 /Users/marciogalli/.forever/Bce7.log 0:0:0:51.143

Помни о логах

forver хранить записи логов, stdout и stderr в файлах, ассоциированных с запущенными процессами - они лежат в скрытой директории .forever директории пользователя, из-под которого forever был запущен.

Самое интересное - автозапуск Node.js-приложения при загрузке операционной системы

Рассмотрим автозапуск приложения относительно Debian 6.

Итак, для начала нужно создать скрипт запуска в директории /etc/init.d. Он будет принимать два параметра start и stop.

В самом скрипте, в строке запуска forever необходимо указать важный ключ -p с путем к директории, в которую будут сохранятся идентификаторы запущенных из-под forever процессов (приложение). Это нужно для того, чтобы forever мог корректно перезапустить приложение в случае чего и остановить его выполнение.

Пример скрипта автозапуска /etc/init.d/your_app_name:

#! /bin/sh
### BEGIN INIT INFO
# Provides: forever node
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Node.js App Init Script
# Description: This file should be used to construct scripts to be
# placed in /etc/init.d.
### END INIT INFO

# Author: LordotU

# Do NOT "set -e"

export PATH=$PATH:/usr/local/bin
export NODE_PATH=$NODE_PATH:/usr/local/lib/node_modules

case "$1" in
start)
exec forever -a -l /path/to/directory/containing_script/forever/forever_log.log -o /path/to/directory/containing_script/forever/your_app_name_output.log -e /path/to/directory/containing_script/forever/your_app_name_errors.log --sourceDir=/path/to/directory/containing_script/ -p /path/to/forever/pidfiles start your_app_name.js
;;
stop)
exec forever --sourceDir=/path/to/directory/containing_script/ stop your_app_name.js
;;
*)
echo "Usage: /etc/init.d/your_app_name {start|stop}"
exit 1
;;
esac

exit 0

Выставляем правильные права (правильные права? о_О):

chmod 755 /etc/init.d/your_app_name

И даем системе знать, что она должна выполнять этот скрипт на перечисленных в нем уровнях запуска и остановки:

sudo insserv -v /etc/init.d/your_app_name

Если потребуется этот скрипт убрать, то нужно выполнить:

sudo insserv -v -r /etc/init.d/your_app_name

На этом - все. Ах, да - полезные ссылки:

четверг, 8 ноября 2012 г.

Как использовать HTML5 Full-Screen API

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

На данный момент HTML5 Full-Screen API реализован в браузерах Chrome, Safari и Firefox.

Использование HTML5 Full-Screen API имеет одно существенное отличие от нажатия клавиши F11: в первом случае в полноэкранный режим переходит конкретный элемент страницы (видео, изображение и т.п.), а во втором случае в полноэкранный режим переходит все внутреннее содержимое окна браузера. Когда какой-либо элемент переходит в полноэкранный режим, пользователю показывается сообщение о том, что он может выйти из этого режима в любой момент, нажав ESC.

Основные методы, свойства и стили API.

element.requestFullScreen()

Данный метод позволяет перевести конкретный элемент в полноэкранный режим, например document.getElementById("myvideo").requestFullScreen().

document.cancelFullScreen()

Выходит из полноэкранного режима и возвращает к обычному просмотру.

document.fullScreen

Возвращает true, если браузер находится в полноэкранном режиме.

:full-screen

Псевдо-селектор в CSS который применяется к элементу, находящемуся в полноэкранном режиме.

РАЗДРАЖАЮЩИЕ ПРЕФИКСЫ

К сожалению, никуда деться от вендорных префиксов не получится - придется их использовать. И для CSS, и для JavaScript.

Standard Chrome/Safari Firefox
.requestFullScreen() .webkitRequestFullScreen() .mozRequestFullScreen()
.cancelFullScreen() .webkitCancelFullScreen() .mozCancelFullScreen()
.fullScreen .webkitIsFullScreen .mozfullScreen
:full-screen :-webkit-full-screen :-moz-full-screen

К еще большему сожалению, вся эта красота не поддерживается ни в Опере, ни в ИЕ. Но с заделом на будещее мы добавим префиксы -ms и -o.

Для удобства написания кода можно использовать такую функция, которая сама подставит необходимые префиксы к методам и свойствам:

var pfx = ["webkit", "moz", "ms", "o", ""];
function RunPrefixMethod(obj, method) {
  var p = 0, m, t;
  while (p < pfx.length && !obj[m]) {
    m = method;
    if (pfx[p] == "") {
      m = m.substr(0,1).toLowerCase() + m.substr(1);
    }
    m = pfx[p] + m;
    t = typeof obj[m];
    if (t != "undefined") {
      pfx = [pfx[p]];
      return (t == "function" ? obj[m]() : obj[m]);
    }
    p++;
  }
}

А таким образом можно перевести какой-либо элемент в полноэкранный режим:

var e = document.getElementById("fullscreen");
e.onclick = function() {
  if (RunPrefixMethod(document, "FullScreen") || RunPrefixMethod(document, "IsFullScreen")) {
    RunPrefixMethod(document, "CancelFullScreen");
  }
  else {
    RunPrefixMethod(e, "RequestFullScreen");
  }
}

CSS

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

#myelement
{
width: 500px;
}
#myelement:full-screen
{
width: 100%;
}
#myelement:full-screen img
{
width: 100%;
}

К несчастью, не получится использовать такой код:

/* НЕ БУДЕТ РАБОТАТЬ */
#myelement:-webkit-full-screen,
#myelement:-moz-full-screen,
#myelement:-ms-full-screen,
#myelement:-o-full-screen,
#myelement:full-screen
{
width: 100%;
}

Вместо него нужно использовать такой код:

/* А это работает */
#myelement:-webkit-full-screen { width: 100% }
#myelement:-moz-full-screen { width: 100% }
#myelement:-ms-full-screen { width: 100% }
#myelement:-o-full-screen { width: 100% }
#myelement:full-screen { width: 100% }

Странно это.

Источник: http://www.sitepoint.com/html5-full-screen-api/

понедельник, 29 октября 2012 г.

Поддержка изображений для retina-дисплеев в вашем CSS-коде при помощи SCSS

Если вам интересно, как можно добавить поддержку изображений для retina-дисплеев в css-код вашего приложения или сайта и вы используете препроцессор scss, то из этой заметки вы узнаете, как это можно сделать очень и очень легко.

Просто подключите такой SCSS-миксин (разумеется, сначала поменяв его параметры на необходимые) в любой набор ваших стилей:

div.logo {
  background: url("logo.png") no-repeat;
  @include image-2x("logo2x.png", 100px, 25px);
}

Код самого миксина выглядит так:

@mixin image-2x($image, $width, $height) {
  @media (min--moz-device-pixel-ratio: 1.3),
  (-o-min-device-pixel-ratio: 2.6/2),
  (-webkit-min-device-pixel-ratio: 1.3),
  (min-device-pixel-ratio: 1.3),
  (min-resolution: 1.3dppx) {
    background-image: url($image);
    background-size: $width $height;
  }
}

Как видите, разрешение дисплея определяется через @media и все сосредоточено в одном месте, что сэкономит ваше время в будущем, когда на рынке появится больше устройств.

Стоит обратить внимание, что при помощи SCSS можно сделать @media-правилами вложенными в другие, т.е. будут работоспособными оба участка кода:

@media print {
  body {
    // Свойства
  }
}
body {
  @media print {
    // Свойства
  }
}

Источник: http://37signals.com/svn/posts/3271-easy-retina-ready-images-using-scss

пятница, 26 октября 2012 г.

JavaScript. Проблемы с безопасностью

Следующий код, собственно, и иллюстрирует проблему:

<script>var str ="</script><script>alert('Pwned');</script>"; </script>

Не верите? Убедитесь в этом сами: http://f.cl.ly/items/2c2D0V1T0D150P2B173R/pwned.html. Браузер игнорирует тот факт, что тэги <script> находятся внутри JavaScript-строки, и нормально отрабатывает функцию alert().

Причина такого странного поведения кроется в том, как HTML-страница обрабатывается браузером. Сначала парсится HTML-код, а потом строится дерево документа. И только потом выполняется уже JavaScript-код. В примере, приведенном выше, в HTML-рендер не понимает, что тэги находятся непосредственно в строковой переменной и парсит их как элементы дерева документа, что после формирования документа приводит к выводу alert-сообщения.

Такое поведения могло бы быть не более, чем просто забавным... Однако, оно может привести к XSS. Например, в ERB-шаблоне (или в любом другом) мы хотим инициализировать JavaScript-переменную JSON-строкой:

<script>var users =<%=@users.to_json.html_safe %>;</script>

Собственно, если в @users содержаться какие-нибудь данные из внешнего источника (например, пришедшие от пользователя), то ваше приложения может подвергнуться XSS-атаке.

Если вы используете Rails, то вы можете закрыть эту уязвимость при помощи установки значения параметра ActiveSupport.escape_html_entities_in_json в true.

Источник: http://blog.alexmaccaw.com/a-javascript-security-flaw

вторник, 23 октября 2012 г.

CSS3 против jQuery-анимаций

Все началось с Флеша... Именно он позволил нам показывать на страницах гораздо большее, чем обычные картинки и текст. Также, Флеш давал разработчикам возможность добавлять различные анимации и другие эффекты на веб-страницы, что позволяло разнообразить пользовательский опыт. Тем не менее, он обладает рядом серьезных недостатков: проблемами с безопасностью, долгим временем загрузки на медленных каналах и т.п. На смену Флешу пришли различные JavaScript-библиотеки: jQuery, Prototype и Mootools, которые могли и могут делать очень много вещей, которые может и Флеш. Плюс ко всему, эти библиотеки работают в нативной среде браузера и более просты для использования обычными разработчиками. А несколько лет назад... Пару лет назад мы получили различные анимационные возможности в CSS3 - что потенциально очень круто, так как теперь все обрабатывается напрямую браузером и мы получаем значительный прирост в скорости.

И все же, какой вид анимаций лучше использовать? В этой статье мы постараемся сравнить анимации, сделанные при помощи jQuery и CSS3, и сделать выводы об их производительности.

Введения в jQuery-анимацию

Библиотека jQuery была специально придумана для того, чтобы оградить и абстрагировать разработчиков от многих сложностей. В качестве примера рассмотрим, как создать простой блок <div> и применить к нему какую-нибудь анимацию после клика по определенной кнопке.

Подключаем jQuery из какой-нибудь CDN:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js?ver=1.8.1"></script>

Создаем блок <div> и применяем к нему базовые стили:

<div></div>
div{ margin-left:10px; margin-bottom:10px; background-color:red; opacity:1; float:left; width:100px; height:1px; }

Теперь, создаем кнопку, клик по которой будет запускать анимацию созданного выше блока:

<button id="start">Start Animation</button>

Напишем немного jQuery-кода, который будет выполняться после клика по кнопке и применять анимацию к блоку. После клика по кнопке высота блока должна увеличиться до 25 пикселей, блок должен стать полупрозрачным, и все это должно произойти в течение 2 секунд:

$("#start").click(function(){ $("div").animate({ opacity: 0.5, height:"25px", } , 2000); });

При помощи jQuery реально легко можно анимировать практически любой элемент, используя совсем немного кода. Но самое замечательное - это то, что такая анимация будет работать в любом браузере, начиная с IE6!

Введение в CSS3-анимацию

Чтобы создать анимацию при помощи CSS3, вам нужно определить две разные конструкции в вашем коде. Сперва-наперво, нужно определить, какие формы будет принимать объект анимации, при помощи правила @keyframes. Это будет выглядеть приблизительно так:

@keyframes my-animation { 0% {height:0px; opacity:1; } 100% {height:25px; opacity:0.5; } }

my-animation - это идентификатор вашей анимации, а каждая строка свойств - определяет состояние анимации для заданного ключевого кадра (в процентном отношении к длительности анимации). В данном случае все очень просто: мы определили состояния блока для начала (0%) и для конца (100%) анимации. Далее, чтобы применить эту анимацию к нашему блоку, мы должны добавить свойство animation в список свойств его стиля:

div{ margin-left:10px; margin-bottom:10px; background-color:red; opacity:0.5; float:left; width:100px; height:25px; animation: my-animation 2s; }

Эта функциональность идентична той, что мы определили при помощи jQuery. К сожалению, поддержка необходимых CSS3-свойств со стороны браузеров оставляет желать лучшего - IE, например, поддерживает эти свойства только с 10 версии. Остальные браузеры обладают поддержкой этих свойств, но не все из них могут делать это без вендорного префикса (-webkit-, -moz-, -ms- и -o-). Так, например, для Оперы мы должны написать:

@-o-keyframes my-animation { 0% {height:0px; opacity:1; } 100% {height:25px; opacity:0.5; } } и div { ... -o-animation: my-animation 2s; }

Это делает код более сложным и громоздким. Однако, если вы хотите сократить все до одного блока, вы можете использовать какой-нибудь препроцессор или библиотеку, как эти:

  • SASS - css-препроцессор, который позволяет использовать переменные, функции и другие фичи, которые позволяют использовать CSS более эффективно;
  • Prefixfree - JavaScript-библиотека, которая в процессе использования добавляет к требуемым свойствам вендорские префиксы.

Очевидно, вы подумали, что использовать jQuery и проще, и лучше, и быстрее. И действительно, если вы хотите, чтобы во всех браузерах было все одинаково, то использовать стоит именно jQuery.

Анимационные войны: CSS3 против jQuery

Итак, пришло время столкнуть лбами CSS3 и jQuery и выяснить, какая же из этих технологий предпочтительней с точки зрения производительности. Для тестирования мы будем использовать код, который уже написали. Вот только анимировать мы будем целых 300 <div>-блоков, причем, одновременно - это позволит нам сделать наиболее объективные выводы.

CSS3

График выполнения CSS3-анимации выглядит следующим образом:

Данный график был сделан при помощи встроенного в Opera Dragonfly профайлера. Тест проводился в браузере Opera версии 12 на Mac OS X.

Как видно на графике, на все про все ушло где-то 2.9 секунды.

Теперь, давайте посмотрим на второй график, который показывает количество использованной памяти. Он был сделан при помощи опции "Память" в панели Timiline инструментов Developer Tools браузера Google Chrome 21:

И что мы видим? Всего-то 1.5 МБайта потребовалось приблизительно 100 действиям по отрисовке и т.п. Итак, подведем итог:

  • Количество действий, потребовавшихся для осуществления анимации, - около 100;
  • Время, потребовавшееся для завершения анимации, - 2.9 секунды;
  • Потребовавшаяся память - всего-то 1.5 МБайта;
  • А теперь, протестируем jQuery-анимацию.

jQuery

График выполнения jQuery-анимации выглядит следующим образом:

Тут мы видим, что на все ушло около 5 секунд - гораздо дольше, не правда ли? Сама анимация, правда, выполнялась не так долго по сравнению с CSS3-вариантом: все остальное время - это накладные расходы на загрузку JavaScript. Также, обратите внимание, что суммарное количество операций, потребовавшихся на осуществление анимации, - больше, чем 2000. Это гораздо больше, чем 100.

А теперь взглянем на график потребления памяти:

В данном случае мы видим, что jQuery-анимация гораздо прожорливее, чем CSS3 - целых 6 МБайт! Подведем итог:

  • Количество действий, потребовавшихся для осуществления анимации, - около 2000;
  • Время, потребовавшееся для завершения анимации, - 5 секунд;
  • Потребовавшаяся память - целых 6 МБайт;
  • Стоит отметить, что в различных браузерах и на компьютерах различной конфигурации мы можем наблюдать разные результаты. Однако, результаты, полученные выше, все же позволяют сделать необходимые нам выводы. На данный момент Chrome выполняет JavaScript быстрее всех своих конкурентов, но когда дело доходит до CSS3-анимаций, то тут на первом месте Opera, так как она выполняет их более плавно и быстро. Firefox и Safari также делают свое дело неплохо. А вот кошмар разработчиков под названием IE (в версии 9 на данный момент), не поддерживает CSS3-анимации вовсе, но весьма сносно выполняет JavaScript.

И победитель...

CSS3! Реально, CSS3 вне конкуренции. А все потому, что процессор CSS3 в браузере написан на C++ и машинный код выполняется несомненно быстрее, чем интерпретация JavaScript.

Полученные выше результаты очень недвусмысленно намекают на то, что для анимаций надо бы использовать CSS3. Однако, вы должны помнить о том, что у вас могут быть клиенты, которые до сих пор используют старые версии браузеров, и если анимация должна работать и в них, то иного выхода, кроме как использование jQuery, у вас нет.

Ну а если поддержка всякого старья для вас не принципиальна, то CSS3 - ваш выбор!

Источник: https://dev.opera.com/articles/css3-vs-jquery-animations/

суббота, 14 апреля 2012 г.

Все на ZFConf 2012!!!

21 апреля в Москве пройдет очередная ежегодная конференция для веб-разработчиков ZFConf 2012, посвященная популярной платформе Zend Framework.

В этом году с докладом выступит гость из Италии — Enrico Zimuel из Zend Framework Core Team. А также Виктор Фараздаги, Александр Веремьев, Алексей Качаев и многие другие специалисты.

На сайте опубликован полный список докладов и открыта регистрация.

Доклады:

К участию также приглашаются спонсоры и инфопартнеры. По всем предложениям и вопросам пишите, пожалуйста, через форму обратной связи.

Следите за последними новостями:

Организатор: компания Wizartech

Партнеры: сообщество Zend Framework и конференция Frameworks Days

воскресенье, 1 апреля 2012 г.

Модуль управления доступом к меню Menu subtree per role для Drupal 6

Итак, второй модуль, призванный помочь администратору в деле управления доступом к меню на страницах создания/редактирования материала. Описание модуля находится тут: http://olevshin.ru/projects/drupal_6_menu_subtree_per_role.