12 мая 2013 г.

node.js express и шаблонизатор underscore


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

Почему express и underscore.
Простая реализация шаблонизатора. Вся логика реализуется на javascript-е в обычной html верстке. В шаблонах имеется доступ к методам библиотеки underscore (но это на любителя underscore). Если вы никогда им не пользовались, то я могу сказать, что все конструкции на js нужно помещать в конструкции <% ... print(variable_name); %> или <%-variable_name%>, <%=variable_name %>.

Устанавливается с пакетом uinexpress через npm. Версия которую я использовал 0.05. По номеру версии видно, что пакет совсем "маленький".

Добавление параметров в шаблон
Ситуация такая, имеется layout файл:
<!DOCTYPE html>
<html>
<head>
    <title><%=$title%></title>
</head>
<body><%=body%></body>
</html>

По умолчанию основной текст представления подставляется в шаблон на место переменной body. Но иногда требуется чтобы в шаблоне подставлялись и другие значения, например значения для meta-тегов.
Соответственно значения необходимых параметров можно задать:
  1. в настройках роутинга
  2. в самом представлении
В настройках роутинга:
// Так можно задать дефолтные параметры в шаблон
var defaultOptions={
    $title:"",
    $description:"",
    $keywords:""
};
app.get('/', function(req, res){         
    res.render('index.html', defaultOptions);
});
В самом представлении:
<% $title="simple page" %>
Правда если в шаблоне обнаружится что переменная нигде не было про инициализирована, то приложение выбросит exception. Поэтому в шаблоне может пригодится и такой код:
<% if(typeof $title != "undefined"){ %>
    <title><%=$title%></title>
<% } %> 

Задание дефолтного шаблона
Пакет uinexpress в качестве дефолтного шаблона использует файл layout  с указанным в настройках расширением и адресом папки с представлениями.

Чтобы иметь возможность задать произвольный файл шаблона в настройках приложения и в представлении я немного модифицировал код библиотеки. То что получилось доступно по ссылке на гитхабе.

Partials
С этим в uinexpess плохо. Partials не реализованы и вообще как нибудь их реализовать в шаблонном движке underscore проблематично.
Так как во время компиляции шаблона невозможно подставить значение из асинхронной callback функции. Именно это будет если считывать файлы из файловой системы. Возможный вариант решения, который мне видится - это при запуске приложения заносить в кэш uinexpress все необходимые partials а уже в самом шаблоне извлекать их значения.

4 февраля 2013 г.

IE следит за твоей мышкой...


IE следит за твоей мышкой...
Нашел дивную серию статей про уязвимость Internet Explorer:
Что-то на подробнее вот этого:
"Пользователи веб-браузера Internet Explorer оказались в щекотливой ситуации: согласно данным западных экспертов в области кибер-безопасности, уязвимость, скрывающаяся в интерпретаторе javascript данного браузера, позволяет злоумышленникам отслеживать движения курсора мыши удаленного пользователя.
Уязвимости подвержены версии Internet Explorer с 6 по 10. А считывание позиции курсора мыши происходит даже при неактивном окне веб-браузера, что ставит под удар пользователей банковских продуктов. Также можно говорить об угрозах для тех, кто использует виртуальные клавиатуры, включая и некоторых пользователей планшетов.
Между тем, корпорация Microsoft уже начала расследование инцидента и, вероятно, в скором времени выпустит патч.
Примечательно, что помимо злоумышленников, данной уязвимостью могут активно пользоваться рекламные компании, осуществляющие рекламу в Сети."
Так сильно удивился эпичности содержания решил проверить эту самую уязвимость.
<div id="detector"></div>
window.attachEvent("onload",function(){
    var     det = document.getElementById("detector");
    det.attachEvent("onmousemove",function(e){
        det.innerHTML = e.screenX + ", " + e.screenY;
    });
    setInterval(function(){
        det.fireEvent("onmousemove");
    },100);
});
Можно использовать и другие события не только mousemove.
Доступны только значения:
e.altKey {Bool} - состояние [ALT]
e.altLeft {Bool} - [ALT Left]
e.altKey {Bool} - состояние [CTRL]
e.altLeft {Bool} - [CTRL Left]
e.clientX {Int} - координаты мыши относительно просматриваемой области документа
e.clientY {Int}
e.offsetX {Int}
e.offsetY {Int}
e.screenX {Int} - координаты мыши относительно верхнего левого угла экрана (0,0) - верхний левый угол экрана
e.screenY {Int}
e.x {Int} - координаты относительно родительского компонента
e.y {Int}

