PDA

View Full Version : Newbie trying to do a rangeSlide extension



Rodolfo
8 Mar 2009, 6:55 PM
deprecated use this
http://www.extjs.com/forum/showthread.php?p=380753#post380753

Hi, this my first try of a ExtJS extension (newbie one jeje)

Its very simple things, only the Ext.Slider with two trackers (in some particular cases could be useful) I call Ext.ex.RangeSlider cause my final intention is try (just try) to do something like this:

http://tobias.klpstn.com/dojo1.1/dojox/form/tests/test_RangeSlider.html

I post here, cause i dont know very well all the "rulez" for an official working extension.

PD: right now, i cant test in MS IE, but its the same code of the Ext.Slider,
so i guess should work ok

PD: sorry for my bad english jeje :)

Ext.ux.RangeSlider



/**
* just a simple range slider
*
* @author Rodolfo Barriga S.
* @class Ext.ux.RangeSlider
* @extends Ext.Slider
*
*/
Ext.ux.RangeSlider = Ext.extend(Ext.Slider, {
/**
* @cfg {Boolean} overlap prevent overlap of the sliders, Defaults to false
*/
overlap : false,

initComponent: function() {
this.valueB = this.valueB || this.maxValue ;
Ext.ux.RangeSlider.superclass.initComponent.call(this);
this.addEvents(
'newbeforechange',
'newchange',
'newchangecomplete',
'newdragstart',
'newdrag',
'newdragend'
);
if(this.vertical){
Ext.apply(this, Ext.ux.RangeSlider.Vertical);
}
}
,
// private override
onRender : function(){
Ext.ux.RangeSlider.superclass.onRender.apply(this, arguments);
this.newThumb = this.innerEl.createChild({tag:'div', cls:'x-slider-thumb'});
this.initTrackerEvents();
}
,
initTrackerEvents : function(){
this.newThumb.addClassOnOver('x-slider-thumb-over');
this.mon(this.el, 'mousedown', Ext.emptyFn, this); // TODO key move

this.newTracker = new Ext.dd.DragTracker({
onBeforeStart: this.onBeforeDragStart.createDelegate(this),
onStart: this.onNewDragStart.createDelegate(this),
onDrag: this.onNewDrag.createDelegate(this),
onEnd: this.onNewDragEnd.createDelegate(this),
tolerance: 3,
autoStart: 300
});

this.newTracker.initEl(this.newThumb);
this.on('beforedestroy', this.destroy);
}
,
destroy : function(){
this.tracker.destroy;
this.newTracker.destroy;
}
,
// private override
afterRender : function(){
Ext.ux.RangeSlider.superclass.afterRender.apply(this, arguments);

if(this.valueB){
var v = this.normalizeValue(this.valueB);
if(v !== this.valueB){
delete this.valueB;
this.setValueB(v, false);
}else{
this.moveNewThumb(this.translateValue(v), false);
}
}

},
// private
onNewDragStart: function(e){
this.newThumb.addClass('x-slider-thumb-drag');
this.dragging = true;
this.dragStartValue = this.valueB;
this.fireEvent('newdragstart', this, e);
},
// private
onNewDrag: function(e){
var pos = this.innerEl.translatePoints(this.newTracker.getXY());
this.setValueB(Math.round(this.reverseValue(pos.left)), false);
this.fireEvent('newdrag', this, e);
},
// private
onNewDragEnd: function(e){
this.newThumb.removeClass('x-slider-thumb-drag');
this.dragging = false;
this.fireEvent('newdragend', this, e);
if(this.dragStartValue != this.valueB){
this.fireEvent('newchangecomplete', this, this.valueB);
}
}
,
setValueB : function(v, animate, changeComplete){
v = this.normalizeValue(v);

if (!this.overlap && this.value >= v) {
return;
}

if(v !== this.valueB && this.fireEvent('newbeforechange', this, v, this.valueB) !== false){
this.valueB = v;
this.moveNewThumb(this.translateValue(v), animate !== false);
this.fireEvent('newchange', this, v);
if(changeComplete){
this.fireEvent('newchangecomplete', this, v);
}
}
},
// private override
setValue : function(v, animate, changeComplete){
v = this.normalizeValue(v);

if (!this.overlap && v >= this.valueB) {
return;
}

if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){
this.value = v;
this.moveThumb(this.translateValue(v), animate !== false);
this.fireEvent('change', this, v);
if(changeComplete){
this.fireEvent('changecomplete', this, v);
}
}
},

moveNewThumb: function(v, animate){
if(!animate || this.animate === false){
this.newThumb.setLeft(v);
}else{
this.newThumb.shift({left: v, stopFx: true, duration:.35});
}
}
,
// private override
onMouseDown : function(e){
if(this.disabled) {return;}
if(this.clickToChange && e.target != this.thumb.dom && e.target != this.newThumb.dom){
var local = this.innerEl.translatePoints(e.getXY());
this.onClickChange(local);
}
this.focus();
},
// private override
onClickChange : function(local){
if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){
var v = Math.round(this.reverseValue(local.left));
var a = Math.abs(this.value - v);
var b = Math.abs(this.valueB - v);
(a > b) ? this.setValueB(v, undefined, true) : this.setValue(v, undefined, true);
}
}
,
getValueB : function(){
return this.valueB;
}
,
getValues : function(){
return [this.value, this.ValueB]
}
});

