Seven Yu @ 12/10/2009 (12:38 pm)

escape, encodeURI 和 encodeURIComponent 的区别

Javascript 中有三个 URI 编码函数, 他们都是全局函数, 但功能稍有不同, 这里简单解释下他们之间的区别:

encodeURI 只将 URI 中的空格和非 AscII 字符进行编码, 编码后的 URI 能正常访问.
encodeURIComponent 除了将所有非 AscII 字符编码外, 还会将一些特殊字符进行编码 (如 ?, &, /, :, # 等), 编码后的 URI 不可访问.
一般要将字符串作为 get 参数传递或保存为 Cookie 的, 都需要使用 encodeURIComponent 编码.

escape 的功能与 encodeURIComponent 的功能一样, 只是个别字符的差异, 对使用没有影响.
但 escape 方法已经在 ECMAScript v3 标准中被删除了, 所以不推荐使用.

对应的解码函数为 unescape, decodeURI 和 decodeURIComponent.

附上测试脚本:

PLAIN TEXT >> JAVASCRIPT:
  1. var url = 'http://labs.phpz.org/jstest/null.html?a=TEST1&b=hello world#'
  2. var results = ['URI: ' + url]
  3. // escape
  4. results.push('escape: ' + escape(url));
  5. // encodeURI
  6. results.push('encodeURI: ' + encodeURI(url));
  7. // encodeURIComponent
  8. results.push('encodeURIComponent: ' + encodeURIComponent(url))
  9. document.write(results.join('<br />'));
  10.  
  11. /*
  12. URI: http://labs.phpz.org/jstest/null.html?a=TEST1&b=hello world#
  13. escape: http%3A//labs.phpz.org/jstest/null.html%3Fa%3DTEST1%26b%3Dhello%20world%23
  14. encodeURI: http://labs.phpz.org/jstest/null.html?a=TEST1&b=hello%20world#
  15. encodeURIComponent: http%3A%2F%2Flabs.phpz.org%2Fjstest%2Fnull.html%3Fa%3DTEST1%26b%3Dhello%20world%23
  16. */

Seven Yu @ 05/08/2009 (5:21 pm)

如何在 GM(greasemonkey) 脚本中使用外部资源

这里所说的外部资源分为三种: 脚本, 图片 和 文本.

先说如何载入外部脚本:

相信很多写 GM 脚本的朋友包括我以前在引入外部脚本时都会使用下面的(或类似的)代码:

PLAIN TEXT >> JAVASCRIPT:
  1. var jQlab = document.createElement('script');
  2. jQlab.type = 'text/javascript';
  3. jQlab.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js';
  4. document.getElementsByTagName('head')[0].appendChild(jQlab);

这段脚本是可以工作的, 但有个问题, 就是每次执行脚本时都会重新去加载这个脚本, 很浪费时间和带宽.
正确的做法是利用 @require 元标签, 代码如下:

PLAIN TEXT >> JAVASCRIPT:
  1. // ==UserScript==
  2. // 此处省略其他一些 GM 元标签 ...
  3. // @require    http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js
  4. // ==/UserScript==

这样做的好处有二: 一是节省代码; 二是不会每次执行脚本都加载, 因为 GM 在安装脚本时会去加载这个文件, 把他下载到本地(脚本所在文件夹中), 之后每次运行脚本时都会到本地文件夹去加载文件, 这样就大大节省了带宽, 同时提高了脚本响应速度.

当然这样做也有一个缺点就是如果被载入文件更新了, 就只能从新安装该脚本, 本地文件不会跟着更新, 因为只在安装时才加载这个文件.

下面再来说说如何加载图片和文本:

这涉及到另外一个 GM 元标签 @resource, 代码如下:

PLAIN TEXT >> JAVASCRIPT:
  1. // ==UserScript==
  2. // 此处省略其他一些 GM 元标签 ...
  3. // @resource    resourceName http://www.example.com/resource.png
  4. // ==/UserScript==

使用时需要用到两个 GM 函数: GM_getResourceURL(resourceName)GM_getResourceText(resourceName), 前者将返回脚本中可用的 url 格式 (base64 编码), 后者返回文件内容.

这个元标签和 @require 一样, 也会在安装脚本的同时将资源下载到本地, 所以如果需要更新资源的话, 请重新安装脚本.

Seven Yu @ 04/09/2009 (5:58 pm)

用 jQuery 获取 iframe 父页面元素

是群里的问题(我发现没事在群里鬼混一下还真能开放思路学到东西啊)

不说废话, 代码如下:

PLAIN TEXT >> JAVASCRIPT:
  1. $('#objId', parent.document);
  2. // 搞定...
  3. /*
  4. 以前一直不理解这第二个参数应该在什么情况下用,
  5. 今天终于知道了, 撒花, 庆祝...
  6. */

Seven Yu @ 04/08/2009 (1:55 am)

自定义 jQuery filter (过滤器)

jQuery选择器中已经定义了丰富的过滤器, 例如 :first, :last, :checkbox 等... 但有时难以适应应用的复杂需求, 这时候我们可以通过自定义过滤器来满足一些特殊需求, 看下面的代码:

演示: http://labs.phpz.org/jquery_test/myfilter.html

html 代码:

PLAIN TEXT >> HTML:
  1.     <li>10</li>
  2.     <li>200</li>
  3.     <li>3000</li>
  4.     <li>150</li>
  5.     <li>470</li>
  6.     <li>390</li>
  7. </ul>

javascript 代码:

PLAIN TEXT >> JAVASCRIPT:
  1. $.extend($.expr[':'], {
  2.     'myfilter' : function(e,i,m,a){return parseInt($(e).html())>= 300;}
  3. });
  4. $(function()
  5. {
  6.     $('li:myfilter').css('background-color','#eee');
  7. });

回调函数有4个参数, 并返回一个布尔值, 以确定当前元素是否符合过滤器要求, 4个参数分别代表:

  • e: 当前元素
  • i: 当前索引值
  • m: 过滤器正则匹配结果
  • a: 保存全部元素是数组

Seven Yu @ 04/07/2009 (9:38 pm)

[实验] checkTree

偶的简单实现:

http://labs.phpz.org/jquery_test/checkbox_tree.html

PLAIN TEXT >> JAVASCRIPT:
  1. $(function()
  2. {
  3.     $(':checkbox').click(function()
  4.     {
  5.         // children
  6.         $(this).parent('li').find(':checkbox').attr('checked', this.checked);
  7.         // parent
  8.         checkParent(this);
  9.     });
  10. });
  11.  
  12. function checkParent(obj)
  13. {
  14.     if(obj == null)
  15.         return;
  16.     if(obj.checked)
  17.     {
  18.         if($(obj).closest('ul').find('>li>input:checkbox').size() == $(obj).closest('ul').find('>li>input:checkbox:checked').size())
  19.             checkParent($(obj).closest('ul').prev().attr('checked', true)[0]);
  20.     }
  21.     else
  22.     {
  23.         checkParent($(obj).closest('ul').prev().attr('checked', false)[0]);
  24.     }
  25. }

一个 jQuery 插件:

http://static.geewax.org/checktree/index.html

update:
今天(2009/4/9)受群里高人指点, 代码又节约了一点(最近脑子不好使了, 难道真的老了??):

PLAIN TEXT >> JAVASCRIPT:
  1. // if($(obj).closest('ul').find('>li>input:checkbox').size() == $(obj).closest('ul').find('>li>input:checkbox:checked').size())
  2. // 改为
  3. if($(obj).closest('ul').find('>li>input:checkbox:not(:checked)').size() == 0)

Seven Yu @ 04/03/2009 (10:20 am)

两个 twitter GM 脚本和一个 picasaweb GM 脚本升级了

以下三个脚本已更新, 请安装最新版本:

  1. Get Picasaweb Image URL
    • 由于 picasaweb 更新了一些页面元素的 class 和 id, 导致脚本失效, 现已更新.
    • 同时修复了之前被忽略的一些细节, 脚本可靠性得到增强.
  2. Twitter friends name helper
    • 由于 twitter 表单 id 的改变, 导致 Ctrl+Enter 快捷键失效, 现已更新.
  3. Twitter timeline updater
    • 新版本中增加了 retweet 功能.
    • 多重 RT 采用 RT @最终RT者: > @中间RT者: > @中间RT者: > @源作者: 内容 的形式

Seven Yu @ 03/28/2009 (12:57 am)

用牛逼的 jQuery 隐藏表格列(关于 :nth-child 选择器)

上午在一 jQuery 群里有朋友问到如何隐藏表格列, 我想都没想就说需要循环. 晚上没事又想了一下发现我错了.

"用循环" 这回答不仅是对提问者的不负责任, 简直是对 jQuery 的侮辱, 实际上很简单的一句话就可以实现对任意(一或多)表格列的隐藏. 这也是 jQuery 所崇尚的 write less, do more 精神的具体体现.

最初我研究的代码是:

PLAIN TEXT >> JAVASCRIPT:
  1. // 隐藏表格第四列
  2. $('table tr').find('td:eq(3)').hide();

后来群里一位叫 "[京]金山" 的朋友指出, 可以用下面的代码实现同样的功能:

PLAIN TEXT >> JAVASCRIPT:
  1. // 隐藏表格第四列
  2. $('table tr td:nth-child(4)').hide();

而且这样的写法更直观, 效率也比上面的稍高. 非常感谢金山同学, 偶又学到一个用法, 对 jQuery 又有进一步了解.

后来测试, 去掉 table 效率还会有所提高, 但还不是很确定, 只是从多次测试的数据观察来的. 有时间游一下代码看看.

另外 :nth-child 还支持 :nth-child(2n+1) 这种写法, 返回奇数项, 2n 返回偶数项, 或者用 oddeven 代替公式. 当然, 类似 3n+5, 4n 这样的写法也是可以的. nth-child 的翻译应该就是 "第n个孩子" ... 囧...

值得注意的是 :nth-child(odd):odd 是有区别的: :odd 是所有返回项整体排序后其中的奇数项, 并且索引从0开始; 而 :nth-child(odd) 则是针对修饰项的子元素进行过滤和运算的(:nth-child 被称为 Child Filter), 并且索引是从1开始的.

更详细的内容参考 jQuery 文档 Selectors 部分, 看来没事读读文档还是相当有必要的, 马上去通读一下吧.

----- 补充分割线 -----
还忘记说一点, jQuery 这个选择器效率还是挺高的, 我对一个 900 行 5 列的表格做了测试, 隐藏某1列的话(也就是隐藏900个单元格), IE 8 是 350ms 左右, firefox 330ms 左右, opera 90ms 左右, chrome 50ms 左右.

还是 chrome 牛逼啊, 对 firefox 很失望...

Next Page »