пятница, 18 февраля 2011 г.

Функция цитирования текста для ответного сообщения (function for wrapping/quoting text on replies)

Писал приложение, в котором была необходимость создать внутреннюю почту, с возможностью отослать письмо и c возможностью на это email потом ответить. Возникла задача цитирования текста предыдущего сообщения при ответах на входящие письма, наподобие, как делают всякого рода email clients, или тот же gmail с web-интерфейсом.

Например:

> Это quoted text.
> Всё что тут было написано, было написано
> не мной, во входящем сообщении.

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

str_replace("\n","\n> ","> ".$text);

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

> повторное цитирование:
>
>> Это quoted text.
>> Всё что тут было написано, было написано
>> не мной, во входящем сообщении.

При повторном цитировании текста,  вначале строки, возле угловой скобки ставится отступ лишь в том случае, если рядом стоит «чистый текст», ранее не обвёрнутый в кавычки цитирования. Так что без дополнительной логики, простым str_replace() тут не обойтись.

Оказалось, что найти такую функцию на PHP среди готовых решений не так-то просто. Поэтому предлагаю свой вариант реализации на PHP:

// function for wrapping/quoting text on replies
public function quote_text(&$body)
{
  $body_quote = ">";        // quotation mark
  $rewrap_body = explode("\n", $body);
  $body = '';
  $cnt = count($rewrap_body);
  for ($i=0;$i<$cnt;$i++)
  {
    if (preg_match("/^(>+)/", $rewrap_body[$i], $matches)) {
      $gt = $matches[1];
      $body .= $body_quote . str_replace("\n", "\n" . $body_quote
         . "$gt ", rtrim($rewrap_body[$i])) ."\n";
    } else {
      $body .= $body_quote . (!empty($body_quote) ? ' ' : '') . str_replace("\n", "\n" . $body_quote . (!empty($body_quote) ? ' ' : ''), rtrim($rewrap_body[$i])) . "\n";
    }
    unset($rewrap_body[$i]);
  }
}

Функция quote_text принимает переменную по ссылке в качестве единственного параметра. Результатом работы этой функции будет процитированный текст, обвёрнутый в метки $body_quote, по схеме цитирования, описанной выше.

четверг, 3 февраля 2011 г.

Подсказки в input: text полях (default search text at input using jQuery)

На сайтах часто попадаются подсказки в input: text полях, например, в полях для поиска, когда написан текст «Поиск по сайту», а при вводе в него значения – он исчезает и пользователь может ввести критерий поиска.

Алгоритм работы данного функционала прост. Задается текст-подсказка (описание поля) по умолчанию, зачастую бледного цвета, а при фокусе на элементе всё очищается. При потере фокуса, если значение поля осталось пустым, то снова возвращается текст подсказка.

Самый простой способ, для «любителей» размещать весь код инлайн, реализуется при помощи JS, навесив два события onfocus и onblur на input элемент формы:

<input type="text" value="Поиск по сайту…" onfocus="if (this.value == 'Поиск по сайту…') {this.value = '';}" onblur="if (this.value == '') {this.value ='Поиск по сайту…';}" />

Есть, конечно, и много уже готовых плагинов для отображения подсказки в input полях, но мне почему-то больше всех приглянулся jquery.hint.js (как пользоваться расписано тут).  Как мне показалось, jquery.hint.js вполне удачное, маленькое и элегантное решение для такой задачи.

В любом случае, плагины уже нашёл после того, как написал собственное решение для этой задачи, да и подгружать отдельный js файл на каждую html страницу - непозволительная роскошь, из-за одного маленького input в блоке поиска. Вот этот кусочек js-кода, который с использованием jQuery навешивает подсказку для input text поля с id-шником search:

$('#search').focus(function(){
    if($(this).val() == $(this).attr('title')){
      $(this).val('').css('color','#333');
    }
  }).blur(function(){
    if($(this).val() != $(this).attr('title') && $.trim($(this).val()).length == 0){
      $(this).val($(this).attr('title')).css('color','#AAA');
    }
}).blur();

Сам элемент input выглядет следующим образом:

<input id="search" type="text" name="search" value="" title=" Поиск по сайту…" />

