Недавно в процессе разработки наткнулся на интересный баг в 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);
};
В 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;
}
Появился поисковый сервис нового поколения – TinEye (www.tineye.com), предназначенный для поиска изображений по подобию. Пока что он имеет статус бета-версии, однако уже работает стабильно и быстро.
Принцип работы сервиса банален, загружаете изображение, либо даёте ссылку на изображение в интернет, на что в ответ сервис выдаст похожие на него картинки. Революционность данного сервиса заключается в том, что поиск происходит не по метаданным или ключевым словам, содержащимся в картинке, а именно по внешнему сходству изображений.
На данный момент проиндексировано свыше одного миллиарда картинок. Разработчики говорят, что они постоянно наращивают скорость сканирования, и сейчас уже достигли скорости индексации 2-3 миллиона картинок в неделю. Таким образом, поисковая база постоянно расширяется.
Сервис имеет свой собственный программный интерфейс (API) для взаимодействия, но, по-моему, сейчас доступна, только коммерческая версия API. Так же поисковик можно встроить в браузер в виде плагинов. Доступны версии плагинов под браузеры IE и Firefox.
В общем всем советую зайти на сайт и побаловаться этим поисковиком для визуального поиска изображений.
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/
Может такое случиться, что понадобится скопировать часть атрибутов одного элемента в другой. «Что тут такого сложного?!», – подумаете вы, но решение такой задачи не тривиальное, как может показаться с первого взгляда.
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 – это мощное дополнение для исследования и отладки веб-страниц под 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.
При использовании реляционных баз данных всегда особое внимание следует уделять оптимизации структур таблиц базы данных. Это прямо сказывается, в дальнейшем, на скорости работы вашего хранилища в целом, особенно, если объёмы хранимых данных очень большие.
Все типы данных, с которыми работает СУБД 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 (домашний адрес: 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 очень понравилась, в частности, из-за количества различных опций и сервисов, а так же наглядных отчётов собранных в одном месте. Единственное, что следовало бы улучшить разработчикам данного программного чуда – это убыстрить работу, например, путём параллельного послания нескольких запросов на серверы поисковиков, а не последовательно на каждый из них по каждому из параметров, как сделано сейчас.
Часто используемые |
| | неразрывный пробел |
  | | короткий пробел |
  | | длинный пробел |
­ | | мягкий перенос |
— | — | длинное тире |
– | – | короткое тире |
… | … | многоточие |
« | « | левая кавычка елочка |
» | » | правая кавычка елочка |
© | © | (c) |
® | ® | (R) |
™ | ™ | TM |
Математические |
± | ± | +- |
× | × | умножить |
≠ | ≠ | не равно |
< | < | < |
> | > | > |
≤ | ≤ | <= |
≥ | ≥ | >= |
√ | √ | квадратный корень |
² | ² | квадрат, вторая степень |
³ | ³ | куб, третья степень |
¼ | ¼ | 1/4 |
½ | ½ | 1/2 |
¾ | ¾ | 3/4 |
∞ | ∞ | бесконечность |
Стрелки |
← | ← | стрелка влево |
↑ | ↑ | стрелка вверх |
→ | → | стрелка вправо |
↓ | ↓ | стрелка вниз |
↔ | ↔ | стрелка влево и вправо |
↵ | ↵ | стрелка вниз, потом влево, как Enter |
⇐ | ⇐ | стрелка двойная влево |
⇑ | ⇑ | стрелка двойная вверх |
⇒ | ⇒ | стрелка двойная вправо |
Прочие |
& | & | амперсанд |
€ | ? | евро |
′ | ′ | ' |
″ | ″ | '' |
· | · | точка на середине высоты строки |
‾ | ‾ | Надчерк |
° | ° | градус |
Эта статья будет полезна тем, кто использует такую мощную штуку как 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>
И тогда всё заработало, как следует..
Насобирал отличную подборочку смешных комментариев в коде, думаю, программисты оценят свою же лирику (=
// 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 для отслеживания посещений на вашем блоге, то вы можете быть удивлены скоростью загрузки страниц, по-крайней мере в Европе точно заметно. Народ начал замечать, что в так называемые «часы-пик» использования Web-а код JavaScript от Google Analytics грузится на 97% медленнее по сравнению с обычной нагрузкой. Это справедливо для Европы. Для США такое падение в скорости тоже имеет место, но не такое заметное, разница составляет всего лишь 27%.
Чем это обусловлено – сложно сказать. Скорее всего, просто большинство серверов Гугла расположено не в Европе, и поэтому большое количество пользователей даёт такую усадку по скорости загрузки. Конечно, это не означает, что нужно перестать пользоваться этим прекрасным сервисом, и боятся за скорость загрузки вашего сайта. Всё это некритично.
Есть конечно и ряд других аналогичных некоммерческих сервисов для отслеживания посещений на вашем сайте. Сегодня один из моих друзей показал мне такую вещь как Woopra (http://www.woopra.com). На данный момент сервис находится в стадии бета-тестирования, но багов мной не было замечено, можно смело пользоваться. По возможностям сервис превосходит аналогичный GA (Google Analytics). Единственный недостаток – у них большая нагрузка на сервера и поэтому можно ждать около месяца пока ваш аккаунт утвердят. Что сразу бросилось в глаза – Woopra может отслеживать посещения и анализировать поведение пользователей вплоть до отдельного индивидуума, такого GA, конечно, не предоставляет.
Кого заинтересовало, думают стоит разобраться более детально, там много ещё чего интересного. А какими сервисами пользуетесь вы для отслеживания и анализа посещений на ваши сайты?
Несколько бесплатных зарубежных хостингов:
Оба, вроде, хороши, по отзывам пользователей. Но Awardspace частенько грешит долгими downtime, в отличии от Freehostia, у которой они гораздо реже и не так заметны. Оба хостинга предоставляют услуги без внедрения рекламы на ваши страницы, и вы можете свободно использовать PHP или Perl скрипты. Кстати, Freehostia даже предоставляет бесплатный план с уже предустановленным рядом скриптов, которые могут быть полезны новичкам.
В общем советую попробовать.
Иллюзия сочетает в себе три простых, общеизвестных эффекта:
- Когда происходит кратковременное событие в одной точке поля зрения, а в близлежащей точке имеет место схожее событие, мы воспринимаем это как движение из одной точки в другую. Это явление называют мнимым движением, или бета-движением, поскольку фактически никакого движения не было. Мнимое движение является основой движущихся неоновых вывесок, фильмов и видео. Мы видим движение поскольку устройство отображения информации (например, монитор) стимулируют рецепторы головного мозга (называемые рецепторами Рейхардта), отвечающие за расшифровку движений. Визуальными событиями в данной иллюзии являются исчезновение сиреневых кружков, а также дальнейшее появление зелёных послеобразов (см. далее).
- Когда исчезает сиреневый раздражитель, присутствующий в определённой области поля зрения в течение длительного времени (скажем, около 10 секунд), появляется зелёный послеобраз. Этот послеобраз остаётся в течение достаточно короткого промежутка времени, и в данном случае, "стирается" повторным появление сиреневого раздражителя. Появление послеобраза является следствием адаптации палочек и колбочек сетчатки. Цвет и яркость определяются соотношением активностей трёх типов колбочек. Под влиянием сиреневого раздражителя колбочки "устают". Когда раздражитель исчезает, усталость колбочек способствует тому, что активность, вызванная в них серым фоном, совпадает с таковой в состоянии покоя. Адаптация палочек и колбочек начинается сразу же после начала действия раздражителя, поэтому длительность послеобразов постепенно начинает расти. Обычно мы их не замечаем, поскольку изменяем положение глаз примерно 3 раза за секунду, и видимое изображение каждый раз попадает на новые, неадаптировавшиеся палочки и колбочки. В этой иллюзии, наши глаза сохраняют неподвижность, что вызывает нарастание длительности послеобразов, возникающих после прекращения действия раздражителя.
- Если в области периферического зрения, появляется размытый раздражитель, и при этом сохраняется неподвижность глаза, то раздражитель исчезает, даже если он всё ещё физически присутствует. Это явление называется затуханием Трокслера (Troxler's fading). Так происходит потому, что даже если наши глаза сфокусированы на точке и слегка двигаются, движения вне этой точки (в области периферического зрения) недостаточны для того чтобы сдвинуть сиреневые пятна на новые нейроны нашей зрительной системы. Эти послеобразы фактически перекрывают основные образы и все сиреневые пятна кажутся серыми, за исключением тех мгновений, когда появляются зелёные послеобразы.
Работа над протоколом jabber была начата ещё в 1998 году, но более широкое распространение получил в середине 2000 года. С того времени появилось много библиотек и реализаций данного протокола, почти для всех языков программирования. Более детальный список можно посмотреть на оффсайте: http://xmpp.org/software/libraries.shtml.
Extensible Messaging and Presence Protocol, сокращённо XMPP, это открытый протокол, основанный на XML, предназначенный для обмена мгновенными сообщениями и информацией о присутствии (списке контактов, например). Был опубликован в виде RFC 3920. Он остаётся основным протоколом технологии обмена мгновенными сообщениями Jabber. Главной целью протокола – была расширяемость, таким образом, он быстро получил много дополнительных возможностей, такие как передача голоса или передача файлов.
На оффсайте набор библиотек для работы на PHP представлен тремя вариантами:
Больше всего приглянулась библиотека 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-магазина, поста из агрегатора новостей или другой важной информации с вашего приложения на сервере.
Я уже подымал тему сортировок в своём блоге, но придется затронуть ещё одно, казалось бы, «ровное» место. Стояла задача сортировки массива данных по 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?