<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>twixed.ru</title>
	<atom:link href="http://twixed.ru/feed" rel="self" type="application/rss+xml" />
	<link>http://twixed.ru</link>
	<description>huh... nothing interesting here</description>
	<lastBuildDate>Fri, 16 Dec 2011 13:09:24 +0000</lastBuildDate>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>MetroUI-like scrolling</title>
		<link>http://twixed.ru/2011/12/16/469</link>
		<comments>http://twixed.ru/2011/12/16/469#comments</comments>
		<pubDate>Fri, 16 Dec 2011 13:09:24 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[wpf]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=469</guid>
		<description><![CDATA[Два месяца этот примерчик ждал своей очереди, и «пылился» на винче без дела. И, наконец-то, я собрался духом, и выкладываю его на всеобщее обозрение и порицание. В этой статье я поделюсь своим методом реализации некоего подобия интерфейса Metro UI, написанного, как говорится, «на коленке» на C# под WPF. В примере используется .Net framework 4, но [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twixed.ru/wp-content/uploads/2011/11/MetroScroll.jpg" rel="lightbox[469]"><img class="size-thumbnail wp-image-464 alignright" style="margin: 10px;" title="MetroScroll" src="http://twixed.ru/wp-content/uploads/2011/11/MetroScroll-150x150.jpg" alt="" width="150" height="150" /></a>Два месяца этот примерчик ждал своей очереди, и «пылился» на винче без дела. И, наконец-то, я собрался духом, и выкладываю его на всеобщее обозрение и порицание.<br />
В этой статье я поделюсь своим методом реализации некоего подобия интерфейса Metro UI, написанного, как говорится, «на коленке» на C# под WPF. В примере используется .Net framework 4, но все описанное можно без изменений использовать в версиях 3 и 3.5. Framework 2.0 не умеет WPF, но реализованный здесь алгоритм можно запросто перенести на WinForms (правда, на VCL отрисовка «плывущих» контролов безбожно тормозит и уродует форму, даже если DoubleBuffered:=true, а на каждый тик таймера вызываются Application.ProcessMessages и/или Refresh). WPF был выбран основным для демонстрации этого алгоритма потому что это «модно, стильно, молодежно»… шучу. Конечно, он был выбран потому, что это удобно, быстро и красиво.<br />
Итак, заинтересованных прошу под кат… <span id="more-469"></span></p>
<h2>Переменные</h2>
<p>Заранее определим все переменные и классы, которые будут использоваться для обработки скроллинга как в Metro UI. В первую очередь, нам нужен таймер, который будет обрабатывать и изменять положение тайлов, в зависимости от ускорения, которое им придал пользователь, потаскав мышкой. Следовательно, нам нужна будет переменная для значения скорости, переменная для смещения (скроллинга), переменные для положения мыши и переменные для времени начала и конца перетаскивания с точностью до миллисекунд. Помимо этого будет еще и булева переменная, работающая как флаг для остановки скроллинга. Позже мы увидим, что она окажется важной, хотя, на первый взгляд, можно было бы обойтись и без нее.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> DispatcherTimer timer <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> DispatcherTimer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>          <span style="color: #006600; font-style: italic;">// main timer</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">private</span> double tileOffset <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>              <span style="color: #006600; font-style: italic;">// actually, it is a scroll offset</span>
<span style="color: #003366; font-weight: bold;">private</span> double tilesWidth <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>              <span style="color: #006600; font-style: italic;">// total width of all tiles</span>
<span style="color: #003366; font-weight: bold;">private</span> double lastMouseXPos <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>           <span style="color: #006600; font-style: italic;">// remembers last mouse position. needed to calculate scroll direction and speed</span>
<span style="color: #003366; font-weight: bold;">private</span> double mouseXPos <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>               <span style="color: #006600; font-style: italic;">// no comments on these two</span>
<span style="color: #003366; font-weight: bold;">private</span> double mouseYPos <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>               <span style="color: #006600; font-style: italic;">// </span>
<span style="color: #003366; font-weight: bold;">private</span> double mouseInertia <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>            <span style="color: #006600; font-style: italic;">// determines scroll speed after the mouse button is released. decreases avery timer tick</span>
<span style="color: #003366; font-weight: bold;">private</span> UInt64 inertiaStart <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>            <span style="color: #006600; font-style: italic;">// mouse drag start time in milliseconds</span>
<span style="color: #003366; font-weight: bold;">private</span> UInt64 inertiaEnd <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>              <span style="color: #006600; font-style: italic;">// mouse drag end time in milliseconds</span>
<span style="color: #003366; font-weight: bold;">private</span> Boolean isInertiaStopped <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>    <span style="color: #006600; font-style: italic;">// useful flag needed to stop scroll by zeroing `mouseInertia` on next timer tick</span></pre></div></div>

<h2>Тайлы</h2>
<p><a href="http://twixed.ru/wp-content/uploads/2011/11/MetroScroll_1.jpg" rel="lightbox[469]"><img class="alignright size-thumbnail wp-image-465" style="margin: 10px;" title="MetroScroll_1" src="http://twixed.ru/wp-content/uploads/2011/11/MetroScroll_1-150x150.jpg" alt="" width="150" height="150" /></a>Теперь создадим и разместим нашу плитку. В примере она будет простой, однако элементарность всего происходящего позволяет использовать практические любые контролы. Я же использовал Grid как простой и удобный элемент, который, к тому же, может служить контейнером для других контролов, а это уже открывает хорошие возможности для кастомизации.<br />
Размещать вновь создаваемые Grid'ы мы будем на основной сетке чистого приложения, любезно созданного для нас средой разработки. Для этого надо присвоить ей имя, например, 'tilesGrid'.<br />
Накрапаем простенькую функцию, в которой будем создавать новый Grid, задавать его параметры, и размещать его на основной сетке:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> AddTile<span style="color: #009900;">&#40;</span>int i<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// grid is one of the simplest WPF controls, but also it's a convinient one,</span>
  <span style="color: #006600; font-style: italic;">// because it can be customized, manipulated and can be a container for other controls</span>
  Grid g <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Grid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  g.<span style="color: #660066;">Width</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">128</span><span style="color: #339933;">;</span>
  g.<span style="color: #660066;">Height</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">128</span><span style="color: #339933;">;</span>
  g.<span style="color: #660066;">Margin</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Thickness<span style="color: #009900;">&#40;</span><span style="color: #CC0000;">5</span> <span style="color: #339933;">+</span> tilesWidth<span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  g.<span style="color: #660066;">Background</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> SolidColorBrush<span style="color: #009900;">&#40;</span>Color.<span style="color: #660066;">FromRgb</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>byte<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">*</span><span style="color: #CC0000;">120</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>byte<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">*</span><span style="color: #CC0000;">110</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>byte<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">*</span><span style="color: #CC0000;">130</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #006600; font-style: italic;">// some &quot;random&quot; background color</span>
  g.<span style="color: #660066;">VerticalAlignment</span> <span style="color: #339933;">=</span> VerticalAlignment.<span style="color: #660066;">Top</span><span style="color: #339933;">;</span>
  g.<span style="color: #660066;">HorizontalAlignment</span> <span style="color: #339933;">=</span> HorizontalAlignment.<span style="color: #660066;">Left</span><span style="color: #339933;">;</span>
  tilesGrid.<span style="color: #660066;">Children</span>.<span style="color: #660066;">Add</span><span style="color: #009900;">&#40;</span>g<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                                  <span style="color: #006600; font-style: italic;">// placing new element into main grid</span>
  g.<span style="color: #660066;">Effect</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> DropShadowEffect<span style="color: #009900;">&#123;</span>Color <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Color <span style="color: #009900;">&#123;</span>A<span style="color: #339933;">=</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>R<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>G<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>B<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>ShadowDepth <span style="color: #339933;">=</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>BlurRadius <span style="color: #339933;">=</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">,</span>Opacity <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>    <span style="color: #006600; font-style: italic;">// simple effect to make our tiles look sweet</span>
&nbsp;
  Label l <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Label<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                                      <span style="color: #006600; font-style: italic;">// actually, this label is not necessary</span>
  l.<span style="color: #660066;">Content</span><span style="color: #339933;">=</span>i.<span style="color: #660066;">ToString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                                     <span style="color: #006600; font-style: italic;">// i'm placing it to make visual counting</span>
  g.<span style="color: #660066;">Children</span>.<span style="color: #660066;">Add</span><span style="color: #009900;">&#40;</span>l<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                                          <span style="color: #006600; font-style: italic;">// of tiles a little bit easier</span>
&nbsp;
  tilesWidth <span style="color: #339933;">=</span> tilesWidth <span style="color: #339933;">+</span> g.<span style="color: #660066;">Width</span><span style="color: #339933;">+</span><span style="color: #CC0000;">5</span><span style="color: #339933;">;</span>                        <span style="color: #006600; font-style: italic;">// we're updating total tiles's width to arrange them correctly directly after creation</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Поместим на сетку двадцать пять тайлов:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">public</span> MainWindow<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  InitializeComponent<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>int i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">25</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> AddTile<span style="color: #009900;">&#40;</span>i <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>          <span style="color: #006600; font-style: italic;">// we'd like to create 25 tiles</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>&nbsp;</p>
<h2>Размещение тайлов</h2>
<p><a href="http://twixed.ru/wp-content/uploads/2011/11/MetroScroll_2.jpg" rel="lightbox[469]"><img class="alignright size-thumbnail wp-image-466" style="margin: 10px;" title="MetroScroll_2" src="http://twixed.ru/wp-content/uploads/2011/11/MetroScroll_2-150x150.jpg" alt="" width="150" height="150" /></a>Естественно, плитку нужно красиво разместить. Для этого создадим отдельную функцию, которая будет вызываться при каждом срабатывании таймера, и размещать тайлы в две строки слева направо, а также сдвигать их в соответствии со смещением скролла. Приведенная функция проста, и, вероятно, неказиста. Я знаю, что было бы великолепно использовать здесь алгоритм из задачи «о рюкзаке», но на столь изощренное велосипедостроительство у меня, к сожалению, нет времени. Поэтому мы действуем «в лоб»: перебираем все дочерние элементы основной сетки, и размещаем наши гриды один за другим, периодически наращивая счетчик столбцов, от которого зависит верхний отступ тайла. Сложностей здесь нет никаких, потому что мы строго задали размеры тайлов при инициализации, и в вычислениях просто используем эти цифры.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> LayoutTiles<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// simplest layout algorithm ever! (:</span>
  <span style="color: #006600; font-style: italic;">// tiles are arranged in two rows with margin of 5 pixels</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>tilesWidth <span style="color: #339933;">&lt;=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>                                        <span style="color: #006600; font-style: italic;">// if total tiles's width less then the main grid's with, do nothing</span>
  tilesWidth <span style="color: #339933;">=</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">;</span>                                                     <span style="color: #006600; font-style: italic;">// set the initial offset of default margin (5 px)</span>
  int count <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>                                                      <span style="color: #006600; font-style: italic;">// columns count</span>
  int totalCount <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>                                                 <span style="color: #006600; font-style: italic;">// total tiles count</span>
  <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>int i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> tilesGrid.<span style="color: #660066;">Children</span>.<span style="color: #660066;">Count</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>                  <span style="color: #006600; font-style: italic;">// loop through main grid's children</span>
  <span style="color: #009900;">&#123;</span>
    Object obj <span style="color: #339933;">=</span> tilesGrid.<span style="color: #660066;">Children</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>obj.<span style="color: #660066;">GetType</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>System.<span style="color: #660066;">Windows</span>.<span style="color: #660066;">Controls</span>.<span style="color: #660066;">Grid</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>      <span style="color: #006600; font-style: italic;">// checking children type. we need only Grids. any other objects remains untouched</span>
    <span style="color: #009900;">&#123;</span>                                                               <span style="color: #006600; font-style: italic;">// this condition must be modified to your needs</span>
      totalCount<span style="color: #339933;">++;</span>
      Grid rect <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Grid<span style="color: #009900;">&#41;</span>obj<span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">%</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span>
        rect.<span style="color: #660066;">Margin</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Thickness<span style="color: #009900;">&#40;</span>tileOffset <span style="color: #339933;">+</span> <span style="color: #CC0000;">5</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">133</span> <span style="color: #339933;">*</span> count<span style="color: #339933;">,</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #006600; font-style: italic;">// </span>
      <span style="color: #000066; font-weight: bold;">else</span>                                                                        <span style="color: #006600; font-style: italic;">// setting current tile margin according to scroll offset </span>
      <span style="color: #009900;">&#123;</span>                                                                           <span style="color: #006600; font-style: italic;">// and column number our tile is placed in</span>
        rect.<span style="color: #660066;">Margin</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Thickness<span style="color: #009900;">&#40;</span>tileOffset <span style="color: #339933;">+</span> <span style="color: #CC0000;">5</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">133</span> <span style="color: #339933;">*</span> count<span style="color: #339933;">,</span> <span style="color: #CC0000;">138</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   <span style="color: #006600; font-style: italic;">//</span>
        count<span style="color: #339933;">++;</span>                                                                <span style="color: #006600; font-style: italic;">// increase column count</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
  tilesWidth <span style="color: #339933;">=</span> <span style="color: #CC0000;">133</span> <span style="color: #339933;">*</span> count <span style="color: #339933;">-</span> tilesGrid.<span style="color: #660066;">ActualWidth</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">;</span>               <span style="color: #006600; font-style: italic;">// set total width to number of columns minus main grid's width</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>totalCount <span style="color: #339933;">%</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">!=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> tilesWidth <span style="color: #339933;">+=</span> <span style="color: #CC0000;">133</span><span style="color: #339933;">;</span>                         <span style="color: #006600; font-style: italic;">// increase it by one column if we have odd number of tiles</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>&nbsp;</p>
<h2>Скроллинг перетаскиванием</h2>
<p>Следующим шагом мы будем скроллить все тайлы влево или в право, «хватая» мышкой любой из них, и перетаскивая его в нужную сторону. Для этого нам потребуется добавить три обработчика — «нажали кнопку мыши», «отпустили кнопку мыши» и «подвинули мышь» — и назначить их каждому тайлу после его создания.<br />
Начнем с обработчика нажатия на клавишу мыши: он должен запомнить время нажатия и координаты мыши, чтобы другие обработчики могли использовать их для построения своего поведения и вычисления смещения тайлов.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> TileMouseDown<span style="color: #009900;">&#40;</span>object sender<span style="color: #339933;">,</span> MouseButtonEventArgs e<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">LeftButton</span> <span style="color: #339933;">==</span> MouseButtonState.<span style="color: #660066;">Pressed</span><span style="color: #009900;">&#41;</span>                       <span style="color: #006600; font-style: italic;">// do anything only if left mouse button is pressed</span>
  <span style="color: #009900;">&#123;</span>
    Grid rect <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Grid<span style="color: #009900;">&#41;</span>sender<span style="color: #339933;">;</span>
    mouseXPos <span style="color: #339933;">=</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span><span style="color: #339933;">;</span>          <span style="color: #006600; font-style: italic;">// save current mouse position</span>
    mouseYPos <span style="color: #339933;">=</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Y</span><span style="color: #339933;">;</span>          <span style="color: #006600; font-style: italic;">// relatively to screen</span>
    lastMouseXPos <span style="color: #339933;">=</span> mouseXPos<span style="color: #339933;">;</span>                                      <span style="color: #006600; font-style: italic;">// update last mouse position on x-pos (we'll need it later)</span>
    mouseInertia <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>                                               <span style="color: #006600; font-style: italic;">// reset the scrolling speed</span>
    TimeSpan span <span style="color: #339933;">=</span> DateTime.<span style="color: #660066;">UtcNow</span> <span style="color: #339933;">-</span> <span style="color: #003366; font-weight: bold;">new</span> DateTime<span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1970</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     <span style="color: #006600; font-style: italic;">// and save scrolling start time in milliseconds</span>
    inertiaStart <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>UInt64<span style="color: #009900;">&#41;</span>span.<span style="color: #660066;">TotalMilliseconds</span><span style="color: #339933;">;</span>                  <span style="color: #006600; font-style: italic;">// (we really need it to be so precise)</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>&nbsp;</p>
<p>Следующим будет обработчик движения мыши над нашими тайлами. Он должен выполнять какие-либо действия только если не все тайлы уместились в экран, и мышь была сдвинута по оси X более чем на пять пикселей в любом направлении. В этом случае мы считаем, что пользователь действительно желает перетащить тайлы, и делаем это, вычисляя дистанцию, которую прошла мышь с последней итерации, и размещаем тайлы в соответствии с изменившимся смещением.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> TileMouseMove<span style="color: #009900;">&#40;</span>object sender<span style="color: #339933;">,</span> MouseEventArgs e<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>tilesWidth <span style="color: #339933;">+</span> Width <span style="color: #339933;">&gt;</span> Width<span style="color: #009900;">&#41;</span>                                             <span style="color: #006600; font-style: italic;">// check if tiles don't fit into window</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">LeftButton</span> <span style="color: #339933;">==</span> MouseButtonState.<span style="color: #660066;">Pressed</span><span style="color: #009900;">&#41;</span>                           <span style="color: #006600; font-style: italic;">// and do somenthing only if left mouse button is pressed</span>
    <span style="color: #009900;">&#123;</span>
      Grid rect <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Grid<span style="color: #009900;">&#41;</span>sender<span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>mouseXPos <span style="color: #339933;">&lt;</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span>  <span style="color: #006600; font-style: italic;">// have mouse moved more than 5 pixels on x-axis?</span>
          <span style="color: #009900;">&#40;</span>mouseXPos <span style="color: #339933;">&gt;</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>    <span style="color: #006600; font-style: italic;">// strart scrolling if she did</span>
      <span style="color: #009900;">&#123;</span>
        double diff <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>lastMouseXPos <span style="color: #339933;">-</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #006600; font-style: italic;">// compute the distance she traveled since last iteration</span>
        lastMouseXPos <span style="color: #339933;">=</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span><span style="color: #339933;">;</span>      <span style="color: #006600; font-style: italic;">// and save current position to use it next time</span>
        tileOffset <span style="color: #339933;">-=</span> diff<span style="color: #339933;">;</span>                                             <span style="color: #006600; font-style: italic;">// change tile scroll offset</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>tileOffset <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> tileOffset <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>                             <span style="color: #006600; font-style: italic;">// restrict excess scrolling to the left</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>tileOffset <span style="color: #339933;">&lt;</span> <span style="color: #339933;">-</span>tilesWidth<span style="color: #009900;">&#41;</span> tileOffset <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>tilesWidth<span style="color: #339933;">;</span>         <span style="color: #006600; font-style: italic;">// and right</span>
        LayoutTiles<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>&nbsp;</p>
<p>Последний «мышиный» обработчик вызывается, когда пользователь отпустил кнопку мыши, и нам надо решить — клик это был или завершение перетаскивания. Для этого используются координаты мыши, сохраненные в последний раз, и, если они отличаются не больше, чем на 5 пикселей, засчитываем клик, если нет — завершаем перетаскивание и вычисляем переданное ускорение.<br />
Как я говорил в начале этой статьи, рассмотрим необходимость существования булевой переменной `isInertiaStopped`. Она может показаться не нужной, потому что (как вы поймете из кода ниже) можно было бы просто обнулять скорость скроллинга. Однако парой лишних строчек мы добавили очень важный функционал — пользователь будет иметь возможность остановить прокрутку без вызова обработчика «клик». Т.е. он сможет остановить скроллинг, понять, что же он видит, и уже потом кликнуть по нужному тайлу, обработчиком на клик по которому может быть запуск приложения, открытие дочерней формы или вообще самоуничтожение программы со смешным описанием исключения.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> TileMouseUp<span style="color: #009900;">&#40;</span>object sender<span style="color: #339933;">,</span> MouseButtonEventArgs e<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">LeftButton</span> <span style="color: #339933;">==</span> MouseButtonState.<span style="color: #660066;">Released</span><span style="color: #009900;">&#41;</span>                      <span style="color: #006600; font-style: italic;">// do anything only if left mouse button was released</span>
  <span style="color: #009900;">&#123;</span>
    Grid rect <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Grid<span style="color: #009900;">&#41;</span>sender<span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>mouseXPos <span style="color: #339933;">&gt;</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span>  <span style="color: #006600; font-style: italic;">//</span>
        <span style="color: #009900;">&#40;</span>mouseXPos <span style="color: #339933;">&lt;</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span>  <span style="color: #006600; font-style: italic;">// have mouse moved more than 5 pixels in any direction?</span>
        <span style="color: #009900;">&#40;</span>mouseYPos <span style="color: #339933;">&gt;</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Y</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span>  <span style="color: #006600; font-style: italic;">//</span>
        <span style="color: #009900;">&#40;</span>mouseYPos <span style="color: #339933;">&lt;</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Y</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>    <span style="color: #006600; font-style: italic;">//</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>isInertiaStopped<span style="color: #009900;">&#41;</span>                                       <span style="color: #006600; font-style: italic;">// are tiles still scrolling?</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// tile click handler should be place here</span>
      <span style="color: #009900;">&#125;</span>
      <span style="color: #000066; font-weight: bold;">else</span>
      <span style="color: #009900;">&#123;</span>
        isInertiaStopped <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>                                <span style="color: #006600; font-style: italic;">// stop scrolling tiles</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066; font-weight: bold;">else</span>
    <span style="color: #009900;">&#123;</span>
      isInertiaStopped <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>                                   <span style="color: #006600; font-style: italic;">// pull down scrolling flag, so next time we will know that tiles are scrolling</span>
      TimeSpan span <span style="color: #339933;">=</span> DateTime.<span style="color: #660066;">UtcNow</span> <span style="color: #339933;">-</span> <span style="color: #003366; font-weight: bold;">new</span> DateTime<span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1970</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
      inertiaEnd <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>UInt64<span style="color: #009900;">&#41;</span>span.<span style="color: #660066;">TotalMilliseconds</span><span style="color: #339933;">;</span>                <span style="color: #006600; font-style: italic;">// save scrolling end time in milliseconds</span>
      double distance <span style="color: #339933;">=</span> mouseXPos <span style="color: #339933;">-</span> rect.<span style="color: #660066;">PointToScreen</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">GetPosition</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">X</span><span style="color: #339933;">;</span>    <span style="color: #006600; font-style: italic;">// compute the distance she traveled since last iteration</span>
      UInt64 time <span style="color: #339933;">=</span> inertiaEnd <span style="color: #339933;">-</span> inertiaStart<span style="color: #339933;">;</span>                    <span style="color: #006600; font-style: italic;">// measure the time this distance was covered by</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>tilesWidth <span style="color: #339933;">+</span> Width <span style="color: #339933;">&gt;</span> Width<span style="color: #009900;">&#41;</span> mouseInertia <span style="color: #339933;">=</span> distance <span style="color: #339933;">*</span> <span style="color: #CC0000;">10</span> <span style="color: #339933;">/</span> time <span style="color: #339933;">*</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>   <span style="color: #006600; font-style: italic;">// and calculate scrolling speed based on these two values </span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>&nbsp;</p>
<p>Эти три обработчика должны быть привязаны к каждому созданному нами тайлу, поэтому в функцию <strong>AddTile</strong> мы добавим еще три строчки:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">g.<span style="color: #660066;">MouseDown</span> <span style="color: #339933;">+=</span> <span style="color: #003366; font-weight: bold;">new</span> MouseButtonEventHandler<span style="color: #009900;">&#40;</span>TileMouseDown<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #006600; font-style: italic;">//</span>
g.<span style="color: #660066;">MouseUp</span> <span style="color: #339933;">+=</span> <span style="color: #003366; font-weight: bold;">new</span> MouseButtonEventHandler<span style="color: #009900;">&#40;</span>TileMouseUp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>      <span style="color: #006600; font-style: italic;">// adding mouse event handlers to newly created grid</span>
g.<span style="color: #660066;">MouseMove</span> <span style="color: #339933;">+=</span> <span style="color: #003366; font-weight: bold;">new</span> MouseEventHandler<span style="color: #009900;">&#40;</span>TileMouseMove<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>        <span style="color: #006600; font-style: italic;">//</span></pre></div></div>

<p>&nbsp;</p>
<h2>Таймер</h2>
<p>Сейчас наша программа позволяет скроллить тайлы только когда их тащат мыщью, а несколько переменных и большая часть последнего рассмотренного обработчика вообще оказываются ненужными. Поэтому мы добавим таймер, и каждые 10 миллисекунд будем вызывать его обработчик, единственная задача которого вычислять изменение скорости скроллинга, и ракладывать тайлы в соответствии с новым смещением.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> TimerTick<span style="color: #009900;">&#40;</span>object sender<span style="color: #339933;">,</span> EventArgs e<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// simple calculations</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>mouseInertia <span style="color: #339933;">!=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span>                                      <span style="color: #006600; font-style: italic;">// if scrolling is needed</span>
  <span style="color: #009900;">&#123;</span>
    tileOffset <span style="color: #339933;">+=</span> mouseInertia<span style="color: #339933;">;</span>                             <span style="color: #006600; font-style: italic;">// change scroll offset</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>tileOffset <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> tileOffset <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>                     <span style="color: #006600; font-style: italic;">// restring excess scrolling to the left</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>tileOffset <span style="color: #339933;">&lt;</span> <span style="color: #339933;">-</span>tilesWidth<span style="color: #009900;">&#41;</span> tileOffset <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>tilesWidth<span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// and right</span>
    mouseInertia <span style="color: #339933;">*=</span> <span style="color: #CC0000;">0.99</span><span style="color: #339933;">;</span>                                   <span style="color: #006600; font-style: italic;">// decrease scrolling speed</span>
    LayoutTiles<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>&nbsp;</p>
<p>В конструкторе  объекта задаем интервал срабатывания таймера, привязываем его обработчик, и запускаем:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">timer.<span style="color: #660066;">Interval</span> <span style="color: #339933;">=</span> TimeSpan.<span style="color: #660066;">FromMilliseconds</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>             <span style="color: #006600; font-style: italic;">//</span>
timer.<span style="color: #660066;">Tick</span> <span style="color: #339933;">+=</span> <span style="color: #003366; font-weight: bold;">new</span> EventHandler<span style="color: #009900;">&#40;</span>TimerTick<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                  <span style="color: #006600; font-style: italic;">// setting up and starting main timer</span>
timer.<span style="color: #660066;">Start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                                              <span style="color: #006600; font-style: italic;">//</span></pre></div></div>

<p>&nbsp;</p>
<h2>Заключение</h2>
<p>Простейший пример готов. Я надеюсь, что он может кому-то пригодиться, и достаточно понятен для затачивания под свои нужды. Я знаю, что в коде есть неиспользуемые переменные (а именно, переменные для хранения положения мыши по оси Y), но убирать их не стал, просто чтобы по прошествии времени было проще реализовать вертикальный/свободный скроллинг, если таковой понадобится.<br />
Приведу скриншот программы, которая использует приведенный здесь алгоритм для отображения подключаемых модулей, «иконки» которых обладают способностью скроллиться мышью влево и вправо, как если бы это было на сенсорном устройстве:</p>
<p style="text-align: center;"><a href="http://twixed.ru/wp-content/uploads/2011/11/photoexpress2.5beta.jpg" rel="lightbox[469]"><img class=" wp-image-467 aligncenter" title="photoexpress2.5beta" src="http://twixed.ru/wp-content/uploads/2011/11/photoexpress2.5beta.jpg" alt="" width="709" height="505" /></a></p>
<p>Ну, и, на последок, <a href="http://bit.ly/slMjkC" rel="nofollow">ссылка на архив с исходником</a>.</p>
<p><strong>PS:</strong> Буду очень благодарен тому, кто поможет с задачей «о рюкзаке» действенным и простым алгоритмом или ссылкой.</p>
<p><strong>UPDATE:</strong> <a href="http://bit.ly/tkGGwv" rel="nofollow">Чуть улучшенная версия</a> — при достижении крайней плитки не останавливает ее как бетонная стена, а постепенно снижает скорость, и возвращает на исходную, как на резинке.</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/12/16/469/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Основные системные показатели на PHP</title>
		<link>http://twixed.ru/2011/10/12/426</link>
		<comments>http://twixed.ru/2011/10/12/426#comments</comments>
		<pubDate>Wed, 12 Oct 2011 10:46:02 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[*nix]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sysinfo]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=426</guid>
		<description><![CDATA[В этой статье я поделюсь своими способами извлечения и отображения на сайте системных показателей, как то: текущая загрузка процессора, потребление системной памяти и свапа, и количество занятого пространства на НЖМД. Рассматриваться будет работа на Ubuntu Server. Под другие nix-системы тоже должно работать, но, возможно, с доработками. Windows серверы не рассматриваются вовсе. Все решения сделаны "в [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twixed.ru/wp-content/uploads/2011/10/stats.png" rel="lightbox[426]"><img src="http://twixed.ru/wp-content/uploads/2011/10/stats-150x150.png" alt="" title="stats" width="150" height="150" class="alignleft size-thumbnail wp-image-427" /></a>В этой статье я поделюсь своими способами извлечения и отображения на сайте системных показателей, как то: текущая загрузка процессора, потребление системной памяти и свапа, и количество занятого пространства на НЖМД. <span id="more-426"></span></p>
<p>Рассматриваться будет работа на Ubuntu Server. Под другие nix-системы тоже должно работать, но, возможно, с доработками. Windows серверы не рассматриваются вовсе.<br />
Все решения сделаны "в лоб", без изысков и фанатичной минимализации/оптимизации. Я использовал jQuery для того, чтобы получить json посредством Ajax, и вывести его на страницу. Примеры простые, и могут быть переделаны под любой другой способ передачи/вывода. Итак...</p>
<h4>1. Загрузка CPU</h4>
<p>Начнем с самого сложного. Сложного потому, что мне не сразу удалось найти способ получения информации о загрузке процессора, а впоследствии, и не сразу найти способ ее обрабатывать. Первой мыслью была "использовать <a href="http://php.net/manual/en/function.exec.php" title="exec()" target="_blank">exec("top -n 1")</a>", однако top не писал в стандартный вывод, а сохранение его (вывод) в файл на диск через '>', приводило к появлению огромного количества 'мусора', что сильно затрудняло последующий парсинг. В итоге, все свелось к чтению нужных файлов в виртуальной файловой системе, подключенной в <a href="http://www.idevelopment.info/data/Unix/General_UNIX/GENERAL_TheProcFilesystem.shtml" title="/proc" target="_blank">/proc</a>. Файл, в котором хранится информация о  текущем использовании процессора называется /proc/stat. По сути, это не файл, а точка доступа к структурам данных ядра, но нам это знать не обязательно, потому что нам будет достаточно прочитать содержимое, а сделать это можно, как и в случае с простым файлом, через <a href="http://php.net/manual/ru/function.file.php" title="file()" target="_blank">file()</a>. Теперь можно привести кусочек кода, который эту информацию достает. После него я объясню, что было сделано, и зачем.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$file</span><span style="color: #339933;">=</span><span style="color: #990000;">file</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/proc/stat&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tmp</span><span style="color: #339933;">=</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_user_old</span><span style="color: #339933;">=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">userdata</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;cpu_user&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_nice_old</span><span style="color: #339933;">=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">userdata</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;cpu_nice&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_sys_old</span><span style="color: #339933;">=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">userdata</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;cpu_sys&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_idle_old</span><span style="color: #339933;">=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">userdata</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;cpu_idle&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_io_old</span><span style="color: #339933;">=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">userdata</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;cpu_io&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_user</span><span style="color: #339933;">=</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_nice</span><span style="color: #339933;">=</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_sys</span><span style="color: #339933;">=</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_idle</span><span style="color: #339933;">=</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">5</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu_io</span><span style="color: #339933;">=</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">6</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$diff_used</span><span style="color: #339933;">=</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_user</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_user_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_nice</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_nice_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_sys</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_sys_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_io</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_io_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$diff_total</span><span style="color: #339933;">=</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_user</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_user_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_nice</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_nice_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_sys</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_sys_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_io</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_io_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$cpu_idle</span><span style="color: #339933;">-</span><span style="color: #000088;">$cpu_idle_old</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cpu</span><span style="color: #339933;">=</span><span style="color: #000088;">$diff_used</span><span style="color: #339933;">/</span><span style="color: #000088;">$diff_total</span><span style="color: #339933;">*</span><span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set_userdata</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;cpu_user&quot;</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$cpu_user</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;cpu_nice&quot;</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$cpu_nice</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;cpu_sys&quot;</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$cpu_sys</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;cpu_idle&quot;</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$cpu_idle</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;cpu_io&quot;</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$cpu_io</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Объяснение начнем с содержимого файла:</p>
<pre>> cat /proc/stat
cpu  2255 34 2290 22625563 6290 127 456 0 0
cpu0 1132 34 1441 11311718 3675 127 438 0 0
cpu1 1123 0 849 11313845 2614 0 18 0 0
intr 114930548 113199788 3 0 5 263 0 4 [... еще куча цифр ...]
...
</pre>
<p>В первой строчке /proc/stat содержится информация о количестве потраченного процессором времени (усредненное для всех ядер/потоков) на выполнение (по порядку): процессов пользователя, высокоприоритетных процессов пользователя, системных процессов, простоя, ожидания ввода/вывода, аппаратных и программных прерываний. В следующих строках, начинающихся на 'cpu', приведены те же данные для каждого ядра/потока в отдельности. В нашем случае вся интересующая информация содержится в первой строке, поэтому дальше разбирать файл не будем.<br />
В приведенном кусочке кода так же есть сохранение этих данных в сессию <a href="http://codeigniter.com/" title="CodeIgniter" target="_blank">CodeIgniter</a>. Это сделано для того, чтобы определять разницу (дельту) между текущими и предыдущими значениями показателей. Загрузка процессора представляет собой отношение времени, затраченного на процессы, к общему затраченному времени, включающему простой. Естественно, чем реже будут происходить эти запросы, тем сильнее будет усреднено значение загрузки процессора за это время.</p>
<h4>2. Оперативная память</h4>
<p>Информацию о количестве свободной оперативной памяти можно найти в файле /proc/meminfo:</p>
<pre>
> cat /proc/meminfo
MemTotal:        2052604 kB
MemFree:          246012 kB
Buffers:          792332 kB
Cached:           584716 kB
...
</pre>
<p>Отсюда мы будем брать две первые строчки, и извлекать из них цифры:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$file</span><span style="color: #339933;">=</span><span style="color: #990000;">file</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/proc/meminfo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$memory</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;total&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #990000;">strrpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$memory</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;free&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #990000;">strrpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Этот и последующие кусочки кода будут куда проще первого, и обширные пояснения им не потребуются. Здесь, например, все очевидно - мы просто "вырезаем" число, расположенное между двумя пробелами, для первой и второй строчки соответственно.</p>
<h4>3. Swap file</h4>
<p>Тут еще проще - берем строчку из /proc/swaps:</p>
<pre>
> cat /proc/swaps
Filename                                Type            Size    Used    Priority
/dev/sda1                               partition       7811064 2732    -1
...
</pre>
<p>В нем перечислены все подключенные своп-файлы, их типы, объемы и занятое место. Нам просто надо "выдернуть" нужные цифры из нужных строк. В моем случае своп один, и строчку я обрабатываю одну:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$file</span><span style="color: #339933;">=</span><span style="color: #990000;">file</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/proc/swaps&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tmp</span><span style="color: #339933;">=</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span><span style="color: #339933;">,</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;partition&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$swap</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;total&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$swap</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;free&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Здесь пояснения тоже не нужны.</p>
<h4>4. Жесткие диски</h4>
<p>В моем примере будет приведен код, который извлекает информацию о количестве свободного места на дисках, точки монтирования которых находятся в /mnt. Ухищрения типа чтения и парсинга файлов из /proc здесь использовать не будут - для этой цели достаточно стандартных <a href="http://www.php.net/manual/ru/function.disk-free-space.php" title="disk_free_space" target="_blank">disk_free_space()</a> и <a href="http://www.php.net/manual/ru/function.disk-total-space.php" title="disk_total_space" target="_blank">disk_total_space()</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$drives</span><span style="color: #339933;">=</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$dir</span><span style="color: #339933;">=</span><span style="color: #990000;">opendir</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/mnt&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">!==</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> <span style="color: #990000;">readdir</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$dir</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$arr</span><span style="color: #339933;">=</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">!=</span><span style="color: #0000ff;">&quot;.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&amp;&amp;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">!=</span><span style="color: #0000ff;">&quot;..&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$arr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;path&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/mnt/&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$file</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$arr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;free&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #990000;">disk_free_space</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/mnt/&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$arr</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;total&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #990000;">disk_total_space</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/mnt/&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$drives</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #000088;">$arr</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h4>5. Uptime</h4>
<p>В качестве небольшого бонуса получим и продолжительность работы системы с последнего запуска:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$uptime</span><span style="color: #339933;">=</span><span style="color: #990000;">exec</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;uptime&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$uptime</span><span style="color: #339933;">=</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;,&quot;</span><span style="color: #339933;">,</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uptime</span><span style="color: #339933;">,</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$uptime</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;up&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$time</span><span style="color: #339933;">=</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;:&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$uptime</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$uptime</span><span style="color: #339933;">=</span><span style="color: #000088;">$uptime</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$time</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; hours &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$time</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; minutes&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Совсем банальный подход - вызов exec(), и форматирование результата.</p>
<h4>Вывод</h4>
<p>Мы смогли получить всю интересующую нас информацию - о заполненности жестких дисков, о загрузке процессора, о состоянии памяти и свопа и даже о продолжительности работы сервера. Как выводить эту информацию, каждый может придумать сам, в зависимости от требований. Я же поделюсь способом, который использую сам...<br />
Сперва я собираю полученные данные в ассоциативный массив и вывожу его как json:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;cpu&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #000088;">$cpu</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;memory&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #000088;">$memory</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;swap&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #000088;">$swap</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$result</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;uptime&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #000088;">$uptime</span><span style="color: #339933;">;</span>
<span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>На выходе получается следующее:</p>
<pre>
{"uptime":"34 days   5 hours 45 minutes","cpu":1.7361111111111,"memory":{"total":"2052604","free":"191424"},"swap":{"total":"7811064","free":7808332}}
</pre>
<p>И, уже в браузере, я работаю с результатом при помощи jQuery:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> json<span style="color: #339933;">=</span>$<span style="color: #339933;">.</span>parseJSON<span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
$<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;#systemInfo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>html<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;CPU: &quot;</span><span style="color: #339933;">+</span>json<span style="color: #339933;">.</span>cpu<span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;&lt;br /&gt;Memory free &quot;</span><span style="color: #339933;">+</span>json<span style="color: #339933;">.</span>memory<span style="color: #339933;">.</span>free<span style="color: #339933;">+</span><span style="color: #0000ff;">&quot; / &quot;</span><span style="color: #339933;">+</span>json<span style="color: #339933;">.</span>memory<span style="color: #339933;">.</span>total<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Это один из простейших примеров. Более красивый вариант можно посмотреть <a href="http://213.88.8.136/stats" target="_blank">тут</a>.</p>
<p>Вот, собственно, и весь фокус. Если у вас есть дополнения или поправки, оставляйте их в комментариях.</p>
<p>Скачать standalone-вариант страницы статистики можно <a href="http://bit.ly/nT4Exr" title="mystats.7z">здесь</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/10/12/426/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows 8 first impressions</title>
		<link>http://twixed.ru/2011/09/14/423</link>
		<comments>http://twixed.ru/2011/09/14/423#comments</comments>
		<pubDate>Wed, 14 Sep 2011 08:23:01 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[Без рубрики]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=423</guid>
		<description><![CDATA[Скачал, установил в VirtualBox и немного попробовал Windows 8. Вот мои первые впечатления: Несмотря на то, что система лишь на стадии Developers Build, ей вполне можно пользоваться. Правда, как система для десктопа она не подходит - заточена под пальцы. Однако, радует подача информации и продуманность именно пальцеориентированного интерфейса. Несмотря на работу в виртуальной среде, без [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twixed.ru/wp-content/uploads/2011/09/windows-8-a.jpg" rel="lightbox[423]"><img src="http://twixed.ru/wp-content/uploads/2011/09/windows-8-a-150x150.jpg" alt="" title="Windows 8" width="150" height="150" class="alignleft size-thumbnail wp-image-424" /></a><a href="http://msdn.microsoft.com/en-us/windows/apps/br229516">Скачал</a>, установил в <a href="http://www.virtualbox.org/">VirtualBox</a> и немного попробовал Windows 8. Вот мои первые впечатления:<br />
 Несмотря на то, что система лишь на стадии Developers Build, ей вполне можно пользоваться. Правда, как система для десктопа она не подходит - заточена под пальцы. Однако, радует подача информации и продуманность именно пальцеориентированного интерфейса.<br />
Несмотря на работу в виртуальной среде, без необходимых драйверов, и с эмуляцией лишь минимально требуемого железа (1.6 ГГц, 2 ядра, 2 Гб памяти, 16 Гб НЖМД), пользоваться установленными приложениями приятно и удобно.<br />
В плане интерфейса изменения грандиозные! И не только с точки зрения настольной системы, но и с точки зрения системы планшетной. Изучать и привыкать придется ооочень долго. Но от будущего не убежать...<br />
Да... В скором времени после появления ОС на прилавках, начинаем искать китайские поделки под ее управлением. Они, думаю, быстро смекнут, что их будут расхватывать как горячие пирожки...</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/09/14/423/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>С днем программиста!</title>
		<link>http://twixed.ru/2011/09/13/419</link>
		<comments>http://twixed.ru/2011/09/13/419#comments</comments>
		<pubDate>Tue, 13 Sep 2011 07:07:07 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[Без рубрики]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=419</guid>
		<description><![CDATA[Вот и наступил долгожданный 256-й день в этом году. В связи с этим, поздравляю всех сочинителей и чинителей программ с их профессиональным праздником, желаю отсутствия багов и интересных задач. Много не пейте!]]></description>
			<content:encoded><![CDATA[<p><a href="http://twixed.ru/wp-content/uploads/2011/09/4bfa0a04.jpg" rel="lightbox[419]"><img src="http://twixed.ru/wp-content/uploads/2011/09/4bfa0a04-150x150.jpg" alt="" title="4bfa0a04" width="150" height="150" class="alignleft size-thumbnail wp-image-420" /></a>Вот и наступил долгожданный 256-й день в этом году. В связи с этим, поздравляю всех сочинителей и чинителей программ с их профессиональным праздником, желаю отсутствия багов и интересных задач. Много не пейте!</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/09/13/419/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#171;Умная самоклейка&#187; на окна</title>
		<link>http://twixed.ru/2011/09/06/404</link>
		<comments>http://twixed.ru/2011/09/06/404#comments</comments>
		<pubDate>Tue, 06 Sep 2011 12:44:54 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[Без рубрики]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=404</guid>
		<description><![CDATA[Идея, которую я разместил в конкурсе трансформаций от ASUS, родилась в моей голове несколько лет назад, когда я впервые увидел виджеты в KDE. Тогда я подумал, что было бы неплохо выводить полезную информацию на плоскостях, которые не используются - на окнах. Ну, подумал, и забыл. Ничего необычного. Позже, когда стали проскакивать новости о гибких жидкокристаллических [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twixed.ru/wp-content/uploads/2011/09/my_work.jpg" rel="lightbox[404]"><img src="http://twixed.ru/wp-content/uploads/2011/09/my_work-150x150.jpg" alt="" title="my_work" width="150" height="150" class="alignleft size-thumbnail wp-image-405" /></a>Идея, которую я разместил в <a href="http://asustransformer.ru/gallery/137">конкурсе трансформаций от ASUS</a>, родилась в моей голове несколько лет назад, когда я впервые увидел виджеты в KDE. Тогда я подумал, что было бы неплохо выводить полезную информацию на плоскостях, которые не используются - на окнах. Ну, подумал, и забыл. Ничего необычного. Позже, когда стали проскакивать новости о гибких жидкокристаллических экранах, эта идея вновь всплыла, но была отброшена как нерабочая из-за невозможности эти дисплеи найти в продаже, и их, вероятно, огромной стоимости. Сейчас, по прошествии времени, я предполагаю, что технологии вполне позволят сделать за относительно небольшие деньги то, о чем речь пойдет ниже...</p>
<p><span id="more-404"></span></p>
<p><a href="http://twixed.ru/wp-content/uploads/2011/09/my_work2.jpg" rel="lightbox[404]"><img src="http://twixed.ru/wp-content/uploads/2011/09/my_work2-150x150.jpg" alt="" title="my_work2" width="150" height="150" class="alignright size-thumbnail wp-image-411" /></a>Итак, "умная самоклейка" - возможно, не самое удачное название для устройства, которое представляет собой гибкий жидкокристаллический экран с небольшим выносным управляющим блоком. Суть устройства заключается в выводе различной графической и/или текстовой информации на поверхность, на которую эта пленка наклеена. В первую очередь имеются в виду окна, так как пленка не обладает собственным источником света, а на непрозрачных поверхностях видимость картинки будет сильно зависеть от их отражающих возможностей. К тому же вывод информации на окне будет обладать еще и эстетическим свойством, которого трудно добиться на, скажем, двери или стене. Я попробую рассказать чуть подробнее о возможностях и внутреннем устройстве, ведь никакой коммерческой тайны здесь нет (но я потребую денег с тех, кто начнет производить это устройство в промышленных мастшабах, хе-хе).</p>
<p>Как я уже сказал, основной видимый элемент устройства - его экран. Экран гибкий, с клейкой подложкой для удобного нанесения на стекло. Его разрешение зависит от размеров, которые, в свою очередь, зависят от возможностей производства подобных экранов и от стандартов на размеры оконных рам. На экране может отображаться различная информация - RSS/twitter ленты, биржевые сводки и графики, список сообщений электронной почты, сводки погоды, etc. Отображение анимации затруднено скоростью отклика используемых дисплеев, но вывод несложной анимации, без резкой динамики, вполне возможен, и даже не будет неприятным. Также при использовании "умной самоклейки", отпадает необходимость в использовании жалюзи или занавесок, потому что количество поступаемого света можно регулировать контрастностью дисплея.</p>
<p><a href="http://twixed.ru/wp-content/uploads/2011/09/my_work3.jpg" rel="lightbox[404]"><img src="http://twixed.ru/wp-content/uploads/2011/09/my_work3-150x150.jpg" alt="" title="my_work3" width="150" height="150" class="alignleft size-thumbnail wp-image-416" /></a>Второй элемент - небольшой блок управления, соединенный с дисплеем тонким шлейфом, который не составит труда замаскировать под элемент рамы. Блок управления работает под управлением специальной версии Linux, и отвечает за связь с внешним миром посредством WiFi/Ethernet/Bluetooth и вывод изображения на экран. Изображение может генерироваться непосредственно на управляющем блоке, путем сбора необходимых данных через интернет. Одиночный блок может управляться посредством смартфона или компьютера через специальное ПО - настройке поддаются источники информации и размеры и положения областей, в которых эта  информация будет находиться, т.е., в итоге, получаются те же виджеты, которые можно наблюдать в KDE, Windows или Android. Несколько устройств могут быть объединены в одно общее поле вывода, управляемое с единственного ПК, что даст возможность не только выводить несколько "виджетов" на одном окне, но и отображать панорамные изображения на нескольких соседних окнах.</p>
<p>В данный момент мне не удалось найти в интернет аналогичных устройств. К сожалению, мне не удалось также найти и поставщиков гибких монохромных дисплеев необходимого размера. Так что идея эта пока так и остается без воплощения, несмотря на то, что руки давно рвутся добавить функционала окну на кухне. Согласитесь, удобно будет видеть текущие погодные условия за окном, глядя на это окно. Или, например, готовить новое блюдо, посматривая на окно, а не листая замученную кулинарную книгу...<br />
Но, я уверен, в скором времени, когда технологии позволят производить дешевые гибкие дисплеи, устройства, подобные описанному здесь, получат широкое распространения как в крупных фирмах, так и в маленьких магазинчиках и дома.</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/09/06/404/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Интерактивные поля ввода при помощи javascript</title>
		<link>http://twixed.ru/2011/08/10/371</link>
		<comments>http://twixed.ru/2011/08/10/371#comments</comments>
		<pubDate>Wed, 10 Aug 2011 10:49:46 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=371</guid>
		<description><![CDATA[Маленький пост о том, как сделать поля ввода более интересными с точки зрения функциональности. Для примера возьмем номер мобильного телефона. Допустим, на нашем сайте человек должен оставить номер своего мобильника для обратной связи. Использование "голого" input'а чревато внесением в это поле любой текстовой информации - от одной буквы и до строчки из библии. Если мы [...]]]></description>
			<content:encoded><![CDATA[<p>Маленький пост о том, как сделать поля ввода более интересными с точки зрения функциональности.<br />
Для примера возьмем номер мобильного телефона. Допустим, на нашем сайте человек должен оставить номер своего мобильника для обратной связи. Использование "голого" input'а чревато внесением в это поле любой текстовой информации - от одной буквы и до строчки из библии. Если мы просим человека ввести номер своего телефона, то и ожидать в серверном скрипте мы тоже будем номер. Но что делать, если вместо него пользователь введет "Здесь был Вася"? А если номер телефона используется в автоматической обработке, завязанной на номере телефона? Тогда в голову приходит мысль ограничить ввод, подогнав его под некий шаблон, с которым нам дальше будет удобно работать...<span id="more-371"></span></p>
<p>Использовать, конечно же, буду jQuery. В данный момент - версии 1.4.4, но все описанное должно быть работоспособным и на других версиях этой библиотеки.<br />
Для сравнения, два input'а:</p>
<input type="text" name="simple" /> - обычный</p>
<input style="color: #737373;" type="text" name="phone" value="+7xxxxxxxxxx" /> - модифицированный</p>
<p>Преимущества - на лицо. Теперь даже без подписи понятно, что нужно вводить в это поле, и в каком формате. К тому же ввести что-либо, отличающееся от цифр не получится... и "+7" в начале, необходимую нам для дальнейшей обработки, тоже убрать не удастся. Теперь мы с большей степенью уверенности можем предполагать, что в серверный скрипт поступит именно то, что нужно, хотя дополнительных проверок еще никто не отменял.<br />
Как же это сделано? Очень просто - четыре нехитрых обработчика:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>ready<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		$<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;input[name='phone']&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>bind<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;blur&quot;</span><span style="color: #339933;">,</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;+7&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">||</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
					$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>css<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;color&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;#737373&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;+7xxxxxxxxxx&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">.</span>bind<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;focus&quot;</span><span style="color: #339933;">,</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;+7xxxxxxxxxx&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
					$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>css<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;color&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;#000000&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;+7&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>focus<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">.</span>bind<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;mousedown&quot;</span><span style="color: #339933;">,</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;+7xxxxxxxxxx&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
					$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>css<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;color&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;#000000&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;+7&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>focus<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">.</span>bind<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;keyup&quot;</span><span style="color: #339933;">,</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    				$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>replace<span style="color: #009900;">&#40;</span><span style="color: #339933;">/</span><span style="color: #009900;">&#91;</span>^<span style="color: #339933;">+</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">9</span>\<span style="color: #339933;">.</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">/</span>g<span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    			$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">12</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>length<span style="color: #339933;">&lt;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> $<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;+7&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Аналогично можно поступить и с другими полями ввода, например, с полем ввода фамилии:</p>
<input style="color: #737373;" type="text" name="fio" value="Фамилия, имя, отчество" />
<p>Код к этому input'у не будет отличаться от предыдущего:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>ready<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		$<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;input[name='fio']&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>bind<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;blur&quot;</span><span style="color: #339933;">,</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;Фамилия, имя, отчество&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">||</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
					$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>css<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;color&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;#737373&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Фамилия, имя, отчество&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">.</span>bind<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;focus&quot;</span><span style="color: #339933;">,</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">==</span><span style="color: #0000ff;">&quot;Фамилия, имя, отчество&quot;</span><span style="color: #009900;">&#41;</span>
					$<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>css<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;color&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;#000000&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Вообще, можно подключить фантазию и умелку, и напридумывать различных вариаций с проверкой по регулярным выражениям, анимацией и AJAX-подгрузкой элементов страницы или их содержимого.</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/08/10/371/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>чОрный день</title>
		<link>http://twixed.ru/2011/07/21/351</link>
		<comments>http://twixed.ru/2011/07/21/351#comments</comments>
		<pubDate>Thu, 21 Jul 2011 08:29:24 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[*nix]]></category>
		<category><![CDATA[админ]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[epic fail]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=351</guid>
		<description><![CDATA[Сегодня совершенно случайно зашел на сервачок одного из проектов, и увидел в топе, что нагрузка на систему превысила единичку. Первым в списке оказался MySQL, который грузил процессор в потолок. Посмотрев в логах, я обнаружил, что кто-то активно шарится по галерее, заставляя скуль изливать в логи по несколько десятков строк дебажной инфы в секунду. Благо, для [...]]]></description>
			<content:encoded><![CDATA[<p>Сегодня совершенно случайно зашел на сервачок одного из проектов, и увидел в топе, что нагрузка на систему превысила единичку. Первым в списке оказался MySQL, который грузил процессор в потолок. Посмотрев в логах, я обнаружил, что кто-то активно шарится по галерее, заставляя скуль изливать в логи по несколько десятков строк дебажной инфы в секунду. Благо, для ведения собственной статистики, я тупо записываю IP-адрес каждого посетителя,.. так, примитивненько. Но этот простой подход позволил мне сразу же определить "нарушителя спокойствия", не шаманя над логами и списками открытых соединений. Вот whois по IP (95.211.111.81) злодея:<span id="more-351"></span><br />
<code><br />
inetnum:         95.211.105.0 - 95.211.156.255<br />
netname:         LEASEWEB<br />
descr:           LeaseWeb<br />
descr:           P.O. Box 93054<br />
descr:           1090BB AMSTERDAM<br />
descr:           Netherlands<br />
descr:           www.leaseweb.com<br />
remarks:         Please send email to "abuse@leaseweb.com" for complaints<br />
remarks:         regarding portscans, DoS attacks and spam.<br />
country:         NL<br />
admin-c:         LSW1-RIPE<br />
tech-c:          LSW1-RIPE<br />
status:          ASSIGNED PA<br />
mnt-by:          OCOM-MNT<br />
source:          RIPE # Filtered<br />
</code><br />
Проблема решилась просто: <code>iptables -A INPUT -s 95.211.111.81 -j DROP</code></p>
<p>Но в моей голове никак не укладывается одна мысль: кому понадобилось шариться по непопулярному ресурсу с иностранного дедика?<br />
С какой целью? Слить картинки? Уронить сайт? Каким образом могут пригодиться миниатюры любительских фотографий, на которых и силуэты-то с трудом распознаются? Как можно было рассчитывать уронить сайт с одного IP?<br />
Ничего кроме вопросов не осталось. Сервер спокоен, а я неудомеваю...</p>
<p>Но чОрным сегодняшний день я окрестил не из-за этой непонятной ситуации... а из-за того, что <strong>Я, Б*ДЬ, ПОТЁР ИСХОДНИКИ XML-ИНТЕРФЕЙСА ДЛЯ ПРИЛОЖЕНИЯ ПО ЗАКАЗУ ФОТОКНИГ, НАД КОТОРЫМ РАБОТАЛ ПОСЛЕДНИЕ ДВА МЕСЯЦА!</strong> И бэкап, как на зло, настолько старый, что мне придется еще два месяца писать все практически с нуля. Вот это - действительно повод напиться... )8</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/07/21/351/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery плагин Darken slideshow версия 1.1</title>
		<link>http://twixed.ru/2011/07/11/340</link>
		<comments>http://twixed.ru/2011/07/11/340#comments</comments>
		<pubDate>Mon, 11 Jul 2011 08:06:22 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=340</guid>
		<description><![CDATA[Данные обещания надо сдерживать. Именно поэтому я выкладываю новую версию своего плагина, анонсированного здесь. По правде говоря, готов он был еще полгода назад, но из-за общей занятости не было времени довести его до того состояния, в котором не стыдно было бы показать. Но, в конце-концов, все случайные глюки устранены, углы подпилены, и плагин вполне можно [...]]]></description>
			<content:encoded><![CDATA[<p>Данные обещания надо сдерживать. Именно поэтому я выкладываю новую версию своего плагина, анонсированного <a href="http://twixed.ru/2010/09/08/74">здесь</a>. По правде говоря, готов он был еще полгода назад, но из-за общей занятости не было времени довести его до того состояния, в котором не стыдно было бы показать. Но, в конце-концов, все случайные глюки устранены, углы подпилены, и плагин вполне можно использовать. Он, кстати, все эти полгода находится в продакшене, где и удалось выявить некоторые неприятности, и, впоследствии, их устранить. Что же нового есть в этой версии? Об этом ниже...<br />
<span id="more-340"></span><br />
<img src="http://twixed.ru/wp-content/uploads/2011/07/jQuery-Darken-Slideshow-1024x578.png" alt="" title="jQuery Darken Slideshow" width="550" height="310" class="aligncenter size-large wp-image-341" /><br />
Для начала я укажу, что же было исправлено в этой версии:<br />
1. Довольно часто фотографии при загрузке отображались в стороне от центра страницы, порой показывая лишь свой маленький краешек. Совершенно случайно, выяснилось, что виноват был обработчик onLoad изображений, который вызывался до помещения изображения в документ. jQuery не мог определить ширину и высоту фотографии, и "плясал" от центра страницы. Решилось помещением setTimeout с 50-миллисекундной задержкой в этот обработчик.<br />
2. Элементы управления были <del datetime="2011-07-11T07:36:45+00:00">нагло стырены</del> позаимствованы у <a href="http://highslide.com/">Highslide JS</a>. В соответствии с лицензией, указываю ссылки на источник везде, где смогу...</p>
<p>Все! Исправлений больше нет. Дальше перечислю новые фичи...</p>
<p><strong>1. Возможность открывать изображение-источник в новом окне.</strong> Может быть полезно, если просматриваемая фотография действительно огромная, и в окно браузера ну никак не влазит. Для этого введены два новых параметра: fullView - булевый, по умолчанию равен true; imgHref - строковый, URL полноразмерного изображения, по умолчанию равен '%id%'. URL полного изображения специально выделен отдельным параметром, чтобы реализовать бОльшую гибкость.</p>
<p><strong>2. Функция обратного вызова.</strong> Необязательная, но порой очень полезная вещь. Передается вторым параметром конструктора $.darken();</p>
<p><strong>3. Возможность удаления загруженных фотографий из документа.</strong> destroy - этот параметр был введен для того, чтобы слайдшоу можно было использовать на страницах с несколькими наборами фотографий, имена которых могут пересекаться. При использовании этой функции, фотографии, которые были загружены во время просмотра, удаляются из документа вызовом метода .remove(), что освобождает память и позволяет повторно использовать занятые идентификаторы изображений для отображения новых слайдшоу.</p>
<p><strong>4. Отображение подсказок по использованию клавиатуры.</strong> Небольшая подсказка для неочевидной функции плагина. Будет полезно тем, что не догадается самостоятельно проверить работу клавиш при просмотре или не прочитает размещенную на сайте инструкцию.</p>
<p>Скачать и посмотреть пример использования можно на <a href="http://testlab.twixed.ru/darken/">соответствующей странице</a>.<br />
Плагин в деле, как и прежде, можно проверить здесь: <a href="http://www.anteyservis.ru/pages/professionals/">http://www.anteyservis.ru/pages/professionals/</a></p>
<p>Надеюсь, мои наработки будут полезны еще кому-нибудь.</p>
<p>Напоследок коротенькое видео:</p>
<p><iframe width="709" height="422" src="http://www.youtube.com/embed/ncJSNMdlCFY?hl=en&#038;fs=1&#038;fmt=22" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/07/11/340/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Качаем файлы с файловых шар в консоли Ubuntu</title>
		<link>http://twixed.ru/2011/06/28/326</link>
		<comments>http://twixed.ru/2011/06/28/326#comments</comments>
		<pubDate>Tue, 28 Jun 2011 07:00:44 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[depositfiles]]></category>
		<category><![CDATA[megaupload]]></category>
		<category><![CDATA[rapidshare]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=326</guid>
		<description><![CDATA[В качестве вступления: понадобилось мне как-то быстро (читай - разом) скачать несколько частей одного здорового архива, который находился на Rapishare, но, естественно, не имея премиум аккаунта, столкнулся с проблемой 160-минутного ожидания между закачками с одного IP-адреса. Решением стало использование нескольких серверов под управлением Ubuntu Server, к которым у меня есть доступ. Оставалось лишь найти способ [...]]]></description>
			<content:encoded><![CDATA[<p>В качестве вступления: понадобилось мне как-то быстро (читай - разом) скачать несколько частей одного здорового архива, который находился на Rapishare, но, естественно, не имея премиум аккаунта, столкнулся с проблемой 160-минутного ожидания между закачками с одного IP-адреса. Решением стало использование нескольких серверов под управлением Ubuntu Server, к которым у меня есть доступ. Оставалось лишь найти способ качать с этой самой Rapidshare из консоли. Lynx отпадал, потому что страница скачивания изобилует javascript'ами, без отработки которых она будет пустой как голова блондинки. Но, покопавшись в интернетах, я наткнулся на очень полезный проект под названием <strong><a href="http://code.google.com/p/plowshare/">plowshare</a></strong>. Несколько шагов, чтобы установить его на свою машину и использовать:<br />
<span id="more-326"></span><br />
1. Качаем последнюю версию с <a href="http://code.google.com/p/plowshare/downloads/list">сайта</a>:</p>
<p><code>twix@server:~$ <strong>wget http://plowshare.googlecode.com/files/plowshare_1~svn1542-1_all.deb</strong></code></p>
<p>2. Устанавливаем:</p>
<p><code>twix@server:~$ <strong>sudo dpkg -i plowshare_1~svn1542-1_all.deb</strong></code></p>
<p>2a. Во время установки, скорее всего, установщик ругнётся на отсутствие завимостей:</p>
<p><code>Выбор ранее не выбранного пакета plowshare.<br />
(Чтение базы данных... на данный момент установлено 31422 файлов и каталогов.)<br />
Распаковывается пакет plowshare (из файла plowshare_1~svn1542-1_all.deb)...<br />
dpkg: зависимости пакетов не позволяют настроить пакет plowshare:<br />
 plowshare зависит от curl, однако:<br />
  Пакет curl не установлен.<br />
 plowshare зависит от tesseract-ocr-eng, однако:<br />
  Пакет tesseract-ocr-eng не установлен.<br />
 plowshare зависит от spidermonkey-bin | rhino, однако:<br />
  Пакет spidermonkey-bin не установлен.<br />
  Пакет rhino не установлен.<br />
 plowshare зависит от perlmagick, однако:<br />
  Пакет perlmagick не установлен.<br />
dpkg: не удалось обработать параметр plowshare (--install):<br />
 проблемы зависимостей -- оставляем не настроенным<br />
При обработке следующих пакетов произошли ошибки:<br />
 plowshare<br />
</code></p>
<p>Чтобы эту неприятность устранить, попросим его поставить и эти зависимости тоже:</p>
<p><code>twix@server:~$ <strong>sudo apt-get -f install</strong></code></p>
<p>3. После установки нам остается воспользоваться установленной программой - это так же просто, как запустить wget:</p>
<p><code>twix@server:~$ <strong>plowdown http://rapidshare.com/files/228922649/PQSERVICE_AS5930_5730.part3.rar</strong></code></p>
<p>Дальше plowshare скачает запрошенный файл без нашего вмешательства:</p>
<p><code><br />
Waiting 320 seconds... done<br />
File URL: http://rs432l35.rapidshare.com/cgi-bin/rsapi.cgi?sub=download_v1&#038;fileid=228922649&#038;filename=PQSERVICE_AS5930_5730.part3.rar&#038;dlauth=09322B08321E39645695F3B481722D7D0062C95426E0122722BFC88C53E6ED24F786FCA37A3B565501E10011D0E0567A16B6DF8471445AADA4E784F1BFA44FCF1151E1672D66163C38BC43B8C4E7B329C93B6800657F2E7ED27058514490E12074F96DFA8FEDB5C1EF655A557AFE7C0E<br />
Filename: PQSERVICE_AS5930_5730.part3.rar<br />
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current<br />
                                 Dload  Upload   Total   Spent    Left  Speed<br />
100  190M  100  190M    0     0  4464k      0  0:00:43  0:00:43 --:--:-- 5442k<br />
PQSERVICE_AS5930_5730.part3.rar<br />
twix@server:~$<br />
</code></p>
<p>Стоит отметить, что plowshare поддерживает множество файлопомоек: Megaupload, Rapidshare, 2Shared, 4Shared, ZShare, Badongo, Divshare.com, Depositfiles, Netload.in, Sendspace, Usershare, x7.to и другие (какие именно, к сожалению, не указано).</p>
<p>Надеюсь, кому-нибудь эта заметка будет полезна. Себе на память я ее точно оставлю... (:</p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/06/28/326/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Подражание льстит</title>
		<link>http://twixed.ru/2011/06/23/312</link>
		<comments>http://twixed.ru/2011/06/23/312#comments</comments>
		<pubDate>Thu, 23 Jun 2011 06:40:26 +0000</pubDate>
		<dc:creator>twix</dc:creator>
				<category><![CDATA[Без рубрики]]></category>
		<category><![CDATA[улыбнуло]]></category>

		<guid isPermaLink="false">http://twixed.ru/?p=312</guid>
		<description><![CDATA[Сегодня мне сообщили, что у организации, в которой я работаю, появился конкурент в сфере печати фотографий через интернет в нашем регионе. Мне стало интересно, что же он такого предлагает, чего нет у нас, и посетил его сайт. Был несколько удивлен, и, конечно же, польщен одним интересным моментом, о котором - под катом. Он буквально "слизал" [...]]]></description>
			<content:encoded><![CDATA[<p>Сегодня мне сообщили, что у организации, в которой я работаю, появился конкурент в сфере печати фотографий через интернет в нашем регионе. Мне стало интересно, что же он такого предлагает, чего нет у нас, и посетил его сайт. Был несколько удивлен, и, конечно же, польщен одним интересным моментом, о котором - под катом. <span id="more-312"></span></p>
<p>Он буквально "слизал" форму заказа фотографий. Выглядит, она, имхо, бедновато, но можно однозначно определить, на кого равнялся автор. Итак, найдите десять отличий:<br />
<a href="http://twixed.ru/wp-content/uploads/2011/06/anteyservice.png" rel="lightbox[312]"><img class="alignleft size-medium wp-image-313" title="anteyservice" src="http://twixed.ru/wp-content/uploads/2011/06/anteyservice-300x213.png" alt="" width="300" height="213" /></a><a href="http://twixed.ru/wp-content/uploads/2011/06/printluxe.png" rel="lightbox[312]"><img class="alignright size-medium wp-image-314" title="printluxe" src="http://twixed.ru/wp-content/uploads/2011/06/printluxe-300x167.png" alt="" width="300" height="167" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Кратко пробегусь по моментам, которые сразу бросаются в глаза:</p>
<ul>
<li>расположение областей управления, предпросмотра и текущей стадии заказа</li>
<li>расположение элементов управления на миниатюре фотографии</li>
<li>отображение индикатора загрузки</li>
<li>подсчет суммы заказа</li>
<li>групповое изменение</li>
</ul>
<p>Остальное по мелочи...</p>
<p>Видимо, форма делалась наспех, и продолжает "допиливаться", но, в любом случае, расстраивает её "сырость", а именно:</p>
<ul>
<li>убогие стандартные кнопки (вообще, отсутствие нестандартного и эффектного подхода)</li>
<li>"плавающая" верстка</li>
<li>не работающий LightBox для полноразмерного просмотра загруженных фотографий</li>
<li>общая аляповатость и отсутствие дизайна</li>
</ul>
<p>Как бы там ни было, желаю автору скорее привести его детище в человеческий вид и перейти на тариф "пожирнее" (а то уж больно долго фотки грузятся). А я сегодня попью пива за здравие конкуренции и в очередной раз улыбнусь мысли, которая меня греет: меня уже начали копировать!</p>
<p>Ну, и напоследок, без всякой рекламы, чтобы каждый мог сравнить, ссылочки:<br />
<a href="http://www.anteyservis.ru/order/unregistered/">наш проект</a><br />
<a href="http://printluxe.net/zakaz">конкурент</a></p>
]]></content:encoded>
			<wfw:commentRss>http://twixed.ru/2011/06/23/312/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  twixed.ru/feed ) in 1.79838 seconds, on Feb 5th, 2012 at 6:38 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on Feb 5th, 2012 at 7:38 am UTC -->
