3 * Copyright(c) 2006-2010 Ext JS, Inc.
5 * http://www.extjs.com/license
9 Ext.ux.Carousel = Ext.extend(Ext.util.Observable, {
11 transitionDuration: 1,
12 transitionType: 'carousel',
13 transitionEasing: 'easeOut',
17 showPlayButton: false,
18 pauseOnNavigate: false,
21 navigationOnHover: false,
22 hideNavigation: false,
26 constructor: function(elId, config) {
27 config = config || {};
28 Ext.apply(this, config);
30 Ext.ux.Carousel.superclass.constructor.call(this, config);
44 this.el = Ext.get(elId);
45 this.slides = this.els = [];
47 if(this.autoPlay || this.showPlayButton) {
51 if(this.autoPlay && typeof config.showPlayButton === 'undefined') {
52 this.showPlayButton = true;
58 if(this.carouselSize > 0) {
63 initMarkup: function() {
64 var dh = Ext.DomHelper;
66 this.carouselSize = 0;
67 var items = this.el.select(this.itemSelector);
68 this.els.container = dh.append(this.el, {cls: 'ux-carousel-container'}, true);
69 this.els.slidesWrap = dh.append(this.els.container, {cls: 'ux-carousel-slides-wrap'}, true);
71 this.els.navigation = dh.append(this.els.container, {cls: 'ux-carousel-nav'}, true).hide();
72 this.els.caption = dh.append(this.els.navigation, {tag: 'h2', cls: 'ux-carousel-caption'}, true);
73 this.els.navNext = dh.append(this.els.navigation, {tag: 'a', href: '#', cls: 'ux-carousel-nav-next'}, true);
74 if(this.showPlayButton) {
75 this.els.navPlay = dh.append(this.els.navigation, {tag: 'a', href: '#', cls: 'ux-carousel-nav-play'}, true)
77 this.els.navPrev = dh.append(this.els.navigation, {tag: 'a', href: '#', cls: 'ux-carousel-nav-prev'}, true);
79 // set the dimensions of the container
80 this.slideWidth = this.width || this.el.getWidth(true);
81 this.slideHeight = this.height || this.el.getHeight(true);
82 this.els.container.setStyle({
83 width: this.slideWidth + 'px',
84 height: this.slideHeight + 'px'
87 this.els.caption.setWidth((this.slideWidth - (this.els.navNext.getWidth()*2) - (this.showPlayButton ? this.els.navPlay.getWidth() : 0) - 20) + 'px')
89 items.appendTo(this.els.slidesWrap).each(function(item) {
90 item = item.wrap({cls: 'ux-carousel-slide'});
91 this.slides.push(item);
92 item.setWidth(this.slideWidth + 'px').setHeight(this.slideHeight + 'px');
94 this.carouselSize = this.slides.length;
95 if(this.navigationOnHover) {
96 this.els.navigation.setStyle('top', (-1*this.els.navigation.getHeight()) + 'px');
101 initEvents: function() {
102 this.els.navPrev.on('click', function(ev) {
104 var target = ev.getTarget();
106 if(Ext.fly(target).hasClass('ux-carousel-nav-disabled')) return;
110 this.els.navNext.on('click', function(ev) {
112 var target = ev.getTarget();
114 if(Ext.fly(target).hasClass('ux-carousel-nav-disabled')) return;
118 if(this.showPlayButton) {
119 this.els.navPlay.on('click', function(ev){
121 ev.getTarget().blur();
131 if(this.freezeOnHover) {
132 this.els.container.on('mouseenter', function(){
134 this.fireEvent('freeze', this.slides[this.activeSlide]);
135 Ext.TaskMgr.stop(this.playTask);
138 this.els.container.on('mouseleave', function(){
140 this.fireEvent('unfreeze', this.slides[this.activeSlide]);
141 Ext.TaskMgr.start(this.playTask);
143 }, this, {buffer: (this.interval/2)*1000});
146 if(this.navigationOnHover) {
147 this.els.container.on('mouseenter', function(){
148 if(!this.navigationShown) {
149 this.navigationShown = true;
150 this.els.navigation.stopFx(false).shift({
151 y: this.els.container.getY(),
152 duration: this.transitionDuration
157 this.els.container.on('mouseleave', function(){
158 if(this.navigationShown) {
159 this.navigationShown = false;
160 this.els.navigation.stopFx(false).shift({
161 y: this.els.navigation.getHeight() - this.els.container.getY(),
162 duration: this.transitionDuration
168 if(this.interval && this.autoPlay) {
174 if (this.fireEvent('beforeprev') === false) {
177 if(this.pauseOnNavigate) {
180 this.setSlide(this.activeSlide - 1);
182 this.fireEvent('prev', this.activeSlide);
187 if(this.fireEvent('beforenext') === false) {
190 if(this.pauseOnNavigate) {
193 this.setSlide(this.activeSlide + 1);
195 this.fireEvent('next', this.activeSlide);
201 this.playTask = this.playTask || {
204 this.setSlide(this.activeSlide+1);
206 interval: this.interval*1000,
210 this.playTaskBuffer = this.playTaskBuffer || new Ext.util.DelayedTask(function() {
211 Ext.TaskMgr.start(this.playTask);
214 this.playTaskBuffer.delay(this.interval*1000);
216 if(this.showPlayButton) {
217 this.els.navPlay.addClass('ux-carousel-playing');
219 this.fireEvent('play');
226 Ext.TaskMgr.stop(this.playTask);
227 this.playTaskBuffer.cancel();
228 this.playing = false;
229 if(this.showPlayButton) {
230 this.els.navPlay.removeClass('ux-carousel-playing');
232 this.fireEvent('pause');
238 this.els.slidesWrap.update('');
240 this.carouselSize = 0;
245 add: function(el, refresh) {
246 var item = Ext.fly(el).appendTo(this.els.slidesWrap).wrap({cls: 'ux-carousel-slide'});
247 item.setWidth(this.slideWidth + 'px').setHeight(this.slideHeight + 'px');
248 this.slides.push(item);
255 refresh: function() {
256 this.carouselSize = this.slides.length;
257 this.els.slidesWrap.setWidth((this.slideWidth * this.carouselSize) + 'px');
258 if(this.carouselSize > 0) {
259 if(!this.hideNavigation) this.els.navigation.show();
260 this.activeSlide = 0;
261 this.setSlide(0, true);
266 setSlide: function(index, initial) {
267 if(!this.wrap && !this.slides[index]) {
272 index = this.carouselSize-1;
274 else if(index > this.carouselSize-1) {
278 if(!this.slides[index]) {
282 this.els.caption.update(this.slides[index].child(':first-child', true).title || '');
283 var offset = index * this.slideWidth;
285 switch (this.transitionType) {
287 this.slides[index].setOpacity(0);
288 this.slides[this.activeSlide].stopFx(false).fadeOut({
289 duration: this.transitionDuration / 2,
290 callback: function(){
291 this.els.slidesWrap.setStyle('left', (-1 * offset) + 'px');
292 this.slides[this.activeSlide].setOpacity(1);
293 this.slides[index].fadeIn({
294 duration: this.transitionDuration / 2
302 var xNew = (-1 * offset) + this.els.container.getX();
303 this.els.slidesWrap.stopFx(false);
304 this.els.slidesWrap.shift({
305 duration: this.transitionDuration,
307 easing: this.transitionEasing
313 this.els.slidesWrap.setStyle('left', '0');
316 this.activeSlide = index;
318 this.fireEvent('change', this.slides[index], index);
321 updateNav: function() {
322 this.els.navPrev.removeClass('ux-carousel-nav-disabled');
323 this.els.navNext.removeClass('ux-carousel-nav-disabled');
325 if(this.activeSlide === 0) {
326 this.els.navPrev.addClass('ux-carousel-nav-disabled');
328 if(this.activeSlide === this.carouselSize-1) {
329 this.els.navNext.addClass('ux-carousel-nav-disabled');