Fixed fancybox
31.10.2009 JmanИз-за того что мне нехватает времени написать свою галерею, пользуюсь в последнее время Fancybox, для тех кто не знаком — плагин jQuery для фотогалереи, очередной клон lightbox. Как у всего в этом мире есть приемущества и есть недостатки.
Основные приемущества — это конечно же настройки. Не надо передавать в скрипт никаких картинок, как в lightbox. Большая часть оформления через css. Приведу основные настройки.
- padding
- Позволяет задать отступ от картинки, по дефолту стоит 10px, нужно менять если меняете стили отображения рамочки
- imageScale (true/false)
- машатабировать изображение чтоб поместилось в окно или нет
- zoomOpacity (true/false)
- Анимировать прозрачность всплвыющего блока при анимации или нет
- zoomSpeedIn, zoomSpeedOut, zoomSpeedChange
- Скорость анимации в милисикундах (если 0 анимации нет) при открытии, закрытии и переключении картинки
- easingIn, easingOut, easingChange
- Управление плавностью, и ефектами анимации (нужен плагин jquery.easing)
- frameWidth, frameHeight
- ширина и высота фрейма (если открываем флеш, iframe, html)
- overlayShow (true/false)
- отображать подложку (по умолчанию не отображается)
- overlayOpacity (от 0 до 1)
- Прозрачность подложки
- hideOnContentClick (true/false)
- Прятать FancyBox, при клике на откртый блок
- centerOnScroll (true/false)
- Центровать картинку при скроле окна
- itemArray ([массив])
- Задать свой массив элементов
- callbackOnStart, callbackOnShow, callbackOnClose
- Вызов произвольной callback-функции по определённому событию — при старте , при отображениии, и при закрытии
Последнее особенно полезная настройка.
Но и проблем у него придостаточно, даже как для неискушённого пользователя-разработчика. Я укажу те что я смог исправить.
- первое попроще, но и столкнутся проще — неправильно отображается рамка если задан отступ через настройку padding
- при завершении работы fancybox, скрипт снимает обработчики событий scroll resize keydown
Кусок кода в котором заключается первая проблема
if (pad > 0) {
width += pad * 2;
height += pad * 2;
$("#fancy_content").css({
'top' : pad + 'px',
'right' : pad + 'px',
'bottom' : pad + 'px',
'left' : pad + 'px',
'width' : 'auto',
'height' : 'auto'
});
if (isIE) {
$("#fancy_content")[0].style.setExpression('height', '(this.parentNode.clientHeight - 20)');
$("#fancy_content")[0].style.setExpression('width', '(this.parentNode.clientWidth - 20)');
}
} else {
$("#fancy_content").css({
'top' : 0,
'right' : 0,
'bottom' : 0,
'left' : 0,
'width' : '100%',
'height' : '100%'
});
}
Тут долго разбиратся и ненадо, если установлен padding то заполяем css атриуты 'top', 'right', 'bottom', 'left' значением отступа (padding), ширину и высоту ставим auto, такое значение MSIE6 не любит, поэтом для него отдельное правило, в котором и заключена ошибка.
По умолчанию padding = 10, в блоке для ие выставляется высота и ширина равная высоте и ширине родительского блока минус отсуп умноженный на 2, тоесть 20. Блин а если мы задали свой padding то пофиг получается
. Исравляется легко, заменяем код для MSIE
if (isIE) {
$("#fancy_content")[0].style.setExpression('height', '(this.parentNode.clientHeight - ' + pad * 2 + ')');
$("#fancy_content")[0].style.setExpression('width', '(this.parentNode.clientWidth - ' + pad * 2 + ')');
}
Вторая проблема возникла из-за способа которым автор устанавливает и удаляет обработчик событий. Просто и ненавящиво
//установил событие
$(window).bind("resize scroll", $.fn.fancybox.scrollBox);
//снял событие
$(window).unbind("resize scroll");
Очень мило со сторны скрипта, разбиндить resize и scroll которые которые назначены на окно. Удаляются все обработчики, и те что назначены фансибоксом и те что назначены другими плагинами или в ручную. Для того чтобы добится совместимости с скриптами правильней было бы сделать вот так
//установил событие
$(window).bind("resize scroll", $.fn.fancybox.scrollBox);
//снял событие
$(window).unbind("resize scroll", $.fn.fancybox.scrollBox);
Благо есть обработчик = хендлер. Но есть ещё одна проблема с обработкой события — обработка нажатия клавиш клавиатуры.
$(document).keydown(function(e) {
if (e.keyCode == 27) {
$.fn.fancybox.close();
$(document).unbind("keydown");
} else if(e.keyCode == 37 && opts.itemCurrent != 0) {
opts.itemCurrent--;
_change_item();
$(document).unbind("keydown");
} else if(e.keyCode == 39 && opts.itemCurrent != (opts.itemArray.length - 1)) {
opts.itemCurrent++;
_change_item();
$(document).unbind("keydown");
}
});
После каждого нажатия клавиши вызывается анониманая функция, в которой определяется какая клавиша была нажата и если это ESC, кусор влево или курсор вправо выполняет определённую функцию и удаляет обработчик события нажатия кнопки, и как свегда если у нас стоит свой обработчик на кнопки они удаляются тоже.
Есть два пути решения это й проблемы.
Переписать назначение обработчика, чтоб исключить аононимную функцию и использовать хендлер.
$(document).keydown(keyHandler(event));
function keyHandler(e){
if (e.keyCode == 27) {
$.fn.fancybox.close();
$(document).unbind("keydown", keyHandler);
} else if(e.keyCode == 37 && opts.itemCurrent != 0) {
opts.itemCurrent--;
_change_item();
$(document).unbind("keydown", keyHandler);
} else if(e.keyCode == 39 && opts.itemCurrent != (opts.itemArray.length - 1)) {
opts.itemCurrent++;
_change_item();
$(document).unbind("keydown", keyHandler);
}
}
И второй способ, который выбрал я (незнаю какой лучше) использует одну фичу в jQuery событиях - неймспейсы, вуаля:
$(document).bind("keydown.fancybox", function(e) {
if (e.keyCode == 27) {
$.fn.fancybox.close();
$(document).unbind("keydown.fancybox");
} else if(e.keyCode == 37 && opts.itemCurrent != 0) {
opts.itemCurrent--;
_change_item();
$(document).unbind("keydown.fancybox");
} else if(e.keyCode == 39 && opts.itemCurrent != (opts.itemArray.length - 1)) {
opts.itemCurrent++;
_change_item();
$(document).unbind("keydown.fancybox");
}
});
намного лучше fancybox не стал, но глобальные баги пофиксены. Свою версию выкладывать пока не буду, так как в том скрипте есть ещё много допилов под конкретный проект. Кому надо, тот может скачать с сайта автора, и внести нужные правки. Вполне возможно, что автор уже и сам всё исправил, так как я писал о найденных багах, и путях устранения в гугл-группу поддержки
Сайт проекта jQuery
Сайт проекта fancybox



01.11.2009 в 09:07
Из всех аналогичных скриптов понравился тоже fancybox и еще один, сейчас не могу найти название… где-то в закладках есть, там очень красиво перелистывались фотографии.
01.11.2009 в 18:04
2alexpts
Неплохой скрипт — prettyPhoto. Но у него тоже куча проблем:
1. плохо скролится
2. непонятный алгоритм ресайза. (немного углублясь в код я понял что многие цыфры берутся с потолка).
01.11.2009 в 19:07
prettyPhoto стоит на моем блоге alexpts.ru и my-wordpress.ru. Работает, но fancyBox симпотичнее, переделывать лень просто.
03.07.2010 в 17:03
Здравствуйте
У меня проблема такого рода. Всплывающие окно прячется под верхнее меню. Как сделать чтоб окно было поверх меню, а не под ним? Вот пример http://dominat-ua.com//images/pmm.jpg