This is a migrated thread and some comments may be shown as answers.

Drag entire range

6 Answers 119 Views
Slider
This is a migrated thread and some comments may be shown as answers.
Henning
Top achievements
Rank 1
Henning asked on 05 Jun 2009, 11:17 AM
I am using the Slider with range, as in this example:
http://demos.telerik.com/aspnet-ajax/slider/examples/rangeslider/defaultcs.aspx

What I want to do is be able to have the whole range increase/decrease. That is to say, when the SelectionEnd moves 3 points to the right, SelectionStart should also move 3 point to the right.

The ideal way to do this is having the entire range move when the user clicks, holds down and drags somewhere withing the range (between the two DragHandles).

Is there a way to do this?

6 Answers, 1 is accepted

Sort by
0
Tsvetie
Telerik team
answered on 11 Jun 2009, 07:40 AM
Hi Henning,
You can easily configure the RadSlider to keep a certain range between its handles using the ClientValueChange and ClientBeforeValueChange events of the RadSlider control. For example:
<telerik:RadSlider ID="RadSlider1" runat="server" SmallChange="5" LargeChange="10" ItemType="tick"  
            IsSelectionRangeEnabled="true" Width="400px" Height="60px" TrackPosition="BottomRight" 
            SelectionStart="0" SelectionEnd="30" OnClientBeforeValueChange="OnClientBeforeValueChange" 
            OnClientValueChange="OnClientValueChange"
        </telerik:RadSlider> 
         
        <script type="text/javascript">  
        var avoidRecusrsion = false;   
        function OnClientBeforeValueChange(sender, args)      
        {      
            if(avoidRecusrsion) return
         
            var rangeBetweenHandles = 30;      
            var newValue = args.get_newValue();      
                      
            var sliderDragHandles = sender.get_dragHandles();      
            var activeDragHandle = sender.get_activeHandle();      
                  
            if(!activeDragHandle) return
             
            avoidRecusrsion = true
            // In case we are moving the selectionStart dragHandle.      
            if(activeDragHandle == sliderDragHandles[0])      
            {                  
                if(newValue + rangeBetweenHandles > sender.get_maximumValue())      
                {      
                    args.set_cancel(true);      
                }      
            }      
            // In case we are moving the selectionEnd dragHandle.      
            else     
            {      
                if(newValue - rangeBetweenHandles < sender.get_minimumValue())      
                {      
                    args.set_cancel(true);      
                }      
            }  
            avoidRecusrsion = false;     
        }          
         
        function OnClientValueChange(sender, args) 
        { 
            if(avoidRecusrsion) return
         
            var rangeBetweenHandles = 30;      
            var newValue = args.get_newValue();      
                      
            var sliderDragHandles = sender.get_dragHandles();      
            var activeDragHandle = sender.get_activeHandle();      
                  
            if(!activeDragHandle) return;     
             
            avoidRecusrsion = true;  
            // In case we are moving the selectionStart dragHandle.                 
            if(activeDragHandle == sliderDragHandles[0])      
            { 
                var rangeEnd = newValue + rangeBetweenHandles; 
                sender.set_selectionEnd(rangeEnd);      
            }      
            // In case we are moving the selectionEnd dragHandle.      
            else     
            {      
                var rangeStart = newValue - rangeBetweenHandles; 
                sender.set_selectionStart(rangeStart);       
            } 
            avoidRecusrsion = false;  
        }     
        </script>  

I have attached my test page for your reference as well.

However, it will not be that easy to change the behavior of the control so that you are able to drag the selection element of the RadSlider. Currently, you can click on the track and selection elements (mousedown) and the dragHandle that is closer to the point where you click will move. Thus, in order to implement the drag functionality of the selection element, you have to override that functionality, for example, handle the mousedown event of the selection element, the mousemove and mouseup events of the document. The difficult part would be to calculate the new values for the two handles while you drag the range, so that the mouse keeps its position relative to the range.

Greetings,
Tsvetie
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
Henning
Top achievements
Rank 1
answered on 16 Jun 2009, 11:56 AM
Thanks for the answer.

