вторник, 12 июля 2011 г.

jQuery, CSS. Как отключить выделение мышкой текста для отдельного блока

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

Решений тут два: используем jQuery либо CSS.

jQuery:
$(".classname").attr('unselectable','on').css('MozUserSelect','none');

CSS:
.classname{
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -o-user-select: none;
  user-select: none;
}
Учитывая пожелания высказанные в комментариях, привожу пример яваскриптового отключения выделения (организованного в плагин), с явным отключением самого ивента 'onselectstart', а также содержащий весь уже выше перечисленный функционал:
jQuery.fn.extend({ 
    disableSelection : function() { 
            this.each(function() { 
                    this.onselectstart = function() { return false; }; 
                    this.unselectable = "on"; 
                    jQuery(this).css({
                      '-moz-user-select': 'none',
                      '-khtml-user-select': 'none',
                      '-webkit-user-select': 'none',
                      '-o-user-select': 'none',
                      'user-select': 'none'
                    });

            }); 
    },
    enableSelection : function() { 
            this.each(function() { 
                    this.onselectstart = function() {}; 
                    this.unselectable = "off";
                    jQuery(this).css({
                      '-moz-user-select': 'auto',
                      '-khtml-user-select': 'auto',
                      '-webkit-user-select': 'auto',
                      '-o-user-select': 'auto',
                      'user-select': 'auto'
                    });
            }); 
    } 
});

// Example:
var selector = "td, span, div";
$(selector).disableSelection(); // disable
....
$(selector).enableSelection(); // enable

среда, 29 июня 2011 г.

Yii. Настройка логирования SQL запросов

В этой статье я расскажу как можно вывести в дебаг SQL которые генерит фреймворк Yii.

