Валидация даты на JavaScript

Для ввода дат на сайтах я обычно использую замечательный плагин Jquery Datepicker, выставляя текстовому полю, к которому он привязан, режим readonly. Таким образом, я точно знаю, в каком формате введенная дата придет на сервер, и как ее там обработать (но не забываю о проверке введенных данных на стороне сервера!). Однако, недавно возникла задача разрешить ручной ввод даты в текстовом поле в формате дд.мм.гггг. Конечно, можно разрешить писать в текстовое поле все, что угодно и проверять валидность введенных данных на сервере. Однако, на мой взгляд, было бы удобней проверить данные сразу на стороне клиента, и если данные введены неверно — принять нужные меры.
Итак, вот как будет работать наша система: при клике на поле для ввода даты будет отображаться стандартный Jquery Datepicker. Если же пользователь хочет ввести дату вручную, он может написать ее прямо в этом текстовом поле. Для облегчения этого добавим к полю маску ввода Jquery Masked Input. Если введенная дата валидна, включаем кнопку сабмита и подсвечиваем поле зеленым. Если дата не валидна — подсвечиваем поле красным и отключаем кнопку сабмита.
Проверить валидность даты можно при помощи Jquery Validate, но я решил написать для этого свой велосипед на нативном JS, так что представленная ниже функция валидации может быть использована без каких-либо JS фреймворков (или в связке с любым из них :)).
Собственно, вот исходник моей функции:

function ValidateDate(date_fl){
str=date_fl.value;
function TstDate(){
str2=str.split(".");
if(str2.length!=3){return false;}
//Границы разрешенного периода. Нельзя ввести дату до 1990-го года и позднее 2020-го.
if((parseInt(str2[2], 10)< =1990)||(parseInt(str2[2], 10)>=2020)) {return false;}
str2=str2[2] +'-'+ str2[1]+'-'+ str2[0];
if(new Date(str2)=='Invalid Date'){return false;}
return str;
}
var S=TstDate()
if(S)
{
//Дата валидна
date_fl.className='date_ok';
document.getElementById("submit").disabled = false;
}
else
{
//Дата не валидна
date_fl.className='date_err';
document.getElementById("submit").disabled = true;
}
}

Немного поясню принцип ее работы: функция принимает на вход объект, в который производится ввод даты. Затем введенное значение разбивается на массив по точке в качестве разделителя и приводится в формат гггг-мм-дд, после чего происходит попытка создания на его основе объекта типа Date. Таким образом проверяется не просто соответствие записи форме xx.xx.xxxx, а именно возможность существования такой даты (31-е февраля не прокатит). Если все отлично — присваиваем полю ввода CSS-класс ‘date_ok’ и включаем кнопку сабмита. Если произошла ошибка — присваиваем класс ‘date_err’ и отключаем кнопку. Конечно, ничто не мешает вам произвести какие-то свои действия.
Ну и в конце архив с примером использования.

Сказ о том, как крутой программист не мог Windows с флэшки поставить

Некоторое время назад стал "счастливым" обладателем ноутбука фирмы DNS. Практически сразу на него была поставлена Ubuntu и поднят LAMP. Однако все течет, все меняется, и в итоге мне понадобилось разработать довольно крупное приложение на ASP.NET, а для этого нужна ОС Windows.

Привычным движением записал на стационарном компе программой UltraISO образ новенькой 8-ки на флэшку, пихнул в USB ноута и… и ничего. Ноут с нее не грузился. Флэшка прекрасно виделась в BIOS, но при попытке с нее загрузится ноут просто не реагировал. Мигал курсором на девственно-чистом черном экране, и все 🙁 

Долго я думал, много мануалов перечитал, и в итоге надумал: форматнул флэшку в FAT32 (до этого она в NTFS была), и записал по новой на нее образ из UltraISO. В итоге система встала без каких-либо проблем. 

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

Drupal: запрет кэширования страницы модуля

Столкнулся недавно с такой проблемой: на сайте www.carhelpinfo.ru, работающим под Drupal, есть форма для поиска автомобильных запчастей, реализованная мной в виде отдельного модуля. Доступ к этой форме должен быть у всех пользователей, даже анонимных.