A follow-up:

I would like to be able to do both a) move each selectionStart/End seperately (normal behaviour) and b) drag the entire range, as described above.

It could nice to have the drag handles do a) and the increase/decrease handles do b)

So when the user drags one of the draghandles, the range increases/decreases, and when the user clicks increasehandle/decreasehandle, the entire range shifts.

Is there a way to recognize what handle is in use/has been used?

I have only found get_dragHandles() and get_activeHandle() from your example and other forum posts/the API reference.

Is there something to check if the activeHandle is of type dragHandle/IncreaseHandle/DecreaseHandle, like

var activeDragHandle = sender.get_activeHandle();     
if (activeDragHandle.Type==RadSlider.DragHandle)  
    //move the selection as per normal behaviour  
else if (activeDragHandle.Type==RadSlider.DecreaseHandle)  
    //move entire range 1 step down  
else if (activeDragHandle.Type==RadSlider.IncreaseHandle)  
    //move entire range 1 step up 

Or is there another way to do it?
0
Accepted
Tsvetie
Telerik team
answered on 17 Jun 2009, 03:11 PM
Hi Henning,
The active handle is a dragHandle - it can be either the first dragHandle or the second one, in case there is a second one. Additionally, the active dragHandle is an HTML element, not a client object and it has only the properties and methods of a simple HTML element.

You can use the SlideStart and SlideEnd client events of the slider control to find out whether the user drags a dragHandle or not. For example:
<telerik:RadSlider ID="RadSlider1" runat="server" 
    OnClientSlideStart="OnClientSlideStart" OnClientSlideEnd="OnClientSlideEnd"
</telerik:RadSlider> 
 
<script type="text/javascript"
var isSliding = false
        
function OnClientSlideStart(sender, args) 
    isSliding = true
 
function OnClientSlideEnd(sender, args) 
    isSliding = false
</script> 

You can find out which of the handles the user clicked - the increase or decrease in case isSliding is false, in the BeforeValueChange or ValueChanged client event. Simply compare the new and old values - in case the new value is smaller than the old value, this means that the user clicked the decrease handle. For example:
function OnClientBeforeValueChange(sender, args) 
    var increase = (sender.get_value() < args.get_newValue()); 
 
    if(isSliding) 
    // dragHandle is moving 
    else if(increase) 
    // the increase handle is clicked 
    else 
    // the decrease handle was clicked     

Kind regards,
Tsvetie
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
Henning
Top achievements
Rank 1
answered on 22 Jun 2009, 11:45 AM
Thanks for the reply!

I got it to work the way I want now. I had to work in a couple of fixes to make it work (get_selectionStart/End is always 1 higher than it should be, avoidRecursion flag has to be reset when a draghandle has been moved only 1 point).

The only thing missing is possibility to disable clicking on the track. From what I can tell from this thread: http://www.telerik.com/community/forums/aspnet-ajax/slider/slider-customization.aspx (question 3) unforunately it is not possible to disable this without also disabling the increase/decrease handles.

I attach my code for anyone who might find it useful.

 
            <telerik:RadSlider ID="RadSlider4" runat="server"   
                MinimumValue="1"   
                MaximumValue="12"   
                IsSelectionRangeEnabled="true"   
                SelectionStart="4"   
                SelectionEnd="6"   
                SmallChange="1"   
                LargeChange="1"   
                ShowIncreaseHandle="true"   
                ShowDecreaseHandle="true" 
                Width="400px"   
                Height="40px"   
                ItemType="tick"   
                Orientation="Horizontal" 
                TrackPosition="BottomRight" 
                Skin="Vista"   
                OnClientLoaded="OnClientLoaded"   
                OnClientSlideStart="OnClientSlideStart"   
                OnClientSlide="OnClientSlide"   
                OnClientSlideEnd="OnClientSlideEnd" 
                OnClientBeforeValueChange="OnClientBeforeValueChange" 
                OnClientValueChange="OnClientValueChange">  
            </telerik:RadSlider> 


