Meta
VILIC15:04 - 05.20 2011

首先, 要说明的是, 这并非一个万能的方法. 兼容性:

经测试兼容的浏览器:
Firefox 4 / Chrome 11
IE 9 / Safari 5 (只对window.location有效, 对window.location.href报错)

经测试不兼容的浏览器:
IE 8- (据说蓝色的网友说Chrome 12+也不行, 未实测.)

其他浏览器的运行情况我就不清楚了.

下面进入正题. 首先要介绍的是在JavaScript 1.8.5中引入的一个接口:
Object.defineProperty(obj, prop, descriptor)

顾名思义, 就是定义属性. 然后要做的事情也很简单, 使用它来覆盖 window.location / window.location.href, 代码如下:

Object.defineProperty(window, "location", { value: window.location, writable: false });
Object.defineProperty(window.location, "href", { value: window.location.href, writable: false });
window.location = "http://www.vilic.info/";
alert(window.location);

那, 就这样咯... 使用的时候try一下就好. 因为毕竟只是作为提高体验的代码, 实在不行还可以用beforeunload事件, 只是就会有窗口弹出了.

我想这个对于 "在浏览器里的浏览器" 会比较有意义. 比如WebQQ那个又丑又弱的浏览器... 不过我猜这个接口在其他地方一定还会大有用途, 哈哈.

Original link of this archive: http://www.vilic.info/blog/archives/681
本文的原始链接: http://www.vilic.info/blog/archives/681

VILIC21:36 - 05.11 2011

这是做ViT的时候遇到的问题, 按说应该是一个非常基础的问题, 因为遇到的情况应该也比较多, 但是很遗憾自己之前却没有一套有效的解决方案. 后来Google了很多, 不过效果并不理想.

后来到群里和众大大们讨论, 想到的第一个方案是用一个div装下textarea中的文本, 让各种相关样式相同, 这样div的高就应该是textarea的高了. 于是很快写了出来. 但因为毕竟一个是text, 一个是html, 各种转换也比较麻烦. 遇到了不换行的长文本(英文), 处理起来就更不方便了. 还有空格什么的处理. 比如 "abc abc" 这样, 中间是不会换行的, 如果替换两个空格为一个空格加一个 " ", 依旧有小问题, 具体就不说了.

说到这里, 大家可能会提出一个常见的方案, 也就是利用textarea自身的scrollHeight属性. 不错, 但是当textarea变高之后, 即使内容删掉, 也变不回原来的高度了. 但, 如果说, 一个textarea的高度很小, 那么scrollHeight不就一直都表示内容的高度了么? 这就是key所在了, 用div做副本不行, 我们可以用textarea啊!

最终代码如下:

<!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>
    <title>文本框高度自适应</title>
    <style type="text/css">
        #shadow, #text { font: 12px/16px Arial; width: 200px; overflow: hidden; height: 16px; }
        #shadow { position: absolute; border-width: 0px; padding: 0px; visibility: hidden; }
        #text { resize: none; }
    </style>
    <script type="text/javascript">
        /*
            文本框高度自适应
            by VILIC VANE
            Web www.vilic.info
            Email i@vilic.info
        */

        window.onload = function () {
            var text = document.getElementById("text"); //用户看到的文本框
            var shadow = document.getElementById("shadow"); //隐藏的文本框

            text.oninput = //非IE的
            text.onpropertychange = //IE的
            onchange;
           
            function onchange() {
                shadow.value = text.value;
                setHeight();
                setTimeout(setHeight, 0); //针对IE 6/7/8的延迟, 否则有时会有一个字符的出入
                function setHeight() { text.style.height = shadow.scrollHeight + "px"; }
            }
        };
    </script>
</head>
<body>
    <textarea id="text"></textarea>
    <textarea id="shadow"></textarea>
</body>
</html>

Original link of this archive: http://www.vilic.info/blog/archives/677
本文的原始链接: http://www.vilic.info/blog/archives/677

VILIC17:58 - 05.02 2011

今天想着, 干脆就扩展了VT SDK的功能. 现在支持Twitter/腾讯/新浪微博, 并且支持发送图片 (限腾讯/新浪微博).

里面有3个Demo, 分别是twitter.hta, txweibo.hta, xlweibo.hta, 里面有简单的例子, 大家可以下载解压后双击执行.

下载地址 http://www.vilic.info/demo/vt.rar

在页面中添加以下脚本引用即可:

<script src="script/crypto.js" type="text/javascript"></script>
<script src="script/sha1.js" type="text/javascript"></script>
<script src="script/hmac.js" type="text/javascript"></script>
<script src="script/vejis.js" type="text/javascript"></script>
<script src="script/vejis.api.js" type="text/javascript"></script>

要是不嫌麻烦的话, 可以把上面的文件合并到一起, 不过我就懒得弄啦. 最后上个图, 就是其中的三个例子.

Original link of this archive: http://www.vilic.info/blog/archives/673
本文的原始链接: http://www.vilic.info/blog/archives/673

VILIC18:24 - 04.28 2011

首先, 道路是曲折的... 之前曾小试过 Basic 验证, 一开是也是不得要领, 不过悟透那个就显然快多了.