Скрипт использует значение, которое задано в атрибуте title в качестве текста подсказки и выводит его серым цветов в самом input. Как только пользователь ставит/убирает курсор в поле для ввода, срабатывает событие focus/blur, которое и показывает/скрывает текст подсказки и меняет CSS стиль для элемента.

Для того чтобы submit формы не происходил с нашим фейк-значением подсказки, я навесил дополнительное событие onsubmit="checkFakeSearchValues();" на элемент form. Эта функция выглядит следующим образом:

function checkFakeSearchValues(){
  var search = $('#search');
  if($(search).val() == $(search).attr('title')){
    $(search).val('');
  }
}

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

четверг, 21 октября 2010 г.

Коды кнопок добавления в социальные закладки (Share Button Codes)

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

Код формирования ссылки для сервиса Facebook:
http://www.facebook.com/sharer.php?u={ссылка на страницу}
Код формирования ссылки для сервиса Twitter:
http://twitter.com/home/?status={заголовок страницы}+{ссылка на страницу} 
Код формирования ссылки для сервиса Google Buzz:
http://www.google.com/buzz/post?url={ссылка на страницу}&title={заголовок страницы}
Код формирования ссылки для сервиса Я.ру:
http://my.ya.ru/posts_add_link.xml?URL={ссылка на страницу}&title={заголовок страницы}
Код формирования ссылки для сервиса Вконтакте:
http://vkontakte.ru/share.php?url={ссылка на страницу}
Код формирования ссылки для сервиса LiveInternet:
http://www.liveinternet.ru/journal_post.php?action=n_add&cnurl={ссылка на страницу}
Код формирования ссылки для сервиса Livejournal:
http://www.livejournal.com/update.bml?event={ссылка на страницу}&subject={заголовок страницы}
Код формирования ссылки для сервиса Memori:
http://memori.ru/link/
Код формирования ссылки для сервиса Мой Мир (mail.ru):
http://connect.mail.ru/share?share_url={ссылка на страницу}
Возможно ещё что-то упустил - смело пишите в комментариях - добавлю.

четверг, 24 июня 2010 г.

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

Читая сегодня Хабр не смог удержаться, чтобы не процитировать золотые слова, с которыми я согласен на все 100%:

Программист должен проверять результат своей работы перед передачей в тестирование
«Моё дело писать код, а их дело проверять», «Ну а их-то зачем понанимали?» — можно услышать в таких командах. Это элементарное отсутствие гигиены, работа ради «отписаться». Где вы видели журналиста, который не перечитывает свою статью перед тем, как передать её в редакцию? Если в коллективе есть программист, который проповедует такой подход, его нужно как можно скорее ликвидировать. Какой бы он ни был классный специалист.

MySQL поиск и удаление дубликатов в таблице

Как найти и удалить дубликаты в таблице MySQL? - оказывается это довольно частый вопрос, возникающий на практике, особенно когда надо установить UNIQUE constraint.

Задачу поиска дубликатов в SQL-таблице всегда можно решить таким простым запросом:

SELECT login, COUNT(login) AS cnt
FROM users GROUP BY login
HAVING ( COUNT(login)>1 );

Этот запрос вернёт все дубликаты login из таблицы пользователей. Ситуация несколько искусственна, на практике врядли будут дубликаты логинов в таблице пользователей, но для примера запроса сгодится.
Другой вариант, возможно более прост для понимания, при SELECT-е сделать простой JOIN таблицы самой на себя. К примеру, есть таблица scriptsettings с настройками какого-то скрипта, в ней нужно найти все дубликаты, где param (имя параметра) и group (логическое название группы параметров) дублируются. Запрос через JOIN примет вид:

SELECT s1.id AS id1, s1.group, s1.param, s2.id AS id2 FROM scriptsettings s1
INNER JOIN scriptsettings s2 ON s2.id>s1.id AND s1.param=s2.param AND s1.group=s2.group;

Удаление дубликатов из таблицы так же можно сделать простым JOIN таблицы самой на себя:

DELETE s1 FROM scriptsettings s1, scriptsettings s2 WHERE s1.param=s2.param AND s1.id>s2.id;

Пока писал, в голову пришёл более лаконичный и элегантный способ удаления дубликатов при помощи MySQL:

