Carousel

Page 2 of 2 FirstFirst 12
  1. #11

    Carousel Hack

    I'd say this qualifies as a "hack," but it's a start. I started with equiman's idea of using the CardLayout + TaskManager using the CardLayout example, but ended up switching to a ColumnLayout to get the left/right sliding effect instead of up/down. I've tested this in 1.2, and will post again as I try it out in the newer versions.

    <%@ Page Language="C#" %>
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    <script runat="server">
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.ResourceMgr.RegisterIcon(Icon.PlayGreen);
        }
    
    </script>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Carousel Hack</title>
        <link href="../../../../resources/css/examples.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <form runat="server">
        <ext:ResourceManager ID="ResourceMgr" runat="server" />
        <ext:XScript ID="xscript" runat="server">
                <script type="text/javascript" >
                
                //Perform the expand of next/shrink of current actions
                var carouselNav = function(change){
                    //Repeated clicks don't look very nice, so use a rudimentary semaphore
                    // to ensure that it will only "spin" after stopping.
                    if(#{CarouselPanel}.spinning !== true){
                        #{CarouselPanel}.spinning = true;
    
                        var current = #{CarouselPanel}.items.itemAt(#{CarouselPanel}.activeItem),
                        idx = #{CarouselPanel}.items.indexOf(current),
                        width = #{CarouselPanel}.getEl().getWidth() -1, //Full width didn't work
                                                                        // (and possibly needs to
                                                                        //  consider padding?)
                        nextIdx = idx + change,
                        next;
    
                        //Get the next or previous item, wrapping around
                        // the total items as needed
                        nextIdx = nextIdx < 0
    	                    ? #{CarouselPanel}.items.length - 1
    	                    : nextIdx % #{CarouselPanel}.items.length;
                        next = #{CarouselPanel}.items.itemAt(nextIdx);
                        moveElementPosition(current, change > 0);
    
                        //Set current's width, and the slide container's width,
                        // to match up with the full width of the column panel
                        current.getEl().parent().setWidth(width);
                        current.getEl().setWidth(width);
    
                        //Set next's width to 0 so it will expand nicely
                        next.getEl().setWidth(0);
                        next.show();
    
                        //Shrink the current item to 0
                        current.getEl().animate(
    	                    { width: { to: 0 } },
    	                    1.5,
    	                    null,
    	                    'easeBoth',
    	                    'run');
                        
                        //Expand the next item to the full width
                        next.getEl().animate(
    	                    { width: { to: width } },
    	                    1.5,
    	                    function(){
    		                    #{CarouselPanel}.activeItem = nextIdx;
    		                    #{CarouselPanel}.spinning = false;
    	                    },
    	                    'easeBoth',
    	                    'run');
                    }
                };
    
                //Rearrange the carousel items in the dom to allow for the "infinite spin" effect
                var moveElementPosition = function(aPanel, moveForward){
                    var parentNode = aPanel.getEl().parent(),
                    currentNode = aPanel.getEl().dom,
                    childNode = moveForward ? parentNode.dom.firstChild : parentNode.dom.lastChild;
    
                    //Only perform the movement actions if the current dom node is not
                    // the node that is to be moved
                    if(currentNode !== childNode){
                        Ext.removeNode(childNode);
                        if(moveForward){
                            //Moving forward, so move the first item to the end
                            parentNode.appendChild(childNode);
                        }
                        else{
                            //Moving backward, so move the last item to the front
                            parentNode.insertFirst(childNode);
                        }
                    }
                };
    
                //Action when the forward or backward buttons are clicked
                var navClick = function(change){
                    navPause(false);
                    carouselNav(change);
                };
    
                //Pause the carousel (occurs when clicking play, or forward and backward)
                //allowPlay - will only restart the task if true
                var navPause = function(allowPlay){
                    if(#{CarouselTaskManager}.tasks && #{CarouselTaskManager}.getTask('CarouselTask').executing){
                        #{CarouselTaskManager}.stopTask('CarouselTask');
                        #{btnPlayPause}.setIconClass('icon-playgreen');
                    }
                    else if(allowPlay){
                        if(#{CarouselTaskManager}.tasks){
                            #{CarouselTaskManager}.startTask('CarouselTask');
                        }
                        else{
                            #{CarouselTaskManager}.initManager();
                        }
                        #{btnPlayPause}.setIconClass('icon-pausegreen');
                    }
                };
    
                //Action to take when the carousel task fires
                var carouselTaskUpdate = function(task){
                    //The first time the task is called, don't advance the carousel item
                    // (since the event fires before the timer, the first item will immediately
                    //  be carouselled away. Can also work around by delaying the task manager,
                    //  but it complicates other matters)
                    if(#{CarouselTaskManager}.getTask('CarouselTask').first){
                        #{CarouselTaskManager}.getTask('CarouselTask').first = false;
                    }
                    else{
                        carouselNav(1);
                    }
                }
    
                //Column Layout adds an extra div to the end of the item contents, which throws
                // off moveElementPosition. It doesn't appear to have any effect in this use case,
                // so just throw it away when the carousel panel renders
                var domKludge = function(){
                    Ext.removeNode(#{CarouselPanel}.items.itemAt(0).getEl().parent().dom.lastChild);
                    #{CarouselPanel}.spinning = false;
                };
    
                </script>
        </ext:XScript>
        <ext:Panel ID="CarouselPanel" runat="server" Layout="ColumnLayout" ActiveIndex="0"
            HideMode="Offsets" AnchorHorizontal="100%" StyleSpec="white-space:nowrap;">
            <Listeners>
                <AfterRender Fn="domKludge" />
            </Listeners>
            <Items>
                <ext:Panel ID="Panel1" runat="server" Html="<h1>Welcome to the Wizard!</h1><p>Step 1 of 3</p>"
                    Border="false" Header="false" AnchorHorizontal="100%" />
                <ext:Panel ID="Panel2" runat="server" Html="<h1>Card 2</h1><p>Step 2 of 3</p>" Border="false"
                    Header="false" Hidden="true" />
                <ext:Panel ID="Panel3" runat="server" Html="<h1>Congratulations!</h1><p>Step 3 of 3 - Complete</p>"
                    Border="false" Header="false" Hidden="true" />
            </Items>
            <Buttons>
                <ext:Button ID="btnPrev" runat="server" Text="Prev" Icon="PreviousGreen">
                    <Listeners>
                        <Click Handler="navClick(-1);" />
                    </Listeners>
                </ext:Button>
                <ext:Button ID="btnPlayPause" runat="server" Icon="PauseGreen">
                    <Listeners>
                        <Click Handler="navPause(true);" />
                    </Listeners>
                </ext:Button>
                <ext:Button ID="btnNext" runat="server" Text="Next" Icon="NextGreen">
                    <Listeners>
                        <Click Handler="navClick(1);" />
                    </Listeners>
                </ext:Button>
            </Buttons>
        </ext:Panel>
        <ext:TaskManager ID="CarouselTaskManager" runat="server">
            <Tasks>
                <ext:Task TaskID="CarouselTask" Interval="5000" OnStart="this.executing = true; this.first = true;"
                    OnStop="this.executing = false; this.first = false;">
                    <Listeners>
                        <Update Fn="carouselTaskUpdate" />
                    </Listeners>
                </ext:Task>
            </Tasks>
        </ext:TaskManager>
        </form>
    </body>
    </html>
    Like I said, definitely a hack! I've also tried it with images in the panels with success as well. The movement isn't exactly carousel-like (it's more like shuffling through a deck of cards), but it gets the idea across. I'll can play around with turning it into an actual control as the opportunity presents itself.
  2. #12
    Hi,

    Thanks for the sharing, looks good.
Page 2 of 2 FirstFirst 12

Similar Threads

  1. [CLOSED] Image Slider, Carousel
    By SouthDeveloper in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Oct 05, 2011, 10:31 AM

Tags for this Thread

Posting Permissions