//Flag that tells whether the draghandles has been used.  
var isSliding = false;   
 
//Flag that stops the script from eternal recursion.  
var avoidRecursion = false;  
 
function OnClientLoaded(sender, args)  
{  
}  
 
//The OnClientSlideStart client-side event occurs just before the drag handle is moved along the track.  
function OnClientSlideStart(sender, args)   
{   
    isSliding = true;   
}   
 
//The OnClientSlide client-side event occurs as the drag handle is moved along the track.  
function OnClientSlide(sender, args)  
{  
}  
 
//The OnClientSlideEnd client-side event occurs as the drag handle stops moving along the track.  
function OnClientSlideEnd(sender, args)   
{   
    isSliding = false;   
}   
 
//The OnClientBeforeValueChange client-side event occurs before the value property changes.  
function OnClientBeforeValueChange(sender, args)   
{   
}   
 
//The OnClientValueChange client-side event occurs as the value property changes.  
function OnClientValueChange(sender, args)  
{  
    //If the new value is larger than current value, increase handle has been clicked.  
    var increase = (sender.get_value() < args.get_newValue());   
      
    //The current selectionEnd  
    var selEnd;  
      
    //The current selectionStart  
    var selStart;  
      
    //In this event, get_selectionEnd is always 1 higher than it should be (bug?).  
    //So always set it 1 lower, and when it's at max it will produce an error that has to be caugth,  
    //in this case just set it to the max value.  
    try   
    {  
        selEnd = sender.get_itemData()[sender.get_selectionEnd()].value-1;  
    }  
    catch (err)  
    {  
        selEnd = sender.get_maximumValue();  
    }  
      
    //In this event, get_selectionStart is always 1 higher than it should be (bug?).  
    //So always set it 1 lower, and when it's at max it will produce an error that has to be caugth,  
    //in this case just set it to the max value.  
    try   
    {  
        selStart = sender.get_itemData()[sender.get_selectionStart()].value-1;  
    }  
    catch (err)  
    {  
        selStart = sender.get_maximumValue();  
    }  
      
    //If this event is fired from the user clicking increase/decrease, do work.  
    if (!avoidRecursion)  
    {  
        //Set this flag so that the work will not be done again after selctionEnd/Start is changed  
        //causing an eternal recursion.  
        avoidRecursion=true;  
 
        if(isSliding)   
        {  
            //dragHandle is moving   
              
            //The flag has to be reset here because when a draghandle has been moved only 1 point,  
            //this event will only be fired once and therefore the flag will not be reset at the end  
            //of this parent branch  
            avoidRecursion=false;  
        }  
        else if(increase)  
        {  
            //the increase handle is clicked  OR the track has been clicked  
              
            //Increase the selectionStart as well.  
            sender.set_selectionStart(selStart+1);  
        }  
        else   
        {  
            //the decrease handle is clicked OR the track has been clicked  
              
            //Decrease the selectionEnd as well.  
            sender.set_selectionEnd(selEnd-1);  
        }  
    }  
    else 
    {  
        //The event was caused by setting selectionStart/End in the previous event.  
        //The event has been fired without any work done.  
          
        //Now set the flag back so that the next time the user clicks increase/decrease,  
        //the work will be done.  
        avoidRecursion=false;  
    }  
}  
 
0
Accepted
Tsvetie
Telerik team
answered on 25 Jun 2009, 10:30 AM
Hi Henning,
What I can offer you in this case, is to override the method that handles the mouseclick event for the track element and the UL element of the ticks. Thus this method will not execute the code and nothing will happen when the user clicks on the track or on a tick. The code you need to add in order to do this is the following:
Telerik.Web.UI.RadSlider.prototype._onTrackMouseDown = function(){};  

Sincerely yours,
Tsvetie
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
Henning
Top achievements
Rank 1
answered on 26 Jun 2009, 08:15 AM
Thanks again!
Tags
Slider
Asked by
Henning
Top achievements
Rank 1
Answers by
Tsvetie
Telerik team
Henning
Top achievements
Rank 1
Share this question
or