Posts Tagged ‘ JavaScript

杂碎笔记:DOM中的Text节点

DOM中的Text节点,has no properties错误

考虑下面一段代码:

<script type=”text/javascript”>
function switch_nextSibling_display(hdl){
hdl=hdl.nextSibling;
if(hdl.style.display==”none”) hdl.style.display=”block”;
else hdl.style.display=”none”;
}
</script>
<input type=”button” value=”Click Me!” onclick=”switch_nextSibling_display(this)”/>
<input type=”button” value=”Hidding Me!”/>

能得到我们想要的结果吗?否!如果用firebug调试的话(有了firebug太爽了哈~),会得到“……has no properties”的提示。这是因为:两个 input 控件之间有个换行符。在DOM树中,包括换行符、空格及其他普通字符都属于Text节点。不能因为换行符和空格看不见就当它不存在,实际上,前 input 节点的 nextSibling 正是这个Text节点,应该nextSibling.nextSibling才对。不过,在IE中,这个Text节点是被忽略的。为了兼容,有两个方法,一就是不要换行;或者,加上这么一句:if(hdl.nodeType==3) hdl=hdl.nextSibling,nodeType等于3表示Text节点。

P的问题~
同样是上面的script,下面的click能预期执行吗?

<input type=”button” value=”Click Me!” onclick=”switch_nextSibling_display(this)”/><p>I want to hide<p>all this!</p></p>

同样不能,”all this”是不受影响的。虽然看起来,后一个p只是前一个p的子节点,好像前面的p包括整句话才能称的上是input的“兄弟”。但实际上,p是不能自包含的,当后一个p出现的时候,前一个p就被关闭了,所以那句话等价于:<p>I want to hide</p><p>all this!</p>。同理,p也不能包含div等块级元素。虽然手工不大可能写出这样的语句,但一些半自动的场合难免,这时用JS读/写DOM树可能会碰到一些意想不到的问题。

var与非var
JavaScript中,在函数外用不用var定义的变量都是全局的,在函数内部,var定义局部变量,不用var定义全局变量,这似乎没什么问题。但下面一段代码会alert出什么呢?

<script type="text/javascript">var a=1;function f(){   alert(a);   var a=2;}f();</script>

1吗?No。因为f()里面声明了与全局变量同名的局部变量,代码在运行前先处理变量声明,所以此a已非彼a了,但是alert的时候a还没有被赋值,所以结果是undefined。倘若把f()里面的声明:var a=2 改成赋值:a=2,此a就仍然是彼a,此时因为a的值尚未被改变,所以结果是1。另,全局的JS变量还能被VBScript访问。

Twitter API 应用

题外话:
———————————————————————
我的需求很简单,就是将最近的几条twitter信息显示在blog上。

首先想到的办法就是,直接用blogger提供的feed功能。可是,输出的每条信息前都有个“Wang Congming:”长长的前缀,不喜欢。而且,blogger每抓取一次feed好像要缓存挺长时间,而twitter应该是实效性比较强的,恩~。

然后,就想到用twitter官方提供的Badges。However,他们给的不是我想要的。所以,只好去看看API说明,自己动手。

小小原理:
———————————————————————
twitter支持四种格式的数据输出:xml, RSS, ATOM, JSON,以及 GET 和 POST 两种方法。当然,只是查询一下不需要授权的数据,自然用不上POST。所以,只需要GET一个JSON就行,通过URL传递适当的参数,得到我们需要的数据。

传递过来的 json 是一个函数,而我们需要的数据作为函数的参数。唯一要做的,就是事先定义这样一个函数,告诉它该怎么执行,怎么显示其中的数据。至于函数名,GET 时由自己用 callback 参数指定。

Click the expand button to read full text…

数据结构
———————————————————————
返回的数据类似以下结构:

twitterCallback([   {      "created_at":"Sat Apr 28 15:45:24 +0000 2007",      "text":"信息的内容~",      "id":43160262/*该条信息的数字编号*/,      "user":{         "name":"Wang Congming",         "profile_image_url":"http:...",         "description":"自我介绍",         "location":"BeiJing",         "screen_name":"WCM/*用户名*/",         "url":"http:...",         "id":5002701/*用户的数字编号*/,         "protected":false      }   },   {      /* 第2/3/4...条信息,重复以上形式 */   }]);

完成
———————————————————————
根据以上数据,得代码如下:

<ul id="my_twitter"><li>Loading...</li></ul>

<script type="text/javascript">function relative_time(time_value) {   var time_correct = time_value.split('+0000');   var parsed_date = Date.parse(time_correct[0]+'GMT+0000'+time_correct[1]);   var relative_to = new Date();   var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);   if(delta < 60) return 'less than a minute ago';   else if(delta < 120) return 'about a minute ago';   else if(delta < (45*60)) return (parseInt(delta / 60)).toString() + ' minutes    ago';   else if(delta < (90*60)) return 'about an hour ago';   else if(delta < (24*60*60)) return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';   else if(delta < (48*60*60)) return '1 day ago';   else return (parseInt(delta / 86400)).toString() + ' days ago';}function twitterCallback(obj){   var twitterHTML = '';   for(var i=0; i<(obj.length); i++){      twitterHTML += '<li><span class="item-title"><a href="http://twitter.com/wcm/statuses/'+obj[i].id+'">' + obj[i].text + '</a></span><span class="item-date"> - ' + relative_time(obj[i].created_at) + '</span></li>';   }   document.getElementById('my_twitter').innerHTML = twitterHTML;}</script>

<script src="http://twitter.com/statuses/user_timeline/5002701.json?callback=twitterCallback&count=5" type="text/javascript"></script>

效果如右侧~

总结一下
———————————————————————
1、以上代码,如果去掉ul间的“<li>Loading…</li>”,然后存为一个单独的文件,将无法正常显示,加上后又变为正常。当然,并不限于Loading…,也并不限于ul之间。也就是说,只要在任何可以的地方,加上任何字符,就OK了,不加就不行,IE和ff均如此,不理解……。

2、twitter输出的”+0000″时区没有指名是哪个标准时间(虽然没多大差别),这将导致IE的Date.parse语法分析出错,所以先在”+0000″前加上GMT再分析。

3、”…/5002701.json?callback=twitterCallback&count=5″。这里的5002701要换成自己的编号;twitterCallback即是指定的返回函数名,可自由命名;除了count外,还有其他筛选条件,如指定起始日期的since等。

4、Twitter API官方文档

关于JSON (JavaScript Object Notation): http://www.json.org/json-zh.html