воскресенье, 15 ноября 2009 г.

Akinator - отличная web-реализация старой идеи

Многие подумают, что пост не по теме, вообще никак не связан с программированием, но это не так.

Давно, когда я ещё начинал писать на Pascal, во многих модных журналах и книгах по программированию предлагали реализовать простой алгоритм хранения бинарных деревьев, и чтобы закрепить эти знания предлагали написать простую игру. Чем, собственно, и занялся от скуки. Заключалась она в том, что компьютер задавал вопросы, последовательно, и вам предлагалось выбрать один из вдух предложенных вариантов ответа, и так рано или поздно он угадает. Игра была самообучающейся, если вы загадали что-то, что не было ранее в её базе знаний, то программа спрашивала у вас правильный ответ и сразу запрашивала наводящий вопрос, который бы позволил узнать этот ответ. Таким образом, после нескольких часов игры у вас уже могла быть приличная база знаний...

Так вот, к чему это я. Мне только что, друг прислал ссылку на сайт akinator.com, это как раз та отличная web-реализация старой идеи. Вы заходите на сайт, загадываете любого известного человека (живого, мертвого, персонажа из кино, мультика, игры) и после нескольких десятков наводящих вопросов тихо офигеваете. У этой игры настолько богатая база знаний, что программа смогла угадать даже гидралиска из старкрафта.

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

Интересно, а что загадали вы, у вас игра угадала?

воскресенье, 1 ноября 2009 г.

Суровые реалии рынка труда

А вам не страшно отправлять резюме в компанию, где в графике работы пишут с 9.00 до 17.00, а сама вакансия на должность выложена на сайте в воскресенье в 3 часа ночи?..

вторник, 20 октября 2009 г.

SQL, задача. Найти минимальное натуральное число, которого нет в таблице

Один друг мне скинул сегодня интересную и странную задачку на знание SQL, вполне годится на собеседования выставлять. Условие следующее:

CREATE TABLE t (i int);
INSERT INTO t VALUES (1), (2), (3), (5), (8), (10), (13), (19);
Вывести минимальное натуральное число, которого нет в таблице t, т.е. 4.

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

Чем менее экзотические средства будут применены - тем лучше.
Варианты решения постим в комменты.

четверг, 15 октября 2009 г.

Robert Muraine, или Mr. Fantastic

Robert Muraine, или Mr. Fantastic - победитель американской танцевальной телепередачи So You Think You Can Dance в 2008 году. Парень, действительно, невероятно двигается, нереальная пластика, оригинальные движения и постановка. В общем, это завораживающее действо, обязательно досмотрите до конца!

вторник, 13 октября 2009 г.

Три кота и один кусок мяса

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

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

четверг, 24 сентября 2009 г.

Как браузер определяет next page на странице для быстрой постраничной навигации?

Как браузер определяет ссылку «next page» на странице? – Задался я сегодня таким вопросом, в процессе навигации по поисковику при помощи комбинаций клавиш, без использования мыши. Общеизвестный факт, что для постраничной навигации в браузере можно использовать комбинации клавиш вида ctrl+курсорные клавиши. По крайней мере, это работает без проблем на многих популярных сайтах в браузерах Opera и Firefox.

Но как же браузер определяет, какая ссылка является следующей логической страницей в цепочке html-документов? Начал рассматривать варианты реализации. Самое первое, что пришло на ум, это использование отношений ссылок в документе при помощи атрибута rel у элементов <a>. Догадка оказалась неверна, её в основном используют поисковики для индексации, но никак не браузеры. Ещё вариант в <head> html-страницы указать

<LINK rel="prev" href="page2.html">
<LINK rel="next" href="page4.html">

но назначние такое же, суть вопроса не меняется.

Второй вариант, как это можно реализовать, это повесить события JavaScript на нажатия клавиш, для быстрого перехода по пейджерам. Собственно, поисследовав код на поисковике Яндекс, я нашёл следующее. Они вешают вызов функции на событие document.onkeydown. Сама функция выглядит следующим образом:

function keyboard_navigation(D) {
  D = D || window.event;
  var A = D.keyCode;
  if (D.ctrlKey) {
    var B = $id("b-head-search");
    if (A == 13) {
      B.submit();
    }
    var E = (D.target || D.srcElement).tagName;
    if (E != "INPUT" && E != "TEXTAREA") {
      var C;
      if (A == 37) {
        C = $id("previous_page");
      }
      if (A == 39) {
        C = $id("next_page");
      }
      if (C) {
        location.href = C.href;
      }
      if (A == 38 && B.text) {
        B.text.focus();
        B.text.select();
      }
    }
  }
}

После этого, полез смотреть на Google, как реализована у них постраничная навигация при помощи комбинации клавиш ctrl+cursor left или ctrl+cursor right. Но, оказалось, что никаких обработчиков событий с клавиатуры у них не висит, и в Firefox подобный финт не работает. Такая комбинация клавиш отрабатывала только в Opera.

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