Что нельзя узнать:
1) А был ли клик
2) какую клавишу нажали кроме (Alt,Schift, Ctrl)
3) правую или левую кнопку мыши нажали
Т.е. нужны еще уязвимости или доп. информация о происходящем на десктопе, что бы сделать какой-нибудь вывод.

Мощная уязвимость?

26 декабря 2012 г.

Автоматизация работы с Google Forms

Предыстория
Сервисом Google Docs пользуюсь хорошо и давно, но только относительно недавно, до меня дошло, что его можно использовать еще лучше (спасибо habrу).
Вся прелесть Google Docs это синергия его компонентов, так:
  • Google Forms – позволяет кастомизировать формы и встраивать на свои странички
  • Google Spreadsheet – поддерживает автоматизацию, с помощью скриптов на javascript, имеется поддержка триггеров и событий.
В каком-то посте на habrahabr узнал, что формы в Google Forms можно не только создавать и открывать для публичного доступа, но и кастомизировать по своему вкусу. Что очень пригодилось — форму можно публиковать на своем сайте, и в своем профиле Google docs собирать данные. Второй момент, эти данные нужны не только мне, и поэтому их требуется как то пересылать другим людям, которые ими будут заниматься. В такой схеме работы  Google выступает как прокси, пересылает сообщения через gmail. О том как я реализовал такую схему будет посвящен этот пост.

Реализация
Так как все данные собираются в  Spreadsheet, то средства автоматизации должны работать оттуда.
И так у вас есть работающая форма Google Forms, которая связана с таблицей в сервисе Google SpreadSheet (Рис. 1). Необходимо реализовать отправку на определенные email адреса заполненных пользователями данных формы при отправке формы.
Рис. 1 Таблица, с полученными данными формы
Для создания скрипта в Spreadsheet необходимо в меню сделать переход «Инструменты» → “Редактор скриптов». В появившемся окне необходимо выбрать пункт «Создать пустой проект».
Появится вкладка с редактором (Рис. 2).
Рис. 2

function sendOnSubmit(e){
  // Тестовый вариант триггера с отправкой всех данных
  var messageString="",
      data = e.namedValues;// исходный объект с заполненными данными
/*  То как выглядят данные от формы — json с заголовками колонок и их значения:
{"Разрешает обработку данных":["желает подписаться"],"Наименование  
организации":["zanussi"],"Желаемый срок кредитования (в  
мес.)":["12"],"Регион в котором осуществляется  
деятельность":["Москва"],"Контактный номер телефона":["+7 (122)  
222-22-22"],"Электронная почта":["www333@mail.ru"],"Желаемая сумма в  
рублях":["10 000 000"],"Как к Вам обращаться":["леопольд2"],"Отметка  
времени":["26.11.2012 22:57:14"]}
Приводим полученный объект к виду удобном для восприятия: */
  
  for(var key in data){
    messageString+=key+" : "+(data[key]&&data[key][0]?data[key][0]:JSON.stringify(data[key]))+"\r\n";
  }
  
  MailApp.sendEmail("mail@yandex.ru", "Заявка", messageString);
}

В данном редакторе можно создать как обычные запускаемые функции (через меню), так и запускаемые по событиям. Такие функции могут принимать в качестве аргумента объект события.
Так функция sendOnSubmit(e) — получает объект e, в котором свойство e.namedValues содержит в JSON формате значения заполненных полей. Объект e.namedValues «обрабатывается» в текстовое сообщение (messageString), которое затем рассылается по email адресам с помощью метода MailApp.sendEmail() .

Теперь осталось созданную функцию привязать к событию отправки формы.
Во вкладке с редактором кода переходим в меню «Ресурсы» → “Триггеры текущего скрипта”.
Появится диалоговое сообщение о необходимости настройки Триггеров текущего проекта (если они не были настроены) (Рис. 3).
Рис. 3
Кликаете по гиперссылке. Должно появиться окно с настройкой триггера (Рис. 4).
 Рис. 4 