Ext.reg('rangeslider', Ext.ux.RangeSlider);

// private class to support vertical sliders
Ext.ux.RangeSlider.Vertical = {

onResize : function(w, h){
this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
this.syncThumb();
},
getRatio : function(){
var h = this.innerEl.getHeight();
var v = this.maxValue - this.minValue;
return h/v;
},
moveNewThumb: function(v, animate){
if(!animate || this.animate === false){
this.newThumb.setBottom(v);
}else{
this.newThumb.shift({bottom: v, stopFx: true, duration:.35});
}
},
onNewDrag: function(e){
var pos = this.innerEl.translatePoints(this.newTracker.getXY());
var bottom = this.innerEl.getHeight()-pos.top;
this.setValueB(this.minValue + Math.round(bottom/this.getRatio()), false);
this.fireEvent('newdrag', this, e);
},
onClickChange : function(local){
if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){
var bottom = this.innerEl.getHeight()-local.top;
var v = this.minValue + Math.round(bottom/this.getRatio());
var a = Math.abs(this.value - v);
var b = Math.abs(this.valueB - v);
(a > b) ? this.setValueB(v, undefined, true) : this.setValue(v, undefined, true);
}
}
};



Pluging for tips...




/**
* Simple plugin for using an Ext.Tip with a range slider to show the tracker value
* @author Rodolfo Barriga
* @class Ext.ux.RangeSliderTip
* @extends Ext.Tip
*
*/
Ext.ux.RangeSliderTip = Ext.extend(Ext.Tip, {
minWidth: 10,
offsets : [0, -10],
init : function(rangeSlider){
rangeSlider.on('dragstart', this.onTrackerSlide, this);
rangeSlider.on('drag', this.onTrackerSlide, this);
rangeSlider.on('dragend', this.hide, this);

rangeSlider.on('newdragstart', this.onNewTrackerSlide, this);
rangeSlider.on('newdrag', this.onNewTrackerSlide, this);
rangeSlider.on('newdragend', this.hide, this);

rangeSlider.on('destroy', this.destroy, this);
},
onTrackerSlide : function(rangeSlider){
this.show();
this.body.update(this.getTrackerText(rangeSlider));
this.doAutoWidth();
this.el.alignTo(rangeSlider.thumb, 'b-t?', this.offsets);
},
onNewTrackerSlide : function(rangeSlider){
this.show();
this.body.update(this.getNewTrackerText(rangeSlider));
this.doAutoWidth();
this.el.alignTo(rangeSlider.newThumb, 'b-t?', this.offsets);
},
getTrackerText : function(rangeSlider){
return rangeSlider.getValue();
},
getNewTrackerText : function(rangeSlider){
return rangeSlider.getValueB();
}

});




sample code.



<html>

<head>
<title>Sample</title>
<!-- ExtJS Style -->
<link rel="stylesheet" type="text/css" href="ext-2.2.1/resources/css/ext-all.css"/>
<link rel="stylesheet" type="text/css" href="ext-2.2.1/resources/css/xtheme-gray.css" id="theme"/>

<!-- ExtJS 2.2.1 Lib (Source) -->
<script type="text/javascript" src="ext-2.2.1/source/core/Ext.js" ></script>
<script type="text/javascript" src="ext-2.2.1/source/adapter/ext-base.js" ></script>
<script type="text/javascript" src="ext-2.2.1/ext-all-debug.js" ></script>

<script type="text/javascript" src="Ext.ux.RangeSlider.js"></script>
<script type="text/javascript" src="Ext.ux.RangeSliderTip.js"></script>

</head>
<body style="background-color:#ccc; padding:20px;">

<script>


Ext.BLANK_IMAGE_URL = 'ext-2.2.1/resources/images/default/s.gif';