Для ускорения работы сайта используется Memcached. С включением опции кэширования страниц для анонимов сайт открывается практически мгновенно. Но вот беда — при этом не работает форма поиска: после запроса анонимному пользователю выдается не страница с результатами, а старая закэшированная страница.

Выходом из этой ситуации может быть использование в модуле своего собственного сегмента кэша и использование cahe_clear_all(). Эта функция может принимать в качестве параметра идентификатор сегмента кэша, который надо очистить. Если его не указывать — будет произведена очистка всего кэша. Но в таком случае при генерации страницы придется каждый раз тратить время на то, чтобы очистить сегмент кэша и записать туда новую версию страницы, которая при следующем вызове вновь будет перезаписанна.

Чтобы избежать этого, я просто стал передавать данные формы методом GET. Таким образом, при каждом запросе URL страницы меняется, и она генерируется снова. А если пользователь запросит то, что кто-то уже искал, то ему будет отдана страница из кэша.

Минусом такого метода является "загрязнение" URL, но в данном конкретном случае для сайта www.carhelpinfo.ru это не имеет значения.

Drupal 7: Разные профили пользователей для разных ролей

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

Итак, задача стоит следующая: на сайте www.carhelpinfo.ru есть две роли: обычный зарегистрированный пользователь и магазин.  В профиле магазина находится информация о его месторасположении (поле с Google Maps), краткое описание магазина (текстовое поле) и название магазина.

Необходимо всех регистрирующихся по умолчанию считать обычными зарегистрированными пользователями. Роль магазина присваивает администратор. 

К сожалению, я не нашел, как штатными средствами Drupal 7 сделать разные профили для разных ролей, и в форме регистрации всем подряд предлагалось указать название и описание магазина, а так же его местоположение. Помог мне в решении этой проблемы доп. модуль Profile 2

После установки этого модуля в разделе "Структура" появится пункт "Тип профиля" (см скриншот)

 

В этом разделе можно завести несколько разных профилей и определить для каждого свой набор полей. Для своей задачи я сделал "Основной профиль", где определил стандартные для всех пользователей поля, и профиль "магазин", в котором определил поля для магазинов.

Теперь, чтобы при нажатии кнопки "регистрация" пользователю предлагалось заполнить "Основной профиль", нужно лишь установить флажок "Show during user account registration.":

 

Теперь остался последний штрих. Необходимо, чтобы профиль "магазин" был только у пользователей с соответствующей ролью. Для этого просто идем в "разрешения ролей" и указываем параметры так, как нам надо.

Проблемы отображения GIF-анимации в Internet Explorer

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

баги анимации

При этом на моем компе во всех браузерах, включая IE, все было нормально. В рунете я практически не нашел упоминаний об этом баге, да и в буржунете информации очень мало. В общем, мне удалось воспроизвести баг на своем компьютере в IE 7. Он проявлялся при изменении масштаба страницы. То есть при 100% масштабе все было ок, но стоило его увеличить или уменьшить, как я получал картинку, приведенную выше. Единственное решение, которое я смог найти: это отключить прозразрочность при сохранении GIF-ки в PhotoShop (Сохранить для web и устройств). Конечно, при этом возрастает вес файла, да и не для всех картинок это можно сделать, так что для каждого конкретного банера придется потанцевать с бубном.

Система Мартингейла в казино. Почему это не работает?

 

Недавно в известной социальноя сети я получил сообщение, в котором мой знакомый «по большому секрету» поделился со смной безпроигрышной системой зароботка денег при игре в рулетку, и тут же предложил опробовать ее на сайте одного из он-лайн казино. 

Суть этой системы сводится к тому, что в ситуациях с двухвариантным исходом (либо да, либо нет; пан или пропал; черное или красное) в случае проигрыша игрок удваивает свою ставку с тем, чтобы отыграться: делаем минимальную ставку, начинаем игру и каждый раз, когда наша ставка проигрывает, мы удваиваем следующую ставку с тем, чтобы не только вернуть потерянное , но и выиграть.

Почему это не работает?

Начнём с того, что в рулетке помимо красного и чёрного полей есть поле Зеро (в американской рулетке  —  два), и мы имеем более 2-х вариантов результата, поэтому рулетка уже по определению не подходит для использования этого метода.

