Archive for the ‘Javascript’ Category

Internet Explorer无法打开站点,已终止操作
Wednesday, April 23rd, 2008

看到这个对话框,谁都会骂微软的娘,妈的,又来浪费老子时间!不过我们骂也就是出出气而已,大部分人群智商比较低,造成了微软市场运作的成功。

关于这个问题比较合理的解释,这里有一个

在页面还没有ready的时候就调用了htmlObject的appendChild或者innerHTML操作,这样会在IE上弹出一个对话框:“Internet Explorer无法打开站点,已终止操作”

解决方法有两个:

  • 在appendChild或者innerHTML操作处判断document.readyState==”complete”, 若为否,则setTimeout若干秒之后重新作这个操作。

    但是,此属性只对ie,opeara有效,ff的document没有readyState属性,永远是undefined.

  • 在script中使用defer属性。意在页面加载完毕后再执行脚本,这样可以避免找不到对象的问题。defer不会考虑外部文件是否全部下载完,只会判当前页面是否全部加载完成。并且,有defer标签的代码块里不能写document.write方法

和一般的javascript语法错误不一样,即使启用了脚本调试,IE也不会让你去调试这个错误。所以看到这个对话框,你就应该检查哪些javascript语句在文档还没有load完成时执行了一些dom操作。

除了上文提到的两种办法,当然也可以把这些操作放在页面的onload事件处理中执行。

Ajax.Autocompleter不支持中文
Wednesday, April 16th, 2008

最近在使用scriptaculous/完成项目中的一处自动提示功能时,发现Ajax.Autocompleter对中文支持很不好。

我用的是Google拼音输入法,在输入汉字的拼音时,输入完第一个字母后即触发输入框的事件,js就向服务器查询相应的匹配。实际上此时汉字尚未上屏,出来的匹配是该汉字首字母匹配(英文的)。这样,自动提示功能不仅毫无用处,而且会让用户莫名其妙。

一番探索之后,发现scriptaculous是在捕捉到keypress事件时向后台发起查询请求的,我仅简单地把keypress改为keyup,即解决了支持中文输入的问题。显然,这是由于输入法在浏览器的更上层处理了键盘事件的缘故。不过本方法没有经过广泛的测试,我只是在Firefox+Google拼音这个组合中试验通过。

似乎现在jQuery的发展正如日中天,各种插件数不胜数。尽管Prototype以及基于它而来的一些js library仍旧占据着很大的市场,但相对于jQuery来说已经是在走下坡路。

script.aculo.us实现Gmail联系人自动补全
Monday, July 30th, 2007

摘自script.aculo.us首页:

script.aculo.us provides you with easy-to-use, cross-browser user interface JavaScript libraries to make your web sites and web applications fly.

What’s inside? animation framework, drag and drop, Ajax controls DOM utilities, and unit testing.

It’s an add-on to the fantastic Prototype framework.

用script.aculo.us有一段时间了,它实现的效果很美观实用,用起来又非常简单,非常舒服。最初的时候我为一个drag drop的任务头疼,后来发现了它,一句代码搞定,真是太爽了。

如果让你现在做一个像Gmail写邮件时自动补全地址的功能,一定会觉得无从下手。是啊,动态创建提示列表,方向键处理,回车,Tab,还不知道在各种浏览器中调试多少次才可以,好麻烦!

别急,有script.aculo.us,这个工作简单了很多。我们用Autocompleter.Local来实现这个效果。先给个效果看看:




我不想为它专门改一下blog模板加个CSS,所以候选项的样式不是很好,分不清哪个被选中了。你可以在上面输入字幕”b”,然后用鼠标点击一个选项。实际使用的时候一定是需要样式的,这样方便用上下方向键选择(现在也可以按上下键然后回车,只是没有表现)。javascipt我也是引用的script.aculo.us的,如果是自己用,可以下载一份到自己的服务器上。

代码我就不再写一遍了,你可以自己查看本页面的源代码。关键就是一句代码:

new Autocompleter.Local(”autocompleter”, “popup-options”, ["aaa", "abc", "bbb", "bbc", "bcd", "cdd"],
{frequency: 0.1, tokens: “,”, afterUpdateElement: function(element) {element.value+=”, “;}}
);

第一个参数是那个input的id,第二个参数是显示後选项的元素的id,第三个参数是候选项数组。第四个参数是选项。tokens指定分隔符,我这里指定了逗号,那么它就会对最后一个逗号后面的内容进行补全操作。afterUpdateElement我定义了一个函数,在输入框中加上一个”, “,这样就可以输入多个项了。

和Gmail的差距?你可以把input换成textarea,加上CSS试一下。我觉得不比Gmail差。

除了可以根据参数中的数组进行补全,script.aculo.us还提供了更多的功能,如通过Ajax请求从服务器取得补全列表。

script.aculo.us的文档其实还不是特别完善。如果你有这样的需求,建议你阅读这几个页面:

其中Ajax.Autocompleter的介绍最为详尽,其中的许多选项是Autocompleter.Local也接受的。有必要的时候可以看script.aculo.us的源代码,它是最权威的文档。

form的onsubmit属性
Monday, July 30th, 2007

在对一个表单(form)进行客户端检验的时候,我们已经习惯了<form onsubmit=”return check()”>这样的形式,如果表单没有通过验证,在check函数中return false就会阻止表单的提交了。

然而,如果要动态地为一个表单添加验证,即HTML代码中没有写onsubmit,而在页面加载后用javascript给这个form加一个handler,问题就来了。

