javascript

Web前端开发QQ群 110939958-业余程序员

关于js的键盘事件

以前总结过各个浏览器中键盘事件的触发情况,可以看出keydown, keyup是比较靠谱的

因为它们是系统提供的比较底层的事件,对应的是键码keyCode标识了哪个键被按下(并不知道输入的是哪个字符)

keypress事件能够给出输入的可打印字符,但是这个事件在各个浏览器和操作系统中存在着很多不兼容性
在火狐中,在keypress中event.charCode保存了键入字符的ASCLL码,而其它的浏览器可以使用keyCode,
要想获得这个字符可以使用String.fromCharCode()

阻止默认行为

用户的键入是可以用js来阻止的,相关代码对应为IE的 returnValue=false;和标准浏览器的preventDefault();
实际中遇到的情况:
除了Opera,在keydown的时候阻止时就可以取消键入的事件
而Opera中需要在keypress的时候阻止。

WebIme测试版

一个通用的web输入法前端
目前实现了基本功能。
主要有:

  1. 左右键移动光标
  2. 上下键移动选词
  3. 自动翻页
  4. 全/半角
  5. 切换输入引擎

已测试的浏览器:

  • firefox
  • opera
  • ie8
  • chrome

已知兼容问题: IE6

测试地址:http://www.jatx.net/lib/webime/demo.html

有国为证:

webime

webime

UI.Window组件

更新了一个Window组件:

基本功能:

  • 拖动标题
  • 拖动边框和右下角
  • 设置标题和内容
  • 设置大小和位置
  • 自定义皮肤

这次主要加入的内容有:

  1. WindowManager
  2. Button类
  3. 边界检测
  4. 层级关系
  5. 新的chrome皮肤

已测试的浏览器:

  • IE8
  • FF3
  • chrome6
  • oprea10

演示地址:http://www.jatx.net/UI/window/window.html

[]==false之原理

问题来源

var a = [];

if(a) alert("true");//true

if(a == true) alert("true");//false

原理

js引擎会先计算括号内的表达式然后将结果转换为布尔值,所以

if(a) => if(!!a) => true

if(a == true) => if(Number(a) == true) => if(0 == true) => false

注: 在比较的两个值中,如果有一个是布尔类型,那么另外一个值将会先被转换为数字类型再与其比较。

参考: 双等号的比较原理

所以,下面这个就会有看起来奇怪的结果

[] == ![] //true

超长叠代

for(var i=0; i<1000000; i++) {
    //do some thing.
}

话说以上代码很可能会被浏览器判作执行超时。

试验了一下可以用浏览器的延时来做:

(function() {
    //do some thing.
    setTimeout(arguments.callee, 0);
})();


这样一来CPU倒是基本没有,但是这样的代码运行过慢,所以综合一下:

<!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">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title> new document </title>
  <script type="text/javascript">

	var interval = function(f, o) {
		var _onceRunTime = 5000;//每5秒一个新的任务队列
		var i = 0;
		(function() {
			var _st = new Date().getTime();
			while(true) {
				if(new Date().getTime() - _st > _onceRunTime) break;
				if(!f.call(o, i)) return;
				i++;
			}
			setTimeout(arguments.callee, 0);
		})();
	};
	function run(i) {
		document.getElementById("log").value = i;
		return i<1000000;
	}

	function test() {
		interval(run, this);
	}
  </script>
 </head>

 <body>
  <input type="text" id="log" /> <button id="b" onclick="test();">start</button>
 </body>
</html>

注意运行时也会使浏览器无反应,不过在每一个任务队列结束时仍然有机会刷新面。

双等号的比较原理

直接摘自ECMA262

章节号:11.9.3 The Abstract Equality Comparison Algorithm

比较 x == y, 当 x 和 y 都是值的时候, 产生truefalse. 这样的一个比较执行如下:

  1. If Type(x) is the same as Type(y), then
    1. If Type(x) is undefined, return true.
    2. If Type(x) is Null, return true.
    3. If Type(x) is Number, then
      1. If x is NaN, return false.
      2. If y is NaN, return false.
      3. If x is the same Number value as y, return true.
      4. If x is +0 and y is −0, return true.
      5. If x is −0 and y is +0, return true.
      6. Return false.
    4. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.
    5. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
    6. Return true if x and y refer to the same object. Otherwise, return false.
  2. If x is null and y is undefined, return true.
  3. If x is undefined and y is null, return true.
  4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
  5. If Type(x) is String and Type(y) is Number,
    return the result of the comparison ToNumber(x) == y.
  6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
  7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
  8. If Type(x) is either String or Number and Type(y) is Object,
    return the result of the comparison x == ToPrimitive(y).
  9. If Type(x) is Object and Type(y) is either String or Number,
    return the result of the comparison ToPrimitive(x) == y.
  10. Return false.

NOTE 1 鉴于以上相等的定义:
• 可以这样强制字符串比较: "" + a == "" + b.
• 可以这样强制数字比较: +a == +b.
• 可以这样强制布尔值比较:!a == !b.
NOTE 2 双等比较保持以下的不变式:
•  A != B 等价于 !(A == B).
•  A == B 等价于 B == A, 除了A和B求值的顺序不同
NOTE 3 The equality operator is not always transitive. For example, there might be two distinct String objects, each
representing the same String value; each String object would be considered equal to the String value by the == operator,
but the two String objects would not be equal to each other.
NOTE 4 Comparison of Strings uses a simple equality test on sequences of code unit values. There is no attempt to
use the more complex, semantically oriented definitions of character or string equality and collating order defined in the
Unicode specification. Therefore Strings values that are canonically equal according to the Unicode standard could test as unequal. In effect this algorithm assumes that both Strings are already in normalised form.

最近这部分待译

自定义事件之双击按键

遇到这样的需求,双击按键的事件
还是直接上代码吧:

//首先准备好常规的事件绑定函数
function addEvent(element, name, callback) {
	//标准浏览器
	if(element.addEventListener) element.addEventListener(name, callback, false);
	//IE
	else element.attachEvent("on" + name, callback);
}
//双击按键绑定函数
function addDblPressEvent(element, callback) {
	var presstime = 2;//次数为2
	addEvent(element, "keyup", press);
	//每次单击触发
	function press(e) {
		presstime--;
		setTimeout(reset, 300);
		if(presstime === 0) fire(e);
	}
	//恢复计数器
	function reset() {
		presstime++;
	}
	//触发双击
	function fire(e) {
		callback.call(element, e);
	}
}

//试一下
window.onload = function() {
	addDblPressEvent(document, function(e) {
		console.log("double clicked");
	});
}