PDA

View Full Version : [FIXED][3.0.0 Core] Ext.ux.Carousel



steffenk
21 Jul 2009, 2:50 AM
Ext version tested:

ExtCore 3




Browser versions tested against:

IE8
FF3 (firebug 1.3.0.10 installed)


Operating System:

Win Vista


Description:
The Ext.ux.Carousel produce JS error when setting property showPlayButton to false.
Also missing is the possibility to add images in config (array) and to set own dimensions width/heigh

Complete Code with working changes:



Ext.ns('Ext.ux');

Ext.ux.Carousel = Ext.extend(Ext.util.Observable, {
interval: 3,
transitionDuration: 1,
transitionType: 'carousel',
transitionEasing: 'easeOut',
itemSelector: 'img',
activeSlide: 0,
autoPlay: false,
showPlayButton: false,
pauseOnNavigate: false,
wrap: false,
freezeOnHover: false,
navigationOnHover: false,
hideNavigation: false,
images: [], // expected objects: {src: pathToPicture. title: titleOfPicture}
constructor: function(elId, config) {
config = config || {};
Ext.apply(this, config);

Ext.ux.Carousel.superclass.constructor.call(this, config);

this.addEvents(
'beforeprev',
'prev',
'beforenext',
'next',
'change',
'play',
'pause',
'freeze',
'unfreeze'
);

this.el = Ext.get(elId);
this.slides = this.els = [];

if(this.autoPlay || this.showPlayButton) {
this.wrap = true;
};

if(this.autoPlay && config.showPlayButton === undefined) {
this.showPlayButton = true;
}

this.initMarkup();
this.initEvents();

if(this.carouselSize > 0) {
this.refresh();
}
},

initMarkup: function() {
var dh = Ext.DomHelper;

if (this.images.length) {
for (var i = 0; i < this.images.length; i++) {
dh.append(this.el, {tag: 'img', src: this.images[i].src, title: this.images[i].title});
};
}

this.carouselSize = 0;

this.els.container = dh.append(this.el, {cls: 'ux-carousel-container'}, true);
this.els.slidesWrap = dh.append(this.els.container, {cls: 'ux-carousel-slides-wrap'}, true);

this.els.navigation = dh.append(this.els.container, {cls: 'ux-carousel-nav'}, true).hide();
this.els.caption = dh.append(this.els.navigation, {tag: 'h2', cls: 'ux-carousel-caption'}, true);
this.els.navNext = dh.append(this.els.navigation, {tag: 'a', href: '#', cls: 'ux-carousel-nav-next'}, true);
if(this.showPlayButton) {
this.els.navPlay = dh.append(this.els.navigation, {tag: 'a', href: '#', cls: 'ux-carousel-nav-play'}, true)
}
this.els.navPrev = dh.append(this.els.navigation, {tag: 'a', href: '#', cls: 'ux-carousel-nav-prev'}, true);

// set the dimensions of the container
this.slideWidth = this.width || this.el.getWidth(true);
this.slideHeight = this.height || this.el.getHeight(true);
this.els.container.setStyle({
width: this.slideWidth + 'px',
height: this.slideHeight + 'px'
});

this.els.caption.setWidth((this.slideWidth - (this.els.navNext.getWidth()*2) - (this.showPlayButton ? this.els.navPlay.getWidth() : 0) - 20) + 'px')

this.el.select(this.itemSelector).appendTo(this.els.slidesWrap).each(function(item) {
item = item.wrap({cls: 'ux-carousel-slide'});
this.slides.push(item);
item.setWidth(this.slideWidth + 'px').setHeight(this.slideHeight + 'px');
}, this);


this.carouselSize = this.slides.length;
if(this.navigationOnHover) {
this.els.navigation.setStyle('top', (-1*this.els.navigation.getHeight()) + 'px');
}
this.el.clip();
},

initEvents: function() {
this.els.navPrev.on('click', function(ev) {
ev.preventDefault();
var target = ev.getTarget();
target.blur();
if(Ext.fly(target).hasClass('ux-carousel-nav-disabled')) return;
this.prev();
}, this);

this.els.navNext.on('click', function(ev) {
ev.preventDefault();
var target = ev.getTarget();
target.blur();
if(Ext.fly(target).hasClass('ux-carousel-nav-disabled')) return;
this.next();
}, this);

if(this.showPlayButton) {
this.els.navPlay.on('click', function(ev){
ev.preventDefault();
ev.getTarget().blur();
if(this.playing) {
this.pause();
}
else {
this.play();
}
}, this);
};

if(this.freezeOnHover) {
this.els.container.on('mouseenter', function(){
if(this.playing) {
this.fireEvent('freeze', this.slides[this.activeSlide]);
Ext.TaskMgr.stop(this.playTask);
}
}, this);
this.els.container.on('mouseleave', function(){
if(this.playing) {
this.fireEvent('unfreeze', this.slides[this.activeSlide]);
Ext.TaskMgr.start(this.playTask);
}
}, this, {buffer: (this.interval/2)*1000});
};

if(this.navigationOnHover) {
this.els.container.on('mouseenter', function(){
if(!this.navigationShown) {
this.navigationShown = true;
this.els.navigation.stopFx(false).shift({
y: this.els.container.getY(),
duration: this.transitionDuration
})
}
}, this);

this.els.container.on('mouseleave', function(){
if(this.navigationShown) {
this.navigationShown = false;
this.els.navigation.stopFx(false).shift({
y: this.els.navigation.getHeight() - this.els.container.getY(),
duration: this.transitionDuration
})
}
}, this);
}

if(this.interval && this.autoPlay) {
this.play();
};
},

prev: function() {
if (this.fireEvent('beforeprev') === false) {
return;
}
if(this.pauseOnNavigate) {
this.pause();
}
this.setSlide(this.activeSlide - 1);

this.fireEvent('prev', this.activeSlide);
return this;
},

next: function() {
if(this.fireEvent('beforenext') === false) {
return;
}
if(this.pauseOnNavigate) {
this.pause();
}
this.setSlide(this.activeSlide + 1);

this.fireEvent('next', this.activeSlide);
return this;
},

play: function() {
if(!this.playing) {
this.playTask = this.playTask || {
run: function() {
this.playing = true;
this.setSlide(this.activeSlide+1);
},
interval: this.interval*1000,
scope: this
};

this.playTaskBuffer = this.playTaskBuffer || new Ext.util.DelayedTask(function() {
Ext.TaskMgr.start(this.playTask);
}, this);

this.playTaskBuffer.delay(this.interval*1000);
this.playing = true;
if(this.showPlayButton) {
this.els.navPlay.addClass('ux-carousel-playing');
}
this.fireEvent('play');
}
return this;
},

pause: function() {
if(this.playing) {
Ext.TaskMgr.stop(this.playTask);
this.playTaskBuffer.cancel();
this.playing = false;
if(this.showPlayButton) {
this.els.navPlay.removeClass('ux-carousel-playing');
}
this.fireEvent('pause');
}
return this;
},

clear: function() {
this.els.slidesWrap.update('');
this.slides = [];
this.carouselSize = 0;
this.pause();
return this;
},

add: function(el, refresh) {
var item = Ext.fly(el).appendTo(this.els.slidesWrap).wrap({cls: 'ux-carousel-slide'});
item.setWidth(this.slideWidth + 'px').setHeight(this.slideHeight + 'px');
this.slides.push(item);
if(refresh) {
this.refresh();
}
return this;
},

refresh: function() {
this.carouselSize = this.slides.length;
this.els.slidesWrap.setWidth((this.slideWidth * this.carouselSize) + 'px');
if(this.carouselSize > 0) {
if(!this.hideNavigation) this.els.navigation.show();
this.activeSlide = 0;
this.setSlide(0, true);
}
return this;
},

setSlide: function(index, initial) {
if(!this.wrap && !this.slides[index]) {
return;
}
else if(this.wrap) {
if(index < 0) {
index = this.carouselSize-1;
}
else if(index > this.carouselSize-1) {
index = 0;
}
}
if(!this.slides[index]) {
return;
}

this.els.caption.update(this.slides[index].child(':first-child', true).title || '');
var offset = index * this.slideWidth;
if (!initial) {
switch (this.transitionType) {
case 'fade':
this.slides[index].setOpacity(0);
this.slides[this.activeSlide].stopFx(false).fadeOut({
duration: this.transitionDuration / 2,
callback: function(){
this.els.slidesWrap.setStyle('left', (-1 * offset) + 'px');
this.slides[this.activeSlide].setOpacity(1);
this.slides[index].fadeIn({
duration: this.transitionDuration / 2
});
},
scope: this
})
break;

default:
var xNew = (-1 * offset) + this.els.container.getX();
this.els.slidesWrap.stopFx(false);
this.els.slidesWrap.shift({
duration: this.transitionDuration,
x: xNew,
easing: this.transitionEasing
});
break;
}
}
else {
this.els.slidesWrap.setStyle('left', '0');
}

this.activeSlide = index;
this.updateNav();
this.fireEvent('change', this.slides[index], index);
},

updateNav: function() {
this.els.navPrev.removeClass('ux-carousel-nav-disabled');
this.els.navNext.removeClass('ux-carousel-nav-disabled');
if(!this.wrap) {
if(this.activeSlide === 0) {
this.els.navPrev.addClass('ux-carousel-nav-disabled');
}
if(this.activeSlide === this.carouselSize-1) {
this.els.navNext.addClass('ux-carousel-nav-disabled');
}
}
}
});

