пятница, 6 декабря 2013 г.

RegExp tutorial


четверг, 5 декабря 2013 г.

Модули в JavaScript



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

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

 Давайте рассмотрим наиболее яркие решения этой проблемы...

пятница, 22 февраля 2013 г.

Jcrop + Twitter Bootstrap js фиксим баг.


Twitter Bootstrap 2.3: Crop Area Continues Moving After Selection



Споймал такой же баг https://github.com/tapmodo/Jcrop/issues/79 (описание на англ)

При выделении области для кропа, она бегает за указателем мыши. В консоли ошибка "Uncaught RangeError: Maximum call stack size exceeded" jcrop.
Оказывается лечится просто:
В Jcrop в функции https://github.com/tapmodo/Jcrop/blob/master/js/jquery.Jcrop.js#L1153

строку: $(document).unbind('.jcrop');
заменим на
все заработало ) 

вторник, 12 февраля 2013 г.

Шаблонизация в js

http://embeddedjs.com/


Предыстория


Я занимаюсь разработкой IFrame приложений для социальной сети ВКонтакте. Самый удобный способ навигации по приложению — это динамическая подгрузка данных, без перезагрузки всей страницы. Раньше я генерил html код который нужно отобразить на сервере, пока не встретил EJS — JavaScript Templates…

EJS — Embedded JavaScript


EJS оказался одним из самых удобных и подходящих мне шаблонизаторов. Он работает, как с одиночными переменными, так и с массивами (читай объектами), присутствует логика (if...else...).

Покажу на примере, что может данный шаблонизатор.

Шаблон — /templates/question.ejs:
<div>
  <% if(question) { %>
   <h2><%= author %>: <%= question %></h2>
   <div><textarea name="answer" id="answer"></textarea></div>
   <ul class="nNav btnList">
     <li>
      <a href="" onclick="ACT.question.answer('index'); return false;">Ответить</a>
     </li>
   </ul>
  <% } else { %>
   <h2>Нет вопросов, на которые можно ответить!</h2>
  <% } %>
</div>

* This source code was highlighted with Source Code Highlighter.


Данные — /data/question.php:
{"id":"98","question":"What are you doing now?","author":"Mihalich88"}

* This source code was highlighted with Source Code Highlighter.


Результат:
$.ajax({
  type: "POST",
  url: "/data/question.php",
  dataType: "json",
  data: data,
  success: function(ans){
   var html = new EJS({url: ' /templates/question.ejs'}).render(ans);
  }
});


* This source code was highlighted with Source Code Highlighter.


В итоге


+ «плюсы»
  1. Экономия траффика, т.к. передаются только данные ввиде json-объекта, шаблон кэшируется и берется из кэша
  2. Снижение нагрузки на сервер, т.к. шаблонизация происходит в браузере
  3. MVC структура, с выводом «V» за пределы сервера
  4. Работает даже на Opera Mobile 10

— «минусы»
  1. Не индексируется, но зато идеально подходит для RIA

Пример приложения, использующего EJS: http://formspring.vk-app.ru
Подводный камень: шаблонизатор работает только с файлами у которых расширение *.ejs. Хотел, чтобы шаблоны имели расширение *.tpl, но не получилось — виснит на рендеринге… Возможно, если поковырять, то все заработет.

четверг, 3 мая 2012 г.

Resize image


function resize($upload_data, $w, $h, $path)
{
$config['source_image'] = $upload_data['full_path'];
$config['maintain_ratio'] = TRUE;
$config['new_image'] = $path;
$config['width'] = $w;
$config['height'] = $h;

if ($upload_data['image_width']/$w < $upload_data['image_height']/$h)
$config['height'] = round($upload_data['image_height']*$w/$upload_data['image_width']);
else
$config['width'] = round($upload_data['image_width']*$h/$upload_data['image_height']);

$this->image_lib->initialize($config);

if ( ! $this->image_lib->resize())
{
   $this->data['error'] .= $this->image_lib->display_errors();
echo $this->data['error']; die();
}
else
{
$config['source_image'] = $config['new_image'];
$config['maintain_ratio'] = FALSE;
if ($config['width'] > $config['height'])
$config['x_axis'] = round(($config['width']-$w)/2);
else
$config['y_axis'] = round(($config['height']-$h)/2);

$config['width'] = $w;
$config['height'] = $h;
$this->image_lib->initialize($config);

$this->image_lib->crop();

}
}

EXAMPLE OF USE


