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

Убийца Яндекс.Маркета =)

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

На сайте пока представлены только телевизоры, пульты, антенны, приставки и кронштейны (причём в смехотворном количестве). Основная идея проекта состоит в простом фильтре товаров и отсутствии лишнего функционала — только телевизионная тематика. При этом информация о видеотехнике там порой более подробная, точная, честная и полезная для потребителя, чем на крупных ресурсах (т. к. собирается вручную).

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




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

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

вторник, 5 августа 2014 г.

Новая программа для торговли

Все слышали о таких гигантах как 1С. Однако существует множество альтернативных программных продуктов для автоматизации в сфере розничной торговли. Причём их количество только растёт. Недавно появилась ещё одна программа для магазинов — nonzenon.

Данное программное обеспечение выделяется из ряда аналогов тем, что оно изначально реализовано в виде веб-сервиса. Т. е. по принципу работы nonzenon похож, например, на почту mail.ru. Продавцы заходят в аккаунты соответствующих магазинов через Интернет и работают в них: продают товары, печатают документы и ценники, просматривают архивы продаж, составляют отчёты и т. д. Также предусмотрены специальные аккаунты для администраторов (работа с поставщиками, складами и т. п.) и владельца магазинов.

Торговая система nonzenon относительно проста, однако требует понимания некоторых аспектов. Поэтому разработчики включили в неё подробную справку по работе со складами, магазинами, товарами, заявками, отчётами и т. д. Помимо этого, на YouTube есть цикл обучающих роликов по использованию торгового ПО.


Кстати, торговая программа не требует установки на рабочие места. Для её работы нужен только браузер и Интернет.


вторник, 22 апреля 2014 г.

Обновление сайта Веста-мебель

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

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

Из шапки был удалён огромный диван. Его место заняло главное меню и бесплатный просчёт мебели (новая возможность). Также вверху появились иконки групп в социальных сетях. Каталог мебель был оформлен более интуитивно. При этом его структура совсем не изменилась.



На гаваной странице появился блок с актуальными предложениями, скидками на мебель и т. п. Были добавлены карты магазинов Веста-мебель. Администраторы сайта получили большую свободу при редактировании. Они теперь могут добавлять не только страницы с мебелью, но и любые другие текстовые страницы с фотографиями и видео.

Будем надеяться, что подобное обновление сайта происходит не в последний раз.

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

Сайт калужской художницы

Вышел в свет сайт художницы Ольги Калининой. Ольга занимается проведением песочных шоу, рисованием светом и водяными картинами (турецким мраморироанием). В дальнейшем она планирует расширение своей художественной деятельности, что будет отражено и на сайте.


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

Сайт об искусственном камне

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

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


понедельник, 1 июля 2013 г.

Поиск недвижимости

Ничего принципиально нового в поиске недвижимости наша компания не придумала. Просто мы решили сделать поиск недвижимости с более простым и функциональным интерфейсом. Возможно, получилось.

RussianDom


понедельник, 22 апреля 2013 г.

Открываем веб-студию la mask

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

Наша специализация — сайты для малого и среднего бизнеса. Мы создаём только уникальный дизайн (никогда не использовали шаблоны), но ставим на первое место удобство использования, а не обманчивый внешний вид. Большинство сайтов создаётся на CMS нашей собственной разработки, что позволяет нам легко добавлять необходимые функции. Оставшаяся часть сайтов разрабатывается с нуля. Это происходит, когда необходимо реализовать функции, выходящие за рамки архитектуры используемой системы управления контентом.

В la mask отдают приоритет современным стандартам. Мы отлично понимаем, что одно дело — создать сайт, и совсем другое — донести его до целевой аудитории. Поэтому базовые SEO-мероприятия выполняются даже для самых маленьких проектов (причём бесплатно).



Я бы мог и дальше описывать — какие мы белые и пушистые, но никто всё-равно не поверит )

воскресенье, 26 июня 2011 г.

Личные сообщения на сайте — неудачная реализация

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


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

Список тем:


Диалог:


Данный вариант гораздо удобнее: темы легко найти, диалог сразу просматривается, экономится много места на экране личных сообщений. Единственный минус — немного более сложная реализация.

четверг, 2 июня 2011 г.

CKEditor — изменение размера редактора

CKEditor — весьма удобный WYSIWYG-редактор (хотя довольно «тяжёлый»), который очень просто подключается к собственному сайту. Задать размер редактора можно в файле config.js следующим образом:

CKEDITOR.editorConfig = function(config)
{
   config.width = '100%';
   config.height = '200px';
}

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

Решение есть. Задать размеры редактору можно прямо при подключении:




Кстати, таким образом можно задать не только размер CKEditor, но и любые другие параметры.

среда, 18 мая 2011 г.

Студия праздника «Paradise» — свадьбы в Калуге, организация праздников

Создал ещё один сайт. На этот раз коммерческий. Сайт создавался для компании по организации свадеб и праздников «Paradise» (работает в Калуге). Конечно, тёмный дизайн весьма спорен для свадеб и праздников, однако заказчик его отстоял. С другой стороны в этом что-то есть.


P. S. Извиняюсь за некоторую поспешность — сайт ещё не заполнен контентом и на треть.

понедельник, 21 февраля 2011 г.

Скорость популярных сайтов

Недавно я решил измерить производительность страниц нескольких крупных сайтов с помощью популярных инструментов Google Page Speed и Yahoo YSlow. Результаты тестов получились довольно интересными:

Page Speed YSlow
Сайт Производительность Сайт Производительность
Яндекс 96% Яндекс 90%
Google 95% YouTube 81%
YouTube 86% Википедия 77%
Lenta.ru 86% Lenta.ru 77%
Википедия 77% Google 71%
КиноПоиск.ru 72% КиноПоиск.ru 67%
RuTube 72% RuTube 66%

Конечно, эти цифры не совсем корректно отображают реальную производительность, но ориентироваться на них можно. Кстати, мой сайт выдаёт 99% в Page Speed и 91% в YSlow. Только не нужно думать, что он лучше Яндекс, Google и т.д. Такая высокая производительность - следствие его простоты (и оптимизации, естественно).

вторник, 4 января 2011 г.

Блог не про программирование

Недавно я создал блог — Сайт о полезном и интересном, не связанный с программированием. Там я просто размещаю интересные и полезные заметки.

среда, 29 декабря 2010 г.

Очистка input file

Для загрузки файла на сервер, обычно, используют <input type="file">. Это удобный и проверенный способ, но в нём есть одна проблема - очистка этого поля от выбранного файла. Её нужно делать, если загрузка не обязательна. Т.е. у пользователя должна быть возможность отменить загрузку выбранного им файла.

Обычная очистка значения на <input type="file"> никак не повлияет, поэтому придётся прибегнуть к разным хитростям. В большинстве статей на эту тему предлагается следующее решение:

<form id="fMain" method="post" enctype="multipart/form-data" action="myAction.php">
   <div id="dFile">
      <input type="file">
      <input type="button" value="Очистить" onclick="ClearFile('dFile');" />
   </div>
</form>

function ClearFile(idFileContainer)
{
   var container = document.getElemetnById(idFileContainer);
   //Разметка элементов перезаписывается и текущее значение исчезает
   container.innerHTML = container.innerHTML;
}

Такой подход выполняет поставленную задачу. Однако он обладает одной очень неприятной особенностью. Если пользователь очистит файловое поле, а потом опять выберет файл, то этот файл не отправится на сервер (точную причину такого поведения я не знаю). Это очень серьёзная ошибка в логике работы файлового поля, поэтому я предлагаю менее красивый, но правильно работающий способ:

<form id="fMain" method="post" enctype="multipart/form-data" action="myAction.php">
   <input type="file">
   <input type="button" value="Очистить" onclick="ClearFile('fMain');" />
</form>

function ClearFile(idForm)
{
   var form = document.getElementById(idForm);
   //Массив значений всех элементов формы 
   var values = new Array(form.elements.length);

   //Запись значений всех элементов формы 
   for (var i = 0; i < form.elements.length; i++) 
   {
      values[i] = form.elements.item(i).value;
   }
   

   form.reset(); //Сброс значений всех элементов формы 

   //Восстановление значений всех элементов формы, кроме input file 
   for (var i = 0; i < form.elements.length; i++)
   {
      //Здесь сравнивается тип, т.к. используется один input file
      //Если элементов input file больше, то нужно использовать id
      if(form.elements.item(i).type != 'file')
      {
         form.elements.item(i).value = values[i];
      }
   }
}

Приходится сбрасывать все значения в форме, т.к. сброс значения для отдельного элемента не предусмотрен. Способ громоздкий и текст в форме один раз мигает при перезаписи значений. Зато вышеописанная проблема исчезает. Если у кого-то есть идея получше, то пишите о ней в комментариях обязательно.