В остальных случаях необходимо понимать одну очень простую вещь, про которую все почему-то забывают: вероятность результата случайного события всегда равна и не зависит от предыдущих результатов. Если бросать монетку девять раз, и девять раз выпадет орел, то люди будут думать, что «ну сей час-то точно выпадет решка. Не может быть, чтобы орел выпадал 10 раз подряд!». И эта мысль не верна. Вероятность выпадания решки после 9 бросков состоавляет все те же 50%, как и при первом броске, и при пятом, и при любом другом. В теории вероятностей это называется «Ошибкой игрока».

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

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

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

Для тех, кто не боится цифр, предлагаю провести небольшие расчеты. Будем играть в орлянку (вероятность выпадания орла/решки составляет 50%, или 0,5). Согласно методу, будем ставить все время на орла. Если мы имеем начальный капитал на n ставок, то вероятность разорения равна 0,5n , а вероятность выигрыша: 1-0,5n 

Например, у нас есть 1023 рубля. При начальной ставке в 1 рубль нам этого хватит на 10 ставок. Результат 10 бросков подрят может быть разным. Могут выпасть 10 орлов подряд, 10 решек, 5 орлов и 5 решек и т.д. Если говорить в цифрах, то всего возможны 210 = 1024 разных варианта. И вероятность выпадения всех этих комбинаций одинакова и составляет 1/1024. Мы ставим на орла, поэтому если выпадет 10 решек подряд — мы проиграем. Вероятность этого состовляет 1 — 1/1024 = 1023/1024. Отношение вероятности разорения к вероятности выигрыша равно (1/1024)/(1-1/1024)=1/1023

Размер выигрыша составляет 1 рубль, а рискуем мы всем капиталом в 1023 рубля. Значит, соотношение выигрыш/риск равно 1/1023, т.е. равно соотношению вероятностей разорения и выйгрыша. Если разыгрывать бесконечное число серий подряд, то в среднем каждую 1024-ю серию вы будете проигрывать, теряя на ней весь выигрыш от предыдущих 1023 серий, и в итоге останетесь при своих. Математическое ожидание игры равно 0. 

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

Бесплатный Wi-Fi. Безопасно?

Мы все большеи больше слышим о бесплатном Wi-Fi в общественных местах. Но все ли понимают, что это такое, "бесплатный wi-fi интернет"? Извесная поговорка гласит, что бесплатный сыр бывает только в мышеловке, и в случае с Wi-Fi ситуация не сильно отличается. Я попытался рассмотреть вопрос безопасности открытых сетей, не вдаваясь в технические подробности. Как это у меня получилось, судить вам: http://charmlab.ru/besplatnyj-wi-fi-v-myshelovke/

Wappalyzer — определение ПО на посещаемом сайте

Приветствую! Сегодня хочу поделится одним замечательным расширенем для браузера (FF и Chrome), найденным мной на просторах сети. Разрешите представить: Wappalyzer. Данная штуковина умеет определять 278 различных CMS, аналитических систем, JS-фреймворков и пр., использующихся на сайте. К сожалению, он пока "не понимает" многих отечественных разработок типа "Битрикс" или "NetCat", однако может показать ОС, сервер и язык, на котором написан сайт. И самое главное — все это без лишних телодвижений. Вся необходимая информация выводится непосредсвенно в адресной строке браузера. В общем, разработчикам веб-совта маст хэв.

Перенос материалов из Joomla 1.5 + K2 в Drupal 6

Недавно устроился на подработку администратором сайта одной местной газеты. Сайт у нее уже был, и сразу сделать его таким, как я его вижу , не получилось. Сайт работает на CMS Joomla 1.5 и расположен на серверах SpaceWeb'а. За контент, как уже понятно из заголовка, отвечает сторонний компонет K2. ИМХО, Joomla вполне удобна для создания небольших сайтов-сателлитов фирм, ведущих свою деятельность вне интернета. Однако, в 21-м веке сайт для газеты — это уже не просто ее "визитка" в сети, и у меня сразу же зачесались руки превратить его в крупный информационный портал с новомодными социальными "штучками".

