четверг, 22 сентября 2011 г.

Зaпоминаем состояние jcarousel с помощью якорей

Решил посвятить пост не TYPO3, а jQuery и довольно известной карусели - jcarousel.

На днях пришлось решать следующую задачку. Есть jcarousel и у нее порядка 10 страниц. С помощью стрелочек "влево" и "вправо" мы гуляем по ней то туда, то сюда. Зашли на страницу - 7. Потом вдруг переходим на другую страницу сайта, после чего опять возвращаемся к странице с каруселью. И что мы имеем в данной ситуации? А имеем:

Первый неприятный момент - карусель показывает нам свою 1-ю страницу, вместо той с которой мы до этого ушли (номер 7). Ну, и мы начинаем пролистывание нашей карусели сначала...

Второй неприятный момент заключается в том, что нельзя отослать кому-то ссылку показывающую 7-ю страницу карусели, т.к. все страницы имееют один и тот же url.

Чтобы избавиться от этих двух недостатков нам нужно как-то запоминать состояние карусели. Сделать это можно с помощью якорей или иначе - хеш-ссылок. Например, http://www.domain.com/page.html#watch1, http://www.domain.com/page.html#watch7 и т.д.

Первое, что нужно сделать, это менять строку адреса браузера при пролистывании карусели. На выручку приходит параметр jcarousel - itemVisibleInCallback (другие параметры мне не подошли, хотя напрашивались, например itemFirstInCallback), который определяет пользовательскую функцию, далее цитирую мануал: "вызываемую (по завершению анимации) когда элемент находится в зоне видимости поля карусели". В данную функцию передается 4 параметра: экземпляр карусели, ссылка на элемент LI этого объекта, индекс, указывающий позицию элемента в списке и состояние карусели (prev, next, init). Итак, готовый кусочек кода выглядит так:

// carouselStart - номер элемента карусели с которого начинается показ
var carouselStart = 3;
var watchPos = -1;
var anchor = ( jQuery.url.attr('anchor') == null ? '' : jQuery.url.attr('anchor') );
watchPos = anchor.indexOf('watch');
if ( watchPos >= 0 ) {
carouselStart = anchor.substring(watchPos+5);
}
if(jQuery.isFunction(jQuery.fn.jcarousel)) {
jQuery('#mycarousel').jcarousel({
easing: 'easeOutQuart',
animation: 900,
scroll: 3,
wrap: 'last',
start: (carouselStart - 2),
itemVisibleInCallback: function (carousel, liElement, itemIndex, action) {
window.location.hash = "watch"+itemIndex;
}
});
}

Поясню кое-что.
1. #mycarousel - id тега UL, который является контейнером элементов карусели - LI;
2. scroll: 3 - у меня на одной странице карусели отображается 3 её элемента;
3. start: (carouselStart - 2) - номер элемента карусели с которого начинается показ
4. itemVisibleInCallback - определяет функцию которая меняет адресную сроку браузера. Самый ценный параметр, который поступает на вход этой функции - itemIndex. Т.к. у меня на каждой странице карусели отображается по 3 её элемента, то при нажатии на кнопку Next itemIndex принимает следующие значения: 3, 6, 9... и т.д.
Так, мы запоминаем состояние карусели.

Для того, чтобы карусель начала показ с нужного места, используется переменная - carouselStart. Значение этой переменной берется из адресной строки браузера.

Ну вот, собственно и все. Надеюсь кому-то помог и сэкономил время.

P.S. Рабочий вариант карусели можно посмотреть здесь.

12 коммент.:

Ergo комментирует...

Вроде то что искал, но есть вот такой вопросик, смотрите сам сайт допустим будет запоминать положение карусели, а вот как с поисковиками дело обстоит, допустим в карусели на 5 странице есть искомая ссылка, гуглю я её, нахожу, захожу на сайт, а тут бах и 1 страница карусели, примерно вот так всё и происходит, ваше решение поможет в моей проблеме?

Вадим Гиркало комментирует...

Если в инете где-то разместить ссылку типа http://www.domain.com/page.html#7, то поисковики проиндексируют ее как отдельную страницу, которую можно выслать другу, например. По такой такую ссылке они отправят вас куда следует ;). Но сами поисковики конечно же не будут автоматически разбивать страницы карусели на #1, #2,... #n и индексировать их по-отдельности. Поэтому и отправят вас на первую страницу.

erp14 комментирует...

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


$(document).ready(function () {

function mycarousel_initCallback(carousel) {
$('#featured-item-next').bind('click', function () {
carousel.next();
return false;
});
$('#featured-item-prev').bind('click', function () {
carousel.prev();
return false;
});




};



$('#featured_content').jcarousel({
vertical: false,
visible: 1,
scroll: 1,
auto: 0, // Sets the time delay between automatic scrolling of the panel

initCallback: mycarousel_initCallback,

// This tells jCarousel NOT to autobuild prev/next buttons
buttonNextHTML: null,
buttonPrevHTML: null
});

});

