65.9K
CodeProject 正在变化。 阅读更多。
Home

创建 Sencha Touch Ext.form.Slider 类的插件以显示更多信息

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.09/5 (4投票s)

2011年8月25日

CPOL

3分钟阅读

viewsIcon

26190

它为 Sencha Touch 标准 Ext.form.Slider 类添加了功能

引言

Sencha Touch 移动框架 有一个 Ext.form.Slider 类,用于显示滑块供用户选择值。 界面在 高度 字段中看起来像这样(单击 此处 进行演示,您可能需要使用移动设备,或计算机上的 Chrome 或 Safari 浏览器)

1.png

它工作正常,但我想显示更多信息,例如设置时的最小值和最大值、用户拖动滑块时的当前值,以及用户停止拖动时的值,就像 价格重量 字段中的那样

0.png

背景

DevGuyDotOrg 做了一个 很棒的工作 来显示用户拖动滑块时的当前值(参见下图)

基于这个想法,我创建了一个类似这样的 Ext.form.Slider 类扩展

Ext.ns('Ext.ux');
Ext.ux.SliderTooltip = new Ext.Panel({
    floating: true,
    height: 30,
    styleHtmlContent: true,
    style: "background-color: #FFF; text-align: center"
});

Ext.ux.Slider = Ext.extend(Ext.form.Slider, {
    listeners: {
        drag: function (theSlider, theThumb, ThumbValue) {
            Ext.ux.SliderTooltip.setWidth(ThumbValue.length * 1.5);
            Ext.ux.SliderTooltip.showBy(theThumb);
            Ext.ux.SliderTooltip.el.setHTML(ThumbValue);
        },
        dragend: function (theSlider, theThumb, ThumbValue) {
            Ext.ux.SliderTooltip.hide();
        },
        scope: this
    }
});

Ext.reg('uxSlider', Ext.ux.Slider);

虽然它在工具提示方面运行良好,但在这种情况下我更喜欢插件。(在某些方面只有一些差异,请参阅 此处。)

代码

对于 Sencha 插件的新手,请参考 参考 1参考 2参考 3

首先,让我们看看插件的所有代码

Ext.ns('Ext.ux');
Ext.ux.CustomSlider = Ext.extend(Object, {
    valueTextClass: 'x-slider-value-text',
    valueUnit: '',
    valueUnitPos: 'before',
    tooltipStyle: 'background-color: #FFF; text-align: center',
    showSliderBothEndValue: true,
    sliderEndValuePos: 'under',
    sliderEndValueStyle: 'color: green',

    constructor: function(config){
        Ext.apply(this, config);
        Ext.ux.CustomSlider.superclass.constructor.apply(this, arguments);
    },
    init: function(parent) {
        var me = this;
        parent.on({
            drag: {
                fn: function(slider, thumb, value) {
                    me.sliderTooltip.setWidth(value.length * 1.5);
                    me.sliderTooltip.showBy(thumb);
                    me.sliderTooltip.el.setHTML(value);
                }
            },
            dragend: {
                fn: function (slider, thumb, value) {
                    me.sliderTooltip.hide();
                    me.showSliderValue(this.valueTextEl, slider, thumb, value);
                }
            },
            afterrender: {
                fn: function(component) {
                    me.createSliderToolTip();
                    if (me.showSliderBothEndValue) me.showSliderEndValue(this);
                    if (!this.valueTextEl) {
                        this.valueTextEl = component.getEl().createChild({
                            cls: me.valueTextClass
                        });
                    }
                }
            }
        });
    },
    showSliderValue: function(valueTextEl, slider, thumb, value) {
        if (this.valueUnitPos == 'before') {
            valueTextEl.setHTML(this.valueUnit + value);
        } else {
            if (parseFloat(value) > 1) {
                valueTextEl.setHTML(value + '&nbsp' + this.valueUnit + 's');
            } else {
                valueTextEl.setHTML(value + '&nbsp' + this.valueUnit);
            }
        }
        
        var left = thumb.getEl().getX(),
        thumbWidth = thumb.getEl().getWidth(),
        thumbHeight = thumb.getEl().getHeight(),
        top = thumbHeight / 2,
        textWidth = valueTextEl.getWidth(),
        sliderLength = slider.getWidth();
        
        if (left > sliderLength - textWidth - thumbWidth) {
            left = left - textWidth - thumbWidth / 2;
        } else {
            left = left + thumbWidth / 2;
        }

        valueTextEl.setLeft(left);
        valueTextEl.setTop(top);        
    },
    showSliderEndValue: function(slider) {
        var sliderPosX = slider.getThumb().getEl().getX();
        var minValueEl = slider.getEl().createChild();
        minValueEl.setHTML(slider.minValue);
        minValueEl.applyStyles('overflow:hidden;position:absolute');
        minValueEl.applyStyles(this.sliderEndValueStyle);
        
        var thumbHeight = slider.getThumb().getEl().getHeight();
        minValueEl.setLeft(sliderPosX - 2);
        if (this.sliderEndValuePos == 'above') {
            minValueEl.setTop(-4);                            
        } else {
            minValueEl.setTop(thumbHeight + 2);
        }
        
        var maxValueEl = slider.getEl().createChild();
        maxValueEl.setHTML(slider.maxValue);
        maxValueEl.applyStyles('overflow:hidden;position:absolute');
        maxValueEl.applyStyles(this.sliderEndValueStyle);
        
        var sliderLength = slider.getEl().getWidth();
        var maxTextWidth = maxValueEl.getWidth();
        maxValueEl.setLeft(sliderLength - maxTextWidth - 25);
        if (this.sliderEndValuePos == 'above') {
            maxValueEl.setTop(-4);
        } else {
            maxValueEl.setTop(thumbHeight + 2);
        }
    },
    createSliderToolTip: function() {
        if (! this.sliderTooltip) {
            this.sliderTooltip = new Ext.Panel({
                floating: true,
                height: 30,
                styleHtmlContent: true,
                style: this.tooltipStyle
            });
        }   
    }
});