Opera FastForward – технология, введенная ещё со времён Opera 7. Она автоматически «угадывает» следующую страницу, и обеспечивает быструю навигацию по цепочке страниц. Это очень удобно, например, при чтении блогов, можно осуществлять постраничное чтение, всего лишь нажимая пробел для пролистывания. Как это работает? Opera загружает содержимое страницы и в нём ищет определённые ссылки, которые часто используются для навигации по многостраничным документам, содержащие текст вида "next" или ">>". Я сразу же полез в папку, где лежит исполняемый файл Оперы, и начал искать в конфигах. Нашёл файл fastforward.ini, в нём и находились настройки для этого заветного FFwd. Оказывается, в нём прописаны самые распространенные сигнатуры для большинства языков, по которым в тексте ссылок ищется адрес перехода на следующую страницу. Опытным путём, я выяснил, если на странице находится несколько подобных ссылок, то во внимание будет взято лишь последнее вхождение на странице. Так что, такую вот хитрую технологию использовали разработчики браузера Opera.

Именно за такие мелкие навороты, удобство и скорость работы я и люблю браузер Opera, постоянно использую для серфинга по internet.

вторник, 22 сентября 2009 г.

Липовый email для регистраций на сайтах

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

http://10minutemail.com/

Как можно судить из названия, данный сервис выделяет вам временный email-ящик на 10 минут. Этого оказывается достаточно чтобы получить активационное письмо и перейти по ссылке для подтверждения вашей учётной записи. Если вы чувствуете, что письмо вот-вот на подходе, а его всё нет, то кликнув по ссылке, вы можете продлить термин действия ящика ещё на 10 минут.

Кстати, вы даже можете ответить на входящие письма, но учтите, ваш э-майл адрес самоуничтожиться через 10 минут.

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

Наслаждайтесь!

четверг, 17 сентября 2009 г.

Эх, работа..

Работа – последнее прибежище для тех, кто больше ничего не умеет.
О. Уайльд (англ.писатель)

среда, 16 сентября 2009 г.

MySQL - Проблемы c русской кодировкой

Только что писал небольшой скрипт, парсер для сайтов, и натолкнулся на проблему, что русские символы не записывались в таблицу MySQL. При update или insert в таблицу все символы записываются нормально, но как только встречается русский текст – он просто обрезается и всё.

Проверил в какой кодировке работает скрипт, в базе данных, в таблице атрибут character set стоял utf8, и collation был задан utf8_general_ci. Всё правильно. Значит проблема не в этом. Тогда попробовал при установке соединения с MySQL задавать «SET NAMES utf8», проверил – тоже нихрена, не помогло. Спросил у сотрудников – сразу сходу мне никто не ответил, в чём собственно проблема.

В итоге, после получаса копаний, всё-таки вставил заветную строчку

$query = iconv("cp1251", "UTF-8", $query);

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

понедельник, 7 сентября 2009 г.

Эквивалент функции function_exists на JavaScript

Бывают ситуации, когда нужно проверить существует ли объявление функции непосредственно перед её вызовом. На языке php для этого существует специальная функция bool function_exists (string $function_name). В языке JavaScript такая функция, увы, отсутствует. Тогда напишем своими ручками...

Эквивалент функции function_exists на JavaScript будет выглядеть следующим образом:

if (window.runThisFunction) { // if function is defined - run it
    runThisFunction();
}

Это было самое простое и короткое решение, но для любителей всё усложнять, могу привести и другой пример, который удалось найти в Интернете. Более сложный пример function_exists на JavaScript приведен ниже, оформлен в виде функции, возвращающей bool-значения:

function function_exists (function_name) {
    if (typeof function_name == 'string'){
        return (typeof this.window[function_name] == 'function');
    } else{
        return (function_name instanceof Function);
    }
}

среда, 26 августа 2009 г.

RAID - Redundant Array of Ignorant Developers

Новая методология разработки программного обеспечения:
RAID = Redundant Array of Ignorant Developers

Уровни:

RAID0 - Задачу поделили на мелкие куски и не вникая в детали, раздали ее девелоперам. Куски не сошлись.

RAID1 - Один дебил пишет, второй за ним переписывает.

RAID1+0 - Задачу поделили на куски, раздали девелоперам, каждый друг за другом переписывает.

RAID5 - Собралось несколько дебилов, пишут софт. Любого можно уволить и никто не заметит.

вторник, 18 августа 2009 г.

Эмулирование border-color:transparent в IE6

Все браузеры, как браузеры, нормально работают со свойством border-color:transparent, один Internet Explorer 6 его не понимает. Приведу кусочек кода для примера:

.mydiv
{
width: 400px;
height: 200px;
border: solid 2px transparent;
}

Браузеры Internet Explorer 7, Firefox, Opera and Safari на границах элемента отобразят пустое прозрачное место шириной в 2px. Вместо прозрачного бордера в IE 6 появится чёрная сплошная полоса.

Исправить это можно, сделав небольшой хак, который поймёт только IE6:

*html .mydiv
{
border-color: pink;
filter: chroma(color=pink);
}

