Drag entire range

7 posts, 2 answers
  1. Henning
    Henning avatar
    6 posts
    Member since:
    Jun 2009

    Posted 05 Jun 2009 Link to this post

    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?
  2. Tsvetie
    Admin
    Tsvetie avatar
    1517 posts

    Posted 11 Jun 2009 Link to this post

    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.
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Henning
    Henning avatar
    6 posts
    Member since:
    Jun 2009

    Posted 16 Jun 2009 Link to this post

    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?
  5. Answer
    Tsvetie
    Admin
    Tsvetie avatar
    1517 posts

    Posted 17 Jun 2009 Link to this post

    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.
  6. Henning
    Henning avatar
    6 posts
    Member since:
    Jun 2009

    Posted 22 Jun 2009 Link to this post

    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;  
        }  
    }  
     
  7. Answer
    Tsvetie
    Admin
    Tsvetie avatar
    1517 posts

    Posted 25 Jun 2009 Link to this post

    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.
  8. Henning
    Henning avatar
    6 posts
    Member since:
    Jun 2009

    Posted 26 Jun 2009 Link to this post

    Thanks again!
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017