假设我们已经得到了表单的DOM节点,保存在变量form中,一般这样来给它加上handler:

if (form.addEventListener) {
form.addEventListener(”submit”, check, false);
} else if (form.attachEvent) {
form.attachEvent(”onsubmit”, check);

但是这个check函数现在应该怎么写呢?验证失败时,仅仅写一个”return false;”在Firefox中是不能阻止表单的提交的(在IE中可以),这就是为什么大家在onsubmit属性中要写”return check()”,而不仅仅是”check()”。

请看ECMAScript Language Binding,其中明确地写着,event listener没有返回值。其实一切的根本都因为IE不支持DOM Level 2,大家都习惯了IE的return false,到了Firefox中也只是一个ugly的变通,而很少去注意正确的做法。

下面是一个可以被动态地attach(见上面的代码)的check函数:

function check() {
if (e && e.preventDefault) e.preventDefault();
return false;
}

在IE和Firefox中,它都可以被动态挂载为onsubmit的handler而且正常工作。

万恶的IE!

想学一下javascript
Sunday, December 17th, 2006

最近对Web编程比较感兴趣了。javascript这些脚本语言语法限制相对C之类的较为宽松,看书也就是浏览一下,主要功夫还在练习上。学习C/C++/Java语言千万别看那种“24小时学会……”的书,纯粹是垃圾,应该看”The C Programming Language”之类的,把语法以及与底层联系实现紧密的一些概念搞清楚。

Javascript就不同了,似乎没有像C语言之类的有那么几本特别权威经典的书籍,别捧着一本宝典在那里钻研,不然兴趣都被磨灭了。不过也不能什么都不看,上来就到网上搜索。这年头尤其在国内,真是天下文章一大抄,往往搜索一个东西,每页结果上都是那么几篇文章,而且有很大几率是错误的。

好的学习途径可能就是初学时找本书看一下基本的语法,了解一些内置支持的对象和基本概念,然后在运用中就会不断有提高了。也许有时候会突然发现某个问题原来可以这样简单地解决,这就是一个积累知识的过程了。听说Javascript也是很强大的东西,我得慢慢学。

目前开始看一本书叫”JavaScript for Breakfast”,写得比较随意,看着舒服。刚开始学,得看看别人(权威)是如何用它来解决问题,解决哪些问题的。比较困惑的几点:

  • Javascript有哪些内置支持的对象如document,document.images这样的呢?在哪里有完整的列表。不知道所谓的Javascript core language到底包含哪些部分。
  • 它和DOM是个什么样的关系。
  • 不同浏览器之间有怎样的兼容性问题。那本书上写着最好用object.property这样的方式来设置属性,而不要用setAttribute。
一些更新
Saturday, October 7th, 2006

我的网站:用上了Gravatar,留言时候有大头贴了。

Paged Threaded Plugin:

  • PHP5对array_merge函数有所修改,参数必须是array类型,于是插件在PHP5环境中就有问题。把参数做个强制类型转换就好了。
  • 原来要回复某个留言,点了"reply to this comment"之后,被回复的留言前面的加号就一直保持不变,今天终于知道是怎么回事了,修正了相关的Javascript。
Firefox显示本机IP(Javascript)
Friday, October 6th, 2006

当初用马桶的时候记得有个插件可以在状态栏上显示本机IP的软件,需要看自己IP的话很方便,免除打开网络连接选项之麻烦。以前想在Firefox里找个这样的插件,可惜搜索不到。现在无聊想自己做,却发现已经有了这样功能的插件,这就省事了,呵呵。不过在这个过程中也学了一些东西,总结一下Javascript显示本机IP的方法(Firefox):

  1. 调用Java(Netscape Navigator系列):
    var localhost = java.net.InetAddress.getLocalHost();
    var hostname = localhost.getHostName();
    var hostIP = localhost.getHostAddress();

    一执行这个代码,系统就多了个javaw进程,不太爽,而且还要求安装Java虚拟机。

  2. 向远程服务器请求(适合于任何浏览器):这种办法最容易想到了,许多网站在用户浏览时都会给出用户机的IP地址,所以只要向一个提供这种服务的Web服务器发送个请求并分析返回页面就可以了。缺点是,需要与服务器交流,服务器地址变动或者停止服务都会出问题。 自己做一个这样的页面也很简单,下面有两个地址是从Live IP Address插件中找到的:
  3. Mozilla软件本身的服务:从Show IP插件里看到这样的方法,应该算是最好的解决方案了。
    cls = Components.classes['@mozilla.org/network/dns-service;1'];
    iface = Components.interfaces.nsIDNSService;
    dns = cls.getService(iface);
    a = new Array();
     try {
    	var nsrecord = dns.resolve(dns.myHostName, true);
    	while (nsrecord.hasMore()) {
    		a[a.length] = nsrecord.getNextAddrAsString();
    	}
    } catch (e) { }
    localip = a.join(" | ");

先就用Show IP了,不过它不像Live IP Address那么简洁,用不了那么多功能。

替换Gmail的链接栏
Wednesday, October 4th, 2006

为Firefox写了一个简单的user script,用于替换Gmail左上角链接栏,效果如下:

gmail

主要是原来链接栏里各个链接都有id,用document.getElementById就找到了,再找其parentNode,把innerHTML替换就可以了。

这里是源代码。想用的话,把替换文本换成自己合适的就行。

先安装GreaseMonkey,然后点击上面用户代码的链接,就会提示安装。