PDA

View Full Version : Ext.ux.CodaSlider



andycramb
7 Jul 2009, 2:36 PM
I have put together my first core user extension.:D
It is an Ext core version of the slider effect that received notoriety through its implementation on the Panic site.

I have put 2 examples on my site to show what its capable of:

The first one (http://www.cramb.org.uk/codaslidereffect/slider.html) is a simple implementation of the extension
The second one (http://www.cramb.org.uk/codaslidereffect/tabbedSlider.html) uses a more defined tabbed navigation approach and some further customistation to get the "prev" and "next" buttons in line with the tabs.


MIT license.

Tested on:

FF3.5
Safari 4
Chrome 2
IE7


**IE7 issue now resolved and latest version(0.2) uploaded on 08/07/2009.**
Not testing it on IE6 but have on IE7 and its throwing an exception on:


line 2413 of ext-core-debug.js
Error: 'h' is null or not an object

function createDelayed(h, o, scope){
return function(){
var args = TOARRAY(arguments);
(function(){
h.apply(scope, args);
}).defer(o.delay || 10);
};
};


The error is thrown after the animations have stopped running as far as I can tell.
Any help or advice here is much appreciated
Any ideas for improvements, bugs and anything else that you can think of are more than welcome.

Example usage is as follows:



Ext.onReady(function(){;

var myTabs = new Ext.ux.CodaSlider('buttons', 'panes',{startingSlide:0, animateHeight: true});

Ext.select('div.prev a').on('click',myTabs.prev,myTabs);
Ext.select('div.next a').on('click',myTabs.next,myTabs);

});


HTML has to be set up to follow the prescribed structure
Examples of this are in the demo in the zip and on-line.

Below is the code for the extension



Ext.ux.CodaSlider = Ext.extend(Ext.util.Observable,{
//------------------------------------------------------------
// config options
//------------------------------------------------------------

// example usage
//var myTabs = new Ext.ux.CodaSlider('buttons', 'panes',{startingSlide:0,animateHeight: true});

/**
* @config {int} starting tab/pane on page load
* array based so first tab is 0
*/
startingSlide : 0
/**
* @config {string} class for the selected tab
*/
,activeButtonClass : 'active'
/**
* @config {string} type of event
* defaults to the click event if no event is specified in the config
*/
,activationEvent : 'click'
/**
* @config {Number} duration of the animations
*/
,fxDuration : 0.8
/**
* @config {boolean} determines if the height should be animated
*/
,navSelector : 'li'
/**
* @config {string} you can pass in a specific selector to identify your navigational items
*/
,animateHeight : true
/**
* @config {Number} the index of the cuurent/active tab
*/
,current : 0 // zero based current pane number, read only
/**
* @config {string} specifies the type of easing to aplly to the height animation
*/
,heightEasingEffect : 'easeBoth'
/**
* @config {string} specifies the type of easing to aplly to the scroll animation
*/
,scrollEasingEffect : 'easeBoth'
/**
* @config {Mixed Element} container element for the div that wraps all the div panes
*/
,outerSlidesBox : null
/**
* @config {Mixed Element} container element for the divs that hold the content for the tabs
*/
,innerSlidesBox : null
/**
* @config {CompositeElement} that holds the collection of Ext elements
*/
,panes : null
/**
* Constructor for this class
* @param {HTML element id} this is the wrapper for the navigational items
* @param {HTMlL element id} this is the outer wrapper for the content div that holds all the panes
* @param {JS lieteral Object}This contains all the configuarble options for the class
* @return {void}
*/
,constructor : function(navContainer, slideContainer, config) {

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

this.addEvents( 'change','startAnimation');
this.initEvents(navContainer);

this.init(navContainer,slideContainer);
}

/**
* Will set up styles and initial config properties
* @param {HTML element id} this is the wrapper for the navigational items
* @param {HTMlL element id} this is the outer wrapper for the content div that holds all the panes
* @return {void}
*/
,init : function(navContainer,slideContainer){

if(navContainer){
//this.buttons = Ext.select('#' + buttonContainer + '> li.nav');
this.buttons = Ext.select('#' + navContainer + '> '+ this.navSelector);
};

this.outerSlidesBox = Ext.get(slideContainer);//return div#panes - correct
this.innerSlidesBox = this.outerSlidesBox.first();//return div#content - correct
//Ext has no getchildren method as far as I can see
this.panes = this.innerSlidesBox.getChildren() // see condor's method

//this.current = this.startingSlide ? this.panes.indexOf(Ext.get(this.startingSlide)) : 0;
this.current = typeof this.startingSlide == 'number' ? this.startingSlide : 0;

var currentEl = this.panes.item(this.current);

this.outerSlidesBox.setStyle({'overflow':'hidden','height':currentEl.getHeight() +'px'});
this.panes.each(function(el,index) {
el.setStyle({
'float': 'left',
'overflow': 'hidden'
});
},this);

this.innerSlidesBox.setStyle('float', 'left');

// calculate widths so that all panes fit aligned horizontally
this.recalcWidths();

//set initial tab if its not the default tab index 0
if(this.current > 0){
this.onTabChange(this.current);
}
else{
this.buttons.item(this.current).addClass(this.activeButtonClass);
}
}
/**
* Will set up events for each child element within the navigational items container
* @param {HTML element id} this is the wrapper for the navigational items
* @return {void}
*/
,initEvents : function(navContainer){
Ext.get(navContainer).on({
click : this.onTabChange,
scope : this,
delegate: this.navSelector
})
}

/**
* handles the click event on the navigational items
* switches the class to active for the selected li
* It can optionally be called direct passing in the index of the navigational item
* @param {Ext event object}
* @param {Ext target object} this will represent the Ext element that was clicked on
* @param {number} the index of the navigational item - array based so first item will be 0
* @return {void}
*/
,onTabChange : function(ev, t) {

var el;

// this handles the event but can take a number(tab index) that specifies the tab to be selected
//will makes sure an ext elemnt is assigned to el
if(typeof ev == "number"){
el = this.buttons.item(ev);
}
else{
el = Ext.get(t);
}

// switch the classes on the li if the tab is not already active
if (el.hasClass(this.activeButtonClass)){
return;
}
else {
el.radioClass(this.activeButtonClass)
}

//get the index of the tab within the button collection
var buttonIndex = this.buttons.indexOf(el);

// now this should match the elemnt within the panes collection we want to scroll to
this.onStartAnimation(this.panes.item(buttonIndex));
}

/**
* Starts the animation for moving the panes
* It may animate the scroll and or the height of the panes
* Fires the startAnimation event
* @param {Ext element} represents the Ext elemnt to scroll to
* @return {void}
*/
,onStartAnimation : function(el){

this.on('startAnimation',this.listenerForAnim,this,{
delay : 3000
});
this.fireEvent('startAnimation',el);

var paneIndex = this.panes.indexOf(el)

var scrollAmount = paneIndex * el.getWidth();

if(this.animateHeight){

this.outerSlidesBox.syncFx().animate(
{
scroll: {to: [scrollAmount,0]}
},
this.fxDuration,
null,
this.scrollEasingEffect,
'scroll'
).animate(
{
height: {to:el.getHeight()}
},
this.fxDuration,
null,
this.scrollHeightEffect,
'run'
);

}
else{
this.outerSlidesBox.animate(
{
scroll: {to: [scrollAmount,0]}
},
this.fxDuration,
null,
this.scrollEasingEffect,
'scroll'
);

this.outerSlidesBox.setHeight(el.getHeight());
}

this.current = paneIndex;
}
/**
* Moves to the next pane
* If the pane is at the end it will move to the first pane
* @param {Ext element} represents the Ext elemnt to scroll to
* @return {void}
*/
,next : function(){
var next = this.current + 1;
//if we are at the end go to the first one
if( next == this.panes.getCount() ){
next = 0;
}

this.onTabChange(next);
}
/**
* Moves to the previous pane
* If the pane is at the start it will move to the last pane
* @param {Ext element} represents the Ext elemnt to scroll to
* @return {void}
*/
,prev : function(){
var prev = this.current - 1;
//if we are at the start go to the last one
if( prev == -1 ){
prev = this.panes.getCount()-1;
}

this.onTabChange(prev);
}
/**
* This is called to align all the panes horizonatlly within its container
* If the pane is at the end it will move to the first pane
* @param {Ext element} represents the Ext elemnt to scroll to
* @return {void}
*/
,recalcWidths : function() {

this.panes.each(function(el, index) {
el.setStyle('width', this.outerSlidesBox.getWidth()+ 'px');
},this);

this.innerSlidesBox.setStyle('width', this.outerSlidesBox.getWidth() * this.panes.getCount() + 'px');

}
});

fangzhouxing
7 Jul 2009, 6:05 PM
Great! Thank you for sharing.

hello2008
8 Jul 2009, 12:43 AM
good job ;)

Animal
8 Jul 2009, 12:59 AM
Not testing it on IE6 but have on IE7 and its throwing an exception on:


line 2413 of ext-core-debug.js
Error: 'h' is null or not an object

function createDelayed(h, o, scope){
return function(){
var args = TOARRAY(arguments);
(function(){
h.apply(scope, args);
}).defer(o.delay || 10);
};
};




Read this code:



this.on('startAnimation',this.listenerForAnim,this,{
delay : 3000
});


Where is this.listenerForAnim defined?

andycramb
8 Jul 2009, 1:14 AM
Thanks Animal

Aaah, I had that in when I was checking that events were working correctly and when I was refactoring for release I took that method out but left that code in - dohh.
It threw me because the other browsers continued to work fine.

I will fix it tonight.

Thanks again.

aconran
8 Jul 2009, 6:41 AM
Neat looking extension

koko2589
8 Jul 2009, 11:01 PM
tankyou this what i want
but i dont know hoe to use it with ext panel

Ext.onReady(function(){;

var myTabs = new Ext.ux.CodaSlider('buttons', 'panes',{startingSlide:0, animateHeight: true});

Ext.select('div.prev a').on('click',myTabs.prev,myTabs);
Ext.select('div.next a').on('click',myTabs.next,myTabs);

});

do you have demo how to put it in tab panel? the best in card panel?=D>

andycramb
9 Jul 2009, 2:34 AM
Sorry I do not have a demo for this

If you are intending to use an Ext tab panel, are you expecting to see the same behaviour(animation on the body) on clicking another tab or are you embedding the slider within an existing tab body?

If it is the latter then you could try using contentEl and pass in the div with id = "wrapper"

As for the former approach I am not sure that it would be straight forward to incorporate this effect but maybe someone who knows the tabPanel functionality a lot better than me would be in a better place to comment.

koko2589
9 Jul 2009, 3:09 AM
i want card panel when i click its with slider you anderstand?


var p = new Ext.Panel({
renderTo: 'container',
collapsible:false,
height:400,

width:'100%', tbar:[{
text:'show1',
handler:function() {
p.getLayout().setActiveItem(0);
}
},{
text:'show2'
,handler:function() {
p.getLayout().setActiveItem(1); }


}, '->',
'-',{


text:'show3',iconCls:'left'
,handler:function() {
p.getLayout().setActiveItem(2);
}
}]
,layout:'card'
,activeItem:0
,layoutConfig:{deferredRender:true}
,defaults:{border:false}
,items:[{

html:'card1'
},{
html:'Card 2'
},{
html:'Card 3'
}]

});

yes i put it panel with contentEl
but explorer 7 do like loding 2- 3 minets its not good

andycramb
9 Jul 2009, 2:02 PM
@koko2589

I have uploaded a demo (http://www.cramb.org.uk/card%20layout%20codaslider/slider.html)to my site that has the card layout with one of the panels hosting the slider

I had to change the extension as IE7 was not handling the "Next" and "Prev" clicks too well and after a while it froze up.

I changed the onTabChange method in the demo but have not tested it fully yet so I will upload a new zip when its fully tested.

Changed to


,onTabChange : function(ev, t, index) {

var el;

// cancelled the default event click due to IE7 issue
ev.preventDefault();
Let me know if it is what you were looking for?

koko2589
9 Jul 2009, 2:46 PM
tankyou are cempion

i use
http://l.yimg.com/static.widgets.yahoo.com/135/images/pg/aro_w_on.png

http://l.yimg.com/static.widgets.yahoo.com/135/images/pg/aro_w_on.png

http://l.yimg.com/static.widgets.yahoo.com/135/images/pg/aro_e_on.png

http://l.yimg.com/static.widgets.yahoo.com/135/images/pg/aro_e_on.png

=D>=D>=D>=D>=D>=D>=D>=D>=D>=D>

koko2589
11 Jul 2009, 4:25 AM
i put in my site look

http://itoto1.com/portal55.html

andycramb
13 Jul 2009, 1:27 AM
Nice, glad it was of use to you.