function save_photo ($upload_data, $i, $id)
{

$path_to_image_directory = './uploads/items/'.$id;

$path = $path_to_image_directory.'/';
$path_th = $path_to_image_directory.'/thumb/';


$path_to_orig_image = $path.$i.'_orig.jpg';

if (!file_exists($path_to_orig_image))
copy($upload_data['full_path'], $path_to_orig_image);

if ($upload_data['image_width'] < 639 || $upload_data['image_height'] < 426)
{
$this->data['error'] .= 'Small image(img' . $i . ')';
$this->data['err_upl_img'][$i] = 'Small image(img' . $i . ')';
}

if ($upload_data['image_width'] < 639 && $upload_data['image_height'] < 426)
{
copy($upload_data['full_path'], $path.$i.'.jpg');
}
else
{
$this->resize($upload_data, 639, 426, $path.$i.'.jpg');
}

$this->resize($upload_data, 40, 40, $path_th.$i.'.jpg');

if($i == 0)
$this->resize($upload_data, 134, 89, $path_th.$i.'_main.jpg');

unlink (  $upload_data['full_path'] );  //-> copy and rename

return true;
}


среда, 21 марта 2012 г.

jQuery File Upload

Ура! Еще один, свеженький… чем он лучше других? Дока


а) Новенький! Всегда кто берется что-то делать, то обычно смотрит, есть ли смысл, и если есть — делает это.
б) Красивенький! Можно не точить, а ставить из коробки. Основан на Bootstrap'е и иконках Glyphicons
в) Само собой мультиселект файлов, Drag&drop, Прогрессбар и превьюшки фотографий.
г) Поддержка кросдоменного соединения, докачка и ресайз фоток на стороне клиента.
д) Готов для любой платформы сервера (PHP, Python, Ruby on Rails, Java, Node.js, и тому подобное.)

blueimp.github.com/jQuery-File-Upload/

Поддержка браузеров:

github.com/blueimp/jQuery-File-Upload/wiki/Browser-support

Apache-Ubuntu-VirtualBox Виртуальный web сервер в Windows


В этой статье я расскажу о том:  как настроить «виртуальную локальную сеть» (ВЛС) с помощью программы VirtualBox, создать «виртуальный компьютер» (ВК), установить на нем ОС UBUNTU с web-сервером Apache.
В качестве основы для создания данной конфигурации, подойдет любой более-менее современный компьютер, с установленной на нем ОС семейства Windows. Точно подойдут XP, Vista, Win7 (подойдет и Linux т.к. VirtualBox «мульти-платформенный», будут только отличаться настройки «взаимодействия сетей»).

вторник, 20 марта 2012 г.

Ждем загрузку картинок Jquery - waitForImages


Usage

Standard

Just provide a callback function and it will be called once all descendent images have loaded.
$('selector').waitForImages(function() {

    alert('All images are loaded.');
    $(this).slideUp();
});
this is a reference to the element that waitForImages() is called on.

Advanced

You can pass a second function as a callback that will be called for each image that is loaded, with some information passed as arguments.
$('selector').waitForImages(function() {

    alert('All images have loaded.');

}, function(loaded, count, success) {

   alert(loaded + ' of ' + count + ' images has ' + (success ? 'loaded' : 'failed to load') +  '.');
   $(this).addClass('loaded');

});
You can also set the third argument to true if you'd like the plugin to iterate over all elements, checking for images referenced in the CSS (by default, it looks at the background-imagelistStyleImageborderImage and borderCornerImage properties). If it finds any, they will be treated as an image and loaded.
The callback will be called on the successful and unsuccessful loading of the image. Check the third argument to determine the success of the image load. It will be true if the image loaded successfully.
Alternatively, you can pass an object literal to the plugin, instead of the arguments individually.
$('selector').waitForImages({
    finished: function() {
        ...
    },
    each: function() {
       ...
    },
    waitForAll: true
});
You may also set the CSS properties that possibly contain image references yourself. Just assign an array of properties to the plugin.
$.waitForImages.hasImgProperties = ['backgroundImage'];
waitForImages also exposes a custom selector, :uncached, which when used in conjunction with the img selector, allows you to select img elements that are not cached already by the browser.
$('img:uncached').attr('title', 'Loading Image');


https://github.com/alexanderdickson/waitForImages 

среда, 14 марта 2012 г.

Директива RewriteRule .htaccess


Директива RewriteRule и есть настоящая рабочая лошадка преобразований. Эта директива может встречаться более одного раза. Каждая директива, в этом случае, определяет одно правило преобразования. Порядок определений этих правил важен, потому что этот порядок используется при обработке правил во время работы.
Шаблон это perl совместимое регулярное выражение которое применяется к текущему URL. Здесь под "текущим" подразумевается значение URL когда применяется это правило. Этот URL не обязательно совпадает с первоначально запрошенным URL, потому что любое количество правил возможно уже были применены к нему и соответственно преобразовали его.

Определяет правила для механизма преобразований 


http://htmlweb.ru/php/htaccess-mod_rewrite-rewriterule.php