将 jQuery UI 滑块添加到旧版本的 jQuery UI

Add jQuery UI slider to old version of jQuery UI

本文关键字:jQuery UI 版本 添加      更新时间:2023-09-26

我正在使用jQuery版本1.8.2和jQuery UI版本1.8.10的环境中工作。

我想使用 jQuery UI Slider 小部件。它不包含在我们当前使用的 $.ui 版本中。我尝试覆盖 $.ui 版本,但在我也用较新版本覆盖 jQuery 之前它不起作用。

我对来回的依赖关系感到困惑。难道不是有一些简单的方法可以使用滑块小部件扩展我当前版本的jQuery UI吗?

尝试将以下代码添加到 jQueryUI 小部件列表中或在 jQueryUI 库之后加载的单独文件中:

// number of pages in a slider
// (how many times can you page up/down to go through the whole range)
var numPages = 5;
$.widget( "ui.slider", $.ui.mouse, {
version: "1.10.3",
widgetEventPrefix: "slide",
options: {
    animate: false,
    distance: 0,
    max: 100,
    min: 0,
    orientation: "horizontal",
    range: false,
    step: 1,
    value: 0,
    values: null,
    // callbacks
    change: null,
    slide: null,
    start: null,
    stop: null
},
_create: function() {
    this._keySliding = false;
    this._mouseSliding = false;
    this._animateOff = true;
    this._handleIndex = null;
    this._detectOrientation();
    this._mouseInit();
    this.element
        .addClass( "ui-slider" +
            " ui-slider-" + this.orientation +
            " ui-widget" +
            " ui-widget-content" +
            " ui-corner-all");
    this._refresh();
    this._setOption( "disabled", this.options.disabled );
    this._animateOff = false;
},
_refresh: function() {
    this._createRange();
    this._createHandles();
    this._setupEvents();
    this._refreshValue();
},
_createHandles: function() {
    var i, handleCount,
        options = this.options,
        existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
        handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
        handles = [];
    handleCount = ( options.values && options.values.length ) || 1;
    if ( existingHandles.length > handleCount ) {
        existingHandles.slice( handleCount ).remove();
        existingHandles = existingHandles.slice( 0, handleCount );
    }
    for ( i = existingHandles.length; i < handleCount; i++ ) {
        handles.push( handle );
    }
    this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
    this.handle = this.handles.eq( 0 );
    this.handles.each(function( i ) {
        $( this ).data( "ui-slider-handle-index", i );
    });
},
_createRange: function() {
    var options = this.options,
        classes = "";
    if ( options.range ) {
        if ( options.range === true ) {
            if ( !options.values ) {
                options.values = [ this._valueMin(), this._valueMin() ];
            } else if ( options.values.length && options.values.length !== 2 ) {
                options.values = [ options.values[0], options.values[0] ];
            } else if ( $.isArray( options.values ) ) {
                options.values = options.values.slice(0);
            }
        }
        if ( !this.range || !this.range.length ) {
            this.range = $( "<div></div>" )
                .appendTo( this.element );
            classes = "ui-slider-range" +
            // note: this isn't the most fittingly semantic framework class for this element,
            // but worked best visually with a variety of themes
            " ui-widget-header ui-corner-all";
        } else {
            this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
                // Handle range switching from true to min/max
                .css({
                    "left": "",
                    "bottom": ""
                });
        }
        this.range.addClass( classes +
            ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
    } else {
        this.range = $([]);
    }
},
_setupEvents: function() {
    var elements = this.handles.add( this.range ).filter( "a" );
    this._off( elements );
    this._on( elements, this._handleEvents );
    this._hoverable( elements );
    this._focusable( elements );
},
_destroy: function() {
    this.handles.remove();
    this.range.remove();
    this.element
        .removeClass( "ui-slider" +
            " ui-slider-horizontal" +
            " ui-slider-vertical" +
            " ui-widget" +
            " ui-widget-content" +
            " ui-corner-all" );
    this._mouseDestroy();
},
_mouseCapture: function( event ) {
    var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
        that = this,
        o = this.options;
    if ( o.disabled ) {
        return false;
    }
    this.elementSize = {
        width: this.element.outerWidth(),
        height: this.element.outerHeight()
    };
    this.elementOffset = this.element.offset();
    position = { x: event.pageX, y: event.pageY };
    normValue = this._normValueFromMouse( position );
    distance = this._valueMax() - this._valueMin() + 1;
    this.handles.each(function( i ) {
        var thisDistance = Math.abs( normValue - that.values(i) );
        if (( distance > thisDistance ) ||
            ( distance === thisDistance &&
                (i === that._lastChangedValue || that.values(i) === o.min ))) {
            distance = thisDistance;
            closestHandle = $( this );
            index = i;
        }
    });
    allowed = this._start( event, index );
    if ( allowed === false ) {
        return false;
    }
    this._mouseSliding = true;
    this._handleIndex = index;
    closestHandle
        .addClass( "ui-state-active" )
        .focus();
    offset = closestHandle.offset();
    mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
    this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
        left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
        top: event.pageY - offset.top -
            ( closestHandle.height() / 2 ) -
            ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
            ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
            ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
    };
    if ( !this.handles.hasClass( "ui-state-hover" ) ) {
        this._slide( event, index, normValue );
    }
    this._animateOff = true;
    return true;
},
_mouseStart: function() {
    return true;
},
_mouseDrag: function( event ) {
    var position = { x: event.pageX, y: event.pageY },
        normValue = this._normValueFromMouse( position );
    this._slide( event, this._handleIndex, normValue );
    return false;
},
_mouseStop: function( event ) {
    this.handles.removeClass( "ui-state-active" );
    this._mouseSliding = false;
    this._stop( event, this._handleIndex );
    this._change( event, this._handleIndex );
    this._handleIndex = null;
    this._clickOffset = null;
    this._animateOff = false;
    return false;
},
_detectOrientation: function() {
    this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
},
_normValueFromMouse: function( position ) {
    var pixelTotal,
        pixelMouse,
        percentMouse,
        valueTotal,
        valueMouse;
    if ( this.orientation === "horizontal" ) {
        pixelTotal = this.elementSize.width;
        pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
    } else {
        pixelTotal = this.elementSize.height;
        pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
    }
    percentMouse = ( pixelMouse / pixelTotal );
    if ( percentMouse > 1 ) {
        percentMouse = 1;
    }
    if ( percentMouse < 0 ) {
        percentMouse = 0;
    }
    if ( this.orientation === "vertical" ) {
        percentMouse = 1 - percentMouse;
    }
    valueTotal = this._valueMax() - this._valueMin();
    valueMouse = this._valueMin() + percentMouse * valueTotal;
    return this._trimAlignValue( valueMouse );
},
_start: function( event, index ) {
    var uiHash = {
        handle: this.handles[ index ],
        value: this.value()
    };
    if ( this.options.values && this.options.values.length ) {
        uiHash.value = this.values( index );
        uiHash.values = this.values();
    }
    return this._trigger( "start", event, uiHash );
},
_slide: function( event, index, newVal ) {
    var otherVal,
        newValues,
        allowed;
    if ( this.options.values && this.options.values.length ) {
        otherVal = this.values( index ? 0 : 1 );
        if ( ( this.options.values.length === 2 && this.options.range === true ) &&
                ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
            ) {
            newVal = otherVal;
        }
        if ( newVal !== this.values( index ) ) {
            newValues = this.values();
            newValues[ index ] = newVal;
            // A slide can be canceled by returning false from the slide callback
            allowed = this._trigger( "slide", event, {
                handle: this.handles[ index ],
                value: newVal,
                values: newValues
            } );
            otherVal = this.values( index ? 0 : 1 );
            if ( allowed !== false ) {
                this.values( index, newVal, true );
            }
        }
    } else {
        if ( newVal !== this.value() ) {
            // A slide can be canceled by returning false from the slide callback
            allowed = this._trigger( "slide", event, {
                handle: this.handles[ index ],
                value: newVal
            } );
            if ( allowed !== false ) {
                this.value( newVal );
            }
        }
    }
},
_stop: function( event, index ) {
    var uiHash = {
        handle: this.handles[ index ],
        value: this.value()
    };
    if ( this.options.values && this.options.values.length ) {
        uiHash.value = this.values( index );
        uiHash.values = this.values();
    }
    this._trigger( "stop", event, uiHash );
},
_change: function( event, index ) {
    if ( !this._keySliding && !this._mouseSliding ) {
        var uiHash = {
            handle: this.handles[ index ],
            value: this.value()
        };
        if ( this.options.values && this.options.values.length ) {
            uiHash.value = this.values( index );
            uiHash.values = this.values();
        }
        //store the last changed value index for reference when handles overlap
        this._lastChangedValue = index;
        this._trigger( "change", event, uiHash );
    }
},
value: function( newValue ) {
    if ( arguments.length ) {
        this.options.value = this._trimAlignValue( newValue );
        this._refreshValue();
        this._change( null, 0 );
        return;
    }
    return this._value();
},
values: function( index, newValue ) {
    var vals,
        newValues,
        i;
    if ( arguments.length > 1 ) {
        this.options.values[ index ] = this._trimAlignValue( newValue );
        this._refreshValue();
        this._change( null, index );
        return;
    }
    if ( arguments.length ) {
        if ( $.isArray( arguments[ 0 ] ) ) {
            vals = this.options.values;
            newValues = arguments[ 0 ];
            for ( i = 0; i < vals.length; i += 1 ) {
                vals[ i ] = this._trimAlignValue( newValues[ i ] );
                this._change( null, i );
            }
            this._refreshValue();
        } else {
            if ( this.options.values && this.options.values.length ) {
                return this._values( index );
            } else {
                return this.value();
            }
        }
    } else {
        return this._values();
    }
},
_setOption: function( key, value ) {
    var i,
        valsLength = 0;
    if ( key === "range" && this.options.range === true ) {
        if ( value === "min" ) {
            this.options.value = this._values( 0 );
            this.options.values = null;
        } else if ( value === "max" ) {
            this.options.value = this._values( this.options.values.length-1 );
            this.options.values = null;
        }
    }
    if ( $.isArray( this.options.values ) ) {
        valsLength = this.options.values.length;
    }
    $.Widget.prototype._setOption.apply( this, arguments );
    switch ( key ) {
        case "orientation":
            this._detectOrientation();
            this.element
                .removeClass( "ui-slider-horizontal ui-slider-vertical" )
                .addClass( "ui-slider-" + this.orientation );
            this._refreshValue();
            break;
        case "value":
            this._animateOff = true;
            this._refreshValue();
            this._change( null, 0 );
            this._animateOff = false;
            break;
        case "values":
            this._animateOff = true;
            this._refreshValue();
            for ( i = 0; i < valsLength; i += 1 ) {
                this._change( null, i );
            }
            this._animateOff = false;
            break;
        case "min":
        case "max":
            this._animateOff = true;
            this._refreshValue();
            this._animateOff = false;
            break;
        case "range":
            this._animateOff = true;
            this._refresh();
            this._animateOff = false;
            break;
    }
},
//internal value getter
// _value() returns value trimmed by min and max, aligned by step
_value: function() {
    var val = this.options.value;
    val = this._trimAlignValue( val );
    return val;
},
//internal values getter
// _values() returns array of values trimmed by min and max, aligned by step
// _values( index ) returns single value trimmed by min and max, aligned by step
_values: function( index ) {
    var val,
        vals,
        i;
    if ( arguments.length ) {
        val = this.options.values[ index ];
        val = this._trimAlignValue( val );
        return val;
    } else if ( this.options.values && this.options.values.length ) {
        // .slice() creates a copy of the array
        // this copy gets trimmed by min and max and then returned
        vals = this.options.values.slice();
        for ( i = 0; i < vals.length; i+= 1) {
            vals[ i ] = this._trimAlignValue( vals[ i ] );
        }
        return vals;
    } else {
        return [];
    }
},
// returns the step-aligned value that val is closest to, between (inclusive) min and max
_trimAlignValue: function( val ) {
    if ( val <= this._valueMin() ) {
        return this._valueMin();
    }
    if ( val >= this._valueMax() ) {
        return this._valueMax();
    }
    var step = ( this.options.step > 0 ) ? this.options.step : 1,
        valModStep = (val - this._valueMin()) % step,
        alignValue = val - valModStep;
    if ( Math.abs(valModStep) * 2 >= step ) {
        alignValue += ( valModStep > 0 ) ? step : ( -step );
    }
    // Since JavaScript has problems with large floats, round
    // the final value to 5 digits after the decimal point (see #4124)
    return parseFloat( alignValue.toFixed(5) );
},
_valueMin: function() {
    return this.options.min;
},
_valueMax: function() {
    return this.options.max;
},
_refreshValue: function() {
    var lastValPercent, valPercent, value, valueMin, valueMax,
        oRange = this.options.range,
        o = this.options,
        that = this,
        animate = ( !this._animateOff ) ? o.animate : false,
        _set = {};
    if ( this.options.values && this.options.values.length ) {
        this.handles.each(function( i ) {
            valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
            _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
            $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
            if ( that.options.range === true ) {
                if ( that.orientation === "horizontal" ) {
                    if ( i === 0 ) {
                        that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
                    }
                    if ( i === 1 ) {
                        that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
                    }
                } else {
                    if ( i === 0 ) {
                        that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
                    }
                    if ( i === 1 ) {
                        that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
                    }
                }
            }
            lastValPercent = valPercent;
        });
    } else {
        value = this.value();
        valueMin = this._valueMin();
        valueMax = this._valueMax();
        valPercent = ( valueMax !== valueMin ) ?
                ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
                0;
        _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
        this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
        if ( oRange === "min" && this.orientation === "horizontal" ) {
            this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
        }
        if ( oRange === "max" && this.orientation === "horizontal" ) {
            this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
        }
        if ( oRange === "min" && this.orientation === "vertical" ) {
            this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
        }
        if ( oRange === "max" && this.orientation === "vertical" ) {
            this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
        }
    }
},
_handleEvents: {
    keydown: function( event ) {
        /*jshint maxcomplexity:25*/
        var allowed, curVal, newVal, step,
            index = $( event.target ).data( "ui-slider-handle-index" );
        switch ( event.keyCode ) {
            case $.ui.keyCode.HOME:
            case $.ui.keyCode.END:
            case $.ui.keyCode.PAGE_UP:
            case $.ui.keyCode.PAGE_DOWN:
            case $.ui.keyCode.UP:
            case $.ui.keyCode.RIGHT:
            case $.ui.keyCode.DOWN:
            case $.ui.keyCode.LEFT:
                event.preventDefault();
                if ( !this._keySliding ) {
                    this._keySliding = true;
                    $( event.target ).addClass( "ui-state-active" );
                    allowed = this._start( event, index );
                    if ( allowed === false ) {
                        return;
                    }
                }
                break;
        }
        step = this.options.step;
        if ( this.options.values && this.options.values.length ) {
            curVal = newVal = this.values( index );
        } else {
            curVal = newVal = this.value();
        }
        switch ( event.keyCode ) {
            case $.ui.keyCode.HOME:
                newVal = this._valueMin();
                break;
            case $.ui.keyCode.END:
                newVal = this._valueMax();
                break;
            case $.ui.keyCode.PAGE_UP:
                newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
                break;
            case $.ui.keyCode.PAGE_DOWN:
                newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
                break;
            case $.ui.keyCode.UP:
            case $.ui.keyCode.RIGHT:
                if ( curVal === this._valueMax() ) {
                    return;
                }
                newVal = this._trimAlignValue( curVal + step );
                break;
            case $.ui.keyCode.DOWN:
            case $.ui.keyCode.LEFT:
                if ( curVal === this._valueMin() ) {
                    return;
                }
                newVal = this._trimAlignValue( curVal - step );
                break;
        }
        this._slide( event, index, newVal );
    },
    click: function( event ) {
        event.preventDefault();
    },
    keyup: function( event ) {
        var index = $( event.target ).data( "ui-slider-handle-index" );
        if ( this._keySliding ) {
            this._keySliding = false;
            this._stop( event, index );
            this._change( event, index );
            $( event.target ).removeClass( "ui-state-active" );
        }
    }
}
});