Showing posts with label keyCode. Show all posts
Showing posts with label keyCode. Show all posts

Sunday, August 17, 2008

AutoCompleter from local based on Prototype


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>completer demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="/lib/prototype.js" type="text/javascript"></script>
<style type="text/css">
body {
font: 11px Lucida Grande, Verdana, Arial, Helvetica, sans serif;
}
</style>
</head>
<body>
<br/>
<div id="content">
<form>
input "a" for test:
<input id="message" name="message" size="30" type="text" />
<input type="submit" value="submit"/>
</form>
<script type="text/javascript">
//<![CDATA[
var contacts = ["aa", "aaa", "aaaa", "abb", "abbb", "ac", "acc", "accc", "aac", "aaac", "bc", "ad", "aad", "aaad", "aaaad", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "中文字体", "测试~!@#$%^&*()/?\"\\';", "北京奥运会", "姚明&刘翔"];

AutoFieldFromLocal = Class.create({
initialize: function(element, items){
this.element = $(element);
this.value = this.element.value;
this.items = items;
this.timer = null;
this.observer = null;
this.counter = 0;
this.index = 0;
this.listElements = [];
this.listsObserved = false;
this.maskShowed = false;
this.divId = "auto_complete_for_" + this.element.id;
this.listsId = "lists_of_" + this.element.id;
this.maskId = "mask_" + this.element.id;
this.element.setAttribute('autocomplete', 'off');
this.insertAfter();
this.observerStart();
},
insertAfter: function(){
new Insertion.After(this.element,
'<div id="' + this.divId + '" style="position:absolute;background-color:#fff;border:1px solid #888;margin:0;padding:0;display:none;height:200px;opacity:0.90;overflow:auto;overflow-x:hidden;z-index:1;filter:alpha(opacity=90);">' +
'<ul id="' + this.listsId + '" style="margin:0;padding:0;list-style-type: none;width:100%;"></ul></div>' +
'<div id="' + this.maskId + '" style="position:absolute;background-color:blue;border:1px solid #888;margin:0;padding:0;display:none;height:0;opacity:0;z-index:2;filter:alpha(opacity=0);"/>'
);
this.completerDiv = $(this.divId);
this.list = $(this.listsId);
this.mask = $(this.maskId);
},
observerStart: function(){
// safari/ie中监听keypress时,arrow keys箭头无法正确激活绑定的事件,改用keydown监听
// Arrow keys no longer result in keypress events, now processed in keydown default event handler
// Reference: https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html
// keydown/keypress区别参考ppk的文章: http://www.quirksmode.org/dom/events/keys.html
if (Prototype.Browser.WebKit || Prototype.Browser.IE) Event.observe(this.element, 'keydown', this.renderLists.bindAsEventListener(this));
else Event.observe(this.element, 'keypress', this.renderLists.bindAsEventListener(this));
Event.observe(this.element, 'blur', this.onBlured.bindAsEventListener(this));
Event.observe(document, 'mousemove', this.hideMask.bindAsEventListener(this));
},
addListsObserver: function(){
var self = this;
this.listElements.each(function(li){
Event.observe(li, 'mouseover', self.onMouseOverList.bindAsEventListener(self));
Event.observe(li, 'click', self.updateField.bindAsEventListener(self));
});
this.hideMask();
},
hideMask: function() {
if (this.maskShowed) {
this.maskShowed = false;
this.mask.style.height = '0px';
this.mask.style.display = "none";
}
},
showMask: function(){
if (!this.maskShowed) {
this.maskShowed = true;
this.mask.style.height = this.completerDiv.clientHeight + 'px';
this.mask.style.display = "block";
}
},
onBlured: function(){
var self = this;
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(function(){
self.hideMask();
self.completerDiv.hide();
}, 100);
},
updateField: function(){
this.element.focus();
if(this.listElements.length > 0 && this.index != -1)
this.element.value = this.listElements[this.index].innerHTML.replace(/&/, "&");
this.completerDiv.hide();
this.hideMask();
},
listsShowed: function(){
return this.completerDiv.style.display.toLowerCase() == 'block';
},
onSelectList: function(){
this.listElements.each(function(li){
li.style.backgroundColor = "#fff";
});
this.listElements[this.index].style.backgroundColor = "#ffb";
},
divScrollTop: function() {
var maxScrollTop = this.completerDiv.scrollHeight - this.completerDiv.clientHeight;
var scrollBottom = this.completerDiv.clientHeight + this.completerDiv.scrollTop;
var listHeight = this.listElements[0] ? this.listElements[0].clientHeight : 20;
// TODO , get li.clientHeight after insert li element and then remove it if ul list has no li child.
if (this.index == 0)
this.completerDiv.scrollTop = 0;
else if (this.index == this.listElements.length - 1)
this.completerDiv.scrollTop = maxScrollTop;
else if (this.index * listHeight < this.completerDiv.scrollTop)
this.completerDiv.scrollTop = this.index * listHeight;
else if (this.index * listHeight >= scrollBottom)
this.completerDiv.scrollTop = this.completerDiv.scrollTop + listHeight;
},
markNextList: function(){
this.showMask();
if(this.index < this.counter - 1) this.index++
else this.index = 0;
this.divScrollTop();
this.onSelectList();
},
markPrevList: function(){
this.showMask();
if(this.index > 0 ) this.index--
else this.index = this.counter - 1;
this.divScrollTop();
this.onSelectList();
},
onMouseOverList: function(event){
var elementLI = Event.findElement(event, 'LI');
this.index = this.listElements.indexOf(elementLI);
this.listElements.each(function(li){
li.style.backgroundColor = "#fff";
});
elementLI.style.backgroundColor = "#ffb";
// this.divScrollTop();
},
renderLists: function(event){
switch(event.keyCode) {
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_ESC:
this.completerDiv.hide();
this.hideMask();
// esc will also empty input field in ie by default, prevent default event.
Event.stop(event);
this.index = -1;
return;
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.updateField();
Event.stop(event);
return;
case Event.KEY_DOWN:
if (this.listsShowed()) {
this.markNextList();
return;
}
case Event.KEY_UP:
if (this.listsShowed()) {
this.markPrevList();
return;
}
}
if (this.observer) clearTimeout(this.observer);
var self = this;
this.observer = setTimeout(function(){self.onFieldChange(event)}, 100);
},
onFieldChange: function(event){
var value = this.element.value.strip();
var autoWidth = this.element.getWidth();
var find = false;
var listItems = "";
this.counter = 0;
this.index = -1;
var self = this;
if (Prototype.Browser.IE || this.value != value || event.keyCode == Event.KEY_DOWN) {
this.value = value;
this.items.each(function(item){
if (item.include(self.value)) {
self.counter ++;
// li element defaults line-height is different in different browser:
// safari 13px, firefox3 14px
// li width must be set 100% and display block for ie, and ie scrollbar movement has related with li width, sign...
// font size should be little than 14px in ie
listItems += "<li style='line-height:14px;padding:3px;margin:0;display:block;width:100%;cursor:default;'>" + item + "</li>";
if (!find) find = true;
}
});
}
if (find) {
this.list.innerHTML = listItems;
var pos = Position.cumulativeOffset(this.element);
this.completerDiv.style.width = this.mask.style.width = (autoWidth - 2) + "px";
this.completerDiv.style.left = this.mask.style.left = pos[0] + "px";
this.completerDiv.style.top = this.mask.style.top = (pos[1] + this.element.getHeight() - 1) + "px";
this.completerDiv.style.display = "block";
this.listElements = this.list.childElements();
this.addListsObserver();
} else {
this.completerDiv.hide();
this.hideMask();
}
}
});

