То, как вы звоните Carousel.init
, в init
функция this
всегда будет Carousel
, то есть есть только один.Вот почему вы видите, что он применяется только к последнему.
Я бы посмотрел на переработку Carousel
, чтобы она была функцией конструктора (та, которую вы используете с new
),@Boo только что бросил new
перед Carousel.init
, что является хорошим началом, но создаваемый объект не будет иметь различных свойств, которые вы наделили Carousel
.
Вотбыстрая переделка;оно полностью не проверено, но должно привести вас в правильном направлении:
// Scoping function so our various member functions can have proper names
var Carousel = (function() {
// The constructor function
function Carousel() {
// Assign vars:
var self = this; // Important for the event handler closures
this.container = container;
this.card_container = this.container.find('.card-cont');
this.cards = this.container.find('div.card');
this.card_width = this.container.width();
this.no_cards = this.cards.length;
this.direction = $(this.container).attr('data-direction');
// Size the container:
this.card_container.width((this.card_width * this.no_cards))
// Add an indicator:
this.indicator = $('<ul class="card-indicator" />');
this.indicator.items = [ ];
if(this.direction == 'v') { this.indicator.addClass('vertical'); }
for(var i = 0; i < this.no_cards; i++)
{
$(this.cards[i]).width(this.card_width);
var indicator_item = $('<li />');
indicator_item.click(function() { self.setCard($(this).index()); });
this.indicator.append(indicator_item);
this.indicator.items.push(indicator_item);
}
this.indicator.appendTo(this.container);
// Position the indicator:
if(this.direction == 'h')
{
var indicator_top_pos = ((this.container.offset().top + this.container.height()) - this.indicator.height());
var indicator_left_pos = (this.container.width() - this.indicator.width()) / 2;
this.indicator.css({ top: indicator_top_pos, left: indicator_left_pos });
}
else
{
var indicator_top_pos = (this.container.height() - this.indicator.height()) / 2;
var indicator_left_pos = (this.container.offset().left + this.container.width()) - 20;
this.indicator.css({ top: indicator_top_pos, left: indicator_left_pos });
}
// Add the current styles to everything:
$(this.cards[0]).addClass('current');
this.indicator.items[0].addClass('current');
// Hook up the drag events:
var mouse_start_x = 0;
var mouse_end_x = 0;
var mouse_start_y = 0;
var mouse_end_y = 0;
var direction_x = null;
var direction_y = null;
var next_index = 0;
this.container.mousedown(function(e) {
mouse_start_x = e.pageX;
mouse_start_y = e.pageY;
});
this.container.mouseup(function(e) {
mouse_end_x = e.pageX;
mouse_end_y = e.pageY;
alert(self.container.attr('id'));
if(mouse_end_x > mouse_start_x) { direction_x = 'right'; }
if(mouse_end_x < mouse_start_x) { direction_x = 'left'; }
if(mouse_end_y > mouse_start_y) { direction_y = 'down'; }
if(mouse_end_y < mouse_start_y) { direction_y = 'up'; }
switch(self.direction)
{
case 'v':
if(direction_y == 'down') { next_index = (self.current_card == 0) ? 0 : self.current_card - 1; }
if(direction_y == 'up') { next_index = (self.current_card == (self.no_cards - 1)) ? self.current_card : self.current_card + 1; }
break;
case 'h':
default:
if(direction_x == 'right') { next_index = (self.current_card == (self.no_cards - 1)) ? self.current_card : self.current_card + 1; }
if(direction_x == 'left') { next_index = (self.current_card == 0) ? 0 : self.current_card - 1; }
break;
}
self.setCard(next_index);
});
// No need to return `this`, that's what constructor functions do by default
}
// Our various member functions, we'll assign them to the prototype below
// Function to check if we're on the last card:
function Carousel$onLastCard() {
return (this.current_card == (this.indicator.items.length - 1)) ? true : false;
}
// Function to check if we're on the first card:
function Carousel$onFirstCard() {
return (this.current_card == 0) ? true : false;
}
function Carousel$setCard(index) {
// If the index matches the current one, don't do anything:
if(index == this.current_card)
{
return;
}
else
{
// Calculate the left position we need to move:
var new_left_pos = this.card_width * index;
this.card_container.css({ left: -new_left_pos });
this.indicator.items[this.current_card].removeClass('current');
this.indicator.items[index].addClass('current');
this.current_card = index;
return true;
}
}
// Fill in the prototype that will be assigned to all objects created
// via `new Carousel`:
Carousel.prototype.onLastCard = Carousel$onLastCard;
Carousel.prototype.onFirstCard = Carousel$onFirstCard;
Carousel.prototype.setCard = Carousel$setCard;
// Return our constructor out of the scoping function to be assigned
// to the public var
return Carousel;
})();
А затем используйте:
$(function(){
$('.carousel').each(function() { new Carousel($(this)); });
});
Опять же, вышеизложенное не означает, что оно идеально, сделано ипосыпанный.Он должен продемонстрировать, как вы переформулируете Carousel
как функцию-конструктор и настраиваете функции на ее прототипе, чтобы они были назначены экземплярам, созданным с помощью new Carousel
.Там будет некоторая отладка требуется.Я рад видеть, что вы уже решаете проблему this
в обработчиках событий (через вашу переменную self
в том, что раньше было init
и теперь является функцией Carousel
).
Возможно, полезное чтение:
- Anonymouses anonymous - объясняет, почему я использовал вышеописанную функцию scoping и реальные именованные функции
- Простые, эффективные Supercalls в JavaScript - обсуждение создания функций конструктора (я назвал их "классами", но я действительно не должен был, я хотел обновить статью) и некоторые утилиты для созданияэто проще, а также включает иерархии, если они вам нужны