воскресенье, 12 декабря 2010 г.

Показ анимации во время выполнения AJAX-запроса

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

В этом примере роль анимации будет исполнять gif-изображение. Если нет возможности создать gif-анимацию самостоятельно, то её можно скачать. Например, с preloaders.net. Для показа анимации нужно создать какой-нибудь элемент рядом с элементом, к которому относится выполняемый запрос:

<table>
   <tr>
      <td><input type="button" value="Отправить"></td>
      <td id="myAnimation" height="16" width="16"></td><!--Элемент для показа анимации-->
   </tr>
</table>

Показ и скрытие анимации в функции, отправляющей запрос:

function MyFunction()
{
   //Анимацию нужно показать перед отправкой запроса
   var tdAnimation = document.getElementById('myAnimation');
   tdAnimation.style.background = 'url(load.gif)';

   if(request.readyState == 4 || request.readyState == 0)
   {
      request.open("GET", "script.php", true);
      request.onreadystatechange = function()
      {
         if(request.readyState == 4)
         {
            if(request.status == 200)
            {
               //Обработка данных 
               //...

               //Скрывать анимацию нужно только после выполнения запроса
               tdAnimation.style.background = null;
            }
         }
      };
      request.send(null);
   }
   else
   {
      setTimeout('MyFunction()', 500);
   }
}

Всё очень просто. Главное показывать и скрывать анимацию в нужное время.

Оформление ссылок в виде кнопок

Если на сайте есть ссылка, то лучше всего (особенно для поисковых систем) сделать её, используя тег <a>. Однако это не всегда уместно с точки зрения оформления. Например, меню, чаще всего, оформляют в виде прямоугольных блоков (кнопок), в которых можно кликнуть не только на текст, но и на сам блок. Кроме того эти блоки, обычно, подсвечиваются при наведении на них указателя мыши.

Есть множество способов создать подобное оформление, но большая их часть довольно неудобна в реализации. В последнее время я стал пользоваться самым простым и эффективным, на мой взгляд, решением - оформлением тега <a> в виде блока через CSS. В файл со стилями добавляем следующий класс:

.menu
{
   display: block; /*Даёт возможность назначать размеры элементу*/
   width: 100px;
   padding: 4px;
   margin-bottom: 2px;
  
   border: 1px solid #000;
   background: #DDD;
   color: #000;
   text-decoration: none;
}

.menu:hover /*Для подсветки при наведении мыши*/
{
   background: #EEE; 
}

Применяем это к ссылкам:

<a class="menu" href="http://www.google.ru">Google</a>
<a class="menu" href="http://www.yandex.ru">Яндекс</a>  

Результат:

GoogleЯндекс
Описанный способ не даёт полной свободы в оформлении (хотя CSS 3 в этом поможет), но это, возможно, единственный его недостаток. Преимущества данного способа:

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

- Отлично (одинаково) работает во всех современных браузерах.

- Максимально прост в использовании.

- Очень удобно вносить изменения в оформление.

- Можно не использовать изображения.

суббота, 4 декабря 2010 г.

Подключение файлов в PHP

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

require - включает текст из файла в скрипт до его выполнения.

require_once - работает так же, как require, и проверяет - не подключается ли этот файл повторно. Повторное подключение может вызвать ошибку.

include - включает текст из файла в скрипт во время его выполнения.

include_once - работает так же, как include, и проверяет - не подключается ли этот файл повторно. Повторное подключение может вызвать ошибку.

Чаще всего (случаи статического подключения файлов), нужно использовать require_once. Например, когда подключается шапка или подвал сайта, скрипт соединения с базой данных, файл с дополнительными функциями и т.п. Использование require_once даёт защиту от ошибок при повторном подключении файла, свободу выбора места вызова в коде (т.к. подключение происходит до выполнения скрипта) и некоторый выигрыш в производительности.

Использовать include и include_once следует в тех случаях, когда использование require и require_once невозможно. Например, если путь подключения файла находится посредством выполнения скрипа (динамическое подключение файлов), а не задаётся в тексте напрямую.

Уменьшение изображения в PHP

Многие начинающие PHP-разработчики задаются вопросом - как уменьшить изображение, переданное пользователем? Это очень просто, поэтому приведённая ниже функция будет не только пропорционально уменьшать изображение, но и обрезать края, выходящие за рамки заданного соотношения сторон. Также будет сохранён альфа-канал (прозрачность) изображения, если он в нём присутствовал.

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

