Russian English
jQuery Plugins & Javascript Functions
PHP Classes & Functions
HTML && CSS Frameworks

jQuery Slider

Public: 05.12.2015

Download jQuery Slider last version

Slider - an element that lets the user select a value by changing his position on the scale.

Version Changes

1.2.0

Added optional parityPartsAddClass marking even division slider special class partParity.

1.1.0

Added optional partsVisible an array which highlights the values of an array of parts division that marks the class partVisible, and the rest of the class partHide.

jquery.slider.js
/*!
 jQuery Slider 1.4.0
 https://skidanov.ru/dev/jquery-plugins/slider/
 https://github.com/skidanovdima/jquery-slider
*/

;(function($){

    $.fn.Slider = function(config, callbacks) {

        var container = $(this);
        var slider = $('<div></div>');

        if (container[0] != undefined) {
            if (container.prop('tagName').toUpperCase() == 'INPUT') {
                container.hide();
                slider = container.wrap(slider).parent();
                config.input = container;
            } else {
                container.replaceWith(slider);
            }

            var defaultConfig = {
                type: 'normal',
                // titleWidth need to force the width of each block title adding overflow: hidden.
                // Used as a means of combating the asynchronous downloading fonts css, if used in the titles of the slider,
                // because they are loaded after document.ready and change the size of the unit after its positioning.
                titleWidth: false,
                hideCenterTitlesOn768: true,
                parityPartsAddClass: true,  // Add parity class
                partsOn: true,
                titlesOn: true,
                loadedOn: false,
                minPartKey: 0,
                maxPartKey: 0,
                DefaultValueMin: 0,
                DefaultValueMax: 0,
                DefaultValue: 0,
                runnerCaught: false,
                position: 'horizontal',
                classes: {
                    main: 'slider',
                    skin: 'default',

                    line: 'line',
                    parts: 'parts',
                    back: 'back',
                    loaded: 'loaded',
                    complete: 'complete',

                    minRunner: 'min-runner',
                    minRunnerImage: 'min-runner-image',
                    maxRunner: 'max-runner',
                    maxRunnerImage: 'max-runner-image',
                    runner: 'runner',
                    runnerImage: 'runner-image',

                    titles: 'titles',

                    part: 'part',
                    partParity: 'parity',
                    partVisible: 'part-visible',
                    partHide: 'part-hide',
                    partFirst: 'first',
                    partLast: 'last',

                    title: 'title',
                    titleFirst: 'first',
                    titleLast: 'last',
                    titleCenter: 'center',
                    titleHide: 'title-hide',
                    titleWidth: 'title-width'
                }
            };
            slider.config = $.extend(true, {}, defaultConfig, config);

            var defaultCallbacks = {
                afterChangeValue: function(slider, user) {
                },
                events: function(slider) {
                }
            };
            slider.callbacks = $.extend(true, {}, defaultCallbacks, callbacks);

            slider.addClass(slider.config.classes.main).addClass(slider.config.classes.skin);

            $.fn.Slider.create(slider);


            if ( slider.config.type == 'range' ) {
                $.fn.Slider.toCount(slider, [slider.config.DefaultValueMin, slider.config.DefaultValueMax], 'range');
            } else if ( slider.config.type == 'normal' ) {
                $.fn.Slider.toCount(slider, slider.config.DefaultValue, 'normal');
            }

            $.fn.Slider.events(slider);

            return slider;
        } else {
            return false;
        }
    };

    $.fn.Slider.create = function (slider) {
        if ( slider.config.line ) {
            slider.config.parts = [];
            for (var value = slider.config.line.min; value <= slider.config.line.max; value = value + slider.config.line.step) {
                slider.config.parts.push(value);
            }
        }

        slider.components = {}; // Components
        slider.components.line = $('<div></div>').addClass(slider.config.classes.line);
        if (slider.config.partsOn) {
            slider.components.parts = $('<div></div>').addClass(slider.config.classes.parts);
        }
        slider.components.back = $('<div></div>').addClass(slider.config.classes.back);
        if (slider.config.loadedOn) {
            slider.components.loaded = $('<div></div>').addClass(slider.config.classes.loaded);
            slider.components.back.append(slider.components.loaded);
        }
        slider.components.complete = $('<div></div>').addClass(slider.config.classes.complete);

        if (slider.config.type == 'range') {
            slider.components.minRunner = $('<div></div>').addClass(slider.config.classes.minRunner);
            slider.components.minRunnerImage = $('<div></div>').addClass(slider.config.classes.minRunnerImage);

            slider.components.maxRunner = $('<div></div>').addClass(slider.config.classes.maxRunner);
            slider.components.maxRunnerImage = $('<div></div>').addClass(slider.config.classes.maxRunnerImage);
        } else {
            slider.components.runner = $('<div></div>').addClass(slider.config.classes.runner);
            slider.components.runnerImage = $('<div></div>').addClass(slider.config.classes.runnerImage);
        }

        if (slider.config.titlesOn) {
            slider.components.titles = $('<div></div>').addClass(slider.config.classes.titles);
        }

        if (slider.config.type == 'range') {
            slider
                .append(slider.components.line
                    .append(slider.components.parts)
                    .append(slider.components.back
                        .append(slider.components.complete)
                        .append(slider.components.minRunner
                            .append(slider.components.minRunnerImage)
                        )
                        .append(slider.components.maxRunner
                            .append(slider.components.maxRunnerImage)
                        )
                    )
                )
                .append(slider.components.titles);
        } else {
            slider
                .append(slider.components.line
                    .append(slider.components.parts)
                    .append(slider.components.back
                        .append(slider.components.complete)
                        .append(slider.components.runner
                            .append(slider.components.runnerImage)
                        )
                    )
                )
                .append(slider.components.titles);
        }

        var parity = false;

        $.each(slider.config.parts, function (partKey, partValue) {
            if (slider.config.partsOn) {
                var part = $('<div data-value="'+partValue+'"></div>');
                part.addClass(slider.config.classes.part);

                if (slider.config.partsVisible) {
                    if ($.inArray(partValue, slider.config.partsVisible) > -1) {
                        part.addClass(slider.config.classes.partVisible);
                    } else {
                        part.addClass(slider.config.classes.partHide);
                    }
                }

                if (slider.config.parityPartsAddClass && parity) {
                    part.addClass(slider.config.classes.partParity);
                }

                if (slider.config.position == 'horizontal') {
                    part.css({left: (partKey) * (100 / (slider.config.parts.length - 1))+'%'});
                } else if (slider.config.position == 'vertical') {
                    part.css({bottom: (partKey) * (100 / (slider.config.parts.length - 1))+'%'});
                }
                if (partKey == 0) {
                    // first
                    part.addClass(slider.config.classes.partFirst);
                } else if (partKey == slider.config.parts.length - 1) {
                    // last
                    part.addClass(slider.config.classes.partLast);
                }
                slider.components.parts.append(part);
            }

            if (slider.config.titlesOn && slider.config.titles && slider.config.titles[partValue]) {
                var title = $('<div></div>');
                title.append(slider.config.titles[partValue]);
                title.addClass(slider.config.classes.title);
                if (slider.config.titleWidth) {
                    title.addClass(slider.config.classes.titleWidth);
                    title.css({width: slider.config.titleWidth});
                }
                if (partKey == 0) {
                    // first
                    title.addClass(slider.config.classes.titleFirst);
                } else if (partKey == slider.config.parts.length - 1) {
                    // last
                    title.addClass(slider.config.classes.titleLast);
                } else {
                    // centers
                    title.addClass(slider.config.classes.titleCenter);
                    if (slider.config.hideCenterTitlesOn768) {
                        title.addClass(slider.config.classes.titleHide);
                    }

                    if (slider.config.position == 'horizontal') {
                        title.css({left: (partKey) * (100 / (slider.config.parts.length - 1))+'%'});
                    } else if (slider.config.position == 'vertical') {
                        title.css({bottom: (partKey) * (100 / (slider.config.parts.length - 1))+'%'});
                    }

                }
                slider.components.titles.append(title);
            }

            if (parity) {
                parity = false;
            } else {
                parity = true;
            }
        });

        $(document).ready(function(){
            $.fn.Slider.titlesCenter(slider);
        });
    };

    $.fn.Slider.titlesCenter = function (slider) {
        if (slider.config.titlesOn) {
            $.each( slider.components.titles.children('.'+slider.config.classes.title+'.'+slider.config.classes.titleCenter), function (key, val) {
                if (slider.config.position == 'horizontal') {
                    $(this).css({marginLeft: -($(this).outerWidth() / 2)});
                } else if (slider.config.position == 'vertical') {
                    $(this).css({marginBottom: -($(this).outerHeight() / 2)});
                }
            });
        }
    };

    $.fn.Slider.events = function (slider) {
        if($.isTouchCapable()) {
            /* jQuery Touch Events https://github.com/benmajor/jQuery-Touch-Events */
            slider.components.runner.bind('tapstart', function(event) {
                slider.config.runnerCaught = true;
                //console.log('Схватили');
                $(document).delegate('body', 'touchmove', false);
                $('body').bind('tapmove', function(event, touch) {
                    //console.log('Ведем');
                    $.fn.Slider.move(slider, event, undefined, touch);
                });
            });
            $(document).bind('tapend', function(event) {
                $(document).undelegate('body', 'touchmove', false);
                $('body').unbind('tapmove');
            });
        };

        slider.components.line.bind('click', function(event, ui) {
            if (slider.config.runnerCaught) {
                slider.config.runnerCaught = false;
            } else {
                //console.log('Кликнули');
                $.fn.Slider.move(slider, event, true);
            }
        });

        $(document).bind('mouseup', function(event, ui) {
            //console.log('Отпустили');
            $('body').css('cursor', 'auto');
            $('body').unbind('mousemove');
            slider.config.runnerCaught = false;
        });

        if (slider.config.type == 'range') {
            slider.components.minRunner.bind('mousedown', function(event, ui) {
                slider.config.runnerCaught = true;
                //console.log('Схватили');
                $('body').bind('mousemove', function(event, ui) {
                    //console.log('Ведем');
                    $('body').css('cursor', 'pointer');
                    $.fn.Slider.move(slider, event, undefined, undefined, 'min');
                });
            });
            slider.components.maxRunner.bind('mousedown', function(event, ui) {
                slider.config.runnerCaught = true;
                //console.log('Схватили');
                $('body').bind('mousemove', function(event, ui) {
                    //console.log('Ведем');
                    $('body').css('cursor', 'pointer');
                    $.fn.Slider.move(slider, event, undefined, undefined, 'max');
                });
            });
        } else {
            slider.components.runner.bind('mousedown', function(event, ui) {
                slider.config.runnerCaught = true;
                //console.log('Схватили');
                $('body').bind('mousemove', function(event, ui) {
                    //console.log('Ведем');
                    $('body').css('cursor', 'pointer');
                    $.fn.Slider.move(slider, event);
                });
            });
        }

        slider.callbacks.events(slider);
    };

    $.fn.Slider.toCount = function (slider, value, type) {
        if (type == undefined) type = 'normal';
        if ( type == 'range' ) {
            slider.valueMin = validator(value[0]);
            var v0 = setValue(slider.valueMin);
            slider.config.minPartKey = v0;
            $.fn.Slider.render(slider, 'min', v0);

            slider.valueMax = validator(value[1]);
            var v1 = setValue(slider.valueMax);
            slider.config.maxPartKey = v1;
            $.fn.Slider.render(slider, 'max', v1);
        } else if ( type == 'normal' ) {
            slider.value = validator(value);
            $.fn.Slider.render(slider, 'runner', setValue(slider.value));
        } else if (type == 'loaded') {
            $.fn.Slider.render(slider, 'loaded', setValue(validator(value)));
            //console.log('LOADED' + value);
        }
        slider.callbacks.afterChangeValue(slider, false);

        function validator(value, maxPart) {
            if (maxPart == undefined) {maxPart = slider.config.parts[slider.config.parts.length - 1];}

            if (value < slider.config.parts[0]) {
                value = slider.config.parts[0];
            }
            if (value > slider.config.parts[slider.config.parts.length - 1]) {
                value = slider.config.parts[slider.config.parts.length - 1];
            }
            return value;
        }

        function setValue(value){
            var returnKey;
            $.each(slider.config.parts, function (partKey, partValue) {
                if (partKey == 0) {
                    if (slider.config.parts[partKey + 1]) {
                        if (value >= partValue && value < partValue + ((slider.config.parts[partKey + 1] - partValue) / 2) ) {
                            returnKey = partKey;
                            return false;
                        }
                    } else {
                        // If the first division in the slider only
                        returnKey = partKey;
                        return false;
                    }
                } else if (partKey == slider.config.parts.length - 1) {
                    if (value > partValue - ((partValue - slider.config.parts[partKey - 1]) / 2) && value <= partValue) {
                        returnKey = partKey;
                        return false;
                    }
                } else {
                    if (value > partValue - ((partValue - slider.config.parts[partKey - 1]) / 2) && value <= partValue + ((slider.config.parts[partKey + 1] - partValue) / 2) ) {
                        returnKey = partKey;
                        return false;
                    }
                }
            });
            return returnKey;
        }

    };

    // Отрисовка слайдера (визуальные изменения позиций компонентов)
    $.fn.Slider.render = function (slider, type, partKey, animate) {
        if (animate) {
            if (type == 'max') {
                if (slider.config.position == 'horizontal') {
                    slider.components.complete.css({right: 'auto'});
                    slider.components.complete.css({left: slider.config.minPartKey * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.stop().animate({width: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                    slider.components.maxRunner.stop().animate({left: partKey * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                } else if (slider.config.position == 'vertical') {
                    slider.components.complete.css({top: 'auto'});
                    slider.components.complete.css({bottom: slider.config.minPartKey * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.stop().animate({height: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                    slider.components.maxRunner.stop().animate({bottom: partKey * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                }
            } else if (type == 'min') {
                if (slider.config.position == 'horizontal') {
                    slider.components.complete.css({left: 'auto'});
                    slider.components.complete.css({right: ((slider.config.parts.length - 1) - slider.config.maxPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.stop().animate({width: (slider.config.maxPartKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                    slider.components.minRunner.stop().animate({left: partKey * 100 / (slider.config.parts.length - 1) +'%'}, 200);
                } else if (slider.config.position == 'vertical') {
                    slider.components.complete.css({bottom: 'auto'});
                    slider.components.complete.css({top: ((slider.config.parts.length - 1) - slider.config.maxPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.stop().animate({height: (slider.config.maxPartKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                    slider.components.minRunner.stop().animate({bottom: partKey * 100 / (slider.config.parts.length - 1) +'%'}, 200);
                }
            } else if (type == 'runner') {
                if (slider.config.position == 'horizontal') {
                    slider.components.complete.stop().animate({width: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                    slider.components.runner.stop().animate({left: partKey * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                } else if (slider.config.position == 'vertical') {
                    slider.components.complete.stop().animate({height: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                    slider.components.runner.stop().animate({bottom: partKey * 100 / (slider.config.parts.length - 1) + '%'}, 200);
                }
            }
        } else {
            if (type == 'max') {
                if (slider.config.position == 'horizontal') {
                    slider.components.complete.css({right: 'auto'});
                    slider.components.complete.css({left: slider.config.minPartKey * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.css({width: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.maxRunner.css({left: partKey * 100 / (slider.config.parts.length - 1) + '%'});
                } else if (slider.config.position == 'vertical') {
                    slider.components.complete.css({top: 'auto'});
                    slider.components.complete.css({bottom: slider.config.minPartKey * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.css({height: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.maxRunner.css({bottom: partKey * 100 / (slider.config.parts.length - 1) + '%'});
                }
            } else if (type == 'min') {
                if (slider.config.position == 'horizontal') {
                    slider.components.complete.css({left: 'auto'});
                    slider.components.complete.css({right: ((slider.config.parts.length - 1) - slider.config.maxPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.css({width: (slider.config.maxPartKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.minRunner.css({left: partKey * 100 / (slider.config.parts.length - 1) +'%'});
                } else if (slider.config.position == 'vertical') {
                    slider.components.complete.css({bottom: 'auto'});
                    slider.components.complete.css({top: ((slider.config.parts.length - 1) - slider.config.maxPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.complete.css({height: (slider.config.maxPartKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.minRunner.css({bottom: partKey * 100 / (slider.config.parts.length - 1) +'%'});
                }
            } else if (type == 'runner') {
                if (slider.config.position == 'horizontal') {
                    slider.components.complete.css({width: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.runner.css({left: partKey * 100 / (slider.config.parts.length - 1) + '%'});
                } else if (slider.config.position == 'vertical') {
                    slider.components.complete.css({height: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
                    slider.components.runner.css({bottom: partKey * 100 / (slider.config.parts.length - 1) + '%'});
                }
            } else if (type == 'loaded') {
                slider.components.loaded.css({width: (partKey - slider.config.minPartKey) * 100 / (slider.config.parts.length - 1) + '%'});
            }
        }
    };

    $.fn.Slider.move = function (slider, event, animate, touch, runner) {

        var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
        var is_opera = navigator.userAgent.toLowerCase().indexOf("op") > -1;

        if (touch) {
            var X = touch.position.x + $(window).scrollLeft();
            var Y = touch.position.y + $(window).scrollTop();
        } else {
            if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && is_chrome && !is_opera ) {
                var X = event.clientX;
                var Y = event.clientY;
            } else {
                var X = event.clientX + $(window).scrollLeft();
                var Y = event.clientY + $(window).scrollTop();
            }
        }
        if (slider.config.position == 'horizontal') {
            var clickPosition =  X - slider.offset().left;
            var partWidth = slider.outerWidth() / (slider.config.parts.length - 1);
        } else if (slider.config.position == 'vertical') {
            var clickPosition =  Y - slider.offset().top;
            var partHeight = slider.outerHeight() / (slider.config.parts.length - 1);
        }

        if (slider.config.position == 'vertical') {
            clickPosition = slider.outerHeight() - clickPosition;
        }

        var valueIsChanged = false;

        $.each(slider.config.parts, function (partKey, partValue) {
            if (slider.config.position == 'horizontal') {
                var begin = ((partKey + 1) * partWidth - partWidth - partWidth / 2);
                var end = ((partKey + 1) * partWidth - partWidth + partWidth / 2);
                if (end > slider.outerWidth()) {end = slider.outerWidth();}
            } else if (slider.config.position == 'vertical') {
                var begin = ((partKey + 1) * partHeight - partHeight - partHeight / 2);
                var end = ((partKey + 1) * partHeight - partHeight + partHeight / 2);
                if (end > slider.outerHeight()) {end = slider.outerHeight();}
            }
            if (begin < 0) {begin = 0;}

            if (clickPosition >= begin && clickPosition < end) {

                if (runner == undefined) {
                    if (slider.config.type == 'normal') {
                        runner = 'runner';
                    } else if (slider.config.type == 'range') {
                        if (partKey <= slider.config.minPartKey) {
                            runner = 'min';
                        } else if (partKey >= slider.config.maxPartKey) {
                            runner = 'max';
                        } else if (slider.config.maxPartKey - partKey > partKey - slider.config.minPartKey) {
                            runner = 'min'
                        } else if (slider.config.maxPartKey - partKey <= partKey - slider.config.minPartKey) {
                            runner = 'max'
                        }
                    }
                }

                if (runner == 'runner') {
                    slider.value = partValue;
                } else if (runner == 'min') {
                    slider.valueMin = partValue;
                } else if (runner == 'max') {
                    slider.valueMax = partValue;
                }

                if (runner == 'min' && partKey >= slider.config.maxPartKey) {
                    partKey = slider.config.maxPartKey - 1;
                    slider.valueMin = slider.config.parts[slider.config.maxPartKey - 1];
                } else if (runner == 'max' && partKey <= slider.config.minPartKey) {
                    partKey = slider.config.minPartKey + 1;
                    slider.valueMax = slider.config.parts[slider.config.minPartKey + 1];
                }

                if (runner == 'max') {slider.config.maxPartKey = partKey;}
                else if (runner == 'min') {slider.config.minPartKey = partKey;}

                $.fn.Slider.render(slider, runner, partKey, animate);
                valueIsChanged = true;
            }
        });

        if (!valueIsChanged) {
            if (clickPosition < 0) {
                slider.value = slider.config.parts[0];
            } else if (clickPosition > slider.outerWidth()) {
                slider.value = slider.config.parts[slider.config.parts.length - 1];
            }
        }
        if (slider.config.input) {
            slider.config.input.val(slider.value);
        }
        slider.callbacks.afterChangeValue(slider, true);
    };

}(jQuery));

Examples

<script src="http://skidanov.ru/sources/jquery-plugins/jquery.slider/jquery.slider.min.js"></script>
<link rel="stylesheet" href="http://skidanov.ru/sources/jquery-plugins/jquery.slider/css/default.min.css">
<div class="slider default"></div>
example.js
;(function($) {
    $('.example').Slider({
        "parts": [
            5000, 10000, 15000, 20000, 25000,
            30000, 35000, 40000, 45000, 50000,
            55000, 60000, 65000, 70000, 75000,
            80000, 85000, 90000, 95000, 100000
        ],
        "partsVisible": [
            5000, 25000, 50000, 75000, 100000
        ],
        "titles": {"5000": "5 000", "50000": "50 000", "100000": "100 000"},
        "DefaultValue": 30000
    }, {
        afterChangeValue: function(slider, user) {
            // Use variable slider.value to get that value of slider
            console.log(slider.value);
        },
        events: function(slider) {
        }
    });
}(jQuery));

Demos

default default.min.css
light-green-runner light-green-runner.min.css
aqua aqua.min.css
light-forest light-forest.min.css
red-alert red-alert.min.css
asphalt asphalt.min.css
media-player media-player.min.css
input element