И вуаля! Убогий бордер исчез и стал прозрачным.

понедельник, 17 августа 2009 г.

«Умные» вопросы

Прочитал сегодня довольно попсовую статью из RSS-агрегатора, в которой были упомянуты около двух десятков «умных» вопросов, которые, якобы, могут помочь жить, если задавать их себе каждый день или с какой-то периодичностью. Их цель – личная мотивации и заставить себя думать.

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

  • Что наиболее важное из дел, которые нужно выполнить сегодня?
  • Что я могу получить от сегодняшнего дня?
  • Какой опыт я получу, сделав это?
  • Можно ли делегировать какие-то задания?
  • Что может придать значительный толчок моему бизнесу?

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

Интересно, а какие «умные» вопросы чаще всего возникают у Вас в голове, позволяющие достичь успеха?

jQuery toggle() IE8 bug

Недавно в процессе разработки наткнулся на интересный баг в jQuery. В библиотеке jQuery ver.1.3.2 реализована некорректная работа функции toggle() под IE8. В остальных браузерах работает нормально. Заключается ошибка в следующем: последовательно применяя toggle() к элементу таблицы в браузере Internet Explorer 8 элемент будет успешно скрыт, но обратно не будет показан при повторном вызове.

Поколупавшись в логике работы функции toogle(), выяснил, что она использует два селектора для определения состояния элемента страницы (видимый/невидимый). Приведу код ниже:

Sizzle.selectors.filters.hidden = function(elem){
    return elem.offsetWidth === 0 || elem.offsetHeight === 0;
};

Sizzle.selectors.filters.visible = function(elem){
    return elem.offsetWidth > 0 || elem.offsetHeight > 0;
};


Оба из них проверяют видимость элемента на странице путём проверки его высоты и ширины. Итак, в чём же кроется проблема данного определения, и почему не работает метод toggle() под IE8? Элемент
, хоть и имеет аттрибут display:none, всё равно имеет ширину > 0. Высота скрытого tr равна 0. Логика :visible/:hidden селекторов считает элемент видимым, если элемент имеет какую-то высоту или ширину, что есть неправильно для «любимого» IE.

Эту проблему можно исправить, проверяя атрибут display у искомого элемента. Тогда селекторы должны принять такой вид:

Sizzle.selectors.filters.hidden = function(elem){
    return (elem.style.display.toLowerCase() !== 'none');
};

Sizzle.selectors.filters.visible = function(elem){
    return (elem.style.display.toLowerCase() === 'none');
};

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

Sizzle.selectors.filters.hidden = function(elem){
    var width = elem.offsetWidth, height = elem.offsetHeight,
         force = /^tr$/i.test( elem.tagName );
    return ( width === 0 && height === 0 && !force ) ?
        true :
            ( width !== 0 && height !== 0 && !force ) ?
                false :
                    !!( jQuery.curCSS(elem, "display") === "none" );
};

Sizzle.selectors.filters.visible = function(elem){
    return !Sizzle.selectors.filters.hidden(elem);
};

пятница, 31 июля 2009 г.

Аналог PHP функции trim() на JavaScript

В php существует такая функция как trim(), обрезающая пробельные символы в начале или конце передаваемой строки. Её обычно используют для того чтобы отсеять пустые, не информативные, символы. Я trim часто использую для того чтобы провалидировать данные, введенные пользователем. К примеру, введенный текст должен быть не пустым, и не иметь просто набор пробельных символов, не отображаемых при выводе.

Данные часто приходится валидировать и на стороне клиента, если у вас есть поле required. Просто проверять по длинне строки - некорректно. В проверке должны отсеиваться все пробельные символы в начале и в конце строки, а уже потом проверяться его длинна. К несчастью, аналога функции trim() в JS нет, но зато есть такая мощная штука, как регулярные выражения.

Функция trim() в JavaScript будет выглядеть следующим образом:

replace(/^\s+|\s+$/g, '')

Тогда валидация с правилом required на поле с именем text формы post_form может принять следующий вид:

if ( $("#post_form [name=text]").val().replace(/^\s+|\s+$/g, '').length < 1 ) {
  //show error message;
}

четверг, 30 июля 2009 г.

TinEye – революционный сервис поиска картинок по подобию


Появился поисковый сервис нового поколения – TinEye (www.tineye.com), предназначенный для поиска изображений по подобию. Пока что он имеет статус бета-версии, однако уже работает стабильно и быстро.

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

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

Сервис имеет свой собственный программный интерфейс (API) для взаимодействия, но, по-моему, сейчас доступна, только коммерческая версия API. Так же поисковик можно встроить в браузер в виде плагинов. Доступны версии плагинов под браузеры IE и Firefox.

В общем всем советую зайти на сайт и побаловаться этим поисковиком для визуального поиска изображений.

пятница, 26 июня 2009 г.

26 программистских шуток про Чака Норриса


