1. #1
    Sencha - Services Team arthurakay's Avatar
    Join Date
    Sep 2008
    Location
    Antioch, IL
    Posts
    1,375
    Vote Rating
    37
    Answers
    61
    arthurakay is a jewel in the rough arthurakay is a jewel in the rough arthurakay is a jewel in the rough arthurakay is a jewel in the rough

      0  

    Default Unanswered: Carousel - load images not in DOM

    Unanswered: Carousel - load images not in DOM


    I've been trying to search the forum for an answer to this question, but I haven't found anything that solves my issue.

    The Carousel example gets the images for its slideshow from existing DOM markup. If I understand things correctly, the DOM must physically load all the images on page load rather than only loading the images on demand. Obviously this can be a problem is (a) you have a lot of images, and/or (b) the sizes of the image files are large.

    It would be ideal if the Carousel had deferred loading of its images. Has anyone been able to extend the Carousel to load images from an array (passed as a config option)?

    Something like:
    PHP Code:
    new Ext.ux.Carousel('html-example', {
        
    //itemSelector: 'div.item',
        
    images: [
        { 
    url'myImg1.jpg' },
        { 
    url'myImg2.jpg' },
        { 
    url'myImg3.jpg' }
        ],
        
    interval5,
        
    autoPlaytrue,
        
    transitionEasing'easeIn'
    }); 
    I've seen this jQuery example which accomplishes this idea (and then some).

    Another added benefit would be that you could add images after rendering with more ease.
    Arthur Kay
    Developer Relations Manager, Sencha Inc.

    Twitter | Sencha Chicago User Group

  2. #2
    Sencha User steffenk's Avatar
    Join Date
    Jul 2007
    Location
    Haan, Germany
    Posts
    2,664
    Vote Rating
    7
    Answers
    4
    steffenk has a spectacular aura about steffenk has a spectacular aura about steffenk has a spectacular aura about

      0  

    Default


    Hi,

    i want to do the same. i did a flickr plugin presenting pics in a DataView, but i want to have them in carousel too.

    Should be possible eg using dh to append the images from given array.
    This has to be changed:
    Code:
    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);
    to build the correct image tags inside.

    Didn't tested, but something like this could work:

    Code:
    for (var i = 0; i < this.images.length; i++) {  
        var el = dh.append(this.els.slidesWrap, {tag: 'img', cls: 'ux-carousel-slide', src: this.images[i].url}, true)
        this.slides.push(el);
        el.setWidth(this.slideWidth + 'px').setHeight(this.slideHeight + 'px');
    };
    vg Steffen
    --------------------------------------
    Release Manager of TYPO3 4.5

  3. #3
    Sencha User steffenk's Avatar
    Join Date
    Jul 2007
    Location
    Haan, Germany
    Posts
    2,664
    Vote Rating
    7
    Answers
    4
    steffenk has a spectacular aura about steffenk has a spectacular aura about steffenk has a spectacular aura about

      0  

    Default


    it's even more simple.

    Here is a working version (image with array is optional)

    Code:
    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: [],
        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].url, 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.el.getWidth(true);
            this.slideHeight = 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;
                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;
                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');
                }
            }
        }
    });
    and the configuration would be

    Code:
    Ext.onReady(function() {
        new Ext.ux.Carousel('simple-example', {
            images: [
               { url: 'slides/1.jpg', title: 'Picture 1' },
               { url: 'slides/2.jpg', title: 'Picture 2' },
               { url: 'slides/3.jpg', title: 'Picture 3' },
               { url: 'slides/4.jpg', title: 'Picture 4' },
               { url: 'slides/5.jpg', title: 'Picture 5' },
               { url: 'slides/6.jpg', title: 'Picture 6' }
            ]
        });
    })
    vg Steffen
    --------------------------------------
    Release Manager of TYPO3 4.5

  4. #4
    Sencha - Services Team arthurakay's Avatar
    Join Date
    Sep 2008
    Location
    Antioch, IL
    Posts
    1,375
    Vote Rating
    37
    Answers
    61
    arthurakay is a jewel in the rough arthurakay is a jewel in the rough arthurakay is a jewel in the rough arthurakay is a jewel in the rough

      0  

    Default


    steffenk - I appreciate the help on this. I'll give it a shot!
    Arthur Kay
    Developer Relations Manager, Sencha Inc.

    Twitter | Sencha Chicago User Group

  5. #5
    Sencha User steffenk's Avatar
    Join Date
    Jul 2007
    Location
    Haan, Germany
    Posts
    2,664
    Vote Rating
    7
    Answers
    4
    steffenk has a spectacular aura about steffenk has a spectacular aura about steffenk has a spectacular aura about

      0  

    Default


    I made an addition. Adding images from array need also possibility to add width/height property for the slides, i added them.

    see http://extjs.com/forum/showthread.php?t=75092
    vg Steffen
    --------------------------------------
    Release Manager of TYPO3 4.5

  6. #6
    Sencha User
    Join Date
    Mar 2007
    Location
    Haarlem, Netherlands
    Posts
    1,243
    Vote Rating
    10
    Answers
    28
    TommyMaintz will become famous soon enough TommyMaintz will become famous soon enough

      0  

    Default


    If you look at the combination example (http://extjs.com/playpen/ext-core-la...xamples/combo/) you see that support for dynamically adding items to the Carousel is already supported. I dont want to put an images or addImage functionality in the example since the carousel can be used for any type of html.

    This is a very short example of what you could do
    Code:
    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.

  7. #7
    Sencha User steffenk's Avatar
    Join Date
    Jul 2007
    Location
    Haan, Germany
    Posts
    2,664
    Vote Rating
    7
    Answers
    4
    steffenk has a spectacular aura about steffenk has a spectacular aura about steffenk has a spectacular aura about

      0  

    Default


    Hi,

    thanks for the example, i wasn't aware of this way creating dynamic items. This is of course a better way doing it. And thanks for the changes you did!
    vg Steffen
    --------------------------------------
    Release Manager of TYPO3 4.5

Thread Participants: 2