var af = new AutoFieldFromLocal('message', contacts);
//]]>
</script>
</div>

</body>
</html>

需要注意一下以下几点:
1、在safari/ie中对于arrow keys事件的处理方式和keydown/keypress二者区别。
2、在ie中esc默认行为会将input框中的值一起cancel。
3、在firefox中mouseover事件的控制,在用arrow keys移动选项时,用一个蒙板挡住了mouse,以防触发mouseover事件。
4、setTimeout()方法中的this需要小心其指向全局的window。
5、当y轴出现滚动条时,其实际可以滚动的长度不是element.scrollHeight,而应该是此值减去element.clientHeight。
6、IE中控制滚动条用overflow:auto; overflow-x:hidden;
7、IE中滚动条和LI元素的宽度有关系,要控制滚动条则需要设置LI宽度为100%。
8、对&作特殊处理。

Sunday, July 15, 2007

Javascript keyCode


<script type="text/javascript" charset="utf-8">
<!--
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}

function isNumberInput(field, event)
{
var key, keyChar;
if (window.event) {
key = window.event.keyCode;
alert(key);
} else if (event) {
key = event.which;
code = event.keyCode;
var d1 = document.getElementById('d1');
d1.appendChild(document.createTextNode(key + "(key)=" + String.fromCharCode(event.which) + "(code) \n"));
// event.shiftKey and event.altKey, Mozilla provides a mapping for the keys, so you could do something. like:
if (event.keyCode == event.DOM_VK_TAB){
alert('TAB is pressed');
} else if (event.keyCode == event.DOM_VK_F1){
alert('F1 is pressed');
}
} else {
return true;
}
// Check for special characters like backspace(8), enter return(13), tab(9), escape(27) etc.
if (key == null || key == 0 || key == 8 || key == 13 || key == 27) {
return true;
}

// Check to see if it's a number
keyChar = String.fromCharCode(key);
if (/\d/.test(keyChar))
{
window.status = "";
return true;
}
else
{
window.alert("Field accepts numbers only.");
return false; // not input error keypress
}
}
//-->
</script>
<div id="d1">