В открывшемся окне необходимо выбрать нужную функцию, «Из таблицы» и событие «Отправка формы». Нажимаете кнопку «Сохранить».
Теперь от Вас потребуются подтвердить ваши действия. А именно разрешения на отправку почты. Ведь все сделанное будет выполняться от вашего имени (учетной записи). Даже почту будет отправляться от вашего gmail профиля.
«Авторизуемся» и окончательно сохраняем триггер.

6 декабря 2012 г.

Маленькие сюрпрайзы PHP PDO.


На днях ковыряясь в mysql при помощи pdo сделал для себя маленькое открытие.
В методах prepere(), execute() не могут использоваться переменные (именованные не именованные  через которые в запрос подставляются название таблиц и колонок. Вот так никакого exception, ни Fatal error, Kernel demage и т.п. Все тихо пропускаем и переходим к следующим инструкциям.

Вот такое не сработает:

$preQuery = $this->pdo->prepare('SHOW ?');
$preQuery->execute(array("tables"));
К вашим услугам конкатенация строк и хранимые процедуры

12 июля 2012 г.

Какое в вашей форме поле ввода номера телефона?

Заполняя контактные данные в веб формах, вижу что то на подобие такого
или такое
На что идут веб мастера, чтобы упрастить себе работу  и навязать посетителю свое видение отформатированного номера телефона.

Лично я считаю, что чем проще форма тем лучше - просто оставить текстовое поле и попробовать сделать одним из двух вариантов:
  1. Задать шаблон в виде регулярного выражения атрибута pattern текстового поля (доступны в HTML5);
  2. Уже отправляя или получая данные, удалять из введенного пользователем значение, к примеру, все не цифровые знаки, распарсивая и приводя к нужной форме.
Начиная с HTML5 тесктовое поле input обзавелось атрибут pattern и сделало возможным проверку введенного значения регулярным выраженнием. (Если бы я не написал регулярное выражение для проверки корректности ввода номера телефона, то и начинать этот пост не было бы смысла.)
Но чтобы распарсить номер телефона надо иметь  модель "типового" номера телефона.
Поэтому приведу сразу какими могут быть номера телефона:
  • С или без указания кода страны +7, 28 или просто 8;
  • С или без указания кода оператора или кода города - 3 цифры (В Санкт-Петербурге других не встречал);
  • 7 цифр номера телефона c пробелами, через тире или все слитно (что то вроде 123-45-67, 1234567, 123 45 67).
Согласно этой модели привожу регулярное выражение которое удовлетворяет озвученным требованиям:
\s*(?:\+\d{1,2}|\d)?\s*(?:\(\s*\d{3}\s*\)\s*|\-?\d{3}(?:\-|\s)?)?\d{3}(?:\-|\s)?\d{2}(?:\-|\s)?\d{2}\s*
Описание с комментарием:
/\s*
(?:\+\d{1,2}|\d)? # +7, +38 или 8 или ничего из этого
\s* # пробелы, или ничего
(?:\(\s*\d{3}\s*\)\s*|\-?\d{3}(?:\-|\s)?)? # код города или оператора, может быть даже в скобочках
\d{3} # 3 обязательных числа
(?:\-|\s)?
\d{2} # 2 обязательных числа
(?:\-|\s)?
\d{2} # 2 обязательных числа
\s*/x
Регулярное выражение это можно использовать для выделения номеров телефона в произвольном тексте (Например если стану sms-спамером и буду писать граббер номеров телефонов с сайтов). Модифицировав выражение, можно извлекать различные части номера телефона.

Чтобы проверить работоспособность регулярного выражения мне нужна была большая выборка примеров номеров телефонов согласно созданной модели номера телефона. Для этой цели я использовал программу генератор seo текстов Seo Anchor Generator. Программа Seo Anchor Generator позволяет по заданному шаблону составить выборку всех возможных комбинаций по заданному шаблону.
Пример используемого в программе шаблона:
{+{7|38}|8|}{| }{({ |}012{ |}){ |}|{-|}012{ |-|}|}345{-| |}67{-| |}89{ |}
Таким образом я собрал 2160 примеров правильных комбинаций написания телефонов.

Javascript код для тестирования:
function isFormattedTelefon(str){
    return /^\s*(?:\+\d{1,2}|\d)?\s*(?:\(\s*\d{3}\s*\)\s*|\-?\d{3}(?:\-|\s)?)?\d{3}(?:\-|\s)?\d{2}(?:\-|\s)?\d{2}\s*$/.test(str);
}
// массив с различными комбинациями написания одного телефона
var testArray2=[ "+7( 012 ) 345-67-89","+7( 012 ) 345-67-89", ... , "345 67-89" ];
for(var i=0, len=testArray2.length;i<len;i++){
    console.log("#%s is: %s",i,isFormattedTelefon(testArray2[i]) );
}
Осталось только обкатать все это дело.

28 июня 2012 г.

Почему я больше не делаю мобильные версии сайтов


Мобильная версия будет отвлекать силы и время на ее поддержание. Смартфоны с удобным выходом в интернет сделают эту работу просто бессмысленной. Они стали доступнее, их качество выросло.
Вот, какие гейши...
Мобильные устройства быстро развиваются, в 2010 году смартфон с разрешением экрана 320 на 480 пикселей стоил около 9 тыс. руб. в 2012 около 4,5 тыс (мой телефон смартфон обесценился в 2 раза! и он все еще продается в магазинах). По собственному опыту могу сказать, что комфортное просматривание страниц начинается именно с этого разрешения экрана. Браузеры  для  смартфонов выполнены на более высоком уровне, чем для обычных мобильных телефонов, которые с малой вероятности вообще будут обновляться. Смартфоны уже  позволяют совмещать  функции некоторых уже привычных устройств, таких как навигаторы, электронные читалки, медиа плееры и будильники, органайзеры, калькуляторы и др, что позволит смартфонам занять место в карманах людей.  Стандартные браузеры для устройств на Android до 4.0 и IOs, Windows Phone, скорее всего, обновляться не будут, но будут доступны устанавливаемые альтернативные браузеры, что позволяет предположить, что качество отображение страниц в браузере будет повышаться.
К тому же, всякая попытка «пересаживать» посетителей на урезанную мобильную версию будет вызывать раздражение у них.
Что будет с мобильными телефонами
Мобильные телефоны с номинальной возможностью выхода в интернет существуют, но их доля среди владельцев будет снижаться и останется на определенном нишевом уровне. Выход в интернет с этих устройств не рассматривается их владельцами в качестве приоритетных опции телефона.
Что делать с сайтом
Теперь сайт будет необходимо тестировать для отображения на мобильных устройствах, применять техники адаптивной верстки с явным использованием viewport-а.

20 июня 2012 г.

Ruby, регулярные выражения и Windows XP


Ruby хоть и является одним из наикроссплатформейших языков общего назначения с которыми мне приходилось работать, но в нем то и дело спотыкаюсь о грабли ее реализации на разных платформах.
Так сегодня мне потребовалось написать скрипт на ruby, который должен был запускаться на Windows XP (При этом я еще хотел его запускать дома, уже на Linux).  Проблема заключалось в том что регулярные выражения, которые я применял к импортируемому тексту из стороннего файла напрачь не работали. Как заведено, в опенсорсе, раскажу о своей проблеме и как ее решал, кому нибудь пригодиться.
Что было:
  • Windows XP
  • ruby (MRI v1.9.3)
  • Большой текстовый файл в кодировке utf-8, почти все содержимое набрано кириллицей.
Соответственно требовалось написать консольный скрипт, который бы потрашил этот злополучный файл регулярными выражениями. Регулярные выражения, конечно же были с модификатором "u", ибо содержали все бе кириллические символы.
Как иследовало ожидать проблемы в Windows XP были в двух кодировках. Консоль в Windows XP в IBM866 (соответственно импортируемый текст тоже был в ней), сам файл в utf-8.

Вообщем пришел к такому варианту:
# coding: utf-8
# Попутно, в Windows, импортированный utf-8 текст (через File) будет в utf-8 (а не IBM866)
Encoding.default_internal = 'UTF-8'
Encoding.default_external = 'UTF-8'
# регулярное выражение:
FIOPATTERN=/^Имя:\s*([^\n^\r]+)/u