1. When Chuck Norris throws exceptions, it’s across the room.
2. All arrays Chuck Norris declares are of infinite size, because Chuck Norris knows no bounds.
3. Chuck Norris doesn’t have disk latency because the hard drive knows to hurry the hell up.
4. Chuck Norris writes code that optimizes itself.
5. Chuck Norris can’t test for equality because he has no equal.
6. Chuck Norris doesn’t need garbage collection because he doesn’t call .Dispose(), he calls .DropKick().
7. Chuck Norris’s first program was kill -9.
8. Chuck Norris burst the dot com bubble.
9. All browsers support the hex definitions #chuck and #norris for the colors black and blue.
10. MySpace actually isn’t your space, it’s Chuck’s (he just lets you use it).
11. Chuck Norris can write infinite recursion functions…and have them return.
12. Chuck Norris can solve the Towers of Hanoi in one move.
13. The only pattern Chuck Norris knows is God Object.
14. Chuck Norris finished World of Warcraft.
15. Project managers never ask Chuck Norris for estimations…ever.
16. Chuck Norris doesn’t use web standards as the web will conform to him.
17. “It works on my machine” always holds true for Chuck Norris.
18. Whiteboards are white because Chuck Norris scared them that way.
19. Chuck Norris doesn’t do Burn Down charts, he does Smack Down charts.
20. Chuck Norris can delete the Recycling Bin.
21. Chuck Norris’s beard can type 140 wpm.
22. Chuck Norris can unit test entire applications with a single assert.
23. Chuck Norris doesn’t bug hunt as that signifies a probability of failure, he goes bug killing.
24. Chuck Norris’s keyboard doesn’t have a Ctrl key because nothing controls Chuck Norris.
25. When Chuck Norris is web surfing websites get the message “Warning: Internet Explorer has deemed this user to be malicious or dangerous. Proceed?”.
26. Chuck Norris doesn’t need a debugger, he just stares down the bug until the code confesses.


было взято тут: http://www.codesqueeze.com/the-ultimate-top-25-chuck-norris-the-programmer-jokes/

суббота, 9 мая 2009 г.

Копирование стиля элемента в JavaScript

Может такое случиться, что понадобится скопировать часть атрибутов одного элемента в другой. «Что тут такого сложного?!», – подумаете вы, но решение такой задачи не тривиальное, как может показаться с первого взгляда.

Internet Explorer 7 и некоторые другие не могут установить значение стиля, класса или хендлера событий используя метод setAttribute. В IE8 вроде бы исправили это, но всё равно нельзя устанавливать обработчики событий. Некоторые браузеры имеют проблемы и со считыванием через getAttribute. В частности, Internet Explorer возвращает результат неправильного типа, например, вместо объекта строку, при использовании getAttribute для получения этих атрибутов. DOM обеспечивает несколько альтернативных решений для выполнения этих задач в такиз браузерах.

Класс доступен для чтения/записи через строку className.

Аттрибут обработчика события доступен через ссылку на функцию,с именем, совпадающем с именем атрибута, к примеру, element.onclick. Он доступен для чтения и записи, но запись должна происходить как ссылка на функцию, а не как прямая строка. Аттрибут можно записать используя конструктор функции:

element.onclick = new Function(codeAsAString);

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

var functioncode = element.onclick.toString();

Значение атрибута style доступно для чтения и записи через строку cssText, которая является свойством стиля объекта, которая в свою очередь является свойством элемента. Это свойство может плохо поддерживаться старыми браузерами, к примеру, Safari не поддерживал его вплоть до версии 1.1. Поэтому для избежания проблем стоит использовать комбинацию cssText и getAttribute/setAttribute. Для чтения:

var cssString;
cssString = element.style.cssText;
if( typeof(cssString) != 'string' ) {
 cssString = element.getAttribute('style');
}

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

var cssString = 'color:lime;font-weight:bold;';
element.style.cssText = cssString;
element.setAttribute('style',cssString);

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

Firebug для Internet Explorer, Opera, и Safari

Firebug – это мощное дополнение для исследования и отладки веб-страниц под Firefox.

Я, например, уже плохо представляю свою разработку web-приложений без такого полезного инструмента для отладки. Но, при написании кроссбраузерных приложений дело приходится иметь и с более глюкавым IE, быстрой Opera и популярным Safari браузерами. У каждого из них есть свои, заточенные инструментарии для отладки, но оказывается любимый Firebug можно прикрутить в каждый из браузеров.

Имя этому чуду Firebug lite. Это ни что иное, как JavaScript, включаемый на страницу. Сделать это можно, подключив js-файл, к примеру, в заголовке требуемой страницы:

<script type='text/javascript' src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>

После перезагрузки страницы вы увидите хорошо знакомую консоль firebug, которая поможет сэкономить вам много времени и нервов на вылизывании кроссбраузерного кода. Если вы отлаживаете веб-приложение локально и нет постоянного доступа к интернету, то вы можете скачать исходный код (есть и compressed js-файл) с официального сайта http://getfirebug.com/lite.html.

воскресенье, 5 апреля 2009 г.

MySQL. Выбирайте правильный числовой формат для полей!