Вадим Гиркало комментирует...

Дайте лучше ссылку, чтобы посмотреть все в живую.

erp14 комментирует...

http://www.isuzu-russia.ru/index.php?id=43

Вадим Гиркало комментирует...

Для начала познакомьтесь с мануалом для разработчика по jКарусели: http://jquerylist.ru/navigation/jcarousel.html
Там вы найдете, что аналогично вашей строке:
initCallback: mycarousel_initCallback
карусели можно задать еще один параметр - itemVisibleInCallback о котором я и пишу. Вот с этой штукой и играйтесь. Вам будет немного проще т.к. ваша карусель показывает только один товар за один клик. Если все-таки не будет получаться - пишите.

erp14 комментирует...

разобрался как поменять адресную строку браузера, а вот как запомнить положение карусели нет или ругается на Cannot call method 'attr' , или съезжает вся карусель... вот рабочий вариант с заменой браузерной строки...

$(document).ready(function () {

function mycarousel_itemVisibleInCallback(carousel, liElement, itemIndex, action) {

window.location.hash = "shema"+itemIndex;

$('#featured-item-next').bind('click', function () {
carousel.next();
return false;
});
$('#featured-item-prev').bind('click', function () {
carousel.prev();
return false;
});

};


$('#featured_content').jcarousel({
vertical: false,
visible: 1,
scroll: 1,
auto: 0, // Sets the time delay between automatic scrolling of the panel

itemVisibleInCallback: mycarousel_itemVisibleInCallback,

// This tells jCarousel NOT to autobuild prev/next buttons
buttonNextHTML: null,
buttonPrevHTML: null
});

});

Вадим Гиркало комментирует...

Молодец, пол-дела ты уже сделал. Теперь нужно сделать обработку якоря при загрузке страницы. У меня этот кусочек выглядит так:
var carouselStart = 3;
var watchPos = -1;
var anchor = ( jQuery.url.attr('anchor') == null ? '' : jQuery.url.attr('anchor') );
watchPos = anchor.indexOf('watch');
if ( watchPos >= 0 ) {
carouselStart = anchor.substring(watchPos+5);
}
но тебе нужно его изменить. Примерно так:
var carouselStart = 1;
var watchPos = -1;
var anchor = ( jQuery.url.attr('anchor') == null ? '' : jQuery.url.attr('anchor') );
watchPos = anchor.indexOf('shema');
if ( watchPos >= 0 ) {
carouselStart = anchor.substring(watchPos+5);
}

Идея какая, нужно узнать число стоящее за словом shema и установить соответствующее значение для атрибута start карусели (start: carouselStart)

Успехов!

erp14 комментирует...

Вот уже какой день как говориться толи лыжи не едут толи .... заменил всё как вы посоветовали... в результате имею Cannot call method 'attr'... толи я не туда или неправильно вставляю ваш код и у меня не обрабатывается хеш при старте скрипта... всю голову уже изломал, честное слово)

Вадим Гиркало комментирует...

Да, что-то затянулась у тебя эпопея с каруселью... Посмотрел я на твои jquery скрипты и ни хрена не пойму. Там ведь бардак полный. То стоит - var j = jQuery.noConflict(), а в скрипте юзается то jQuery, то $. То потом появляется строка с jQuery.noConflict(). Приведи для начала все к "общему знаменателю". Добейся того, чтобы консоль ошибок в ФФ не выдавала никаких сообщений.

erp14 комментирует...

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

var anchor = (jQuery.url.attr('anchor') == null ? '' : jQuery.url.attr('anchor') );

или скрипт я криво по вашему примеру сделал или просто еще не могу въехать...

вот что на данный момент у меня:

var carouselStart = 1;
var watchPos = -1;
var anchor = (jQuery.url.attr('anchor') == null ? '' : jQuery.url.attr('anchor') );
watchPos = anchor.indexOf('shema');
if ( watchPos >= 0 ) {
carouselStart = anchor.substring(watchPos+5);
}


$('#featured-item-next').bind('click', function () {
carousel.next();
return false;
});
$('#featured-item-prev').bind('click', function () {
carousel.prev();
return false;
});


if(jQuery.isFunction(jQuery.fn.jcarousel)) {
jQuery('#featured_content').jcarousel({
easing: 'easeOutQuart',
vertical: false,
start: (carouselStart - 2),
visible: 1,
wrap: 'last',
scroll: 1,
auto: 0, // Sets the time delay between automatic scrolling of the panel

itemVisibleInCallback: function (carousel, liElement, itemIndex, action) {
window.location.hash = "shema"+itemIndex;
}

});
}

Вадим Гиркало комментирует...

Подгрузи еще библиотечку https://github.com/allmarkedup/jQuery-URL-Parser

Отправить комментарий

О себе

Моя фотография
Вадим Гиркало
Фрилансер, веб-разработчик сайтов на базе бесплатной, мощнейшей и очень гибкой CMS системы - TYPO3.
Просмотреть профиль

Позвонить мне в Skype

TOP - 3