这是第一次做 OAuth 的验证, 在此实在想狠狠地骂腾讯的 API 说明文档, 不清不楚, 害得我到处查, 到处试... 总算, 经过一个上午的奋斗, 成功获取了 Request Token, 下午再稍加努力, 终于把 Access Token 拿到了手, 晚上又继续奋战, 搞定了微博发送, 至此, 也算对 OAuth 及腾讯微博的 API 有了个基本的了解.

JavaScript 实现腾讯微博的 OAuth 的难点在于 HMAC-SHA1 加密, 而且之后还得转换成 Base64, 最变态的是, 获取 Request Token 的时候, 加密时 AppKey 后面还得跟上个 "&"!!! 比如原来 AppKey 是 "123456", 那么加密时的 Key 就是 "123456&"

好吧, 既然大家在看这篇文章, 相信关于 XMLHttpRequest 这些也比较熟悉了, 我就说说重点 (因为我是第一次真正接触 OAuth, 所以对里面一些约定俗成的东西可能还不清楚, 所以高手看了不要笑我这些 "重点" 太幼稚).

HMAC-SHA1 加密的 JavaScript 实现

在网上搜这个搜了很久, 最后找到了一个叫 Crypto-JS 的东西, 一看, 果然是好家伙, 里面提供了非常丰富的加密方式, 值得收藏. http://code.google.com/p/crypto-js/ 下载后引用 crypto.js, sha1.js, hmac.js 三个文件, 加密方式如下:

var message = "Message to be encoded";
var secret = "Secret phrase";

var bytes = Crypto.HMAC(Crypto.SHA1, message, secret, { asBytes: true }) ;
//但仅仅这样还不行, 还得转换成Base64.
//在Crypto.util下找到相应的方法.
var signature = Crypto.util.bytesToBase64(bytes);

这样就搞定啦. 需要注意的是 (前面我也有提到), 在获取 Request Token 的时候, secret需要在 App Secret 后面加上 "&". 获取 Access Token 的时候, 则是用 "&" 把 App Secret 和 Token Secret连起来.

参数编码

按说这个是算不上重点的, 不过实在找不到东西写, 就把这个算上去吧.

方法很简单, 使用JavaScript内置的encodeURIComponent()方法即可.

看来这里还真是重点, 编码要求要什么 [RFC3986], 在 encodeURIComponent() 的基础上, 还要额外编码 ! * ( ) ' 这5个字符.

否则当添加微博的内容中出现这些字符的时候, oauth_signature 参数会有误, 导致鉴权失败.

时间戳

注意单位是哦! new Date().getTime()的单位是毫秒, 所以注意先除以1000再取整.

要签名的Base String

里面的参数要排序, 当然这个文档中也强调了. 另外就是这些参数中是不包括 oauth_signature 的. 显然, 也没法包含这个参数, 不过我这样点明下, 免得大家心生疑惑.

 

最后, 这个是我用 HTA (JavaScript) 实现的一个验证和发微博的小Demo, http://www.vilic.info/demo/vt.rar . 源码是基于 vejis 的, 如果有看不太明白的可以参考 vejis.js 文件中的说明. (补充, 后来发现有个小Bug, 其实不算Bug, 我一开始以为所有的API都可以用POST方法, 就全部使用的是POST, 对应的稍微小改就可以了)

Original link of this archive: http://www.vilic.info/blog/archives/659
本文的原始链接: http://www.vilic.info/blog/archives/659

VILIC22:03 - 04.26 2011

今天在群里和大大们讨论问题, 顺便就谈到了开发 Prever 2 的时候遇到的一个. 归结下来, 就是希望能保护一些对象, 使之不能被修改.
后来Franky大神提到一个方法, Object.defineProperty, 据说是IE8部分支持, 其他浏览器的最新应该都是支持的. 因为我现在不求兼容很多浏览器, 所以对我来说, 这自然是非常有用的东西了.
查了查MSDN和MDC, 解释如下(翻译得不恰当的地方请见谅):

语法

Object.defineProperty(obj, prop, descriptor)

参数

obj
要定义属性的对象
prop
要修改或者定义的属性名称
descriptor
属性定义和修改的描述符

描述

这个方法允许对象属性的严格添加和修改. 普通的属性添加创建的属性可以在属性枚举(for...in 循环)中枚举, 这时候, 值可能被改变或者删除. 这个方法允许修改这些额外的特性(即可改变或可删除).

属性描述符是对象形式的, 它可以由两种方式表示: 数据描述符和访问描述符. 数据描述符是一个有值, 可写或者不可写的属性. 访问描述符是通过一个getter和setter函数对来描述的. 一个描述符必须是这两种之一, 不能掺杂. 这两种描述符都可以使用configurable和enumerable.

一个属性描述符是一个具有以下字段的对象:

value
属性的值. (仅限数据描述符). 默认为undefined.

writable
如果值为true, 属性的值可以被改变. (仅限数据描述符). 默认是false.

get
属性的getter, undefined表示没有getter. (仅限访问描述符). 默认是undefined.

set
属性的setter, undefined表示没有setter. (仅限访问描述符). 默认是undefined.

configurable
如果值为true, 则该属性的描述符可以被修改并且该属性可以从相关对象上删去. 默认为false.

enumerable
如果只为true, 则该属性可以从相关对象上枚举. 默认是false.

Original link of this archive: http://www.vilic.info/blog/archives/655
本文的原始链接: http://www.vilic.info/blog/archives/655