</div>
<form name="testform" id="testform" action="#" method="get">
Robot Serial Number:
<input type="text" name="serialnumber" id="serialnumber" size="10" maxlength="10"
onkeypress="return isNumberInput(this, event);" title="Serial number contains only digits" />
</form>

Using Keyboard Events

Prior to the release of Netscape 4.0, JavaScript programs couldn't detect keyboard
actions—just mouse actions. This made it difficult to create some types of programs
in JavaScript. For example, games were difficult to play using Go Left and Go Right
buttons.

Thankfully, JavaScript 1.2 and later can detect keyboard actions. The main event
handler for this purpose is onKeyPress, which occurs when a key is pressed and
released, or held down. As with mouse buttons, you can detect the down and up parts
of the keypress with the onKeyDown and onKeyUp event handlers.

Of course, you may find it useful to know which key the user pressed. You can find
this out with the event object, which is sent to your event handler when the event
occurs. In Netscape, the event.which property stores the ASCII character code for the
key that was pressed. In Internet Explorer, event.keyCode serves the same purpose.

NOTE

ASCII (American Standard Code for Information Interchange) is the standard numeric
code used by most computers to represent characters. It assigns the numbers 0–128 to
various characters—for example, the capital letters A through Z are ASCII values 65
to 90.

Displaying Typed Characters

If you'd rather deal with actual characters than key codes, you can use the
fromCharCode string method to convert them. This method converts a numeric ASCII code
to its corresponding string character. For example, the following statement converts
Netscape's event.which property to a character and stores it in the key variable:

Key = String.fromCharCode(event.which);

Since Internet Explorer and Netscape have different ways of returning the key code,
displaying keys browser-independently is a bit harder. However, you can create a
script that displays keys for either browser. The following function will display
each key in the status line:

function DisplayKey(e) {
if (e.keyCode) keycode=e.keyCode;
else keycode=e.which;
character=String.fromCharCode(keycode);
window.status += character;
}

The DisplayKey function receives the event object from the event handler and stores
it in the variable e. It checks whether the e.keyCode property exists, and stores it
in the keycode variable if present. Otherwise, it assumes the browser is Netscape and
assigns keycode to the e.which property.

Key Pressed Javascript Key Code
backspace 8
tab 9
enter 13
shift 16
ctrl 17
alt 18
pause/break 19
caps lock 20
escape 27
page up 33
page down 34
end 35
home 36
left arrow 37
up arrow 38
right arrow 39
down arrow 40
insert 45
delete 46
0 48
1 49
2 50
3 51
4 52
5 53
6 54
7 55
8 56
9 57
a 65
b 66
c 67
d 68
e 69
f 70
g 71
h 72
i 73
j 74
k 75
l 76
m 77
n 78
o 79
p 80
q 81
r 82
s 83
t 84
u 85
v 86
w 87
x 88
y 89
z 90
left window key 91
right window key 92
select key 93
numpad 0 96
numpad 1 97
numpad 2 98
numpad 3 99
numpad 4 100
numpad 5 101
numpad 6 102
numpad 7 103
numpad 8 104
numpad 9 105
multiply 106
add 107
subtract 109
decimal point 110
divide 111
f1 112
f2 113
f3 114
f4 115
f5 116
f6 117
f7 118
f8 119
f9 120
f10 121
f11 122
f12 123
num lock 144
scroll lock 145
semi-colon 186
equal sign 187
comma 188
dash 189
period 190
forward slash 191
grave accent 192
open bracket 219
back slash 220
close braket 221
single quote 222