При использовании реляционных баз данных всегда особое внимание следует уделять оптимизации структур таблиц базы данных. Это прямо сказывается, в дальнейшем, на скорости работы вашего хранилища в целом, особенно, если объёмы хранимых данных очень большие.

Все типы данных, с которыми работает СУБД MySQL можно разбить на три большие группы: числовые, текстовые и даты-времени. В данной статье хочу рассмотреть именно числовые типы, потому что у многих с ними возникает непонимание.

Числовые типы полей являются неотъемлемой частью любой таблицы базы данных. В MySQL существует 9 числовых типов данных:

  • целочисленные: TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT;
  • с плавающей запятой: FLOAT, DOUBLE;
  • с фиксированной запятой: DECIMAL;
  • и другие: BIT, и, возможно, ENUM.‫

Никогда НЕ СТОИТ ИСПОЛЬЗОВАТЬ такие комбинации, если вы не до конца понимаете их назначения и смысла:

- INT(1)‫‏‬
- BIGINT AUTO_INCREMENT
- не использовать UNSIGNED
- DECIMAL(31,0)

INT(1) – 1 не значит, что под хранение этого числа будет выделен один байт. Это глубочайшее заблуждение начинающих разработчиков программного обеспечения. Многие так и будут думать до конца жизни, что это количество байт под размещение этого поля. Но, ведь, это бред, обратитесь к официальному мануалу. Там чётко написано «Int (M)… M indicates the maximum display width for integer types». То есть, это число используется лишь при клиентском выводе числа и означает количество знаков для отображения. В общем, если кому-то интересно, то int(1) и int(11) имеют одинаковую размерность и вообще идентичны, если не использовать ZEROFILL при определении поля (для справки, ZEROFILL - означает, что число будет отображено с ведущими нулями).

Под TINYINT отводится 1 байт для хранения. TINYINT UNSIGNED может хранить числа 0 – 255. BIT –лучше всего использовать когда числа принимают значения 1 или 0. DECIMAL обычно используют для хранения денежных значений.

И никогда не стоит юзать BIGINT с AUTO_INCREMENT, это же зло. Возьмите INT UNSIGNED, он уже может вмещать ~4,3 миллиарда значений. При таком количестве записей в миллиарды в одной таблице, уже стоит серьёзно задуматься о том, чтобы разделить эти данные на несколько других таблиц. BIGINT используется для других целей, например, для суммирования больших значений.

Вообще хорошая практика – всегда использовать UNSIGNED поле для числовых значений, если нет видимой причины для использования отрицательных значений.

Надеюсь, программеры возьмут мои замечания на заметку. Сделаем код лучше!

Утилита Site-Auditor – сбор данных о видимости сайта в поисковиках

По наводке друзей набрёл на интересную программу, при помощи которой можно легко собрать основные данные о текущем уровне оптимизации сайта. Имя ей Site-Auditor (домашний адрес: www.site-auditor.ru).

Утилита Site-Auditor позволят всего одним «мышедвижением» получить все необходимые данные из основных поисковых систем не только рунета, но и популярных поисковиков Google, Yahoo и MSN. Внешний вид окна программы приведен ниже.

На момент написания этого поста, на сайте была доступна версия 1.68. Одним из достоинств программы является её кроссплатформенность, так как написана она с применением технологии Flash. Всё что вам нужно – это иметь установленный flash player версии 8.0 или выше, и она будет одинаково работать как в Windows ОС, так и для MAC OS X и Linux систем.

Весь функционал утилиты сгруппирован по трём вкладкам: Экспресс-анализ, Подбор запросов и Видимость сайта.

В первом разделе собраны основные данные о текущем уровне оптимизации сайта. Среди них индексы цитирования, количество проиндексированных страниц, количество ссылок на этот сайт и многое другое. Кроме того, если на сайте будет обнаружен счетчик Рамблер Top100, утилита соберет данные о количестве посетителей и просмотренных страниц за последние 7 дней. Также умеет сможет распознать и счетчики ряда других статистических систем, о которых можно почитать на официальном сайте. Путём клика на выпадающем меню «Внешние сервисы» можно пользоваться рядом полезных инструментов, таких как WHOIS, Traceroute (RU) и Traceroute (COM), WayBack Machine и другими. Каждый раз, когда вы будете получать новые данные об уровне оптимизации сайта, программа будет сохранять их в истории запросов. Так открывается возможность наглядного просмотра данных во временной шкале и отслеживания тенденций развития сайта.

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

Вкладка "Видимость сайта" позволяет получить суммарный отчет о положении анализируемого сайта в результатах поиска Google, Яндекса и Рамблера.

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

суббота, 28 марта 2009 г.

Коды основных символов HTML