// application main entry point
Ext.onReady(function() {
Ext.QuickTips.init();

var rangeSlider = new Ext.ux.RangeSlider({
renderTo:'range',
width: 300,
increment: 10,
minValue: 0,
maxValue: 200,
plugins: new Ext.ux.RangeSliderTip()
});
rangeSlider.on( 'change', function(m, v) { console.log('changed A: ' + v); } );
rangeSlider.on( 'newchange', function(m, v) { console.log('changed B: ' + v); } );

var tip = new Ext.ux.RangeSliderTip({
getTrackerText: function(rangeSlider){
return String.format('<b>{0}% complete tracker A</b>', rangeSlider.getValue());
},
getNewTrackerText: function(rangeSlider){
return String.format('<b>{0}% complete tracler B</b>', rangeSlider.getValueB());
}
});

var rangeVerticalSlider = new Ext.ux.RangeSlider({
height:200,
increment: 10,
minValue: 0,
maxValue: 100,
vertical:true,
plugins: tip,
overlap: true
});
rangeVerticalSlider.on( 'change', function(m, v) { console.log('vertical changed A: ' + v); } );
rangeVerticalSlider.on( 'newchange', function(m, v) { console.log('vertical changed B: ' + v); } );

var win = new Ext.Window({
width:50,
items: rangeVerticalSlider
})

win.show();
});
// eo function onReady

</script>
<br/>
<br/>
<div id="range" />
</body>
</html>

moegal
9 Mar 2009, 11:43 AM
Looks good in FF2+ on XP.

Getting an error in IE7 on XP of "Unexpected call to method or property access." line 59

Also, I would add width: 300 to the window. It shows up very large in FF.

Very nice BTW

Rodolfo
9 Mar 2009, 4:43 PM
thanks for testing..

(fixed and working) on MS IE7, I also test in Google Chrome too and works OK

moegal
9 Mar 2009, 5:48 PM
Have you updated the code here? I still get the same error.

Anyway to prevent overlap of the sliders?

Rodolfo
9 Mar 2009, 7:01 PM
yeap its updated

Was a typing mistake in the sample code (dib -> div) thats all, sorry for that :-)

(Also on IE I guess its necessary the width property on window widget, i dont know that, cause i dont use IE).

haaa... just in case, you know on IE you cant use console.log --> Its necessary change or comment this lines if you or some one else are using the sample code

And yeap sure, i wanna work in a property for (overlap:true or false ) and other things too.., but until this weekend, i dont have time...



thanks for your interest and for your help in this first try :)
Rodolfo

moegal
10 Mar 2009, 1:54 AM
Rodolfo,

No problem. I changed the div and all is well. I have been developing for both FF and IE lately so I did know about the console.log thing. Now that would be a handy extension, one that detects if IE and doesn't show the console errors or displays it in a extjs pop-up. Just an idea.

There is another range slider. Have you seen this.

http://www.jaredgisin.com/software/Ext.ux.SlideZone/ext2/examples_h.html

It uses other images so it would be nice to have a range slider without any additional graphics needed so themeing would be easier.

Nice work.

Marty

Rodolfo
22 Mar 2009, 11:40 AM
Have you updated the code here? I still get the same error.

Anyway to prevent overlap of the sliders?

- added overlap property for prevent overlap of the sliders.
- added Ext.ux.RangeSilder.js, Ext.ux.RangeSliderTip.js, Sample.html into a zip file..

moegal
22 Mar 2009, 8:47 PM
Great, I will check it out tomorrow.
Marty

dreas
23 Mar 2009, 12:05 AM
Now that would be a handy extension, one that detects if IE and doesn't show the console errors or displays it in a extjs pop-up. Just an idea.
Even better would be to check if console is defined. So you could simply type something like that:

window.console !== undefined ? console.log(debugMessage) : Ext.Msg.alert("Console", debugMessage);

moegal
23 Mar 2009, 6:34 AM
- added overlap property for prevent overlap of the sliders.
- added Ext.ux.RangeSilder.js, Ext.ux.RangeSliderTip.js, Sample.html into a zip file..

Works great in FF and IE, nice work.

Thanks, Marty

boyan.dimitrov
17 Dec 2009, 8:56 AM
Great work Rudolfo. I used your slider in my project. Would it be possible to add some visual indication of the slider values.

As for the jared's component it's abandoned project. I first tried it but couldn't make it work with formpanel containers.

JEASIASINGUTT
19 Dec 2009, 10:55 AM
dialog = new Ext.ux.UploadDialog.Dialog url: upload-dialog-request.php, reset_on_hide: false, allow_close_on_upload: true, upload_autostart: true, permitted_extensions: jpg, jpeg, gif ;But there was a bug in file type check methods, so please get the fixed version of the extension.