I did my first Ext Core extension.
I need advices how to do it much better.

Thanks a lot for all commets.

http://vreshenie.ru/work/ext-core/wi...l-1/index.html

Here is code
http://vreshenie.ru/work/ext-core/wi...carousel-1.rar





Run widget
Code:
new Ext.widgets.Carousel({
	wayToImages:'images',
	images:['thumb1.jpg','thumb2.jpg','thumb3.jpg','thumb4.jpg','thumb5.jpg','thumb6.jpg','thumb7.jpg']
});
Extension
Code:
Ext.ns('Ext.widgets');

Ext.widgets.Carousel = Ext.extend(Ext.util.Observable, {
	wayToImages:'',
	images:'',
	id:'',
	x:50,
	y:50,
	width:500,
	height:130,
	stepSlide:0,
	firstSlideNumber:0,
	lastSlideNumber:2,
	duration:2,
	easing:'easeOut',
	inMove:false,
	renderTo:Ext.getBody(),
    constructor: function(config) {
        config = config || {};
        Ext.apply(this, config);		
		
		Ext.widgets.Carousel.superclass.constructor.call(this, config);
				
		this.appendParentElement();
		this.runTemplate();
		this.appendEvents();
    },
	appendParentElement:function(){
		var id = Ext.id(null,'-');
		this.number = id;
		var id_template = 'ext-carousel-';
		
		this.id=id_template+'ul'+id;
		var widget = this;
		
		var parentDiv = Ext.DomHelper.append(this.renderTo, {
			tag: 'div'
		},true);
		
		var ul_width = widget.images.length*(120+10);
		var el = Ext.DomHelper.append(parentDiv, {
			tag: 'div',
			id:id_template+'div'+id,
			cls: 'div-images',
			//width:10+widget.images.length*(120+20),
			html: '<ul style="width:'+ul_width+'px" id="'+this.id+'"></ul>'
		},true);
		
		widget.stepSlide = ul_width/widget.images.length;
		console.log(widget.stepSlide);
		
		parentDiv.insertFirst({
			tag: 'div',
			html: '<a style="position:absolute;left:0px;top:50%;" id="ext-carousel-a-prev'+id+'" href="#"><img src="images/onebit_29.png" /><a><a id="ext-carousel-a-next'+id+'" href="#" style="position:absolute;right:0px;top:50%;"><img src="images/onebit_27.png" /><a>'
		});
		
		parentDiv.setStyle('position','absolute');
		parentDiv.setLeft(this.x);
		parentDiv.setTop(this.y);
		parentDiv.setWidth(this.width);
		parentDiv.setHeight(this.height);
	},
	runTemplate:function(){
		var t = new Ext.Template(
			'<li>',
				'<div class="default-image">',
					'<a href="#"><img src="{wayToImages}/{image}" width="120" height="72"></a>',
				'</div>',
			'</li>'
		);
		var widget = this;
		var el = Ext.select(widget.id+" ul");
		Ext.each(this.images,function(value){
			t.append(widget.id, {wayToImages:widget.wayToImages,image:value});
		});
	},
	appendEvents:function(){
		Ext.select("#"+this.id).on('click', function(e, t) {
			e.stopEvent();
			
			Ext.select("#"+this.id+' li div').each(function(el){
				el.addClass('default-image');
				el.removeClass('cute-image');
			});
			
			Ext.fly(t).addClass('cute-image');
			Ext.fly(t).removeClass('default-image');
			
		}, null, {delegate:'div'});
		this.arrowsEvents();
	},
	arrowsEvents:function(){
		Ext.get('ext-carousel-a-prev'+this.number).setOpacity(0.5);
		//Ext.get('ext-carousel-a-next'+this.number).setOpacity(0.5);
		var widget = this;
		
		Ext.get('ext-carousel-a-prev'+this.number).on('click',function(e){
			e.stopEvent();
			
			if(widget.firstSlideNumber<=0 || widget.inMove){
				return;
			}
			
			var el = Ext.get(widget.id);
			
			widget.inMove=true;
			
			widget.firstSlideNumber--;
			widget.lastSlideNumber--;
			
			if(widget.firstSlideNumber==0){
				Ext.get('ext-carousel-a-prev'+widget.number).setOpacity(0.5);
			}
			
			if(widget.lastSlideNumber==widget.images.length-2){
				Ext.get('ext-carousel-a-next'+widget.number).setOpacity(1.0);
			}
			
			el.setX(el.getX()+widget.stepSlide,{
				duration:widget.duration,
				easing: widget.easing,
				callback:function(){
					widget.inMove=false;
				}
			});
		});
		
		Ext.get('ext-carousel-a-next'+this.number).on('click',function(e){
			e.stopEvent();
			var el = Ext.get(widget.id);
						
			if(widget.lastSlideNumber>=widget.images.length-1 || widget.inMove){
				return;
			}
			
			widget.inMove=true;
			
			widget.firstSlideNumber++;
			widget.lastSlideNumber++;
						
			if(widget.firstSlideNumber==1){
				Ext.get('ext-carousel-a-prev'+widget.number).setOpacity(1.0);
			}
			
			if(widget.lastSlideNumber==widget.images.length-1){
				Ext.get('ext-carousel-a-next'+widget.number).setOpacity(0.6);
			}
			
			el.setX(el.getX()-widget.stepSlide,{
				duration:widget.duration,
				easing: widget.easing,
				callback:function(){
					widget.inMove=false;
				}
			});
		});
	}	
});