第 1 行到第 7 行是默认配置,可以在将此插件插入其容器时覆盖,并且如果其构造函数以上述方式设置。

插件将添加或修改的所有功能都在函数 init() 中。 在此函数中,非常重要的是要知道,在 parent.on({...}) 代码块中,代词 this 指的是插件的父级(即 Slider 类),而 me 指的是插件本身。

afterrender 事件处理程序中,一个工具提示面板由函数 createSliderToolTip 准备,供拖动事件使用。 函数 createSliderToolTip 为不同的插件实例创建不同的工具提示实例,并且可以通过更改插件的 tooltipStyle 选项来更改工具提示样式,请参见下面的屏幕截图

2.png    3.png

如果我们不想要不同的工具提示样式,那么我们可以重新编写该函数以在一个页面上仅创建一个工具提示面板,并在性能方面获得一点提升,就像这样

createSliderToolTip: function() {
	var sliderTooltip = Ext.getCmp('sliderTooltip');
	if (! sliderTooltip) {
		sliderTooltip = new Ext.Panel({
			floating: true,
			height: 30,
			id: 'sliderTooltip',
			styleHtmlContent: true,
			style: this.tooltipStyle
		});
	}
	this.sliderTooltip = sliderTooltip;        
}

以这种方式更改后,工具提示面板将采用第一个插件的样式配置(在本例中,只有 价格 字段中的 tooltipStyle 选项生效。重量 字段中的将被简单地忽略)。

同样重要的是,滑块值文本的 CSS 类应至少定义为具有绝对位置属性,以便我们可以将文本移动并对齐到我们想要的位置。 我的定义是

.x-slider-value-text {
	overflow:hidden;
	position:absolute;
	z-index:9999;
	color:rgb(255,55,55); 
}

有了这个,我们可以定位在 afterrender 事件处理程序中创建的那些元素,例如 valueTextElminValueElmaxValueEl。 函数 showSliderValueshowSliderEndValue 处理所涉及的定位和样式问题。

Using the Code

我们可以这样使用插件

items: [{
		xtype: 'sliderfield',
		minValue: 0,
		maxValue: 10000,
		increment: 0.5,
		id: 'price',
		plugins: [new Ext.ux.CustomSlider({
			valueUnit: '$',
			tooltipStyle: 'background-color: #AAA; text-align: center',
			showSliderBothEndValue: true,
			sliderEndValuePos: 'above'
		})],
		label: 'Price ($)'
	}, {
		xtype: 'sliderfield',
		increment: 0.5,
		id: 'weight',
		plugins: [new Ext.ux.CustomSlider({
			valueUnit: 'carat',
			tooltipStyle: 'background-color: #FFF; text-align: center',
			valueUnitPos: 'after',
			showSliderBothEndValue: true
		})],
		label: 'Weight (carat)'
	},
	...
}]
...

从这个例子中,我们可以看到我们可以自定义选项和样式,如值单位及其位置、工具提示样式、显示或不显示滑块的最小值和最大值。

如果我们不喜欢插件工作,只需从 plugins 选项中删除它(如果我们在位有一个以上的插件),或者完全删除 plugins 选项。

关注点

编写插件很有趣。 它并不像人们想象的那么困难。

© . All rights reserved.