steffenk
23 Jul 2009, 2:22 AM
something wrong with the report?

evant
23 Jul 2009, 2:24 AM
No, but it's not high priority at the moment. Also, you'd be better off not trying to slip in functional requirements into a bug report as well, it often just confuses the issue. Just because it doesn't do ~everything~ doesn't mean it's a bug.

steffenk
23 Jul 2009, 2:32 AM
Hi,

thx for the answer. The additions are so small that i didn't thought it's a problem. Also as a normal user i'm not allowed to post feature requests, so i don't know how to do better.

As i marked the changes red you find the real bug changes as the last 2 changes in code.

TommyMaintz
4 Aug 2009, 12:04 PM
I dont want to put an images or addImage functionality in the example since the carousel can be used for any type of html. If you want this type of behavior (because you know they will always be images) I think the best way to go is creating an override like you did already.

This is a very short example of what you could also do to dynamically add images at a later point.


var img = document.createElement('img');
img.src = 'someimage.png';
img.title = 'some title';
carousel.add(img, true); // true to instantly refresh the carousel

// another way would be
carousel.clear() // remove all the current items in carousel
var img = Ext.DomHelper.append(document.body, {tag: 'img', src: 'someimage.png', title: 'some title'});
carousel.add(img);
carousel.refresh();


Using the carousel.clear, carousel.add and carousel.refresh methods you can dynamically add items to the carousel.

I did however added your changes for the 'width' and 'height' configuration options, and fixed the showPlayButton bug in SVN.