Однако, возможностей Joomla, даже с установленным K2(который нехило грузит сервер) для этого явно не хватает. Значит, надо переводить сайт на более гибкую и масштабируемую CMS. Поскольку идея K2 скопированна с CCK для Drupal, для портала я решил выбрать именно данную CMS. Но на существующем сайте газеты уже имеются тонны информации, и потерять ее просто недопустимо. Если бы не K2, то можно было бы воспользоваться конвертером Joomla to Drupal, но в данном случае всю "малину" обламывал злосчастный K2. Учитывая, что структура базы данных CMS меняется в зависимости от настроек пользователя, написать универсальный конвертер "все-в-одном", переносящий сразу все, довольно сложно и, на мой взгляд, не оправдывает целей. Так что я решил слить все таблицы двух CMS в одну базу и написать скрипт, который бы подключался к ним и переносил данные на прямую.

Итак, нам придется работать со следующими данными:

Информация о категориях K2 хранится в таблице `k2_categiries`. В друпале я для этого использовал модуль таксономии, создав необходимые словари и термины в админ-панели Drupal'а. При этом создаются записи в таблицах:

`term_data`  — данные терминов

`term_node` — привязка терминов к нодам

`vocabulary` — данные по словорям

Далее, хранение материаллов в Drupal организованно несколько сложнее K2. Для этого используются таблицы:

`node` — базовая информация о нодах. Стоит обратить внимание на следующие поля:

  • `type` — тип материалла Drupal. Берется из таблицы `node_type`.
  • `status` — параметры видимости ноды. 1 — опубликовано.
  • `comment` — праметры коментариев. 2 — разрешены чтение/запись.
  • `promote` — публиковать на главной. 0/1 — нет/да
  • `language` — язык статьи из таблицы `languages`

Непосредствено текст материалла содержит таблица `node_revisions`, разобраться в струтуре которой, на мой взгляд, не должно составить труда. Единственный момент: обратите внимание на отношения полей `nid` и `vid` таблиц `node` и `node_revisions`.

К моему счастью, на существующем сайте в K2 небыло созданно дополнительных полей, использовались только стандартные для него "изображение материала", "видео материала" и "галерея материала". Тут и думать нечего — в drupal'е я просто создал такие же поля при помощи CCK.

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

Если с тем, где в K2 хранится код видео, понятно из струтуры таблицы `k2_items`, то с изображением и галереей все несколько сложней. В поле `gallery` таблицы `k2_items` указанно лишь непонятное число. Так вот , это число — название папки с картинками галереи, которая лежит в ./media/k2/gallery/.

С изображением материала тоже не все так просто. Ни в одной таблице БД  K2 нет записей о нем. Я смог найти необходимую информацию только на официальном англоязычном сайте K2. Оказывается, картинки хранятсе все в той же папке ./media/k2/, а вот путь к ним формируется следующим образом: $file_name=md5("image".`k2_items.id`)."_L.jpg".

В помощь криворукому web-дизайнеру

Как быть, если вы крутой программист и можете за один вечер сваять полностью рабочий сайт с нуля, но выглядеть он будет как детская поделка? Ответ очевиден — сотрудничать с толковым дизайнером. Однако, если проект не коммерческий, или вы просто не хотите ни с кем делится? Недавно я нашел выход из данной ситуации: Artisteer — программный продукт для автоматического создания веб сайтов, а также дизайна для шаблонов (тем) различных CMS, включая WordPress, Joomla!, Drupal, DotNetNuke, для блогов Blogger, шаблонов для приложений ASP.NET, CodeCharge Studio, а также HTML страниц.

Лично у меня уже давно сложилось негативное отношение к проектам, в основе которых лежит автоматическая генерация кода. Я видел много программ, в описаниях к которым встречались слова типа "теперь вам не надо знать язык программирования, чтобы стать программистом", и все они на выходе давали довольно тяжелый и однотипный результат. С Artisteer ситуация не сильно изменилась — как ни крути, а это тот же автоматический генератор кода (по сути — WISIWIG-редактор). Если вы хотите получить действительно уникальный шаблон для Drupal или WordPress, то без ковыряния кода вам не обойтись, однако с данным ПО можно существенно сократить время на рутину и быстренько склепать "черновой" вариант дизайна, который уже потом и дорабатывать. Хотя, буду с вами откровенен: я использовал эту программу всего один раз для генерации шаблона для Drupal 6, после чего доработал его напильником. Теперь же я просто беру этот доработанный шаблон и затачиваю его под конкретный проект. 

В общем, на мой взгляд, программа интересная, но своих денег она не стоит. Вполне хватит и демо-версии.