为 jQuery UI 滑块添加填充

6
有没有一种简单的方法来为jQuery UI滑块条添加填充?我希望能够使滑块手柄不到达条的两端。因此,如果这是常规的左端:
no padding
\/
[]------------------

我希望左右两端都有内边距:
padding of 10px for instance
\/
--[]----------------

我在css文件中尝试了以下代码:
.ui-slider-horizontal { height: .8em; padding: 0 10px; }
但是jQuery UI Slider似乎使用完整的(outerWidth())宽度来确定手柄的滑动范围,而不是去除padding后的宽度。我还尝试过修改代码,将outerWidth()替换为width(),但没有任何效果。
我明确不想采用设置最小和最大值的hack方法。值应始终按预期工作。
有什么建议吗?
编辑:
根据pkauko的评论;我正在将滑块用作其上方有三个标签的元素。
   not                      very
important    important    important
----[]-----------[]----------[]----

上面的插图显示了我希望手柄出现的位置,位于标签下方的中心位置。但是,该条形图在视觉上需要延伸到边缘。

我只是好奇,为什么你想让它这样工作?除非你的想法是使用滑块根本无法设置最小和最大值,而不仅仅是外观。否则,如果在设置最小或最大值时滑块不在滑动的最末端,它看起来就像滑块没有正常工作一样。 - pkauko
@pkauko:请看我对问题的补充。 - Decent Dabbler
啊,好的,现在我明白你为什么希望它能像描述的那样工作了。很遗憾我无法帮助你实现所需的行为。不过我可能有一个想法,稍后会回答你。 - pkauko
@pkauko:好的,期待您可能提出的任何建议。提前致谢! - Decent Dabbler
2个回答

8
好的,我自己也经常希望有这样的功能,但从未真正下定决心去做些什么。既然你现在提出了要求,我就坐下来,修改了jQuery UI的滑块,按照你的要求添加了填充选项。
注意:我只为具有单个手柄的水平滑块添加了该选项。其他情况并不更加复杂。我只是没有动力去输入和测试可能目前并不需要的案例。
在您包含了jQuery UI中原始滑块后,请包含此代码扩展。该扩展程序将覆盖几种方法,并向Slider小部件添加“paddingMin”和“paddingMax”选项(值必须为数字,并将被解释为像素;显然,这也可以轻松地扩展以采用其他单位,但这又意味着要对目前未请求的案例进行更多的输入/测试)。
简单的使用示例如下:
$('#slider').slider({ paddingMin: 50, paddingMax: 100 });

扩展黑客代码(按原样提供,不要起诉我):

