<?xml version="1.0" encoding="windows-1251" ?> 
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Дмитрий Шейко ‹ Корпоративный блог ‹  Red Graphic Systems</title> 
<link>http://blog.redgraphic.ru/</link> 
<description>Последние публикации в блоге Дмитрий Шейко (Red Graphic Systems)</description> 
<language>ru</language> 
<managingEditor>info@redgraphic.ru</managingEditor> 
<copyright>Copyright (c) 2003 Red Graphic Systems</copyright> 
<generator>PHP script</generator> 

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/18-03-08_399/</guid> 
<title>(18/03/08) Корпоративный блог Red Graphic замораживается, а блог Шейко переезжает</title> 
<link>http://blog.redgraphic.ru/sheiko/18-03-08_399/</link> 
<description>
&lt;p>&lt;span>Этот корпоративный блог был впервые открыт в 2003 
году. В том время мы были вынуждены писать пояснение на главное странице «Что 
такое блог». Не прошло и пяти лет, а такое ощущение, что это было в прошлом 
веке. Каждый год приходят новые технологии, новые идеи и решения. Часть из них 
теряется в истории, но часть принимается широкой общественностью и превращается 
в глобальные тренды. Тренды обретают популярность и их реализуют все в новых и 
новых проектах. Но чтобы это произошло, кто-то обязан предрекать их успех. 
Именно в этом я видел миссию нашего блога – открывать то, что может стать 
ключевым в Вебе будущего. Благие намерения и ненасытное тщеславие движут мною и 
по сей день. Чего не скажешь про остальных авторов блога. А так как материалов 
от прочих авторов давненько нет и не предвидится, корпоративный блог ныне более 
походит на личный блог Шейко. Это обстоятельство заставило собраться тех, кто 
некогда учреждал проект блога и принять решение. И вот оно принятое решение. 
Корпоративный блог &lt;/span>&lt;span lang="EN-US">Red Graphic &lt;/span>&lt;span>замораживается, а Шейко переносит свои материалы 
на личный сайт (&lt;/span>&lt;span lang="EN-US">&lt;a href="http://blog.cmsdevelopment.com" target="_blank">http://blog.cmsdevelopment.com&lt;/a>&lt;/span>&lt;span>), где он будет публиковаться в 
дальнейшем.&lt;/span>&lt;/p>
&lt;p style="margin: 0cm 0cm 0pt;">&lt;span lang="EN-US">&lt;/span>&lt;/p>
&lt;p style="margin: 0cm 0cm 0pt;">&lt;span>Тех кто был подписан на &lt;/span>&lt;span lang="EN-US">RSS &lt;/span>&lt;span>моей ленты, попрошу 
изменить адрес канала на &lt;/span>&lt;span lang="EN-US">&lt;a href="http://blog.cmsdevelopment.com/rss/" target="_blank">http://blog.cmsdevelopment.com&lt;span lang="RU">/&lt;/span>rss/&lt;/a></description> 
<dc:date>2008-03-18T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/06-03-08_398/</guid> 
<title>(06/03/08) Социальные сервисы и права пользователей </title> 
<link>http://blog.redgraphic.ru/sheiko/06-03-08_398/</link> 
<description>
&lt;p>То, что мы наблюдаем сегодня - это шквальный рост числа новых сервисов. Каждый день появляется что-то новое. Что можно сказать о пользователях, на которых рассчитаны все эти сервисы? Они растерянны, сбиты с толку этим бесконечным потоком предложений. Они мне представляются как несчастные граждане, не ведающие о своих правах, завязшие в водовороте бурлящего рынка. А есть ли какие-либо права у пользователей этого «дикого» социального веба? Участники группы &lt;a href="http://opensocialweb.org/">Open Social Web&lt;/a> убеждены, что каждый пользователь имеет право владения персональными данными, право контроля над тем, с кем эти данные могут быть разделены и право предоставлять постоянный доступ к этим данным для определенных внешних сайтов. Но чем это может помочь нашим раздосадованным пользователям? Видите ли, для того чтобы в полной мере опробовать какой-либо новый сервис, требуется регистрироваться в нем, заполнять все свои персональные данные, формировать свой круг друзей, проявлять активность и накапливать авторитет. Вот она - проблема. &lt;a name="habracut"> &lt;/a>Вам потребуется много времени и сил для того, чтобы узнать, нужен ли вам действительно этот сервис. Времени и сил уже потраченных на каком-то другом сервисе. Но если разработчики нового сервиса солидарны с идеями Open Social Web, то достаточно будет лишь делегировать новому сервису доступ к вашим персональным данным, к вашей активности. Вы войдете на новый сервис преисполненными собственной значимостью, со всем накопленным авторитетом, с вашими друзьями по социальным сетям и прочее. Более того, новый сервис импортирует структуру ваших предпочтений и покажет вам на переднем плане то, что вы хотели бы увидеть и в том виде в котором вам это понравиться. Звучит как фантастика. Но теоретически это достижимо. Как?&lt;/p>
&lt;p>&lt;/p>
&lt;p>Международная группа достаточно известных в социальном вебе экспертов именуемая как &lt;a href="http://www.dataportability.org/" target="_blank">Data Portability&lt;/a> рекомендует использовать определенные существующие технологии как раз для достижения описанной выше миссии. Так что же это за технологии и как их использовать в собственных проектах?&lt;/p>
&lt;p>&lt;/p>
&lt;h2>&lt;em>Идентификация пользователя и данные его профиля&lt;/em>&lt;/h2>

&lt;p>&lt;/p>
&lt;p>Начнем с идентификации пользователя. Самый простой стандарт в этом отношении &lt;a href="http://microid.org/" target="_blank">MicroID&lt;/a>. Он использует пару email + url для идентификации пользователя. Вот его формула:&lt;/p>
&lt;p>&lt;/p>&lt;pre>microID = sha1(&lt;/pre>&lt;pre> sha1( "mailto:sheiko@mysite.com" ) &lt;/pre>&lt;pre>+ &lt;/pre>&lt;pre>sha1( "http://cmsdevelopment.com/" ) &lt;/pre>&lt;pre>)&lt;/pre>
&lt;p>&lt;/p>
&lt;p>Для подтверждения того, что пользователь реально владеет указанной им страницей, достаточно лишь указать в ее секции HEAD следующее:&lt;/p>
&lt;p>&lt;/p>&lt;pre>meta name="microid" content="mailto+http:sha1:код_microID"/&lt;/pre>

&lt;p>&lt;/p>
&lt;p>Несмотря на всю видимую простоту стандарта его уже поддержали такие проекты как &lt;a href="http://digg.com/">Digg&lt;/a>, &lt;a href="http://plaxa.com/">Plaxa&lt;/a>, &lt;a href="http://claimid.com/">ClaimID&lt;/a>, &lt;a href="http://www.last.fm/">Last.fm&lt;/a>, &lt;a href="http://ma.gnolia.com/">Ma.gnolia&lt;/a>, &lt;a href="http://wikitravel.org/en/Main_Page">Wikitravel&lt;/a>, и &lt;a href="http://yedda.com/">Yedda&lt;/a>. &lt;/p>

&lt;p>&lt;/p>
&lt;p>Лично мне показалось интересным, что MicroID может быть использован не только для подтверждения подлинности пользователя при обратной связи, но и, скажем, для подтверждения его репутации на стороннем сервисе:&lt;/p>
&lt;p>&lt;/p>
&lt;p>&lt;code>span class="score microid-mailto+http:sha1:fe98b5adf288318c0763e1d5b0855b3d2266338c"5/span&lt;/code>&lt;/p>
&lt;p>&lt;/p>
&lt;p>Второй стандарт по идентификации пользователя, полагаю, вам знаком – это OpenID. Я уже ранее рассматривал &lt;a href="http://habrahabr.ru/blog/php/20899.html">этот стандарт на Хабрахабре&lt;/a> в отношении идентификации пользователя на собственном проекте (OpenID consumer). Однако коль уж мы заговорили о правах пользователей, то было бы справедливо предоставить пользователям вашего сервиса эдакий «виртуальный паспорт», который они смогли бы предъявлять на сторонних проектах. Для этого потребуется раздавать пользователям адрес личных страниц на сервисе в поддоменах типа &lt;a href="http://sheiko.pozzzy.ru/">http://sheiko.pozzzy.ru&lt;/a>. Для тех, кому не случалось делать подобное, порекомендую использовать в конфигурации Apache (если вы используете этот сервер) в секции VirtualHost параметр ServerAlias на манер ServerAlias *.pozzzy.ru. После этого останется лишь разбирать содержание переменной $_SERVER["HTTP_HOST"] в стартовом скрипте PHP. Для того чтобы сделать свой сервис OpenID provider вам понадобиться соответствующее программное обеспечение. В общем случае можно использовать библиотеку от &lt;a href="http://www.openidenabled.com/">OpenID Enabled&lt;/a> (имеются PHP, Python, Ruby версии). Однако меня покорил своей простотой крохотный фреймворк &lt;a href="http://siege.org/projects/phpMyID">PHPMyID&lt;/a>. &lt;/p>

&lt;p>&lt;/p>
&lt;p>&lt;img src="http://cmsdevelopment.com/views/delivery/img/blog/openid_provider.jpg" alt="Применение OpenID Provider" border="0" height="379" hspace="10" vspace="10" width="436">
&lt;/p>
&lt;p>&lt;/p>
&lt;p>Имеется так же крохотный стандарт &lt;a href="http://pavatar.com/" target="_blank">Pavatar&lt;/a>, позволяющий связать изображение 80x80px. (аватару) с пользователем. Допускаются форматы PNG, JPG и GIF. Достаточно лишь добавить на странице пользователя код:&lt;/p>
&lt;p>&lt;/p>
&lt;p>&lt;code>link rel="pavatar" href="http://example.com/path/my-pavatar.png" /&lt;/code>&lt;/p>
&lt;p>&lt;/p>
&lt;p>Кстати говоря, pavatar и MicroID могут предоставляться с прочей информацией из профиля пользователя провайдером OpenID.&lt;/p>
&lt;p>&lt;/p>
&lt;p>&lt;/p>
&lt;p>Информация о пользователе так же может быть задана посредством микроформата &lt;a href="http://microformats.org/wiki/hcard-examples">hCard&lt;/a>.&lt;/p>

&lt;p>&lt;/p>
&lt;h2>&lt;em>Информация о социальных связях пользователя&lt;/em>&lt;/h2>
&lt;p>&lt;/p>
&lt;p>Ок. Мы разобрались с тем как можно идентифицировать пользователя и предоставить ему возможность делегировать право чтения данных его профиля. Но как можно получить информацию о его друзьях в различных социальных сетях? Как минимум это позволило бы нам показать пользователю, кто из его друзей представлен на нашем сервисе. &lt;/p>
&lt;p>&lt;/p>
&lt;p>Небезызвестный Брэд Фицпатрик (&lt;a title="Brad Fitzpatrick" href="http://en.wikipedia.org/wiki/Brad_Fitzpatrick">Brad Fitzpatrick&lt;/a>), основатель LiveJournal, автор стандарта OpenID последнее время активно продвигает концепцию &lt;a href="http://code.google.com/apis/socialgraph/">Social Graph&lt;/a> и гугловский API к ней. Идея в том, что Google индексирует информацию о связях пользователей в социальных сетях если они, эти связи, представлены в заданных форматах (&lt;a href="http://gmpg.org/xfn/">XFN&lt;/a> и &lt;a href="http://www.foaf-project.org/">FOAF&lt;/a>). API позволяет получать эту информацию в удобном виде. Кстати, если вам вдруг не достаточно Google, воспользуйтесь &lt;a href="http://www.plaxo.com/info/opensocialgraph">Plaxo Open Social Graph&lt;/a>.Т.е. когда пользователь вошел на наш сервис, мы можем опросить Social Graph по поводу его друзей в других сервисах. Далее останется лишь сравнить их идентификаторы по базе пользователей нашего сервиса и сообщить пользователю о его друзьях на проекте. Поскольку получить данные от Social Graph достаточно просто (предлагается ответ по вашему запросу в форме text, JSON, XML), имеет смысл остановиться над тем, как оформить данные для их дальнейшей индексации в граф. &lt;/p>

&lt;p>&lt;/p>
&lt;p>Прежде всего, следует изменить код ссылок на страницах пользователей в рамках сервиса в соответствии с микроформатом &lt;a href="http://gmpg.org/xfn/">XFN&lt;/a>.&lt;/p>
&lt;p>&lt;/p>
&lt;p>Можно использовать a rel="me" ..../a для дополнительных ссылок, связанных с владельцем открытой страницы и a rel="friend" ..../a для ссылок на страницы его друзей. Если в вашем сервере доступны подробности отношения пользователя с его друзьями это можно отразить, скажем, как a rel="friend met" ..../a.&lt;/p>

&lt;p>&lt;/p>
&lt;p>&lt;img src="http://cmsdevelopment.com/views/delivery/img/blog/xfn_usecase.gif" alt="Использование XFN" border="0" height="349" hspace="10" vspace="10" width="450">
&lt;/p>
&lt;p>&lt;/p>
&lt;p>Что касается стандарта &lt;a href="http://www.foaf-project.org/">FOAF&lt;/a> (The Friend of a Friend), то позволяет описать пользователя и его связи в более структурированной форме, в RDF. Вам следует указать в коде страницы пользователя ссылку на его RDF-документ:&lt;/p>&lt;pre>link rel="meta" type="application/rdf+xml" title="FOAF" href="http://sheiko.pozzzy.ru/foaf/"/&lt;/pre>&lt;pre>&lt;/pre>
&lt;p>Сам RDF-документ должен формироваться автоматически на основании данных о пользователе и его связях в рамках проекта.&lt;/p>
&lt;p>&lt;/p>
&lt;h2>&lt;em>Информация о предпочтениях пользователя&lt;/em>&lt;/h2>
&lt;p>&lt;/p>
&lt;p>Говоря о правах пользователя, я также упоминал возможность обмена информацией о предпочтениях пользователя между сервисами. Одной из наиболее любимой в еще одном коллективе почтенных джентльменов &lt;a href="http://media2.0workgroup.org/">Media 2.0 Workgroup&lt;/a> является технология &lt;a href="http://www.apml.org/">APML&lt;/a>. Существует множество различных методов учета предпочтений пользователя на основании его активности. Для этого служат и настольные приложения (&lt;a href="http://www.particls.com/">Particls&lt;/a>) и такие онлайн сервисы как &lt;a href="http://www.bloglines.com/">Bloglines&lt;/a>, &lt;a href="http://www.cluztr.com/">Cluztr&lt;/a>, &lt;a href="http://dandelife.com/">Dandelife&lt;/a> и конечно Google. Указанные сервисы за исключением Google используют язык разметки APML для описания профилей предпочтений пользователей. Что собственно и открывает возможность обмена этими профилями между сервисами с позволения пользователя. &lt;/p>

&lt;p>&lt;/p>
&lt;p>&lt;/p>
&lt;p>В заключении хотелось бы также отметить и технологию &lt;a href="http://www.hueniverse.com/hueniverse/oauth/index.html">OAuth&lt;/a>. Она позволяет делегирование прав на постоянный или временный доступ к персональным данным пользователя для сторонних сервисов и их API. &lt;/p>
&lt;p>&lt;/p>
&lt;p>&lt;/p>
&lt;p>&lt;/p>
&lt;p>Как видите это в наших руках - сделать социальный веб открытым, дать пользователям законные права касательно их личных данных. Умные люди уже продумали, как это может быть достижимо и задача разработчиков сервисов лишь воплотить эти идеи. &lt;/p></description> 
<dc:date>2008-03-06T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/01-02-08_397/</guid> 
<title>(01/02/08) Социальная сеть в трех лицах</title> 
<link>http://blog.redgraphic.ru/sheiko/01-02-08_397/</link> 
<description>
&lt;p>Если мы говорим о социальных сетях в русскоязычном сегменте Интернета, то на  ум приходят лишь три проекта &lt;a href="http://vkontakte.ru/">vkontakte.ru&lt;/a>, &lt;a href="http://odnoklasniki.ru/">odnoklasniki.ru&lt;/a> и &lt;a href="http://moikrug.ru/">moikrug.ru&lt;/a>. Причем, две первые сети самые  посещаемые сайты Рунета, если верить Alexa. В этой связи любопытно, что лидер  чартов &lt;a href="http://vkontakte.ru/">vkontakte.ru&lt;/a> в Беларуси практически не  упоминается, в то время как &lt;a href="http://odnoklasniki.ru/">odnoklasniki.ru&lt;/a> обсуждаются даже в очередях в  магазинах.&lt;br>&lt;br>Я опробовал все три сети и пришел к выводу, что вроде как  конкурентные проекты, тем не менее, все они отвечают различным потребностям  аудитории. Самая несовершенная в техническом плане сеть &lt;a href="http://odnoklasniki.ru/">odnoklasniki.ru&lt;/a> опирается, как и ее  прародитель &lt;a href="http://classmates.com/">classmates.com&lt;/a> (&lt;a href="http://chasinggoogle.blogspot.com/2007/11/12-years-of-social-networks-who-was.html">кстати,  о том кто был первым&lt;/a>), на ностальгические чувства к утерянным в водовороте  жизни «боевым друзьям» детства и юности. Ну, это общепринятая практика  фактически для любой страны: &lt;a href="http://xiaonei.com/">xiaonei.com&lt;/a>, &lt;a href="http://nasza-klasa.pl/">Nasza-klasa.pl&lt;/a>, &lt;a href="http://studivz.de/">studiVZ.de&lt;/a>, &lt;a href="http://studiln.it/">studiLN.it&lt;/a>, &lt;a href="http://estudiln.es/">estudiLN.es&lt;/a>, &lt;a href="http://www.trombi.com/">trombi.com&lt;/a>, &lt;a href="http://connect.com.ua/">connect.com.ua&lt;/a>. И надо отметить, как бы не  расширялся список возможных зависимостей между пользователями в подобном  проекте, едва ли он сможет конкурировать со специализированной сетью,  опирающейся, скажем, на генеалогические связи &lt;a href="http://myheritage.com/">MyHeritage.com&lt;/a>, &lt;a href="http://geni.com/">Geni.com&lt;/a> или на отношения сложившиеся в  туристических поездах &lt;a href="http://travbuddy.com/">TravBuddy.com&lt;/a>, &lt;a href="http://wayn.com/">WAYN.com&lt;/a>. Парадокс? Нет, просто в специализированной  сети проще найти релевантных вашим запросам людей.&lt;/p>
&lt;br />&lt;br />

&lt;p>&lt;img src="http://blog.redgraphic.ru/img/classmates450.gif" alt="">&lt;br>&lt;br>Что же касается сети  &lt;a href="http://vkontakte.ru/">vkontakte.ru&lt;/a>, было много сказано о том, что  это прямой аналог &lt;a href="http://facebook.com/">facebook.com&lt;/a>. Не бывает  дыма без огня, чувствуется упор уже не на одноклассников, а на сокурсников.  Нельзя упустить из виду знаменитую «стену» из &lt;a href="http://facebook.com/">facebook.com&lt;/a>. Однако нынешний &lt;a href="http://facebook.com/">facebook.com&lt;/a> примечателен уже ни сколько как  социальная сеть, сколько как распределенная платформа для веб-приложений. Уже  доступны многие тысячи таких приложений и некоторые мои знакомые просто удивляют  своим энтузиазмом, подключая по десятку новых приложений на свой профиль  ежедневно. Проект &lt;a href="http://vkontakte.ru/">vkontakte.ru&lt;/a> ничего  подобного вроде бы не предлагает, но является уникальным местом для создания  локальных сообществ по интересам. Отличный сервис для загрузки изображений,  кое-какой сервис для загрузки видео и аудио плюс лента коротких сообщений  открывают широкие возможности для самовыражения. Если учесть потенциальную  аудиторию в 6,5 млн. участников – есть, где постараться.&lt;/p>
&lt;br />&lt;br />
&lt;p>&lt;img src="http://blog.redgraphic.ru/img/facebook450.gif" alt="" height="318" width="450">&lt;br>&lt;br>И, наконец,  самая совершенная техническая реализация, &lt;a href="http://svoikrug.ru/">svoikrug.ru&lt;/a> – типичная бизнес сеть. Во многом  подобная &lt;a href="http://linkedin.com/">LinkedIn.com&lt;/a>, &lt;a href="http://plaxo.com/">Plaxo.com&lt;/a>, &lt;a href="http://www.ecademy.com/">Ecademy.com&lt;/a>, &lt;a href="http://xing.com/">XING.com&lt;/a> (бывший OpenBC).&lt;br>&lt;br>Конечно, там тоже  можно поискать друзей, но это малоэффективно. Зато поискать коллег очень даже  полезно. Как правило, пользователи &lt;a href="http://svoikrug.ru/">svoikrug.ru&lt;/a>  представлены своими бизнес-карточками, у них заполнено CV, описана  профессиональная деятельность, достижения и т.д., есть исчерпывающая информация  о человеке, как о специалисте. Таким образом, &lt;a href="http://svoikrug.ru/">svoikrug.ru&lt;/a> – отличная возможность не только  восстановить утерянные бизнес-контакты, но и обрести новые. Попробуйте пройтись  по спискам контактов ваших друзей первого круга. Действительно обнаруживается  много интересного. Но более того, органично интегрированная в сеть система  поиска работы в нынешние «трудные» времена, когда найти специалиста реально  сложно, открывает новые перспективы. А возможность предварительно осведомиться о  кандидате у общих друзей, обнаруженных в его кругах, делает такой путь особенно  эффективным.&lt;/p>
&lt;br />&lt;br />
&lt;p>&lt;img src="http://blog.redgraphic.ru/img/linkedin450.gif" alt="" height="401" width="450">&lt;br>&lt;br>Порадовали меня также и такие «фишечки» как блоги и  обсуждения относительно указанных компаний. В общем и целом, похоже, этот проект  из трех указанных наиболее полно раскрывает потенциал социальных  сетей.&lt;br>&lt;br>Но как полагается, должно быть место и критике. Почему-то ни одна  из трех сетей пока не содержит сервиса рекомендаций. Даже странно – иметь такие  огромные сообщества и не предоставить возможность пользователям рекомендовать  друг другу книги, рестораны, клубы, туры и т.д. Как-то незаметно привязки  пользователей, компаний, школ и ВУЗов к картам, пусть к тому же Google Map.  Пользовательские интересы во всех сетях кликабельны, но под ними нет обсуждений  и электронной коммерции. Я бы добавил в сеть moikrug.ru сервис «&lt;a href="http://answers.yahoo.com/">Answers&lt;/a>» с автоматическим поступлением  вопросов в специальные окна страниц специалистов запрошенного профиля. И  главное, очень не хватает полноценной поддержки OpenID во всех трех сетях. Не  малая часть пользователей зарегистрирована более чем в одной сети. Было бы  удобно, если бы однажды заполненный профиль переносился автоматически при каждой  новой регистрации.&lt;br>&lt;br>В любом случае, все три сети вполне зрелые проекты.  Если я пару лет назад на приглашения вступить в МойКруг смотрел эдак свысока,  ныне нахожу каждую сеть по своему полезной.&lt;/p></description> 
<dc:date>2008-02-01T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/12-01-08_396/</guid> 
<title>(12/01/08) Конструктор для создания контент-зависимых приложений в стиле Веб 2.0</title> 
<link>http://blog.redgraphic.ru/sheiko/12-01-08_396/</link> 
<description>
&lt;P>Речь пойдет о недавно открытом Open Source проекте SAPID CMF. Само по себе название SAPID кому-то может показаться чем-то смутно знакомым. Да, жила-была такая простенькая CMS SAPID, которая позволяла администрировать сайты inline, требовала лишь 1МБ дискового пространства и умудрялась обходиться без СУБД. Однако мало кто помнит, что создавалась эта система с целью продемонстрировать возможности парадигмы XML Sapiens. CMS SAPID благополучно и помпезно встретила свою первую годовщину, а затем 2 года никаких существенных ее новых релизов, как это ни прискорбно, не наблюдалось. Впрочем, последний год на сайте сообщества SAPID (&lt;A href="http://www.sapid-club.com/">www.sapid-club.com&lt;/A>) время от времени проскакивала информация о работах над новой ветвью проекта SAPID CMF. Вуаля! Вот она - ветка, доступна для загрузки (&lt;A href="http://sapidcmf.sourceforge.net/">http://sapidcmf.sourceforge.net&lt;/A>) и для «шапочного» знакомства (&lt;A href="http://cmfdemo.xmlsapiens.org/">http://cmfdemo.xmlsapiens.org&lt;/A>). &lt;/P>
&lt;P>&lt;/P>&lt;br />
&lt;P>SAPID CMF – это, что-то вроде набора «два в одном», где SAPID – система управления контентом с базовым административным интерфейсом и CMF – конструктор для превращения это интерфейса в собственную кастомизированную систему. &lt;/P>
&lt;P>&lt;/P>&lt;br />
&lt;P>Любая CMS – это с одной стороны движок для веб-приложений, с другой – интерфейс для администрирования этих приложений. Логично было бы предположить, что приложения области доставки (те, что доступны пользователям сайта) и приложения административной панели CMS функционируют на базе одного движка, подчиняются единой логике, используют единый принцип шаблонов. Таким образом, CMS, позволяющая создание внешних веб-приложений, с той же легкостью должна обеспечить создание внутренних административных интерфейсов. Сердце SAPID – процессор XML Sapiens. &lt;a href="http://xmlsapiens.org">XML Sapiens&lt;/a> - декларативный язык, для описания шаблонов структур данных, оформления и функциональности. С помощью языка можно создавать компоненты для всех трех уровней (данные, оформление, функциональность) и использовать их многократно (reusing), подобно кубикам конструктора, для получения самых различных решений. Процессор XML Sapiens компилирует эти компоненты в готовый пользовательский интерфейс приложения. &lt;/P>
&lt;P>&lt;/P>&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/sapid02_450.gif" />
&lt;br />
&lt;P>&lt;/P>
&lt;P>Для веб-приложений, в отличие от настольных программ, нет заданного набора элементов управления GTK. Это и достоинство и недостаток. При создании каждого нового приложения или группы приложений разработчики вынуждены создавать новый GTK. Дабы облегчить жизнь разработчикам, GTK административной панели SAPID CMF выполнена на манер Windows. В каждом ее приложении имеются рабочая область, меню, модальные окна, окна сообщений, диалогов, процессов. Доступны компоненты – tree view и list view. Таким образом, мы имеем эдакий «джентльменский набор» для быстрого создания приложений административной панели в едином стиле. &lt;/P>
&lt;P>&lt;/P>
&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/sapid03_450.gif" />
&lt;br />
&lt;P>&lt;/P>
&lt;H3>Готовность к развитию&lt;/H3>
&lt;P>&lt;/P>
&lt;P>Вы скажете: «Отлично! Я добавлю в административную панель собственные приложения. Через месяц появится новый релиз фреймворка. Я выполню обновление и потеряю всю свою работу». На самом деле SAPID CMF организован так, что при обновлении заменяются лишь базовые компоненты, а дополнительные компоненты, добавленные разработчиком останутся нетронутыми. Возникает вопрос: «Как модифицировать базовые компоненты и защитить код модификации от перезаписи при обновлении?». В SAPID CMF используется событийная модель в стиле &lt;a href="http://www.cmsdevelopment.com/ru/articles/aosdinphp/">аспект-ориентированного программирования&lt;/a>. В системе определены различные события. Вы можете добавить собственные обработчики различных событий, модифицирующие среду должным образом. Код модификации будет помещен в папку plugins, которая пропускается при обновлении фреймворка. В терминах АОП для внесения модификаций в базовые компоненты (библиотеки API, контроллеры и т.д.) вы определяете некоторый аспект модификации.&lt;/P>
&lt;P>&lt;/P>
&lt;P>$ModalWindowCustomization = new Aspect(); &lt;/P>
&lt;P>&lt;/P>
&lt;P>Задаете для него область прослушивания, скажем все классы и все методы &lt;/P>
&lt;P>&lt;/P>
&lt;P>$pc = $ModalWindowCustomization->pointcut("call *::*");&lt;/P>
&lt;P>&lt;/P>
&lt;P>и назначаете определенному событию код модификации &lt;/P>
&lt;P>&lt;/P>
&lt;P>$pc->_event("ModalWindowSchemasDefined", "customizateModalWindow($obj);");&lt;/P>
&lt;P>&lt;/P>
&lt;P>&lt;/P>
&lt;P>Как уже говорилось сверхзадача SAPID CMF обеспечить эффективное многократное использование заготовок структур данных, оформления и функциональности при создании веб-приложений. Фреймворк содержит корневую папку VIEWS. В ней имеются папка DEFAULT для шаблонов темы оформления административной панели по умолчанию и папка DELIVERY для шаблонов приложений, созданных на базе фреймворка. Если вы добавите дополнительные темы оформления, здесь появятся соответствующие им папки. Любая из них содержит шаблоны функциональности (папка DDC), наборы полей (папка FIELDSETs), шаблоны запросов содержания (папка QCs) и шаблоны оформления (папка TEMPLATES). &lt;/P>
&lt;P>&lt;/P>
&lt;H3>Однажды написав, используем многократно&lt;/H3>
&lt;P>&lt;/P>
&lt;P>При создании веб-приложения в сверстанном скетче логической страницы определяются динамические области. К примеру, мы вырезаем блоки меню, блоки списков и т.д. и переносим их код оформления в соответствующие DDC. &lt;a href="http://habrahabr.ru/blog/webdev/8832.html">DDC помимо кода оформления задает также и логику динамического блока&lt;/a>. Здесь могут быть использованы условия, перечисления данных у запрошенных приложений CMS, включения, выражения XML Sapiens, а также неограниченная вложенность данных структур. Для описания данной логики используется XML. XML Sapiens позволяет использовать один и то же DDC для формирования различных динамических блоков. При вызове DDC могут быть переданы параметры, которые могут быть рассмотрены в условиях DDC. &lt;/P>
&lt;P>&lt;/P>
&lt;P>&lt;sapi:apply name="ddc.#submenu.value">&lt;/P>
&lt;P>&lt;sapi:param name="root">structure&lt;/sapi:param>&lt;/P>
&lt;P>&lt;/sapi:apply>&lt;/P>
&lt;P>&lt;/P>
&lt;P>Если в коде динамического блока или в коде шаблона логической страницы предполагается форма ввода данных, мы обращаемся к QC. QC определяет каким образом будут отображены или запрошены сообщенные ему данные. Скажем, если мы используем вызов типа &lt;sapi:apply name="qc.contentblock.value" type="article" title="Введите содержание" />, в состоянии администрирования логической страницы мы увидим запрос с редактором WYSIWYG (соответствует типу article) и с заголовком "Введите содержание". В состоянии доставки содержания (просмотра) страницы, нам будет показано содержание контейнера contentblock, введенное по данному запросу при администрировании. &lt;/P>
&lt;P>&lt;/P>
&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/sapid04_450.gif" />
&lt;br />
&lt;P>&lt;/P>
&lt;P>Если набор полей формы запроса данных варьируется динамически (зависит от состояния среды), мы можем использовать вызов набора полей. Например, &lt;/P>
&lt;P>&lt;/P>
&lt;P>&lt;sapi:include href="fieldset1.xml" parse="fieldset" state="admin" />&lt;/P>
&lt;P>&lt;/P>
&lt;P>Данная конструкция вернет набор полей запроса содержания, соответствующий состоянию admin в файле fieldset1.xml.&lt;/P>
&lt;P>&lt;/P>
&lt;H3>Какова теория на практике?&lt;/H3>
&lt;P>&lt;/P>
&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/sapid01_450.gif" />
&lt;br />
&lt;P>&lt;/P>
&lt;P>Вполне возможно дочитав до этого места, вы подумали: «Все эти нагромождения выглядят как-то страшновато. Интересно, а может ли хоть что-то на этом фреймворке реально заработать?». В дистрибутивном пакете вместе с фреймворком поставляется готовый демонстрационный сайт. Помимо типовых вещей сайт содержит пример формы авторизации/регистрации с использованием AJAX. Форма также включает возможность авторизации по OpenID. На сайте представлен пример рекламного места для баннеров, смешанных типов (GIF/Flash/DHTML/RichMedia). Имеется также пример использования технологии IntelliTXT. Термины, внесенные в тезаурус системы автоматически преобразовывается в текстах страниц сайта в ссылки tooltip (ссылки с двойным подчеркиванием). При наведении курсора мыши на ссылку всплывает окно с подсказкой. Система ведет статистику показов связанных со ссылками окон, так что этот механизм вполне можно использовать для контекстной рекламы. &lt;/P>
&lt;P>Демонстрационный сайт содержит пример многоуровневой галереи с возможностью комментирования фотографий. Допустимо голосование, как за фотографии, так и за комментарии. Пример каталога на сайте демонстрирует возможности группировки продуктов по тегам (схожие товары, облако тегов). В общем, есть с чем работать и более того есть некоторый базовый набор решений, которые можно смело использовать в своих проектах. &lt;/P></description> 
<dc:date>2008-01-12T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/19-10-07_395/</guid> 
<title>(19/10/07) Какова она социальная сеть нового образца?!</title> 
<link>http://blog.redgraphic.ru/sheiko/19-10-07_395/</link> 
<description>
Уже некоторое время в Интернете циркулирует информация о социальной сети нового поколения от Google SocialStream. Звучит многообещающе, но, по сути, данный  проект является скорее агрегатором, нежели полноценной социальной сетью нового образца.  SocialStream позволяет вам связать ваши коммуникации из различных источников в едином пространстве. Скажем, вы видите на своей странице обновления фотоальбомов ваших друзей с Flickr и Picasa, видео с Youtube, новые сообщения друзей с популярных блоговых сервисов. &lt;a name="habracut"> &lt;/a>На обошедшем Сеть малоразличимом скриншоте с сайта университета Карнеги (&lt;a href="http://www.hcii.cs.cmu.edu/M-HCI/2006/SocialstreamProject/index.php" title="http://www.hcii.cs.cmu.edu/M-HCI/2006/SocialstreamProject/index.php">http://www.hcii.cs.cmu.edu/M-HCI/2006/So…&lt;/a>) не видно никаких особенных нововведений, что могло бы отразить новые тенденции и моду для  социальных сетей. Я бы отметил лишь два специфичных виджета: список контактов и календарь событий. Причем первый – фактически калька Google Talk, зарекомендовавшего себя в Gmail. &lt;br>
&lt;br>
&lt;img src="/img/screenshot.gif" alt="SocialStream" border="0" hspace="10" vspace="10">&lt;br>
&lt;br>
&lt;br>
Параллельно со слухами о SocialStream муссировалась информация о проекте Yahoo! Mash. С недавних пор интерес к последнему возрос в связи с началом публичного тестирования. Я вчера нежданно обнаружил инвайт в почте от контакта с Yahoo! 360. Любопытство взяло вверх и я на скорую руку заполнил профиль &lt;a href="http://mash.yahoo.com/dsheiko" title="http://mash.yahoo.com/dsheiko">http://mash.yahoo.com/dsheiko&lt;/a>. &lt;br>
&lt;br>
Надо отдать должное разработчикам Mash, они таки абстрагировались от клеше в сфере разработки сервисов социальных сетей и попытались создать что-то новое. Суть сервиса – предоставить вам вашу личную страничку в Интернете, эдакую визитную карточку, посредством которых, виртуальные друзья обмениваются друг с другом. Само собой есть специальный механизм для коммуникаций с друзьями, наблюдения за их активностью.  В этом нет ничего нового. Незамысловатая проекция простых потребностей человека в социуме (презентовать себя, наладить общественные отношения) на Веб. Но вот что мне показалось свежим решением – изначально виртуальное пространство, которое вы получаете под свою опеку исключительно аскетично. Всего несколько вопросов и тегов, характеризующих вас как личность, доска для самовыражения и список друзей. Все остальное как оформление, так и приложения вы добавляется на страницу  по своему желанию. &lt;br>

&lt;br>
&lt;img src="/img/mash02.gif" alt="SocialStream" border="0" hspace="10" vspace="10">&lt;br>
&lt;br>
&lt;br>
&lt;br>
Как показывает опыт MySpace - страсть широких масс к захламлению своей страницы безвкусицей не имеет границ. Сервис Facebook в свою очередь демонстрирует, что нет смысла разработчикам самим писать новые приложения для проекта, эту задачу можно поручить пользователям. Yahoo! Mash учел обе тенденции в лучшем виде, плюс к тому, добавил также возможность манипулировать блоками страницы подобно как в Netvibes. Однако то, что меня особенно удивило, Mash позволяет (при желании вы можете отключить эту опцию) вашим друзьям редактировать вашу страницу. Когда я осознал это факт, мое сознание какое-то время отказывалось следовать данной логике по инерции. Однако затем мне представилось как типичная представительница новой волны интернет-пользователей, в полной мере владеющая лишь ICQ, просит знакомого настроить ей личную страничку. По мере того как в ее профиле Mash появляются новые RSS-ленты, видео на доске, гаджеты настраиваемых приложений и гламурные фоны ее чело озаряет безграничная радость. Первое что она сделает затем – разошлет ссылку на эту страницу (то бишь на сервис Yahoo! Mash) всем своим неисчислимым знакомым. Можно сказать - мечта для промоутера стартапа.  Но это еще не все. Разработчики добавили в изначальный состав страницы физиономию домашнего любимца. Это что-то вроде тамагочи.  Его можно кормить, лелеять, бутузить и даже убивать. Уверен описанная выше «блондинка в Интернете» частенько будет возвращаться на свою страницу, дабы покормить и холить своего питомца. А когда выяснить что его могут кормить и друзья – всем им будет выдано соответствующее распоряжение. Потенциал вовлечение в сервис впечатляющий. &lt;br>
&lt;br>
&lt;img src="/img/mash03.gif" alt="SocialStream" border="0" hspace="10" vspace="10">&lt;br>
&lt;br>
&lt;br>
К минусам сервиса я бы отнес вопросы раздела “About me”. Сама по себе попытка дать представление о человеке заслуживает уважения, но реализация, по-моему, провальная. Если на сервисах типа MySpace от пользователя требуют «опиши себя» (можно подумать, это так просто сделать, если, конечно, не описывать буквально), то здесь мы видим список вопросов из разряда тех, что любят задавать в интервью при устройстве на работу в западных компаниях. Едва ли они  поощряют пользователя к заполнению. &lt;br>
Давайте подумаем, к чему вообще все эти социальные сети? Предполагается, что они должны помочь пользователю обрести новых друзей. Они должны помочь выбрать среди миллионов только тех людей, которые реально интересны пользователю.  На MySpace по-прежнему есть армия пользователей, для которых единственным критерием при выборе друга является фотография в профиле. Они особенно не ищут смежные интересы и тому подобное.  Они используют сервис как службу знакомств. Те же, кто заинтересован в расширении круга общения в сфере личных или профессиональных интересов желают, прежде чем начать общение понять, что представляет потенциальный собеседник, будет ли он интересен, стоит ли вообще тратить на него время.  Т.е. должна быть соответствующая информация в профиле пользователя. Как ее получить? Мне попадалась реализация сети, где предлагалось 5 десятков вопросов, на языке практикующего психолога. Это скучно не только заполнять, но и читать.  У пользователя стоит запрашивать что-то, на что ему легко ответить, где ему не придется ломать голову над формой и последовательностью подачи, что-то более близкое к живому общении. Ну, представьте себе – вы беседуете с человеком и он вам: «опишите себя».  Было бы куда проще, если бы в профиле пользователя были вопросы типа «Расскажите о каком-нибудь запомнившемся случае из вашего детства / произошедшем с вами за последнее время ». Под ответом можно оставить кнопку для посетителей профиля «Расскажи о СВОЕМ случае». Тогда это будет похоже на ветку живого общения. Как в реальной жизни незнакомые люди (скажем в купе поезда) по началу не решаются общаться, но стоит кому-нибудь о чем-нибудь рассказать, как все включаются со своими аналогичными историями. Общение оживает, каждый участник открывается, становиться ясно кто вам ближе по духу, кто вовсе не интересен. Судя по нынешним заявкам, рано или поздно легкость живого общения будет воссоздана в социальных сетях. Как это будет сделано? Кто его знает, поживем - увидим. </description> 
<dc:date>2007-10-19T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/10-10-07_394/</guid> 
<title>(10/10/07) Joost на пути от социального веба к интернет-ТВ</title> 
<link>http://blog.redgraphic.ru/sheiko/10-10-07_394/</link> 
<description>
     Все больше и больше случается разговоров про интернет-телевидение нового поколения и в этой связи про проект Joost (&lt;a href="http://www.joost.com/">&lt;/a>&lt;a href="http://www.joost.com" title="http://www.joost.com">http://www.joost.com&lt;/a>). Признаться, когда я впервые увидел проект с его десктопной версией, я был поражен эффектностью этого решения. Дизайн приложения весьма ненавязчивый, свободный, но в тоже время все элементы управления хорошо продуманы, обогащены интерактивностью в лучших традициях RIA. Видео проигрывается в полноэкранном режиме во вполне приемлемом качестве (очевидный шаг вперед по сравнению с качеством YouTube-роликов). Все представленные видео-шоу в проекте созданы профессионалами, и для зрителя неизбалованного качеством западного ТВ все это производит, по крайней мере, по началу неизгладимое впечатление. Заявление самого Joost о наличии 1500 шоу в 250 каналах, прям таки, обещает бесконечное удовольствие. Однако что представляет собой Joost в действительности?&lt;br>
&lt;br>
&lt;img src="http://blog.redgraphic.ru/img/joost01.jpg" alt="Видео-подкаст Reuters на Joost" border="0" hspace="10" vspace="10">
&lt;br>
&lt;img src="http://blog.redgraphic.ru/img/joost02.jpg" alt="Опросник на канале Joost" border="0" hspace="10" vspace="10">
&lt;br>
&lt;img src="http://blog.redgraphic.ru/img/joost03.jpg" alt="Список каналов Joost" border="0" hspace="10" vspace="10">
&lt;br>
&lt;img src="http://blog.redgraphic.ru/img/joost04.jpg" alt="Список шоу Joost" border="0" hspace="10" vspace="10">
&lt;br>
&lt;br>
Идем на &lt;a href="http://www.joost.com/download/">&lt;/a>&lt;a href="http://www.joost.com/download/" title="http://www.joost.com/download/">http://www.joost.com/download/&lt;/a> и загружаем себе настольное приложение. В ходе инсталляции программа предложит зарегистрироваться на сервере Joost, что позволит в дальнейшем нам персонализировать своей виртуальное пространство в проекте. Что это даст? Традиционный набор: список избранных шоу, возможность голосования за шоу, набор виджетов. Надо заметить, что Joost показывает рекламу в весьма ненавязчивом виде, что едва ли отвлекает вас от просмотра. Тоже касается различных опросов. &lt;br>

&lt;br>
Что касается минусов, на мой взгляд, есть неудобство в самой концепции проекта – Joost показывает не потоковое видео, а предзагруженные ролики. Т.е. Joost - это что-то средне между ТВ и Youtube. &lt;br>
&lt;br>
Для того чтобы определить насколько удачно реализован проект имеет смысл сравнить его с конкурентами (в данном случае с его клонами). Habrahabr уже писал о клоне DNAStream (&lt;a href="http://dnastream.tv/">&lt;/a>&lt;a href="http://dnastream.tv" title="http://dnastream.tv">http://dnastream.tv&lt;/a>), однако это не лучший вариант для сравнения, по двум причинам. DNAStream полностью повторяет пользовательский интерфейс Joost во флеш-реализвации и данный проект не использует десктопное приложение. Давайте лучше взглянем на Babelgum (&lt;a href="http://www.babelgum.com/">&lt;/a>&lt;a href="http://www.babelgum.com" title="http://www.babelgum.com">http://www.babelgum.com&lt;/a>). Babelgum реализован по тем же принципам что и Joost, но в собственной манере. Панель управления просмотром выполнена в стиле классического пульта дистанционного управления. Что интуитивно понятно зрителю, но весьма ограничивает его в новых возможностях интерактивного ТВ. Каналы Babelgum категоризированы посредством тегов, что закономерно в эпоху Веб 2.0, но едва ли удобно в данном случае. Кроме того, архивы шоу на Babelgum распределены по двум каналам TV и Video. Интерфейс построен, так что не очень понятно к чему раздел Видео. Возможно для создания собственных каналов, на основе своего видео-контента. &lt;br>
&lt;br>
&lt;img src="http://blog.redgraphic.ru/img/babelgum02.jpg" alt="Просмотр шоу в Babelgum" border="0" hspace="10" vspace="10">
&lt;br>
&lt;img src="http://blog.redgraphic.ru/img/babelgum01.jpg" alt="Выбор канала в Babelgum" border="0" hspace="10" vspace="10">
&lt;br>
&lt;img src="http://blog.redgraphic.ru/img/babelgum03.jpg" alt="Раздел видео в Babelgum" border="0" hspace="10" vspace="10">
&lt;br>
&lt;br>
Проект Babelgum определенно найдет свою аудиторию, но есть такое впечатление, что Сильвио Скалья (учредитель проекта) несмотря на свои миллионы, похоже, выделил не достаточно инвестиций в Babelgum. В сравнении с Joost реализация Babelgum определенно проигрывает. Впрочем, качество, объем и скорость загрузки видео-контента на Joost пока тоже вне конкуренции.</description> 
<dc:date>2007-10-10T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/20-08-07_391/</guid> 
<title>(20/08/07) Выбираем онлайн-хранилище файлов</title> 
<link>http://blog.redgraphic.ru/sheiko/20-08-07_391/</link> 
<description>
Не знаю как у вас, но у меня периодически возникает потребовать в онлайн-хранилище данных. Всегда есть файлы, которые могут потребоваться мне как на работе, так и дома – документация, фрагменты кода (snippets), наброски статей и т.д. Впрочем, иные документы, такие как карты, описания туристических маршрутов, материалы по истории городов и достопримечательностей могут понадобиться и вдалеке от родины. В первом случае можно обойтись синхронизацией данных домашнего и офисного компьютеров (что, кстати, не гарантирует вам отсутствие «головной боли»). Во втором случае можно воспользоваться популярным плагином Firefox Gspace. Однако едва ли вам принесет много радости обилие сообщений со страшными заголовками в вашем почтовом ящике Gmail. Кроме того, когда у вас возникнет необходимость поделиться с кем-то файлами, вам не останется ничего иного как высылать эти файлы ему почтой. Теперь можно представить, как блаженная улыбка озаряет лицо вашего знакомого, когда The Bat намекает, что ему придется ждать загрузки письма длинной 20Мб. 
&lt;br />&lt;br />
Совершенно очевидно, здесь требуется удаленное хранилище файлов, с веб-интерфейсом и прямыми ссылками для скачивания файлов. Требует возможность создать свою структуру файлов где-то на сервере, а при необходимости поделиться ссылкой со знакомыми. Конечно, мы должны управлять доступом к нашим файлам и когда следует надежно защитить их от несанкционированного доступа. Очень кстати здесь пришлось бы и удобное настольное приложение для загрузки и синхронизации файлов на сервер, а также возможность адекватного предпросмотра в Веб медиа-файлов различного формата. И главное – все эти прелести должны быть бесплатными. 
&lt;br />&lt;br />
4 года назад, когда я пришел работать в Red Graphic Systems, мы владели собственной хостинговой компанией и грезили о сервис ориентированном будущем. Я раз за разом предлагал построить онлайн-хранилище файлов, для его дальнейшего коммерческого использования. Но тогда было крайне сложно обрисовать радужные перспективы бесплатного сервиса в Рунете. Теперь времена изменились и изменились кардинально. Но я думаю, будь у нас ныне собственное решение, было чертовски сложно выдержать его на уровне западных аналогов. Теперь же мне как пользователю остается лишь одна проблема – проблема выбора. 
&lt;br />&lt;br />
Ныне на рынке как наиболее заметные можно выделить следующие сервисы:
&lt;br />&lt;br />
&lt;A href="http://www.esnips.com/">http://www.esnips.com&lt;/A> – предоставляется 5Гб для хранения файлов, распознает медиаформаты, предоставляет настраиваемые виджеты, имеется настольное приложение для загрузки файлов;
&lt;br />&lt;br />&lt;img src="http://blog.redgraphic.ru/img/files/2007-08-20_133403.jpg" border=0 alt="Настройка виджетов в esnips.com" hspace=10 vspace=10>
&lt;br />&lt;b>Настройка виджетов в esnips.com&lt;/b>
&lt;br />&lt;br />

&lt;A href="http://www.box.net/">http://www.box.net&lt;/A> – очень простой и удобный пользовательский интерфейс, предоставляет 1,5ГБ для хранения файлов, распознает медиа-форматы, предоставляет настраиваемые виджеты, доступен как приложение для netvibes.com; 
&lt;br />&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/files/2007-08-20_133312.jpg"  border=0 alt="box.net и netvibes.com" hspace=10 vspace=10>
&lt;br />&lt;b>box.net и netvibes.com&lt;/b>
&lt;br />&lt;br />
&lt;A href="http://www.omnidrive.com/">http://www.omnidrive.com&lt;/A> - предоставляет 1ГБ для хранения файлов, есть приложение для синхронизации данных локального компьютера с виртуальным хранилищем;
&lt;br />&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/files/2007-08-20_140853.jpg" border=0 alt="Интеграция в проводник omnidrive.com" hspace=10 vspace=10>
&lt;br />&lt;b>Интеграция в проводник omnidrive.com&lt;/b>
&lt;br />&lt;br />
&lt;A href="http://www.mediamax.com/">http://www.mediamax.com&lt;/A> - предоставляет 25ГБ(!) для хранения файлов, доступно приложение MediaMax XL Beta для синхронизации и резервного копирования;
&lt;br />&lt;br />
&lt;A href="http://skydrive.live.com/">http://skydrive.live.com&lt;/A> – ответ Microsoft. Ничего не могу о нем сказать, так как мне он сообщает следующее: «Эта бета-версия службы еще не доступна в вашем регионе. Однако можно использовать папки других пользователей при наличии разрешения. Чтобы узнать, когда служба будет доступна в вашем регионе, посетите &lt;A href="http://go.microsoft.com/fwlink/?LinkId=85202">блог группы разработчиков&lt;/A>»;
&lt;br />&lt;br />
&lt;A href="http://www.pando.com/">http://www.pando.com&lt;/A> – предоставляет 1ГБ для хранения файлов, основной упор разработчики сделали на удобство обмена мультимедиа;
&lt;br />&lt;br />
&lt;A href="http://www.boxcloud.com/">http://www.boxcloud.com&lt;/A> – похоже что здесь нет ограничений на объем предоставляемого пространства (что откровенно говоря пугает). Для бесплатного аккаунта разрешено создание одного рабочего пространства для 3 пользователей;
&lt;br />&lt;br />
&lt;A href="http://www.tubesnow.com/">http://www.tubesnow.com&lt;/A> – сервис ориентирован преимущественно на синхронизации данных и резервное копирование, содержит приложение-панель в стиле ICQ;
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;A href="http://www.megaupload.com/">http://www.megaupload.com&lt;/A> – единственный сервис в обзоре (исключая Microsoft Skydrive) имеющий автоматическую локализацию интерфейса (русский язык), предоставляет 50ГБ для хранения файлов. Имеется настольное приложение - менеджер файлов и плагин-панель для облегчения загрузки файлов. Впрочем, не обольщайте этими возможностями – сервис предназначен для обмена файлами, но не для их хранения. Т.е. вы можете загрузить свой .AVI и сообщить другу, чтобы он поспешил скачать файл. Через несколько дней этот файл будет автоматически удален. 
&lt;br />&lt;br />
&lt;A href="http://xdrive.com/">http://xdrive.com/&lt;/A> - предоставляет 5ГБ для хранения файлов, есть возможность резервного копирования. Разработчики сервиса умудрились выделиться на общем фоне с помощью приложения Xdrive® Shows. Идея шикарная. Пользователи удивительно простым образом создаются свои реально эффектные слайдшоу. Они просто перетаскивают фотоснимки на панель временной шкалы, затем назначают файл звукового оформления, задают видео эффекты из доступной библиотеки и в результате получают Flash-микрофильм, которым они тут же могут похвастаться своим друзьям;
&lt;br />&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/files/show.jpg" border=0 alt="Приложение Xdrive® Shows" hspace=10 vspace=10>
&lt;br />&lt;b>Приложение Xdrive® Shows&lt;/b>

&lt;br />&lt;br />
&lt;A href="http://openomy.com/">http://openomy.com&lt;/A> - предоставляет 1ГБ для хранения файлов. Изюминка сервиса в его социальности – даже файлы в нем рубрицируются тегами. Имеется API для взаимодействия с сервисом из вне;
&lt;br />&lt;br />
&lt;A href="http://mozy.com/">http://mozy.com&lt;/A> - предоставляет 2ГБ для хранения файлов, версионный контроль. В проекте предпринята попытка максимально обезопасить данные пользователя (448-bit Blowfish encryption, 128-bit SSL encryption);
&lt;br />&lt;br />
&lt;A href="http://www.4shared.com/">http://www.4shared.com&lt;/A> - предоставляет 1ГБ для хранения файлов, широкие возможности, которые сводит на нет то факт, что бесплатный аккаунт здесь более походит на trial-доступ.
&lt;br />&lt;br />
Из всех этих сервисов особого внимания заслуживают box.net, esnips.com и omnidrive.com. Все три весьма популярны. Похоже ныне omnidrive.com - идеальное решение для удаленного резервного копирования. Работать с сервисом достаточно легко. После установки локального приложения в проводнике Windows появляется опция синхронизации файлов с веб-сервером. Можно указать график по которому программа сама будет синхронизировать файлы. В omnidrive.com также добавлена интеграция с виртуальным офисом Zoho, RSS-подписка на файлы подкастов, а также инструмент &lt;A href="http://www.tangler.com/">www.tangler.com&lt;/A>. 
Сервису Box.net пошла на пользу интеграция с netvibes.com. Это действительно удобно зайти на свой виртуальный рабочий стол и получить там миниатюрный файловый менеджер. Кроме того, разработчикам Box.net удаются весьма симпатичный виджеты и пользователи с удовольствием размещают их на своих сайтах. С недавнего времени обладатели iPhone могут использовать хранилище фалов Box.net. Доступен плагин Box.net для Microsoft Office. 
&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/files/eboxwidget.jpg"  border=0 alt="Виджет box.net" hspace=10 vspace=10>
&lt;br />
Сервис esnips.com также позволяет пользователям настраивать виджеты, как на отдельные файлы, так и на папки. Здесь также можно ограничить доступ к фалам и папкам для пользователей и групп. Присутствует полный комплект социального веба: имеется возможность создания сетей друзей, показ публичных папок других пользователей, близких по содержанию вашим, сервис видео/аудио/текстовых комментариев к файлам, социальные закладки, плейлисты, сообщества. Сервис позволяет записывать видео и аудио напрямую из веб. 
&lt;br />&lt;img src="http://blog.redgraphic.ru/img/files/player.jpg" border=0 alt="Загрузка файлов на esnips.com" hspace=10 vspace=10>
&lt;br />&lt;b>Загрузка файлов на esnips.com&lt;/b>&lt;br />&lt;br />
&lt;img src="http://blog.redgraphic.ru/img/files/2007-08-20_133620.jpg" border=0 alt="Виджет мультимедиа плеера в esnips.com" hspace=10 vspace=10>
&lt;br />&lt;b>Виджет мультимедиа плеера в esnips.com&lt;/b>

&lt;br />&lt;br />
Итог. Если вы желаете делиться с посетителями вашего блога файлами простым и симпатичным образом – пользуйтесь box.net. Если вас прельщает идея автоматического резервного копирования критичных для вас данных – используйте omnidrive.com. И, наконец, если вам хотелось бы обрести благодарную аудиторию для ваших медиа-файлов, попробуйте esnips.com. 
&lt;br />&lt;br />
Успешного и комфортного вам файл-шаринга!
</description> 
<dc:date>2007-08-20T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/18-08-07_390/</guid> 
<title>(18/08/07) Пара приемов</title> 
<link>http://blog.redgraphic.ru/sheiko/18-08-07_390/</link> 
<description>
&lt;P>В последнее время все чаще используются всплывающие слои для различных сообщений с эффектом тени. Возникает вопрос как эту тень корректно сверстать. Известный факт – Firefox корректно отображает «тени» сохраненные в PNG, а IE можно заставить их отображать посредством инструкций в HTC файле. По инструкциям существует множество решений. Мне понравилось следующее:&lt;/P>
&lt;br />&lt;br />
&lt;P>1) Располагаем в корневой папке файл png.htc со следующим содержанием:&lt;/P>
&lt;br />&lt;br />
&lt;P>PUBLIC:COMPONENT lightWeight="true"&lt;BR> PUBLIC:ATTACH EVENT="oncontentready" ONEVENT="filterImage()" /&lt;BR> SCRIPT LANGUAGE="JScript"&lt;BR> var orignalImage = element.src;&lt;BR> var spacerImage = "images/x.gif";&lt;BR> var htcCapable = /MSIE ((5.5)|[6])/.test(navigator.userAgent)  &lt;/P>
&lt;P> function filterImage() {&lt;BR> if(/.png$/.test(orignalImage)) {&lt;BR> if(htcCapable) {&lt;BR> element.src = spacerImage;&lt;BR> element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + orignalImage + ",sizingMethod='scale')";&lt;BR> }&lt;BR> }&lt;BR> element.style.visibility = 'visible';&lt;BR> } &lt;/P>
&lt;P> /SCRIPT &lt;BR>/PUBLIC:COMPONENT&lt;/P>
&lt;br />&lt;br />
&lt;P>Где x.gif - прозрачный GIF 1x1 пиксел. &lt;/P>
&lt;br />&lt;br />
&lt;P>2) Тень сохраняем в файле PNG и определяем класс shadow при декорации ее в HTML:&lt;/P>
&lt;br />&lt;br />
&lt;P> img class="shadow" src="images/shadow.png" alt="0" /&lt;/P>
&lt;br />&lt;br />
&lt;P>3) В PHP-скрипт формирующий HTML добавляем код:&lt;/P>
&lt;P>?&lt;BR>if(preg_match("/sMSIEs/is", $_SERVER["HTTP_USER_AGENT"])) &lt;BR>print 'style&lt;BR>img.shadow { visibility:hidden; behavior: url(png.htc); } &lt;BR>/style';&lt;BR>? &lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;P>Все чаще ныне используются всплывающие диалоги подтверждений (confirm), «замораживающие» прочие элементы окна до принятия пользователем какого-либо решения. Для «заморозки» окна достаточно показать полупрозрачный слой на переднем плане (Z-index выше прочих элементов). Все просто, до тех пор, пока не выясняется, что ширина и высота этого слоя должны точно соответствовать актуальным габаритам рабочей области окна. Причем, эти показатели меняются не только при различных разрешениях экранов, но зависимости от числа баров браузера, его состояния и т.д. Самая удобная функция для определения текущей ширины и высоты окна их тех, что мне попадались:&lt;/P>
&lt;br />&lt;br />
&lt;P>window.size = function()&lt;BR>{&lt;BR>var w = 0;&lt;BR>var h = 0;&lt;/P>
&lt;P>//IE&lt;BR>if(!window.innerWidth)&lt;BR>{&lt;BR>//strict mode&lt;BR>if(!(document.documentElement.clientWidth == 0))&lt;BR>{&lt;BR>w = document.documentElement.clientWidth;&lt;BR>h = document.documentElement.clientHeight;&lt;BR>}&lt;BR>//quirks mode&lt;BR>else&lt;BR>{&lt;BR>w = document.body.clientWidth;&lt;BR>h = document.body.clientHeight;&lt;BR>}&lt;BR>}&lt;BR>//w3c&lt;BR>else&lt;BR>{&lt;BR>w = window.innerWidth;&lt;BR>h = window.innerHeight;&lt;BR>}&lt;BR>return {width:w,height:h};&lt;BR>}&lt;BR>&lt;/P>
&lt;br />&lt;br />
&lt;P>Использовать можно так &lt;/P>
&lt;P>window.center = function()&lt;BR>{&lt;BR>var hWnd = (arguments[0] != null) ? arguments[0] : {width:0,height:0};&lt;/P>
&lt;P>var _x = 0;&lt;BR>var _y = 0;&lt;BR>var offsetX = 0;&lt;BR>var offsetY = 0;&lt;/P>
&lt;P>//IE&lt;BR>if(!window.pageYOffset)&lt;BR>{&lt;BR>//strict mode&lt;BR>if(!(document.documentElement.scrollTop == 0))&lt;BR>{&lt;BR>offsetY = document.documentElement.scrollTop;&lt;BR>offsetX = document.documentElement.scrollLeft;&lt;BR>}&lt;BR>//quirks mode&lt;BR>else&lt;BR>{&lt;BR>offsetY = document.body.scrollTop;&lt;BR>offsetX = document.body.scrollLeft;&lt;BR>}&lt;BR>}&lt;BR>//w3c&lt;BR>else&lt;BR>{&lt;BR>offsetX = window.pageXOffset;&lt;BR>offsetY = window.pageYOffset;&lt;BR>}&lt;/P>
&lt;P>_x = ((this.size().width-hWnd.width)/2)+offsetX;&lt;BR>_y = ((this.size().height-hWnd.height)/2)+offsetY;&lt;/P>
&lt;P>return{x:_x,y:_y};&lt;BR>}&lt;/P>
&lt;br />&lt;br /></description> 
<dc:date>2007-08-18T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/17-07-07_387/</guid> 
<title>(17/07/07) «Делаем стартап гостеприимным» или «Как использовать OpenID на своем сайте»</title> 
<link>http://blog.redgraphic.ru/sheiko/17-07-07_387/</link> 
<description>
&lt;img src="/img/openidicon.gif" alt="Как использовать OpenID на своем сайте" align="left" border="0" height="150" hspace="10" vspace="10" width="150">&lt;br>
Уверен, вам не раз подалась на глаза аббревиатура OpenID. Вполне возможно у вас сложилось мнение, что это эдакая модная штуковина, о поддержке которой все чаще заявляют различные популярные проекты. По большому счету так и есть, но зачем эта технология на самом деле нужна? Предположим, вы заядлый блоггер, у вас имеется учетная запись на wordpress.com, но случилось вам прочесть сообщение в чужом дневнике и возникло непреодолимое желание оставить автору комментарий. Но вот незадача – чужой дневник оказался на &lt;a href="http://livejournal.com/">livejournal.com&lt;/a>. Неужели только для того, чтобы оставить комментарий вам придется регистрироваться на «вражеском» блог-хостинге?! &lt;a name="habracut"> &lt;/a>А вот и нет. В форме авторизации &lt;a href="http://livejournal.com/">livejournal.com&lt;/a> имеется малозаметная ссылка «Войти по OpenID». Вы переходите по этой ссылке, вводите свой идентификатор с wordpress (скажем, ivan.wordpress.com). Открывается «родной» &lt;a href="http://wordpress.com/">wordpress.com&lt;/a> и лукаво прищурившись интересуется у вас «Do you want to pass your identity to this “soup-admirers’ site”?». Вы скрепя сердцем жмете «Yes; just this time», после чего оказываетесь на той злополучной странице &lt;a href="http://livejournal.com/">livejournal.com&lt;/a> c формой добавления комментария. Но (!) на этот раз вы авторизованы на ЖЖ под своей «вордпресосвской» учетной записью. Наконец-то можно оставить комментарий. Не пройдет много времени как в адрес OpenID прозвучит очередное «Wow!», но уже от пользователя &lt;a href="http://livejournal.com/">livejornal.com&lt;/a>, спешащего вернуть вам ответ. &lt;br>

&lt;br>
&lt;img src="/img/openID_and_php.gif" alt="Как работает OpenID" border="0" height="550" hspace="10" vspace="10" width="550">&lt;br>
&lt;br>
&lt;br>
&lt;a href="http://openid.net/">OpenID&lt;/a> – это децентрализованная система единой регистрации. Это несколько шире, чем заявлено на &lt;a href="http://wordpress.com/">wordpress.com&lt;/a>: «OpenID – это открытый стандарт, который позволяет вам авторизоваться на чужих сайтах, используя вашу учетную запись WordPress.com» :) Если вы зарегистрированы в проекте, являющимся, помимо прочего, провайдером OpenID, вы сможете авторизоваться под этой единственной учетной записью на любом сайте, поддерживающим OpenID. Звучит замечательно, идея – фантастика, но возникает резонный вопрос: «А много ли таких проектов, поддерживающих OpenID или это вопрос непредсказуемого будущего?». В принципе, не мало. Уже заявлено порядка 1200 сайтов, поддерживающих OpenID и каждый день прибывает 10-15 новых. Среди этих сайтов немало популярных проектов: &lt;a href="http://livejournal.com/">Livejournal.com&lt;/a>, &lt;a href="http://jyte.com/">Jyte.com&lt;/a>, &lt;a href="http://www.vox.com/">Vox.com&lt;/a>. &lt;a href="http://www.wikitravel.org/">Wikitravel.org&lt;/a>, &lt;a href="http://www.zooomr.com/">Zooomr.com&lt;/a>, &lt;a href="http://ma.gnolia.com/">Ma.gnolia.com&lt;/a>, &lt;a href="http://www.movabletype.org/">Movabletype&lt;/a>, &lt;a href="http://www.iconbuffet.com/">Iconbuffet.com&lt;/a>, &lt;a href="http://basecamphq.com/">Basecamphq.com&lt;/a>. Существуют модули интеграции для такого популярного ПО, такого как &lt;a href="http://wordpress.com/">Wordpress&lt;/a>, &lt;a href="http://www.joomla.org/">Joomla!&lt;/a>, &lt;a href="http://plone.org/">Plone&lt;/a>, &lt;a href="http://drupal.org/">Drupal&lt;/a>. &lt;a href="http://www.mediawiki.org/wiki/MediaWiki">MediaWiki&lt;/a>, &lt;a href="http://www.cakephp.org/">CakePHP&lt;/a>, &lt;a href="http://www.symfony-project.com/">Symfony Framework&lt;/a>. О поддержке технологии заявили Microsoft и AOL. Поддержка OpenID будет реализована в &lt;a href="http://mozillalinks.org/wp/2007/01/planned-features-for-firefox-3/">Firefox 3.0&lt;/a>. &lt;br>

&lt;br>
Но как использовать OpenID на своем сайте? Если вы собираете проект на фреймворке CakePHP или Symfony, вам достаточно настроить плагины &lt;a title="http://cakebaker.42dh.com/2007/01/11/cakephp-and-openid/" href="http://cakebaker.42dh.com/2007/01/11/cakephp-and-openid/">CakePHP OpenID component&lt;/a> и &lt;a title="http://www.symfony-project.com/trac/wiki/sfOpenIDPlugin" href="http://www.symfony-project.com/trac/wiki/sfOpenIDPlugin">sfOpenIDPlugin&lt;/a> соответсвенно. Если вы не используете фреймворк, но просто желаете привлечь пользователей лояльностью к регистрации на вашем проекте (быть может стартапе), проще всего воспользоваться маленькой библиотекой &lt;a href="http://www.phpclasses.org/browse/package/3290.html">Simple OpenID PHP Class&lt;/a>. В комплекте, доступном для скачивания помимо библиотеки, имеется скрипт примера, где в доступной форме показано как авторизовать пользователя посредством протокола OpenID. Единственная неприятность, с которой вы можете столкнуться – данная библиотека использует функции библиотеки расширения PHP Libcurl. Т.е. если ваш PHP собран с опцией --with-curl – все замечательно. Иначе использовать эту библиотеку едва ли получиться. Автор этого решения был вынужден использовать специфичные функции там где можно было бы обойтись более традиционными методами HTTP-запроса из-за того, что многие провайдеры OpenID требуют SSL-соединения. &lt;br>
&lt;br>
Если же вы настроены более серьезно и собираетесь реализовать полноценное управление учетными записями пользователей в своем проекте, опираясь на популярные решения, такие как &lt;a href="http://openid.net/">OpenID&lt;/a>, &lt;a href="http://lid.netmesh.org/">LID&lt;/a> (Light-Weight Identity) и &lt;a href="http://yadis.org/">Yadis&lt;/a> воспользуйтесь библиотекой &lt;a title="http://netmesh.org/downloads/" href="http://netmesh.org/downloads/">NetMesh InfoGrid LID PHP&lt;/a>. Стоит также обратить внимание на &lt;a href="http://www.openidenabled.com/openid/libraries/php">PHP OpenID library&lt;/a>. Однако в данном случае вам потребуется консольный PEAR-инсталлятор. &lt;br>

&lt;br>
В заключении надо сказать, что имеется ряд нареканий к OpenID касательно уязвимости в безопасности. На мой взгляд, также необходимость чтения целостной HTML страницы для последующего анализа тегов микроформата – подход крайне неэффективный (в спецификации OpenID 2.0 запрашивается документ XRDS или Yadis-документ). Хотелось бы использовать REST, но на этот &lt;a href="http://superfluo.org/blojsom/blog/pic/taken_cues/2007/02/26/OpenID-and-REST-doubts.html?page=comments">счет есть некоторые сомнения&lt;/a>. Тем не менее, OpenID - как раз тот случай, когда замечательная идея все же работает. Так, что лично я буду рад, если смогу воспользоваться своей учетной записью OpenID на собранном вами новой оригинальном многообещающем проекте. 
&lt;br />&lt;br />
P.S. Вы можете обнаружить некорректную работу Simple OpenID PHP Class с аккаунтами LiveJornal. Ошибка чевидно в следующем: в &lt;a href="http://openid.net/specs/openid-authentication-1_1.html#anchor27">спецификации&lt;/a> сказано что для режима check_authentication требуется POST HTTP-метод.&lt;br />&lt;br />
Остается просто добавить в начало функции CURL_Request() (class.openid.php) следующую проверку
&lt;br />&lt;br />
if(isset($params["openid.mode"])) $method = "POST";
&lt;br />&lt;br />

P.S.2 Ко всему прочему также хотелось бы добавить. Есть любопытный сервис  &lt;a href="http://setup.sxipper.com/tryitout" targe="_blank">Sxipper&lt;/a>. Они предоставляют плагин для Firefox. Пройдя регистрацию в нем вы получаете учетную запись OpenID и при авторизации на прочих проектах типа Livejournal вы сразу же получаете подтверждение подлинности. 
</description> 
<dc:date>2007-07-17T00:00:00</dc:date>
</item>

<item>
<guid isPermaLink="true">http://blog.redgraphic.ru/sheiko/11-07-07_386/</guid> 
<title>(11/07/07) Программируем стартап Веб 2.0 на PHP</title> 
<link>http://blog.redgraphic.ru/sheiko/11-07-07_386/</link> 
<description>
&lt;P>Итак, вы воодушевлены идеей стартапа Веб 2.0. Вы полагаете, что придумали что-то оригинальное и свежее. Вам видится эффектная реализация вашей идеи. Вы верите, что ваш проект произведет революцию на рынке. Если именно такие мысли занимают вас, самое время заняться бизнес-планом. Планирование бизнеса – это отдельная дисциплина и об этом можно найти множество литературы. Впрочем, если вы не имеете опыта составления бизнес-планов, лучше прибегнуть к помощи профессионалов. Чем хуже спрогнозирован бизнес, тем выше риски его краха.&lt;/P>
&lt;br />&lt;br />
&lt;P>Однако допустим, что вы располагаете привлекательным бизнес-планом, вы ожидаете самоокупаемость проекта уже через 2 года от момента его старта, и предвкушаете ежегодный 50% рост его рекламного потенциала. В MS-Visio подготовлены многообещающие схемы пользовательского интерфейса проекта. И даже более того, ваш дизайнер, вооружившись &lt;A href="http://pavlik.livejournal.com/36870.html">модным руководством&lt;/A>, в рекордные сроки обозначил графический вид проекта. Так, что сверстанные в лучших традициях безтабличной верстки типовые страницы пользовательского интерфейса дожидаются своего звездного часа в вашей локальной папке проекта. &lt;/P>
&lt;br />&lt;br />
&lt;H2>Схема проекта&lt;/H2>
&lt;br />&lt;br />
&lt;P>Я не могу знать, в чем суть вашего стартапа, в чем его особенность. Но для того чтобы отталкиваться от какого-либо практического примера, давайте рассмотрим упрощенный вариант всеми любимого коллективного блога habrahabr.ru. Очевидно, что едва ли вы планируете повторить известный проект. Вы можете пойти по проверенному пути и разработать фотоблог в стиле flicr.com, социальную сеть a-la facebook.com, социальные закладки на манер &lt;A href="http://ma.gnolia.com/">ma.gnolia.com&lt;/A> или социальные новости в традициях digg.com. Возможно, вы выберите собственную извилистую тропу на пути к коммерческому успеху. В любом случае вы столкнетесь с общими для проектов Веб 2.0 подходами, такие как комментирование, рейтингование, тегирование, всплывающие контекстные подсказки (tooltips) и т.д. А что касается ленты статей или, скажем, пользовательской панели – эти решения справедливы фактически для любого проекта. &lt;/P>
&lt;br />&lt;br />
&lt;img src="/img/startup.gif" alt="Схема" border="0" height="493" hspace="10" vspace="10" width="450" />
&lt;br />&lt;br />
&lt;P>Итак, в нашем примере имеется всего несколько информационных страниц («О сайте», «Помощь»), лента статей, пользовательская панель («Регистрация», «Авторизация»), облако тегов, связанное с лентой статей и лента последних комментариев.&lt;/P>
&lt;P>Предположим, нам хотелось бы, чтобы итерации с формами (регистрация, авторизация, добавление комментария) по возможности не требовали перегрузки веб-страницы. Системные сообщения появлялись в заданном оформлении и поддерживали принцип «перетянул и оставил» (Drag&lt;/P>
&lt;P>include(ROOT_PATH."config/config.inc.php");&lt;/P>
&lt;P>include(ROOT_PATH."app/basics.inc.php");&lt;/P>
&lt;P>include(ROOT_PATH."app/patterns.inc.php");&lt;/P>
&lt;P>include(ROOT_PATH."app/init.inc.php");&lt;/P>
&lt;br />&lt;br />
&lt;P>$db = Lib::factory('db');&lt;/P>
&lt;P>$db->applyAuthorization();&lt;/P>
&lt;br />&lt;br />
&lt;P>// Получить контроллер&lt;/P>
&lt;P>if($CTRLPATH) {&lt;/P>
&lt;P>// Если есть кеш-образ ответа&lt;/P>
&lt;P>if(file_exists(ROOT_PATH."cache/".md5("ajax_controllers{$CTRLPATH}").".tmp")) &lt;/P>
&lt;P>$OUT = file_get_contents(ROOT_PATH."cache/".md5("ajax_controllers{$CTRLPATH}").".tmp"); &lt;/P>
&lt;P>else { &lt;/P>
&lt;P>$ctrl = Lib::factory('controller');&lt;/P>
&lt;P>include(ROOT_PATH."app/ajax_controllers{$CTRLPATH}index.inc.php");&lt;/P>
&lt;P>}&lt;/P>
&lt;P>} else {&lt;/P>
&lt;P>// Если есть кеш-образ страницы, показать его &lt;/P>
&lt;P>if(file_exists(ROOT_PATH."cache/".md5($APPPATH).".tmp")) &lt;/P>
&lt;P>$OUT = file_get_contents(ROOT_PATH."cache/".md5($APPPATH).".tmp"); &lt;/P>
&lt;P>else {&lt;/P>
&lt;P>// Получить веб-страницу&lt;/P>
&lt;P>$InterfaceScript = ($RECORD_ID?"record":"index").".inc.php";&lt;/P>
&lt;P>include(ROOT_PATH."app/controllers/common.inc.php");&lt;/P>
&lt;P>if(file_exists(ROOT_PATH."app/controllers{$APPPATH}".$InterfaceScript)) include(ROOT_PATH."app/controllers{$APPPATH}".$InterfaceScript);&lt;/P>
&lt;P>include(ROOT_PATH."app/models/common.inc.php");&lt;/P>
&lt;P>if(file_exists(ROOT_PATH."app/models{$APPPATH}".$InterfaceScript)) include(ROOT_PATH."app/models{$APPPATH}".$InterfaceScript);&lt;/P>
&lt;P>if(file_exists(ROOT_PATH."app/views{$APPPATH}".$InterfaceScript)) &lt;/P>
&lt;P>include(ROOT_PATH."app/views{$APPPATH}".$InterfaceScript);&lt;/P>
&lt;P>else &lt;/P>
&lt;P>include(ROOT_PATH."app/views/_404/index.inc.php");&lt;/P>
&lt;P>}&lt;/P>
&lt;P>}&lt;/P>
&lt;br />&lt;br />
&lt;P>header("Content-type: text/html; charset=UTF-8");&lt;/P>
&lt;P>print $OUT;&lt;/P>
&lt;P>if(isset($_GET["createcache"]))&lt;/P>
&lt;P>file_put_contents(ROOT_PATH."cache/".md5($APPPATH).".tmp", $OUT);&lt;/P>
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>app/patterns.inc.php&lt;/B>&lt;/P>&lt;/DIV>
&lt;P>&lt;?&lt;/P>
&lt;P>class Lib&lt;/P>
&lt;P>{&lt;/P>
&lt;P>// The parameterized factory method&lt;/P>
&lt;P>public static function factory($type)&lt;/P>
&lt;P>{&lt;/P>
&lt;P>if (include_once ROOT_PATH.'libs/' . $type . '.lib.php') {&lt;/P>
&lt;P>$classname = $type;&lt;/P>
&lt;P>return new $classname;&lt;/P>
&lt;P>} else {&lt;/P>
&lt;P>throw new Exception ('Driver not found');&lt;/P>
&lt;P>}&lt;/P>
&lt;P>}&lt;/P>
&lt;P>}&lt;/P>
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;P>Далее система устанавливает соединение с БД и проверяет, не авторизован ли пользователь. Так как была запрошена веб-страница, а не запись списка будут последовательно опрошены &lt;/P>
&lt;br />&lt;br />
&lt;P>app/controllers/blog/index.inc.php&lt;BR>app/models/blog/index.inc.php&lt;/P>
&lt;P>app/views/blog/index.inc.php&lt;/P>
&lt;br />&lt;br />
&lt;P>POST и GET не содержат данных и соответственно скрипт контроллера будет пропущен. В скрипте модели app/models/blog/index.inc.php будут приняты данные для списка статей, а в скрипте вида app/views/blog/index.inc.php эти данные будут оформлены для вывода.&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>app/models/blog/index.inc.php&lt;/B>&lt;/P>&lt;/DIV>
&lt;P>&lt;?&lt;/P>
&lt;P>$CONTENT["WINDOW_TITLE"] = "Стартап: блоги";&lt;/P>
&lt;P>$NAVIGATION["limit"] = 5;&lt;/P>
&lt;P>$get = Lib::factory('get');&lt;/P>
&lt;P>$DATA["MEDIALIST"] = $get->articleList();&lt;/P>
&lt;P>$DATA["PAGINATION"] = $get->pagination();&lt;/P>
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>app/views/blog/index.inc.php&lt;/B>&lt;/P>&lt;/DIV>
&lt;P>&lt;?&lt;/P>
&lt;P>$CONTENT["BODY"] = '';&lt;/P>
&lt;P>foreach($DATA["MEDIALIST"] as $row) {&lt;/P>
&lt;P>$rec_url = HTTP_PATH.$MEDIATYPES[$row["media_type"]]["var"].'/'.getIDUrl($row["media_id"]).'/';&lt;/P>
&lt;P>$CONTENT["BODY"] .= '&lt;/P>
&lt;P>&lt;div class="media_line">&lt;/P>
&lt;P>&lt;div class="info">Добавил(а) '.$row["fullname"].', просмотрено '.(int)$row["visited"].' раз&lt;/div>&lt;/P>
&lt;P>&lt;div class="text">'.$row["description"].'&lt;/div>&lt;/P>
&lt;P>&lt;div class="footer">'.($row["cache_commentnumber"]?'&lt;a href="'.$rec_url.'">'.$row["cache_commentnumber"].' комментариев&lt;/a>':'&lt;a href="'.$rec_url.'">Добавить комментарий&lt;/a>').'&lt;/P>
&lt;P>&lt;/div>&lt;/P>
&lt;P>&lt;/div> ';&lt;/P>
&lt;P>}&lt;/P>
&lt;br />&lt;br />
&lt;P>include(INCLUDEPATH."header.inc.php");&lt;/P>
&lt;P>$OUT .= '&lt;/P>
&lt;P>&lt;div class=”left_col”>&lt;/P>
&lt;P>'. $CONTENT["BODY"].$CONTENT["PAGINATION"].'&lt;/P>
&lt;P>&lt;/div>&lt;/P>
&lt;P>&lt;div class=”right_col”>&lt;/P>
&lt;P>&lt;div id=”UserPanel”>&lt;/div>&lt;/P>
&lt;P>&lt;div id=”TagCloud”>&lt;/div>&lt;/P>
&lt;P>&lt;div id=”LastestComments”>&lt;/div>&lt;/P>
&lt;P>&lt;script type="text/javascript">&lt;/P>
&lt;P>showBlock("UserPanel");&lt;/P>
&lt;P>showBlock("TagCloud");&lt;/P>
&lt;P>showBlock("LastestComments");&lt;/P>
&lt;P>&lt;/script>&lt;/P>
&lt;P>&lt;/div>&lt;/P>
&lt;P>';&lt;/P>
&lt;P>include(INCLUDEPATH."footer.inc.php");&lt;/P>
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;P>Возможно вы обратили внимание на вызов класса get для получения списка статей. Благодаря паттерну factory, мы можем загружать в память только те библиотеки, которые мы используем в актуальных задачах. Но предлагаю пойти дальше и спроектировать библиотеки таким образом, чтобы для наиболее часто запрашиваемых веб-страниц мы ограничились минимальным расходом памяти. Давайте поместим все методы запросов данных, которые будут востребованы в каждом интерфейсе в класс get. Прочие методы можно распределить по классам в соответствии с логикой нашего проекта. Они будут получены фабрикой лишь по мере необходимости. Например, когда требуется сохранить содержание пользовательского комментария. &lt;/P>
&lt;br />&lt;br />
&lt;P>Как видно из скрипта вида в данном случае будет отображена страница, содержащая &lt;B>список статей&lt;/B> в левой колонке. В правой колонке ожидаются пользовательская панель, облако тегов, последние комментарии. В скрипте вида пока мы можем видеть только контейнеры этих панелей. Однако вызовы функции showBlock примут и вставят в эти контейнеры содержание панелей. &lt;/P>
&lt;br />&lt;br />
&lt;P>Итак, мы получили список статей. Теперь требуется рассмотреть случай запроса пользователем отдельной статьи из этого списка. В этом случае в ходе инициализации среды будет определена переменная $RECORD_ID. Система опросит универсальную модель для любой из записей списка blog. Модель будет найдена по адресу app/models/blog/record.inc.php. $RECORD_ID послужит параметром для запроса данных статьи.&lt;/P>
&lt;br />&lt;br />
&lt;P>$get->article($RECORD_ID);&lt;/P>
&lt;br />&lt;br />
&lt;P>Скрипт вида система будет искать по адресу app/views/blog/record.inc.php.&lt;/P>
&lt;br />&lt;br />
&lt;P>По аналогии с веб-страницей списка статей, когда пользователь запросит &lt;B>информационную страницу&lt;/B> (например, &lt;A href="http://нашсайт/about/">http://нашсайт/about/&lt;/A>) в скрипте модели будут получены данные страницы (app/models/about/index.inc.php), в скрипте вида (app/views/about/index.inc.php) будет задано оформление. &lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;H2>Обогащаем пользовательский интерфейс&lt;/H2>
&lt;br />&lt;br />
&lt;P>По условиям задачи система должна при необходимости показывать сообщения в стилизированных перемещаемых окнах, сообщать о состоянии процессов. Наиболее простой путь – использовать компонент panel из библиотеки пользовательских интерфейсов от Yahoo (&lt;A href="http://developer.yahoo.com/yui/container/panel/">http://developer.yahoo.com/yui/container/panel/&lt;/A>). Однако если вы желаете избавить пользователей вашего проекта от необходимости ожидания загрузки дополнительного JS-скрипта размером порядка 100Кб, можно попробовать сделать собственную библиотеку. Для системных сообщений вам потребуются две функции showSystemMessage() и hideSystemMessage(). Первая будет показывать скрытый слой окна сообщения ( document.getElementById ("window_id").style.display="block" ) и помещать туда переданное в функцию сообщение ( document.getElementById("window_content_is").innerHTML = message ). Вторая функция будет скрывать сообщение ( document.getElementById ("window_id").style.display="none" ). Желательно также перед показом слоя программно позиционировать его в центре окна браузера. &lt;/P>
&lt;br />&lt;br />
&lt;P>Отлично, теперь мы можем показывать окно системного сообщения и скрывать его. Но как включить для него Drag }&lt;/P>
&lt;br />&lt;br />
&lt;P>// Определяем тип браузера&lt;/P>
&lt;P>if(document.implementation &lt;/P>
&lt;P>else var isMozilla=false;&lt;/P>
&lt;br />&lt;br />
&lt;P>// Захватить объект для перемещения и его координаты&lt;/P>
&lt;P>function windowMouseDown(divNamePref, ev) { &lt;/P>
&lt;P>if (isMozilla) { event=ev; }&lt;/P>
&lt;P>currentWindowDivNamePref = divNamePref; &lt;/P>
&lt;P>// Save offset&lt;/P>
&lt;P>currentWindow[divNamePref] = {&lt;/P>
&lt;P>"x" : event.clientX + document.body.scrollLeft - $(divNamePref).style.left.replace("px",""),&lt;/P>
&lt;P>"y" : event.clientY + document.body.scrollTop - $(divNamePref).style.top.replace("px","")&lt;/P>
&lt;P>};&lt;/P>
&lt;P>}&lt;/P>
&lt;P>// Двигать объект&lt;/P>
&lt;P>function windowMouseMove(ev) {&lt;/P>
&lt;P>if(!currentWindowDivNamePref) return false;&lt;/P>
&lt;P>if(!currentWindow[currentWindowDivNamePref]) return false;&lt;/P>
&lt;P>if (isMozilla) { event=ev; }&lt;/P>
&lt;P>$(currentWindowDivNamePref).style.left = (event.clientX + document.body.scrollLeft - currentWindow[currentWindowDivNamePref].x) + "px";&lt;/P>
&lt;P>$(currentWindowDivNamePref).style.top = (event.clientY + document.body.scrollTop - currentWindow[currentWindowDivNamePref].y) + "px";&lt;/P>
&lt;P>return false;&lt;/P>
&lt;P>}&lt;/P>
&lt;br />&lt;br />
&lt;P>// Отпустить объект&lt;/P>
&lt;P>function windowMouseUp(divNamePref) { currentWindow[divNamePref] = null; currentWindowDivNamePref = false; } &lt;/P>
&lt;br />&lt;br />
&lt;P>if (isMozilla) { document.captureEvents(Event.MOUSEMOVE); }&lt;/P>
&lt;P>document.onmousemove = windowMouseMove;&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;P>В случае окна состояния процесса ниже слоя окна добавляется еще полупрозрачный слой, залитый серым цветом и закрывающий собой содержание всего окна браузера. Таким образом мы получаем эффект временного «замораживания» пользовательского интерфейса. В сообщении окна можно добавить динамичное изображение, визуализирующее процесс. Как правило, в коде слоя окна системного сообщения размещается кнопка «Закрыть». В случае окна состояния процесса этого не требуется. &lt;/P>
&lt;br />&lt;br />
&lt;P>Теперь рассмотрим практическую задачу, которая потребует, описанных функций управления системными окнами. Нам необходимо реализовать в проекте пользовательскую панель. Это компонент, позволяющий посетителям проекта либо зарегистрироваться, либо авторизоваться. Т.е. когда пользователь заполнил форму для регистрации, система должна отправить его данные на сервер, проанализировать их и либо сообщить об ошибке заполнения (скажем, если был введен некорректно код подтверждения Captcha), либо зарегистрировать пользователя и, опять же, сообщить о результате. Сообщить о чем-либо мы теперь можем с помощью окна системного сообщения. Как вы, должно быть, помните уже, для того чтобы система просто отображала пользовательскую панель нам потребуется JS-запрос на сервер (функция showBlock()). Для того, чтобы проверить введенные пользователем данные не перегружая веб-страницу опять же не обойтись без AJAX. Таким образом, нам нужен набор JS-функций для отправки асинхронных запросов в контроллер на сервере и получения ответов контроллера. В данном случае опять же можно использовать собственное решение, а можно положиться на опыт популярных open source библиотек. Давайте рассмотрим вариант использования компонента Connection Manager из YUI (&lt;A href="http://developer.yahoo.com/yui/connection/">http://developer.yahoo.com/yui/connection/&lt;/A>). Для его использования придется вызывать в коде страниц проекта два скрипта yahoo-min.js и connection-min.js. &lt;/P>
&lt;br />&lt;br />
&lt;P>Давайте посмотрим, каким образом работает функция showBlock, отображающая вспомогательные компоненты веб-страницы.&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>js/&lt;/B>&lt;B>common.&lt;/B>&lt;B>js&lt;/B>&lt;/P>&lt;/DIV>
&lt;P>// Функции AJAX&lt;/P>
&lt;br />&lt;br />
&lt;P>// Быстрый доступ к объекту&lt;/P>
&lt;P>function $(divName) { return document.getElementById(divName); }&lt;/P>
&lt;br />&lt;br />
&lt;P>// Послать запрос контроллеру&lt;/P>
&lt;P>function showBlock(BlockID) {&lt;/P>
&lt;P>YAHOO.util.Connect.asyncRequest('POST', "&lt;A href="http://нашсайт/controller/">http://нашсайт/controller/&lt;/A>"+ BlockID.toLowerCase() +"/", callback, "ctrl_action=getComponent");&lt;/P>
&lt;P>}&lt;/P>
&lt;br />&lt;br />
&lt;P>// Определить поведение системы при получении ответа &lt;/P>
&lt;P>var callback =&lt;/P>
&lt;P>{&lt;/P>
&lt;P>success:CtrlRespond,&lt;/P>
&lt;P>failure:commonHandleFailure,&lt;/P>
&lt;P>argument:['foo','bar']&lt;/P>
&lt;P>};&lt;/P>
&lt;br />&lt;br />
&lt;P>// Неудачный ответ&lt;/P>
&lt;P>var commonHandleFailure = function(o){ &lt;/P>
&lt;P>if(o.responseText !== undefined){&lt;/P>
&lt;P>showSystemMessage("Connection Error");&lt;/P>
&lt;P>}&lt;/P>
&lt;P>};&lt;/P>
&lt;br />&lt;br />
&lt;P>// Анализ ответа контроллера&lt;/P>
&lt;P>var CtrlRespond = function(obj){&lt;/P>
&lt;P>if(obj.responseText == undefined) return false;&lt;/P>
&lt;P>if(obj.responseText.substr(0,1)=="{") {&lt;/P>
&lt;P>var respondStructure = eval( '(' + obj.responseText + ')' ); &lt;/P>
&lt;P>// Контроллер просит показать ошибку&lt;/P>
&lt;P>if( respondStructure.ErrorMsg ) return showSystemMessage(“ОШИБКА:” + respondStructure.ErrorMsg); &lt;/P>
&lt;P>// Контроллер просит выполнить соответствующее коду действие&lt;/P>
&lt;P>if( respondStructure.ActionCode==1 ) { $( respondStructure.ID ).innerHTML= respondStructure.Body; return true; }&lt;/P>
&lt;P>// Контроллер просит показать сообщение&lt;/P>
&lt;P>if( respondStructure.Body ) showSystemMessage(respondStructure.Body); &lt;/P>
&lt;P>} else alert(obj.responseText); // Отладка в случае ответа &lt;/P>
&lt;P>// с некорректной для JSON структурой&lt;/P>
&lt;P>};&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>app/ajax_controllers/userpanel/index.inc.php&lt;/B>&lt;/P>&lt;/DIV>
&lt;br />&lt;br />
&lt;P>&lt;?&lt;/P>
&lt;P>// Контроллер для пользовательской панели&lt;/P>
&lt;P>class RD extends controller {&lt;/P>
&lt;P>private $user;&lt;/P>
&lt;P>function __construct() {&lt;/P>
&lt;P>$this->user = Lib::factory('user');&lt;/P>
&lt;P>}&lt;/P>
&lt;br />&lt;br />
&lt;P>function getComponent() {&lt;/P>
&lt;P>$this->ID = "UserPanel";&lt;/P>
&lt;P>$this->ActionCode = 1;&lt;/P>
&lt;P>$this->Body = " ..Содержание панели .. ";&lt;/P>
&lt;P>}&lt;/P>
&lt;P>&lt;BR>}&lt;/P>
&lt;P>$rd = new RD();&lt;/P>
&lt;P>if(isset($_POST["ctrl_action"])) {&lt;/P>
&lt;P>call_user_method($_POST["ctrl_action"], $rd);&lt;/P>
&lt;P>}&lt;/P>
&lt;P>$rd->respond();&lt;/P>
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>libs/controller.lib.php&lt;/B>&lt;/P>&lt;/DIV>
&lt;br />&lt;br />
&lt;P>&lt;?&lt;/P>
&lt;P>// Исходный класс контроллера&lt;/P>
&lt;P>class controller {&lt;/P>
&lt;P>public $ActionCode=1;&lt;/P>
&lt;P>public $ErrorMsg="";&lt;/P>
&lt;P>public $Body="";&lt;/P>
&lt;P>public $ID="";&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;P>function respond($message="", $errormsg="") {&lt;/P>
&lt;P>if($message) $this->Body = $message;&lt;/P>
&lt;P>if($errormsg) $this->ErrorMsg = $errormsg;&lt;/P>
&lt;P>$out = '{&lt;/P>
&lt;P>"ActionCode": "'.$this->ActionCode.'",&lt;/P>
&lt;P>"ID": "'.$this->ID.'",&lt;/P>
&lt;P>"ErrorMsg" : "'.($this->ErrorMsg?addslashes(preg_replace("/[rn]/", "", $this->ErrorMsg)):"").'",&lt;/P>
&lt;P>"Body" : "'.($this->Body?addslashes(preg_replace("/[rn]/", "", $this->Body)):"").'"&lt;/P>
&lt;P>}';&lt;/P>
&lt;P>header("Content-type: text/html; charset=UTF-8");&lt;/P>
&lt;P>print $out; &lt;/P>
&lt;P>exit;&lt;/P>
&lt;P>}&lt;/P>
&lt;P>} &lt;/P>
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;P>Когда отработала инструкция в HTML веб-страницы showBlock("UserPanel") происходит запрос к контроллеру app/ajax_controllers/userpanel/index.inc.php. В параметре запроса ctrl_action указывается запрашиваемый метод. Контроллер возвращает в Java Script JSON-структуру с переменными ID, ActionCode, Body. Функция JS CtrlRespond() анализирует полученные переменные. Для ActionCode==1, как это в нашем случае, она вставляет содержание, полученное в BODY в слой с идентификатором ID. &lt;/P>
&lt;br />&lt;br />
&lt;P>Коль скоро мы получили пользовательскую панель, мы можем написать функцию для передачи данных контроллеру при регистрации посетителя проекта. &lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>js/common.js&lt;/B>&lt;/P>&lt;/DIV>
&lt;br />&lt;br />
&lt;P>// Послать данные в контроллер&lt;/P>
&lt;P>function registerUser(obj) {&lt;/P>
&lt;P>if(obj.login.value=='' || obj.password.value=='' || &lt;/P>
&lt;P>obj.email.value=='' || obj.fullname.value=='' || obj.gencode.value==''&lt;/P>
&lt;P>) showSystemMessage('Следует заполнить все поля формы');&lt;/P>
&lt;P>else YAHOO.util.Connect.asyncRequest('POST', "&lt;A href="http://нашсайт/controller/">http://нашсайт/controller/&lt;/A>userpanel/", callback, "ctrl_action=createUser&lt;/P>
&lt;P>}&lt;/P>
&lt;br />&lt;br />
&lt;P>…&lt;/P>
&lt;br />&lt;br />
&lt;P>// Анализ ответа контроллера&lt;/P>
&lt;P>var CtrlRespond = function(obj){&lt;/P>
&lt;P>…&lt;/P>
&lt;P>if( respondStructure.ActionCode==2 ) return showSystemMessage(respondStructure.Body); &lt;/P>
&lt;P>…&lt;/P>
&lt;P>};&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>app/ajax_controllers/userpanel/index.inc.php&lt;/B>&lt;/P>&lt;/DIV>
&lt;br />&lt;br />
&lt;P>&lt;?&lt;/P>
&lt;P>// Контроллер для пользовательской панели&lt;/P>
&lt;P>class RD extends controller {&lt;/P>
&lt;P>…&lt;/P>
&lt;P>function createUser() {&lt;/P>
&lt;P>if(!$_POST) { $this->ErrorMsg = "Не заполнены необходимые поля"; return false; }&lt;/P>
&lt;P>if(!$this->user->add($data)) { $this->ErrorMsg = "Ошибка при добавлении пользователя"; return false; }&lt;/P>
&lt;P>$this->ActionCode = 2;&lt;/P>
&lt;P>$this->Body = "Пользователь создан успешно";&lt;/P>
&lt;P>}&lt;/P>
&lt;P>…&lt;/P>
&lt;P>}&lt;/P>
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;P>Форма регистрации пользователя содержит кнопку &lt;input type="button" value="Присоединиться" onclick="registerUser(this) " />. При клике по ней в контроллер app/ajax_controllers/userpanel/index.inc.php передаются данные из формы и запрашивается метод createUser() для их обработки. В ходе выполнения метода в структуру ответа контроллера могут быть направлены сообщение об ошибке ErrorMsg, код требования о выполнении команды на клиентской стороне ActionCode или текст сообщения Body. В данном случае при успешном создании пользователя отобразится соответствующее сообщение, а в случае ошибки сообщение о ней. &lt;/P>
&lt;br />&lt;br />
&lt;P>Аналогичным образом мы можем написать функции для запросов проверки наличия введенного логина или email в БД. Они будут запрашивать методы класса контроллера app/ajax_controllers/userpanel/index.inc.php checkLogin и checkEmail соответственно. Сами методы могут выполнять проверку и сообщать о результате в переменной BODY. По схожему принципу можно организовать отображение формы авторизации и реакцию на события в ней. Впрочем, это касается любых компонентов пользовательского интерфейса проекта, требующих AJAX.&lt;/P>
&lt;br />&lt;br />
&lt;P>При отображении облака тегов вам может пригодиться следующая функция&lt;/P>
&lt;br />&lt;br />
&lt;br />&lt;DIV style="border-bottom: 1px solid black">
&lt;P>&lt;B>Облако тегов&lt;/B>&lt;/P>&lt;/DIV>
&lt;P>&lt;?&lt;/P>
&lt;P>function cmp_tag($a, $b) {&lt;/P>
&lt;P>if($a["tag"] == $b["tag"]) return 0;&lt;/P>
&lt;P>return strcmp($a["tag"] , $b["tag"]);&lt;/P>
&lt;P>}&lt;/P>
&lt;P>function getClouds() {&lt;/P>
&lt;P>global $db;&lt;/P>
&lt;P>$lines = array();&lt;/P>
&lt;P>$sizes = array( "x-small", "small", "medium", "large", "x-large" );&lt;/P>
&lt;P>$sql = "SELECT * FROM ".TAGCLOUDINDEXTABLE." LIMIT 0,20";&lt;/P>
&lt;P>$sth = $db->prepare($sql);&lt;/P>
&lt;P>$sth->execute();&lt;/P>
&lt;P>$result = $sth->fetchAll(PDO::FETCH_ASSOC);&lt;/P>
&lt;P>if(!$result) return false;&lt;/P>
&lt;P>$indexes = array();&lt;/P>
&lt;P>$tags = array();&lt;/P>
&lt;P>foreach ($result as $line) {&lt;/P>
&lt;P>$tags[trim($line["tag"])] = $line["tag_index"];&lt;/P>
&lt;P>$indexes[] = $line["tag_index"];&lt;/P>
&lt;P>} &lt;/P>
&lt;P>$min = min($indexes);&lt;/P>
&lt;P>$max = max($indexes);&lt;/P>
&lt;P>$range = ($max-$min);&lt;/P>
&lt;P>foreach ($tags as $tag => $index) {&lt;/P>
&lt;P>$lines[$tag]["tag"] = $tag;&lt;/P>
&lt;P>$lines[$tag]["tag_index"] = $index;&lt;/P>
&lt;P>$lines[$tag]["size"] = $sizes[sprintf("%d", ($index-$min)/$range*4 )];&lt;/P>
&lt;P>$lines[$tag]["title"] = "Тег ".$tag." найден ".$index.' раз ';&lt;/P>
&lt;P>}&lt;/P>
&lt;P>usort ($lines, "cmp_tag");&lt;/P>
&lt;P>return $lines;&lt;/P>
&lt;P>} &lt;/P>
&lt;br />&lt;br />
&lt;P>?>&lt;/P>
&lt;br />&lt;br />
&lt;P>Для реализации всплывающих контекстных подсказок вы можете использовать тот же принцип, по которому были созданы окна системных сообщений, с той лишь разницей, что подсказки следует позиционировать непосредственно в позиции курсора мыши в момент клика. Функции позиционирования, отображения и кеширования подсказок вы можете взять в моей библиотеке Thesaurus (&lt;A href="http://www.phpclasses.org/browse/package/3505.html">http://www.phpclasses.org/browse/package/3505.html&lt;/A>) &lt;/P>
&lt;br />&lt;br />
&lt;img src="/img/thesaurus.gif" alt="Пример Tooltip" border="0" height="288" hspace="10" vspace="10" width="444">&lt;br>
&lt;br />&lt;br />
&lt;br />&lt;br />
&lt;H2>Оптимизация &lt;/H2>
&lt;br />&lt;br />
&lt;P>Уверен, вы рассчитываете на высокую посещаемость разрабатываемого проекта. Значит, будет не лишним снизить нагрузку на сервер, настолько насколько это возможно. &lt;/P>
&lt;br />&lt;br />
&lt;P>Укажите планировщику (CRONTAB) вашего сервера задачу «раз в 30 минут» выполнять скрипт index.php c GET параметром createcache (/usr/bin/php -f/полныйадрес/index.php "&lt;/P>
&lt;P>}&lt;/P>
&lt;br />&lt;br />
&lt;P>Добавить в метод respond исходного класса условие создание кеш-образа ответа:&lt;/P>
&lt;br />&lt;br />
&lt;P>print $out; &lt;/P>
&lt;P>if(isset($_GET["createcache"]))&lt;/P>
&lt;P>file_put_contents(ROOT_PATH."cache/".md5("ajax_controllers{$CTRLPATH}").".tmp", $OUT);&lt;/P>
&lt;P>exit;&lt;/P>
&lt;br />&lt;br />
&lt;P>Теперь при прямом обращении к контроллеру &lt;A href="http://нашсайт/controller/">http://нашсайт/controller/&lt;/A>tagcloud/? ctrl_action=getComponent_createcache=on будет создан кеш его ответа. &lt;/P>
&lt;P>Осталось назначить планировщику задачи запуска заданных скриптов с параметрами (/usr/bin/php -f/полныйадрес/index.php "_ ctrl_action=getComponent_createcache=on_request_uri=/controller/tagcloud/") через заданные промежутки времени (скажем, обновлять облако тегов каждые 2 часа). Только не забудьте убедиться о проверке наличия в скрипте инициализации среды app/init.inc.php параметра GET request_uri. Если таковой имеется, система должна использовать его взамен $_SERVER['REQUEST_URI']. &lt;/P>
&lt;br />&lt;br />
&lt;H2>Заключение&lt;/H2>
&lt;br />&lt;br />
&lt;P>В это шальное время, &lt;A href="http://www.kommersant.ru/doc.aspx?DocsID=780978">когда проекты Веб 2.0 оцениваются в миллионы долларов даже в России&lt;/A>, вполне объяснимо желание попробовать себя на этом рынке. Вывод проекта на рынок, его капитализация – это вопросы бизнеса, а не программирования. Однако чтобы заниматься этим бизнесом, требуется продукт. Данная статья не являет руководством по программированию проекта Веб 2.0. Статья содержит материал, который может направить вас, если вы ищите подходящий путь разработки проекта. Я хотел здесь также показать, что, приловчившись можно «оживить» типовой Веб 2.0 стартап в относительно небольшие сроки. Если у вас есть интересная оригинальная идея, то пусть трудности ее реализации не останавливают вас. Дерзайте и, кто знает, возможно, именно ваша идея окажется реально востребованной, возможно она принесет вам больше чем вы смеете надеется. В Интернете имеется достаточно историй ошеломительного успеха стартапов Веб 2.0, стратапов сделанных людьми, которые осмелились. Возможно, через время там появиться и ваша success story. Успехов!.&lt;/P>

&lt;br />&lt;br />&lt;a href="http://cmsdevelopment.com/dcontent/how_create_web20_startup_with_php.pdf">Оригинал статьи в PDF&lt;/a></description> 
<dc:date>2007-07-11T00:00:00</dc:date>
</item>
</channel>
</rss>