//$image - исходное изображение, созданное функцией imagecreatefrompng или подобными
//$width - ширина уменьшенного изображения
//$height - высота уменьшенного изображения
function GetResampledImage($image, $width, $height)
{
   //Сохраняем длину и ширину исходного изображения
   $widthOriginal = imagesx($image);
   $heightOriginal = imagesy($image);

   //Объявляем переменные для размеров пропорционально сжатого изображения (без обрезки)
   //Изначально приравниваем их к размерам уменьшенного изображения
   $widthSampled = $width ;
   $heightSampled = $height;

   //Вычисляем коэффициенты соотношения сторон уменьшенного и исходного изображений
   $aspect = $height / (float)$width;
   $aspectOriginal = $heightOriginal / (float)$widthOriginal;

   //Вычисляем соотношение коэффициентов
   $aspectAspect = $aspect / $aspectOriginal;

   //Объявляем переменные для смещения изображения (нужно для обрезки)
   $dX = 0;
   $dY = 0;

   //Вычисляем размеры пропорционально сжатого изображения (без обрезки) и смещение изображения
   if($aspectAspect > 1)
   {
      $widthSampled *= $aspectAspect;
      $dX = ($widthSampled - $width) / 2;
   }
   else
   {
      $heightSampled /= $aspectAspect;
      $dY = ($heightSampled - $height) / 2;
   }


   //Создаём прозрачное изображение для вывода уменьшенного изображения
   $imageResult = imagecreatetruecolor($width, $height);
   imagesavealpha($imageResult, true);
   imagefill($imageResult, 0, 0, imagecolorallocatealpha($imageResult, 0, 0, 0, 127));
  
   //Создаём прозрачное изображение для хранения пропорционально сжатого изображения
   $imageSampled = imagecreatetruecolor($widthSampled, $heightSampled);
   imagesavealpha($imageSampled, true);
   imagefill($imageSampled, 0, 0, imagecolorallocatealpha($imageSampled, 0, 0, 0, 127));

   //Пропорционально сжимаем исходное изображение
   imagecopyresampled($imageSampled, $image, 0, 0, 0, 0, $widthSampled, $heightSampled, $widthOriginal, $heightOriginal);

   //Обрезаем пропорционально сжатое изображение 
   imagecopy($imageResult, $imageSampled, 0, 0, $dX, $dY, $widthSampled, $heightSampled);

   return $imageResult;
}

Полученное изображение можно сохранить с помощью функции imagepng() или подобных ей.

пятница, 12 ноября 2010 г.

Что-то с датой в JavaScript

Недавно столкнулся с одной особенностью JavaScript, а точнее класса Date. Во всех известных мне языках программирования (и других языках) 01-01-2000 - это первое января двухтысячного года. В JavaScript - это первое февраля двухтысячного года.

Чтобы получить первое января нужно создавать объект Date так: new Date(2000, 0, 1). Соответственно от остальных месяцев тоже нужно отнять единицу, т.к. в конструкторе класса Date они нумеруются с 0 по 11.

суббота, 6 ноября 2010 г.

Осторожно, динамическая типизация JavaScript

Недавно возникла такая проблема - все браузеры, кроме Internet Explorer (чудеса случаются), получая параметра от элемента, считали этот параметр строкой, а не числом. Это происходило примерно в следующей ситуации:

for (var i = 0; i < objects.length; i++) //objects - строки таблицы, например
{
   objects[i].setAttribute('i', i); //i сейчас точно является числом
}

...

for (var i = 0; i < objects.length; i++) //objects - те же строки таблицы
{
   value[i] = objects[i].getAttribute('i') + 1; //что окажется в value[i]?
}

Internet Explorer в value[i] запишет 1, 2, 3 и т.д. Другие браузеры запишут туда 01, 11, 21 и т.д. Вроде, результат очевиден: к выражению содержащему только цифры прибавляется число в явном виде - должно получиться число. Однако это понимает только Internet Explorer.

Если возникнет подобный случай, сразу используйте функцию parseInt(objects[i].getAttribute('i')).

пятница, 5 ноября 2010 г.

Забавные комментарии в коде

//Mr. Compiler, please do not read this.

last = first; /* Biblical reference */

long long ago; /* in a galaxy far far away */

//Comment this later

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

$this->getSelect()->where('main_table.product_id = -1');//Mom, Dad... sorry

/* Logger */
private Logger logger = Logger.getLogger();
  
Комментарии взяты с сайта www.remobred.ru.
Мои записи и на Я.ру — levelost!