Часто используемые
&nbsp;   неразрывный пробел
&ensp; короткий пробел
&emsp; длинный пробел
&shy; ­ мягкий перенос
&mdash; длинное тире
&ndash; короткое тире
&hellip; многоточие
&laquo; « левая кавычка елочка
&raquo; » правая кавычка елочка
&copy; © (c)
&reg; ® (R)
&trade; TM
Математические
&plusmn; ± +-
&times; × умножить
&ne; не равно
&lt; < <
&gt; > >
&le; <=
&ge; >=
&radic; квадратный корень
&sup2; ² квадрат, вторая степень
&sup3; ³ куб, третья степень
&frac14; ¼ 1/4
&frac12; ½ 1/2
&frac34; ¾ 3/4
&infin; бесконечность
Стрелки
&larr; стрелка влево
&uarr; стрелка вверх
&rarr; стрелка вправо
&darr; стрелка вниз
&harr; стрелка влево и вправо
&crarr; стрелка вниз, потом влево, как Enter
&lArr; стрелка двойная влево
&uArr; стрелка двойная вверх
&rArr; стрелка двойная вправо
Прочие
&amp; & амперсанд
&euro; ? евро
&prime; '
&Prime; ''
&middot; · точка на середине высоты строки
&oline; Надчерк
&deg; ° градус

jQuery Tabs. Ajax загрузка в один и тот же div контейнер

Эта статья будет полезна тем, кто использует такую мощную штуку как jQuery UI, в частности элемент интерфейса Tabs. jQuery Tabs позволяет в несколько строчек кода создавать удобный и быстрый набор вкладок на HTML странице.

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

Приведу пример использования:

<div id="contacttabs">
  <ul>
    <li><a href="all.html"><span>Все контакты</span></a></li>
    <li><a href="friends.html"><span>Друзья</span></a></li>
    <li><a href="invisible.html"><span>Список невидящих</span></a></li>
    <li><a href="ignore.html"><span>Список игнорируемых</span></a></li>
  </ul>
</div>

