系统滚动条实现的NUD控件Unusable版
来源:互联网 发布:商科留学 知乎 编辑:程序博客网 时间:2024/06/05 12:04
昨天研究了一下系统滚动条,准备使用它来实现一个NumericUpDown控件,因为它可以带来最正宗的微调按钮外观,并说了一下可以使用viewport里的onScroll事件来获取系统滚动条的上下点击动作。
同时昨天还说了onScroll事件的一个问题是,在点击了滚动条的上下按钮后,onScroll事件会被连续的触发n次(n取[1,4])。我们发现这些连续事件都在一个很小的timespan里触发的,也就在12ms以内。于是我们在onScroll事件中使用setTimeout来启动一次有意义的数值变化,代码如下,分支false用来判断点击的方向。
if ( NumericUpDown.ScrollBegin == 0 )
{
NumericUpDown.ScrollBegin = new Date().getTime();
NumericUpDown.ChangeNumeric.Element = elmt;
window.setTimeout(NumericUpDown.ChangeNumeric, 12);
}
else
{
var time = new Date().getTime();
if ( NumericUpDown.ScrollDirection == 0 )
{
var scrollOffset = NumericUpDown.ScrollTopValue - elmt.scrollTop;
NumericUpDown.ScrollDirection = scrollOffset > 0 ? 1 : -1;
NumericUpDown.ScrollTopValue = elmt.scrollTop;
}
}
{
NumericUpDown.ScrollBegin = new Date().getTime();
NumericUpDown.ChangeNumeric.Element = elmt;
window.setTimeout(NumericUpDown.ChangeNumeric, 12);
}
else
{
var time = new Date().getTime();
if ( NumericUpDown.ScrollDirection == 0 )
{
var scrollOffset = NumericUpDown.ScrollTopValue - elmt.scrollTop;
NumericUpDown.ScrollDirection = scrollOffset > 0 ? 1 : -1;
NumericUpDown.ScrollTopValue = elmt.scrollTop;
}
}
控件使用一个DIV,一个SPAN和一个INPUT type='hidden'来实现,DIV的overflow-y设为scroll,SPAN用来显示当前的数值,INPUT type='hidden'用来存放控件当前的数值。
<div tabindex="0" Step="1" Precision="0" onscroll="NumericUpDown.DoScroll(this)"
style="cursor: default; border: solid 1px red; overflow-y: scroll; width: 50;
height: expression(this.all.tags('SPAN')[0].offsetHeight);">
<span style="display: block; white-space: nowrap; text-indent: 2;">1span><input
type="hidden" id="Hidden1" value="1" />div>
由于在这个页面上注入代码太麻烦了,就把demo放到这里了。虽然这个NumericUpDown自然的就可以支持键盘Up & Down和PageUp & PageDown,可是最后一个问题却真的没有招了,以至于我最终只能放弃这个尝试了。看看demo,框里的数字有些抖动是吧?这是系统的默认行为,而且点击的越快,抖的也越快,真的没有办法了。
所以完成了也只能叫做Unusable版...
style="cursor: default; border: solid 1px red; overflow-y: scroll; width: 50;
height: expression(this.all.tags('SPAN')[0].offsetHeight);">
<span style="display: block; white-space: nowrap; text-indent: 2;">1span><input
type="hidden" id="Hidden1" value="1" />div>
由于在这个页面上注入代码太麻烦了,就把demo放到这里了。虽然这个NumericUpDown自然的就可以支持键盘Up & Down和PageUp & PageDown,可是最后一个问题却真的没有招了,以至于我最终只能放弃这个尝试了。看看demo,框里的数字有些抖动是吧?这是系统的默认行为,而且点击的越快,抖的也越快,真的没有办法了。
所以完成了也只能叫做Unusable版...
初始化控件的时候,再动态添加两个SPAN分别到默认SPAN的两端,这是因为滚动条如果处在任何一个顶端(top或bottom)是不会触发onScroll事件的,也就是说要把默认那个SPAN放到DIV的正中间,前后在分别有一个SPAN。
elmt.Current = elmt.Input.value;
var current = parseInt(elmt.Current);
var step = parseInt(elmt.Step);
var previousSpan = NumericUpDown.CreateSpan();
previousSpan.innerText = current - step;
var nextSpan = NumericUpDown.CreateSpan();
nextSpan.innerText = current + step;
var currentSpan = elmt.all.tags('SPAN')[0];
currentSpan.insertAdjacentElement('beforeBegin', previousSpan);
currentSpan.insertAdjacentElement('afterEnd', nextSpan);
NumericUpDown.ScrollTo.CurrentSpan = currentSpan;
window.setTimeout(NumericUpDown.ScrollTo, 1);
elmt.IsInitialized = true;
var current = parseInt(elmt.Current);
var step = parseInt(elmt.Step);
var previousSpan = NumericUpDown.CreateSpan();
previousSpan.innerText = current - step;
var nextSpan = NumericUpDown.CreateSpan();
nextSpan.innerText = current + step;
var currentSpan = elmt.all.tags('SPAN')[0];
currentSpan.insertAdjacentElement('beforeBegin', previousSpan);
currentSpan.insertAdjacentElement('afterEnd', nextSpan);
NumericUpDown.ScrollTo.CurrentSpan = currentSpan;
window.setTimeout(NumericUpDown.ScrollTo, 1);
elmt.IsInitialized = true;
控件NumericUpDown代码为:
<script language="javascript">
function NumericUpDown()
{
this.toString = function()
{
return '[class NumericUpDown]';
};
}
NumericUpDown.InitializeAll = function()
{
var muds = document.all.tags('DIV');
for ( var i=0 ; i < muds.length ; ++i )
{
var mud = muds[i];
if ( typeof(mud.Step) != 'undefined' && mud.onscroll )
{
NumericUpDown.Initialize(mud);
}
}
};
NumericUpDown.Initialize = function(elmt)
{
if ( !elmt.IsInitialized )
{
var inputs = elmt.all.tags('INPUT');
if ( inputs.length == 1 )
{
elmt.Input = inputs[0];
}
else
{
throw 'must have an INPUT element in DIV.';
}
elmt.Current = elmt.Input.value;
var current = parseInt(elmt.Current);
var step = parseInt(elmt.Step);
var previousSpan = NumericUpDown.CreateSpan();
previousSpan.innerText = current - step;
var nextSpan = NumericUpDown.CreateSpan();
nextSpan.innerText = current + step;
var currentSpan = elmt.all.tags('SPAN')[0];
currentSpan.insertAdjacentElement('beforeBegin', previousSpan);
currentSpan.insertAdjacentElement('afterEnd', nextSpan);
NumericUpDown.ScrollTo.CurrentSpan = currentSpan;
window.setTimeout(NumericUpDown.ScrollTo, 1);
elmt.IsInitialized = true;
}
};
NumericUpDown.ScrollTo = function()
{
var currentSpan = NumericUpDown.ScrollTo.CurrentSpan;
currentSpan.parentElement.scrollTop = currentSpan.offsetHeight;
NumericUpDown.ScrollTopValue = currentSpan.offsetHeight;
};
NumericUpDown.CreateSpan = function()
{
var span = document.createElement('SPAN');
span.style.display = 'block';
span.style.whiteSpan = 'nowrap';
span.style.textIndent = 2;
return span;
};
NumericUpDown.ScrollBegin = 0;
NumericUpDown.ScrollDirection = 0;
NumericUpDown.ScrollTopValue = 0;
NumericUpDown.DoScroll = function(elmt)
{
if ( !elmt || elmt.tagName != 'DIV' )
{
return;
}
if ( NumericUpDown.ScrollBegin == 0 )
{
NumericUpDown.ScrollBegin = new Date().getTime();
NumericUpDown.ChangeNumeric.Element = elmt;
window.setTimeout(NumericUpDown.ChangeNumeric, 12);
}
else
{
var time = new Date().getTime();
if ( NumericUpDown.ScrollDirection == 0 )
{
var scrollOffset = NumericUpDown.ScrollTopValue - elmt.scrollTop;
NumericUpDown.ScrollDirection = scrollOffset > 0 ? 1 : -1;
NumericUpDown.ScrollTopValue = elmt.scrollTop;
}
}
};
NumericUpDown.ChangeNumeric = function()
{
var elmt = NumericUpDown.ChangeNumeric.Element;
status = NumericUpDown.ScrollDirection;
NumericUpDown.ScrollTo();
var span = elmt.all.tags('SPAN')[1];
var step = parseInt(elmt.Step);
var value = parseInt(span.innerText);
var input = elmt.all.tags('INPUT')[0];
span.innerText = value + NumericUpDown.ScrollDirection*step;
input.value = span.innerText;
NumericUpDown.ScrollBegin = 0;
NumericUpDown.ScrollDirection = 0;
};
script>
function NumericUpDown()
{
this.toString = function()
{
return '[class NumericUpDown]';
};
}
NumericUpDown.InitializeAll = function()
{
var muds = document.all.tags('DIV');
for ( var i=0 ; i < muds.length ; ++i )
{
var mud = muds[i];
if ( typeof(mud.Step) != 'undefined' && mud.onscroll )
{
NumericUpDown.Initialize(mud);
}
}
};
NumericUpDown.Initialize = function(elmt)
{
if ( !elmt.IsInitialized )
{
var inputs = elmt.all.tags('INPUT');
if ( inputs.length == 1 )
{
elmt.Input = inputs[0];
}
else
{
throw 'must have an INPUT element in DIV.';
}
elmt.Current = elmt.Input.value;
var current = parseInt(elmt.Current);
var step = parseInt(elmt.Step);
var previousSpan = NumericUpDown.CreateSpan();
previousSpan.innerText = current - step;
var nextSpan = NumericUpDown.CreateSpan();
nextSpan.innerText = current + step;
var currentSpan = elmt.all.tags('SPAN')[0];
currentSpan.insertAdjacentElement('beforeBegin', previousSpan);
currentSpan.insertAdjacentElement('afterEnd', nextSpan);
NumericUpDown.ScrollTo.CurrentSpan = currentSpan;
window.setTimeout(NumericUpDown.ScrollTo, 1);
elmt.IsInitialized = true;
}
};
NumericUpDown.ScrollTo = function()
{
var currentSpan = NumericUpDown.ScrollTo.CurrentSpan;
currentSpan.parentElement.scrollTop = currentSpan.offsetHeight;
NumericUpDown.ScrollTopValue = currentSpan.offsetHeight;
};
NumericUpDown.CreateSpan = function()
{
var span = document.createElement('SPAN');
span.style.display = 'block';
span.style.whiteSpan = 'nowrap';
span.style.textIndent = 2;
return span;
};
NumericUpDown.ScrollBegin = 0;
NumericUpDown.ScrollDirection = 0;
NumericUpDown.ScrollTopValue = 0;
NumericUpDown.DoScroll = function(elmt)
{
if ( !elmt || elmt.tagName != 'DIV' )
{
return;
}
if ( NumericUpDown.ScrollBegin == 0 )
{
NumericUpDown.ScrollBegin = new Date().getTime();
NumericUpDown.ChangeNumeric.Element = elmt;
window.setTimeout(NumericUpDown.ChangeNumeric, 12);
}
else
{
var time = new Date().getTime();
if ( NumericUpDown.ScrollDirection == 0 )
{
var scrollOffset = NumericUpDown.ScrollTopValue - elmt.scrollTop;
NumericUpDown.ScrollDirection = scrollOffset > 0 ? 1 : -1;
NumericUpDown.ScrollTopValue = elmt.scrollTop;
}
}
};
NumericUpDown.ChangeNumeric = function()
{
var elmt = NumericUpDown.ChangeNumeric.Element;
status = NumericUpDown.ScrollDirection;
NumericUpDown.ScrollTo();
var span = elmt.all.tags('SPAN')[1];
var step = parseInt(elmt.Step);
var value = parseInt(span.innerText);
var input = elmt.all.tags('INPUT')[0];
span.innerText = value + NumericUpDown.ScrollDirection*step;
input.value = span.innerText;
NumericUpDown.ScrollBegin = 0;
NumericUpDown.ScrollDirection = 0;
};
script>
- 系统滚动条实现的NUD控件Unusable版
- 实现外部控件滚动条控制Dsoframer word的滚动
- 滚动条的实现;
- MFC EditBox控件滚动条保持在底部的实现
- 仿网易ios滚动条控件的实现
- MFC之picture控件滚动条的实现
- 滚动条控件的测试
- 滚动条控件的使用
- 用系统滚动条实现NumericUpDown的原理
- NUD
- 窗口滚动条与滚动条控件的区别
- 控件的滚动实现
- C# panel控件实现鼠标滚轮滚动拖动滚动条
- 实现Ajax的滚动条
- 页面滚动条的实现
- 树控件的滚动条的隐藏
- *控件*有滚动条的LISTBOX
- 去掉树控件的水平滚动条
- 用户定制Web页中元素的排版布局策略
- 关于HTML Object中三个Style实例的区别
- 使用button元素自定义别具风格的按钮
- 用系统滚动条实现NumericUpDown的原理
- 从JEDI里面提取出来的Hash函数
- 系统滚动条实现的NUD控件Unusable版
- 细说HTML元素的ID和Name属性的区别
- 挺好玩的uniqueID&uniqueNumber属性
- 终于开始读核了-1-内核的引导(核内引导)
- 程序员创业成功必须遵守的几条铁律
- 分久必合 - Vista、Visual Studio Orcas、SilverLight、Expression Studio、WPF、XAML 给我们带来的开发趋势
- 精通CSS(层叠样式单)语法请帮忙看看
- [BCB]怎样让程序脱离BCB独立运行
- JavaScript中的5种事件使用方式解说