(
    function($, undefined)
    {
        $.ui.slider.prototype.options =
            $.extend(
                {},
                $.ui.slider.prototype.options,
                {
                    paddingMin: 0,
                    paddingMax: 0
                }
            );

        $.ui.slider.prototype._refreshValue =
            function() {
                var
                    oRange = this.options.range,
                    o = this.options,
                    self = this,
                    animate = ( !this._animateOff ) ? o.animate : false,
                    valPercent,
                    _set = {},
                    elementWidth,
                    elementHeight,
                    paddingMinPercent,
                    paddingMaxPercent,
                    paddedBarPercent,
                    lastValPercent,
                    value,
                    valueMin,
                    valueMax;

                if (self.orientation === "horizontal")
                {
                    elementWidth = this.element.outerWidth();
                    paddingMinPercent = o.paddingMin * 100 / elementWidth;
                    paddedBarPercent = ( elementWidth - ( o.paddingMin + o.paddingMax) ) * 100 / elementWidth;
                }
                else
                {
                    elementHeight = this.element.outerHeight();
                    paddingMinPercent = o.paddingMin * 100 / elementHeight;
                    paddedBarPercent = ( elementHeight - ( o.paddingMin + o.paddingMax) ) * 100 / elementHeight;
                }

                if ( this.options.values && this.options.values.length ) {
                    this.handles.each(function( i, j ) {
                        valPercent =
                            ( ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100 )
                            * paddedBarPercent / 100 + paddingMinPercent;
                        _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
                        $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
                        if ( self.options.range === true ) {
                            if ( self.orientation === "horizontal" ) {
                                if ( i === 0 ) {
                                    self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
                                }
                                if ( i === 1 ) {
                                    self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
                                }
                            } else {
                                if ( i === 0 ) {
                                    self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
                                }
                                if ( i === 1 ) {
                                    self.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 )
                        * paddedBarPercent / 100 + paddingMinPercent;

                    _set[ self.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 } );
                    }
                }
            };

        $.ui.slider.prototype._normValueFromMouse =
            function( position ) {
                var
                    o = this.options,
                    pixelTotal,
                    pixelMouse,
                    percentMouse,
                    valueTotal,
                    valueMouse;

                if ( this.orientation === "horizontal" ) {
                    pixelTotal = this.elementSize.width - (o.paddingMin + o.paddingMax);
                    pixelMouse = position.x - this.elementOffset.left - o.paddingMin - ( this._clickOffset ? this._clickOffset.left : 0 );
                } else {
                    pixelTotal = this.elementSize.height - (o.paddingMin + o.paddingMax);
                    pixelMouse = position.y - this.elementOffset.top - o.paddingMin - ( 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 );
            };
    }
)(jQuery);

@Thomas:这个工作得非常好!非常感谢你!因为我使用了 min: 1, max: 3,它已经将位置均匀分布,所以对于吸附并不是特别必要。但如果你觉得需要微调一下,可以发布新版本。 :) 到目前为止,做得非常好。真的很棒! - Decent Dabbler
1
@Thomas:太棒了!你帮我省了很多工作,否则我就得自己挖掘代码。而且由于我还不熟悉jQuery小部件等内容,这可能需要我超过一天的时间才能完成。除了给你最佳答案奖励之外,你有PayPal账户吗?我很乐意向你捐赠几杯啤酒! - Decent Dabbler
1
@Thomas - 看起来应该有更简单的方法来做这件事。请看一下我的问题,我正在使用非线性增量值 - http://stackoverflow.com/questions/8646796/jquery-ui-slider-max-value-not-end-of-slider - 所以我需要在最后一个增量处停止滑块(或者创建一个被忽略的最后一个增量)。 - Jason
对我不起作用,使用jQueryUI 1.8.23。没有JS错误,但滑块出了问题。 - AnimaSola
2
@AnimaSola:这并不让我惊讶,因为这段代码已经有3年了。 :) 试试这个fiddle:http://jsfiddle.net/cx6AF/。这种方法略有不同,但也不会对原有代码产生太大影响。fiddle中使用的jQueryUI版本是1.9.2。我希望它也能与你的版本兼容。我已经包含了一个简短的描述,虽然它很小,但你可能很容易就能理解它。 - Thomas
显示剩余8条评论

3
“吸附到增量”和“不兼容”(与吸附值不均匀)的最小值和最大值是否能产生所需效果?我知道这很可能会导致应用程序端的值转换,因为现在使用的值可能无法获得,但如果它起作用,这是一个“hack and slash”的“解决方案”。
我的建议是将最小值设置为750,吸附值设置为1200,最大值设置为4050。这样,最低吸附值比最小值高450,并且滑块永远不应达到最左边的边缘。对于最大值也是如此,即3 x 1200 + 450 = 4050。这里使用的值是任意的,仅供参考。
我还没有测试过这个方法,也不知道它是否有效,我知道这不是你想要的,但这只是我在jqueryui.com检查jquery UI滑块工作示例时想到的一个想法。
编辑:不能放手,现在我知道这可以防止滑块到达滑动的两端。您只需要相应地设置初始值,以防止页面加载时滑块位于一端或另一端。

我现在有点迟钝,无法理解为什么需要这些值,但它们似乎有效。例如,我也尝试了最小300、最大3900、步长1200,但这导致手柄超出了左侧。嗯,很奇怪。不过我会除以10,基本上是一样的。虽然我希望有一个不需要转换所选值的解决方案,但现在我会使用这个。谢谢! - Decent Dabbler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接