ALTER IGNORE TABLE scriptsettings ADD UNIQUE INDEX(param);

среда, 16 июня 2010 г.

Regexp to replace placeholders at string (замена плейсхолдеров в строке на элементы массива)

Довольно часто встречается задача подстановок каких-либо значений из ассоциативного массива  в определённые места в строке. Думаю, многие повседневно сталкиваются с ней при формировании персонализированных email-писем, формировании мультиязычных сообщений пользователю с подстановками из личных данных и других повседневных задачах.
Задача замены плейсхолдеров, или так называемых меток-заполнителей, в строке на соответствующие элементы ассоциативного массива может быть решена несколькими способами, но, на мой взгляд, самый элегантный способ - при помощи preg-а (регулярных выражений).
Допустим, у нас есть ассоциативный массив с подстановками $placeholders, и строка $str c метками-заполнителями вида {var_name}, в которой нужно произвести замену на соответствующие значения из массива. Решение на PHP будет выглядеть следующим образом:
$placeholders = array("name"=>"User", "link"=>"http://webaurum.blogspot.com");
$str = "Hello {name}, you are here {link}";
echo preg_replace('~\{\w+\}~e', '@$placeholders$0', $str);
echo preg_replace( '/\{(\w+)\}/e', '@$placeholders["\\1"]', $str);
Две последние строки абсолютно идентичны по функциональному назначению, я их просто привёл для примера, может кому-то будет понятнее второй вариант. Обе последние строки вернут результат:
Hello User, you are here http://webaurum.blogspot.com
Реализация работает быстро и элегантно, использую во многих собственных проектах.

понедельник, 17 мая 2010 г.

ICANN разрешила в domain names кириллицу и другие алфавиты. А как же совместимость?!

Новые правила позволят использовать в доменных именах 100 тысяч новых символов. В ICANN новые правила наименования доменов называют крупнейшим техническим изменением Интернета за все время его существования. Но это изменение к лучшему ли?
Россия, по-моему, одна из первых начала регистрировать домены в зоне .РФ. Зашёл на правительственный сайт http://правительство.рф и уже это нововведение вызвало у меня улыбку.
Домен-то написан кириллицей, но все внутренние линки остались латиницей. =) Бред, имхо, всю затею и удобство свели на нет. Смешно смотрится адрес вида http://правительство.рф/staff/.

Ещё меня заинтересовало - как будут работать все современные браузеры с кириллицей в адресной строке. Проверил во всех основных, что у меня стояли на рабочем компьютере. Оказалось что нормально варит только Opera 10.53, не корёжит символы и отображает во всех URL-ах нормальное написание. Тот же Firefox и остальные собратья при вводе в адресную строку заветного адреса вели себя ненормально, но открыть сайт смогли. Firefox при вводе "правительство.рф" затем заменил этот адрес на ненормальный "http://xn--80aealotwbjpid2k.xn--p1ai/#", но сайт открыл успешно. А Google Chrome и вовсе неправильно отреагировал. Получив адрес "правительство.рф" он сразу пошёл искать его в поисковике гугл, вместо того, чтобы просто открыть этот адрес. Там, нажав на первой странице результатов поиска на соответствующей ссылке, я уже смог попасть на требуемый сайт.

Самое главное, что меня расстроило, это нюансы разработки сайтов и другого ПО, при таком нововведении. Представьте сколько проблем будет в заготовленных скриптах определения корректности введенного e-mail или валидации URL. Попробуйте в практически любой подобный скрипт внести русские символы. С мобильными устройствами тоже проблемы: не все смогут попасть на заветные сайты, так как вообще не предусмотрена возможность ввода символов отличных от латиницы. Вся интернациональность ломается на корню, люди с других стран, просто не смогут зайти на ваш сайт, даже зная язык, потому что у них на клавиатуре нет таких символов. А как же старые стандарты и реализации? Тот же RFC 2821 (Simple Mail Transfer Protocol), www.ietf.org/rfc/rfc2821.txt, что, тоже переписывать и создавать новые стандарты?!

Необходимо переписать тонны кода, который уже отлажен и работает годами!
Я против таких сомнительных прорыров в Интернете.

Рекоммендую

Попробуйте надёжный хостинг от Scala Hosting