Все изменения будут производится в главном конфиге,  который находиться тут: /protected/config/main.php
Найдем в нем строчку
'components' => array(
Наша основная задача - настроить компонент логирования и компонет работы с БД, укажем параметры компоненту log и допишем параметры компоненту db:
'components' => array(
   'db' => array(
      ..., 
      'enableProfiling' => true,
      'enableParamLogging' => true
    ),
    'log' => array(
      'class' => 'CLogRouter',
      'routes' => array(
         'db' => array(
         'class' => 'CWebLogRoute',
         'categories' => 'system.db.CDbCommand',
         'showInFireBug' => true //Показывать в FireBug или внизу каждой страницы
       )
    ),
    ...
)
Теперь в любом месте кода, например в каком-то контроллере нужно указать какой блок кода профилировать. В следующем примере выведутся те запросы которые генерит фреймворк для кода замкнутого в блок профилирования:
   Yii::beginProfile('blockId');
   $users = Users::model()->findAll("id>2");
   Yii::endProfile('blockId');

пятница, 10 июня 2011 г.

jQuery. Как найти и удалить класс по паттерну

Постановка задачи: есть элемент страницы у которого есть много классов, необходимо удалить из этого списка классы которые попадают под определенный шаблон. Необходимо удалить те имена классов которые содержать суффикс "-find".

some content

Я предлагаю два способа решения задачи: первый способ заключается в том, чтобы получить массив классов, пройти по нему последовательно сравнивая элементы с заданным шаблоном, второй способ заключается в том, чтобы сразу искать совпадения классов шаблонов по строке (если к тегу применяется несколько классов, то они разделяются пробелами)

Пример 1:
$.fn.removeClassesByPattern = function(pattern) {
   var el = $(this);
   var items = [];
   var re = new RegExp(pattern);            
   $.each(el.attr('class').split(/\s+/), function(index, item){
     if(re.test(item)){
       items.push(item);
     }
   });
   el.removeClass(items.join(' '));
   return el;
}

Использование:
$("#div1").removeClassesByPattern(/-find/);

Пример 2
$.fn.removeClassesByPattern2 = function(pattern) {
  var el = $(this);
  el.removeClass(function (index, _class) {
    var matches = _class.match (pattern) || [];                
    return (matches.join(' '));
  });
  return el;
}

Использование:
$("#div1").removeClassesByPattern2(/\s?(\w+-find)/);

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

Какой способ использовать - зависит от поставленной задачи.

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



вторник, 19 апреля 2011 г.

PHP. Как узнать количество страниц в PDF файле

Нашел интересный пример, как узнать количество страниц в документе PDF, достаточно применить регулярное выражение:
$pdf_content = file_get_contents($pdf_filename);
$count = preg_match_all("/\/Page\W/", $pdf_content, $matches);
echo "Count: {$count}";

Где $pdf_filename - путь к файлу

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

Гораздо правильнее поискать в файле параметр где указано количество страниц, а не самим подсчитывать:
$f = fopen($pdf_filename, "r");
while(!feof($f)) {
  $line = fgets($f,255);
  if (preg_match('/\/Count [0-9]+/', $line, $matches)){
    preg_match('/[0-9]+/',$matches[0], $matches2);
    if ($count<$matches2[0]) $count=$matches2[0]; 
  } 
}
fclose($f);
echo "Count: {$count}";

Считываем файл построчно и анализируем пока не найдем искомое

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

PHP. Создать multi-page PDF на основне набора SVG файлов

Появилась интересная задача: как на основе SVG файла создать PDF. SVG файл должен содержать картинки с подписями и  background  (создаваться может в сторонней программе).

Путем проб и ошибок выяснил: ImageMagic еще не умеет обрабатывать картинки при конвертации   SVG, если они задаются относительным путем или ссылкой. 

Выбор пал на Inscape - открытый редактор векторной графики. Кроме графической оболочки он предоставляет для работы консоль с набором команд (что собственно и требовалось). Кроме того, он полностью кросс-платформенный.

Устанавливаем его, если под Winndows то прописываем в Path путь к приложению.

Теперь из PHP можно юзать следующим образом:

$filename = "svg_dir/test.svg"; //path to SVG file
$pdf_filename="pdf_dir/test.pdf"; // output PDF

if(!file_exists($filename)){
  throw new Exception("{$filename} not exists!");
}

system("inkscape -T $filename -A $pdf_filename",$success);
if($success!=0){
  throw new Exception('Error inkscape convertation!');
}

На Хабре предлагают не создавать PDF c помощью Inkscape, так как они большого размера и предлагают сначала конвертировать в PostScript формат, а потом использовать утилиту  ps2pdf из пакета GhostScript для генерации непосредственно PDF. Размер такого файла действительно намного меньше чем прямая генерация PDF. Но у меня в задачи было условие создать много страничный PDF (inkscape и ps2pdf этого не умеют как оказалось).

Потому я поступил проще: с помощью Inkscape я генерю отдельные PDF файлы, например с именами page1.pdf, page2.pdf, ...., pageN.pdf.

Дальше я скачал утилиту pdftk,  которая умеет генрить мульти-страничные PDF и многое другое. Более детально по этому вопросу смотрим тут.

Пример использования:

pdftk pdf1.pdf pdf2.pdf ... pdfn.pdf cat output multipage.pdf

или по маске:

pdftk *.pdf cat output multipage.pdf

для вызова из PHP нужно вызывать в контексте system("pdftk....")


Если необходимо, то теперь можем с помощью pdf2ps и  ps2pdf  утилит (пакет GhostScript) оптимизировать получившийся PDF (оптимизация ухудшает качество, и как по мне, может только для предварительного просмотра использоваться или для особых задач- когда клиент получает высокое разрешение картинки только за отдельную плату).

Пример очень прост (незабываем, команды в ПХП прогоняем через оператор system или exec):

pdf2ps multipage.pdf multipage.ps
ps2pdf multipage.ps multipage.pdf

суббота, 16 апреля 2011 г.

PHP. Как получить список установленных расширений (extensions)

Для того чтобы получить список установленных extensions для php, существует отдельная функция: get_loaded_extensions(). Она возвращает массив, в котором присутствует список установленых расширений.

Пример:
$list = get_loaded_extensions();
print_r($list);

Ответ:
Array
(
  [0] => Core
  [1] => bcmath
  [2] => calendar
  [3] => com_dotnet
  [4] => ctype
  [5] => date
  ....
)

Еще пример:
if(!in_array("gd", $list)){
  echo "GD extension not installed!";
}

Установка ImageMagic под Windows

Заходим сюда: http://www.imagemagick.org/script/binary-releases.php#windows, качаем бинарник и ставим