<script type="text/javascript">
  $(document).ready(function() {
    $("#contacttabs").tabs({
      spinner: 'загрузка...'
});
  }
</script>

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

<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
...
</ul>
<div id="ui-tabs-16" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
<div id="ui-tabs-27" class="ui-tabs-panel ui-widget-content ui-corner-bottom"></div>
<div id="ui-tabs-29" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
<div id="ui-tabs-31" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>

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

В текущий момент времени пользователь видит только активную вкладку, и может взаимодействовать только с элементами, находящимися в контейнере выбранной вкладки. Все остальные имеют атрибут hidden. Это значит, что элементы загружены в DOM для каждой из вкладок, хотя и не видны в данный момент времени, и если обратиться по уникальному ID-шнику элемента на вкладке, то может возникнуть «коллизия», и селектор выберет совсем не тот элемент, который хотелось из активной вкладки.

Единственным выходом для меня было – подчищать содержимое контейнеров неактивных вкладок, дабы не возникало дублирование ID-шников. Такой опции в jQuery Tabs, я найти не смог, пришлось написать небольшой hook. Я навесил на событие select, возникающее в Tabs, в момент переключения активной вкладки, очистку всех неактивных контейнеров <div>.

<script type="text/javascript">
  $(document).ready(function() {
    $("#contacttabs").tabs({
      spinner: 'загрузка...',
      select: function(event, ui) {
        /*clear all divs content except active one*/
        fakes = ui.panel.parentNode.getElementsByTagName('div');
        for(i=0;i<fakes.length;i++){
          if(fakes[i] != ui.panel){
            fakes[i].innerHTML = '';
          }
        }
      }
    });
  });
</script>

И тогда всё заработало, как следует..

четверг, 5 марта 2009 г.

Смешные комментарии в коде

Насобирал отличную подборочку смешных комментариев в коде, думаю, программисты оценят свою же лирику (=


// sometimes I believe compiler ignores all my comments

// drunk, fix later

return 1; //returns 1

// Magic. Do not touch.

const int TEN=10; // As if the value of 10 will fluctuate...

//This code sucks, you know it and I know it. Move on and call me an idiot later.

doRun.run(); // ... "a doo run run".

try {
} finally { // should never happen
}

/* These magic numbers are fucking stupid. */

/* TODO: this is obviously not right ... this whole fucking module sucks anyway */

/* FIXME: please god, when will the hurting stop? Thus function is so fucking broken it's not even funny. */

//I am not sure why this works but it fixes the problem.

// I am not sure if we need this, but too scared to delete.

// I have to find a better job

// Remove this if you wanna be fired

if (case1) { // trivial
...
}
else { // we are screwed
/* fill in later */
}

if (/*you*/ $_GET['action']) { //celebrate

Замедляет ли Google Analytics сайт?

Если вы используете Google Analytics для отслеживания посещений на вашем блоге, то вы можете быть удивлены скоростью загрузки страниц, по-крайней мере в Европе точно заметно. Народ начал замечать, что в так называемые «часы-пик» использования Web-а код JavaScript от Google Analytics грузится на 97% медленнее по сравнению с обычной нагрузкой. Это справедливо для Европы. Для США такое падение в скорости тоже имеет место, но не такое заметное, разница составляет всего лишь 27%.

Чем это обусловлено – сложно сказать. Скорее всего, просто большинство серверов Гугла расположено не в Европе, и поэтому большое количество пользователей даёт такую усадку по скорости загрузки. Конечно, это не означает, что нужно перестать пользоваться этим прекрасным сервисом, и боятся за скорость загрузки вашего сайта. Всё это некритично.

Есть конечно и ряд других аналогичных некоммерческих сервисов для отслеживания посещений на вашем сайте. Сегодня один из моих друзей показал мне такую вещь как Woopra (http://www.woopra.com). На данный момент сервис находится в стадии бета-тестирования, но багов мной не было замечено, можно смело пользоваться. По возможностям сервис превосходит аналогичный GA (Google Analytics). Единственный недостаток – у них большая нагрузка на сервера и поэтому можно ждать около месяца пока ваш аккаунт утвердят. Что сразу бросилось в глаза – Woopra может отслеживать посещения и анализировать поведение пользователей вплоть до отдельного индивидуума, такого GA, конечно, не предоставляет.

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

вторник, 17 февраля 2009 г.

Free hosting

Несколько бесплатных зарубежных хостингов:

Оба, вроде, хороши, по отзывам пользователей. Но Awardspace частенько грешит долгими downtime, в отличии от Freehostia, у которой они гораздо реже и не так заметны. Оба хостинга предоставляют услуги без внедрения рекламы на ваши страницы, и вы можете свободно использовать PHP или Perl скрипты. Кстати, Freehostia даже предоставляет бесплатный план с уже предустановленным рядом скриптов, которые могут быть полезны новичкам.

В общем советую попробовать.

среда, 4 февраля 2009 г.

Оптическая иллюзия "Lilac chaser"

Иллюзия сочетает в себе три простых, общеизвестных эффекта:

  1. Когда происходит кратковременное событие в одной точке поля зрения, а в близлежащей точке имеет место схожее событие, мы воспринимаем это как движение из одной точки в другую. Это явление называют мнимым движением, или бета-движением, поскольку фактически никакого движения не было. Мнимое движение является основой движущихся неоновых вывесок, фильмов и видео. Мы видим движение поскольку устройство отображения информации (например, монитор) стимулируют рецепторы головного мозга (называемые рецепторами Рейхардта), отвечающие за расшифровку движений. Визуальными событиями в данной иллюзии являются исчезновение сиреневых кружков, а также дальнейшее появление зелёных послеобразов (см. далее).
  2. Когда исчезает сиреневый раздражитель, присутствующий в определённой области поля зрения в течение длительного времени (скажем, около 10 секунд), появляется зелёный послеобраз. Этот послеобраз остаётся в течение достаточно короткого промежутка времени, и в данном случае, "стирается" повторным появление сиреневого раздражителя. Появление послеобраза является следствием адаптации палочек и колбочек сетчатки. Цвет и яркость определяются соотношением активностей трёх типов колбочек. Под влиянием сиреневого раздражителя колбочки "устают". Когда раздражитель исчезает, усталость колбочек способствует тому, что активность, вызванная в них серым фоном, совпадает с таковой в состоянии покоя. Адаптация палочек и колбочек начинается сразу же после начала действия раздражителя, поэтому длительность послеобразов постепенно начинает расти. Обычно мы их не замечаем, поскольку изменяем положение глаз примерно 3 раза за секунду, и видимое изображение каждый раз попадает на новые, неадаптировавшиеся палочки и колбочки. В этой иллюзии, наши глаза сохраняют неподвижность, что вызывает нарастание длительности послеобразов, возникающих после прекращения действия раздражителя.
  3. Если в области периферического зрения, появляется размытый раздражитель, и при этом сохраняется неподвижность глаза, то раздражитель исчезает, даже если он всё ещё физически присутствует. Это явление называется затуханием Трокслера (Troxler's fading). Так происходит потому, что даже если наши глаза сфокусированы на точке и слегка двигаются, движения вне этой точки (в области периферического зрения) недостаточны для того чтобы сдвинуть сиреневые пятна на новые нейроны нашей зрительной системы. Эти послеобразы фактически перекрывают основные образы и все сиреневые пятна кажутся серыми, за исключением тех мгновений, когда появляются зелёные послеобразы.


среда, 28 января 2009 г.

Работа из PHP с xmpp (jabber)

Работа над протоколом jabber была начата ещё в 1998 году, но более широкое распространение получил в середине 2000 года. С того времени появилось много библиотек и реализаций данного протокола, почти для всех языков программирования. Более детальный список можно посмотреть на оффсайте: http://xmpp.org/software/libraries.shtml.

Extensible Messaging and Presence Protocol, сокращённо XMPP, это открытый протокол, основанный на XML, предназначенный для обмена мгновенными сообщениями и информацией о присутствии (списке контактов, например). Был опубликован в виде RFC 3920. Он остаётся основным протоколом технологии обмена мгновенными сообщениями Jabber. Главной целью протокола – была расширяемость, таким образом, он быстро получил много дополнительных возможностей, такие как передача голоса или передача файлов.

На оффсайте набор библиотек для работы на PHP представлен тремя вариантами:

  • JAXL
  • Lightr
  • xmpphp

Больше всего приглянулась библиотека xmpphp, как самая простая в использовании и с довольно удобными вызовами. О ней и пойдёт разговор.

Для того чтобы начать её использовать необходимо подключить файл XMPP.php, перед началом работы. Дальше создать объект класса XMPPHP_XMPP с указанием основных параметров соединения: джаббер сервера, порта подключения, данных для авторизации, и уровня логирования.

Фрагмент кода приведен ниже.

include ‘XMPPHP/XMPP.php’;

$conn = new XMPPHP_XMPP('jabber_server_here', 5222, 'your_login', ' your_password', 'xmpphp', 'jabber.ru', $printlog=false, $loglevel=XMPPHP_Log::LEVEL_INFO);
$conn->useEncryption(false);        //disable encryption
try
{
    $conn->connect();
    $conn->processUntil('session_start');
    $conn->presence();
    $conn->message('your jabber here', 'текст сообщения, которое хотите отправить');
    $conn->disconnect();
}
catch(XMPPHP_Exception $e)
{
    //here you can process $e->getMessage() if some error occurred;
}

В примере было отключено шифрование командой $conn->useEncryption(false). Это нужно делать непосредственно перед вызовом метода connect, пока не было установлено соединение. Позволит решить проблему, если вы получили ошибку вида «Fatal error: Cannot access protected property XMPPHP_XMPP::$use_encryption …», или в случае, если вы хотите отключить SSL/TLS шифрование.

Данное решение, использовать джаббер для отсылки сообщений средствами PHP, может пригодится для отправки извещения вам прямо в messenger об очередном пришедшем комментарии с вашего форума, заказе на покупку из web-магазина, поста из агрегатора новостей или другой важной информации с вашего приложения на сервере.

понедельник, 5 января 2009 г.

asort() – SORT_NUMERIC with non numeric values

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

В PHP есть такая замечательная функция asort() и arsort() для сортировки в обратном порядке. Она позволяет производить сортировку данных в массиве, при этом оставляя соотношение ключей и значений неизменным. Собственно, это и требовалось для нашей задачи.

asort($arr, $sort_flags);

В качестве первого параметра передал массив для сортировки, в качестве ключей сортировки указал $sort_flags=SORT_NUMERIC. Отсортировал, вывел данные в таблицу для отображения. Как ни странно, но данные вывелись не в отсортированном порядке. Так как выборка данных была не большая, то смог заметить, что порядок следования всё-таки хаотично поменялся.

Так как ломаться было нечему, функция небольшая, то сразу понял, что проблема была где-то в участке кода с использованием функции asort(). Создал ассоциативный массив из 25 элементов, в котором ключами были простые числа в порядке следования, а в качестве значений были нехитро сгенерированные float числа. Получился следующий массив:

Array
(
  [0] => 0.00
  [1] => 0.00
  [2] => 0.00
  [3] => 55.00
  [4] => 0.00
  [5] => 1.00
  [6] => 0.00
  [7] => 0.00
  [8] => 0.00
  [9] => 0.00
  [10] => 0.00
  [11] => 1.00
  [12] => 0.95
  [13] => 1.00
  [14] => 1.00
  [15] => 0.00
  [16] => 0.00
  [17] => 0.00
  [18] => 0.00
  [19] => 0.00
  [20] => 0.00
  [21] => 0.00
  [22] => 0.00
  [23] => 8.00
  [24] => 0.00
)

После сортировки функцией asort() с ключём SORT_NUMERIC получил следующий результат:

Array
(
  [23] => 8.00
  [3] => 55.00
  [5] => 1.00
  [11] => 1.00
  [14] => 1.00
  [13] => 1.00
  [12] => 0.95
  [22] => 0.00
  [7] => 0.00
  [18] => 0.00
  [4] => 0.00
  [6] => 0.00
  [1] => 0.00
  [19] => 0.00
  [17] => 0.00
  [20] => 0.00
  [10] => 0.00
  [21] => 0.00
  [16] => 0.00
  [15] => 0.00
  [2] => 0.00
  [24] => 0.00
  [8] => 0.00
  [9] => 0.00
  [0] => 0.00
)

И после этого прозрел о_О. Почему элементы не в отсортированном порядке? Пошёл смотреть в PHP-мануал. Но, ни слова не сказано, что функция не будет работать с float числами, она должна одинаково хорошо работать как со string-ами, так и с integer или float объектами для сортировки, для этого лишь нужно использовать соответсвующий ключ сортировки. Для численных параметров нужно использовать именно SORT_NUMERIC, впрочем, как мы и делали. Ладно, попробовал отсортировать в реверсивном порядке при помощи arsort(), а потом просто перевернуть массив. Но результат был аналогичен – НЕ РАБОТАЕТ.

Версия PHP, на котором запускалось – Version 5.2.3.

Any ideas?

Рекоммендую

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