上半年账单统计

上半年账单发布,从2月到7月底的数据,除去学费,包括生活费和自己买书(非教科书)以及租主机的费用。到什么时候来把这个记账的专题做起来,再用JavaScript 把表格跑一遍出张图什么的。地址在:地址已失效 。ods 电子表格源文件会在专题做好之后放出。

等到下周会优化一下两个demo 的代码(主要是看到教主在微博上说谁污染原型就切谁小鸡鸡。。。),然后写两篇文章说说这两个东西。

Tab 切换

在写一个Chrome 的快速拨号扩展。起因是Chrome 默认的新标签页很让人头疼,没有快速拨号,那 8 个最常访问网站会随着一段时间的浏览习惯而动来动去。好的地方就是有网站缩略图,还有那个“最近关闭的标签页”挺好的。

缩略图这一块,现在是没有办法了。在Chromium 的Issues 里看到有人反映过,但是目前还是禁止扩展访问chrome://thumb/ 的,chrome://favicon/ 倒是可以访问,前提是在扩展的manifest 中请求chrome://favicon 权限。

“最近关闭的标签页”这个还真是没有想到具体实现方式,默认新标签页源码太多了,实在是没有耐心去完整地看一遍。(不过性能真的是优化得很好)现在在看Sexy Undo Close Tab 的代码。

扩展中使用到了我自己写的query 选择器,不过我昨天找到了一个非常优秀的替代品——司徒正美的Icarus,有很大的可能会使用它。还使用到了Mousetrap 来绑定快捷键(这货真的很方便的说),所以原来的Tab 切换函数不能用了。(因为用快捷键的话要能记住当前焦点在哪个Tab 或Item 上)记一下现在用的。(没有优化过,现在很容易报错。)

// Tab and item switch.
var Tab = {};
Tab.TabMax = 3;
Tab.ItemMax = 0;
Tab.nowTab = 1;
Tab.nowItem = 0;
Tab.switchToTab = function(targetTabId){
  var self = this;
  self.nowItem = 0;
  if(targetTabId != self.nowTab){
    $('#tab-controler').$('.now')[0].removeAttribute('class');
    $('#tab-controler').children[targetTabId-1].setAttribute('class', 'now');
    $('#fall-tabs').$('.now')[0].setAttribute('class', 'falltab');
    $('#fall-tabs').children[targetTabId-1].setAttribute('class', 'now');
    self.nowTab = targetTabId;
    self.ItemMax = $('#fall-tabs').children[self.nowTab-1].$('a').length;
  }
  return self.nowTab;
};
Tab.switchToItem = function(targetItemId){
  var self = this;
  if(targetItemId != self.nowItem){
    $('#fall-tabs').children[self.nowTab-1].$('a')[targetItemId-1].focus();
    self.nowItem = targetItemId;
  }
  return self.nowItem;
};

比较简单,其他的就不记了哈。

百度贴吧のHTML 实体符号

在学校的贴吧里看到这样一个帖子:谁的电脑能打出这两个字,你的电脑起码两万以上!!不信试试...

说实话这种帖子标题是非常可笑的,属于猫扑脑残帖的一种。楼主想说的其实是,百度屏蔽了“涅槃”这两个字,所以能发表这两个字回复的必然都是高级主。8楼随后贴出了一段JavaScript 代码迎合了这种需要。

(function (){
  var str=rich_postor._editor.getHtml();
  var out="";
  for(var i=0;i<str.length;i++){
    if(str.charCodeAt(i)<128){
      out+=str.charAt(i);
    }else{
      out+="&#"+str.charCodeAt(i)+";";
    }
  }
  rich_postor._editor.getHtml=function (){
    return out;
  };
  rich_postor._submit();
})();

这里貌似构造了一个闭包?鉴于我还完全没有参透闭包的奥妙,也完全不会使用闭包,我们先把它放一放。其实这段代码只做了一件事就是把字符转义为HTML 符号实体。

取自W3SCHOOL 的资料(虽然W3SCHOOL 有很多错误,但是这个没有错误):一些字符在 HTML 中拥有特殊的含义,比如小于号 (<) 用于定义 HTML 标签的开始。如果我们希望浏览器正确地显示这些字符,我们必须在 HTML 源码中插入字符实体。字符实体有三部分:一个和号 (&),一个实体名称,或者 # 和一个实体编号,以及一个分号 (;)。比如,要在 HTML 文档中显示小于号,我们需要这样写:&lt;或者 &#60;

HTML 字符实体本来是用来向HTML 文档中插入一些特殊字符用的,比如尖括号(&lt;&gt;),但是在这个例子中它把所有字符都转义成了符号实体,比如“涅槃”这两个汉字被转义成了&#28037;&#27075;

这样的话百度就不屏蔽了。

但是在HTML 文档到达浏览器的时候,浏览器会认出来这是一串符号实体,所以该是汉字的会还原成汉字。如果你查看一下源文件就会发现这两个字确实是符号实体了。

发现还真有很多人乐于发表这种帖子啊:【转】惊现百度超级漏洞,5亿万人只有60多个人能打出此字,...。。。果然非技术宅们容易被伪科学玩弄呢。

这个方法可以用来做一些好玩的事,比如发繁体的帖子之类的。

for 循环求值

虽说提倡“退吧保智商”,不过我时常还会去瞄两眼的,毕竟贴吧在去年我人生最低谷的时候帮助我走了上来。刚刚在贴吧里看到一个并不很起眼的帖子for循环求值

本来看到这种帖子根本都不会去点开的,天知道我今天下午是不是被热坏了脑子打开看了一下那张图片。大意就是说这样一个循环执行之后j 的值为什么等于4:

for(i = 0; i < 5; i ++) j = i ++;

下面回复的有说“for的写法没有括号默认执行第一句”,虽然没有听过这个说法,不过我表示赞同。平时谁会这样用for 循环啊,自增量放到循环体里面用的场景我还真没见过==|||。

解决这个问题很简单,F12 开发工具跑一下。

for(i = 0; i < 5; i ++){
  console.log("before: i="+i+"\n");
  j = i ++;
  console.log("after: j="+j+"\n");
  console.log("after: i="+i+"\n");
}
// 结果:
// before: i=0
// after: j=0
// after: i=1
// before: i=2
// after: j=2
// after: i=3
// before: i=4
// after: j=4
// after: i=5

这样看明白了没有?在作 a = b ++ 这种运算时,是这样的:a = b; b ++ 。在 for 循环里也是这样的,判断完 i < 5 之后,先执行循环体,然后 i 的值增加 1 ,再继续下一次循环。如果没有 j = i ++ 这一句,而是 j = i 的话,j 的值就是从 0 到 4 ;但是这里第一个循环,到 j = i ++ 这一句时, i 的值为 0 , j = i ++ 实际等价于 j = i; i = i + 1 ,这样 j 第一个值为 0 ,之后 i 的值增加 1 ,再之后循环体结束, i 的值加 1 (这是 for 那个小括号里的 i ++ 语句),此时 i 的值为 2 。

顺着这种逻辑推理下去,够明白了吧?

搞清楚之后,可以尝试一下下面这种变体。

for(i = 0; i < 5; ++i){
  console.log("before: i="+i+"\n");
  j = i ++;
  console.log("after: j="+j+"\n");
  console.log("after: i="+i+"\n");
}
// 结果:
// before: i=0
// after: j=0
// after: i=1
// before: i=2
// after: j=2
// after: i=3
// before: i=4
// after: j=4
// after: i=5

做过这个就会知道 for 循环的用法。在 for 循环里,自增运算符的位置其实无关紧要,自增量总是在整个循环体结束之后加 1 。可以参照 C 语言相关的书,或是这里:for 循环中的i++ 和 ++i有什么区别?

HoverHey Chrome扩展

昨天写成了第一个 Chrome 扩展之后,手痒痒,想一鼓作气再写几个。正好室友在看考研信息,那个网站上做了表格的 hover 效果,鼠标指针移上去会变换背景颜色,室友觉得这个效果不错。所以我就写了个这样的扩展。今天花了一天的时间改了改,现在可以调整颜色和过渡时间了。下载:http://www.qblog.kilu.net/source/HoverHey.crx。(没有钱,本来想放到 Webstore 上去的,发现要先交5美元的注册费)

记录一下一些代码。

// 改变鼠标所在元素背景色。
var highlight = function(e){
  e = e || window.event;
  var _now = e.target || e.srcElement;
  oriBg = _now.style.backgroundColor;
  _now.style.backgroundColor = rgba;
  _now.style.webkitTransition = "background-color "+duration+"s ease-in-out";
};
window.addEventListener('mouseover', highlight);
// 向背景页面请求设置中保存的数据,其实就是交换json 。(因为脚本是inject 到页面中使用的,不能读取自身扩展的localStorage )
chrome.extension.sendRequest({askfor: "rgba"}, function(response){
  rgba = response.RGBA;
  duration = response.duration;
});
// 背景页面响应请求,发送设置数据。
chrome.extension.onRequest.addListener(
  function(request, sender, sendResponse){
    if(request.askfor == "rgba"){
     sendResponse({"RGBA": rgba, "duration": duration});
   }else{
     sendResponse({"RGBA": rgba, "duration": duration});
   }
  }
);
// 设置页面,写入localStorage 。
_saveOptions = function(){
  var rgba = "rgba(" + red + ", " + green + ", " + blue + ", " + alpha + ")";
  localStorage.setItem("duration", duration);
};
// localStorage 的用法与window 的一个属性一样,只要存取直接量就行了,不需要记住相关的函数。

使用了 jQuery 的部分比较简单(在成功了之后才觉得挺简单的),没有记录在内。

离线下载Chrome扩展

今天算是写了第一个Chrome扩展了。早上在点点网上看到东京幻想的一组图,非常喜欢,习惯性地用谷歌类图搜索找大图。但是有个网站被Q了,死活打不开,这样的话就少了两张图,对于我这个强迫症来说是不能忍受的,于是开始酝酿写一个离线下载的玩意,更确切地说是一个代理下载。

在以前的VOA 聚合器项目中使用过一个HTTP 下载类,正好顺手就拿来用。这个类不知道是谁写的,其中有一个 SaveBinFile() 方法没有定义,我也不知道该如何修补,索性直接用 SaveToBin() 方法代替好了,加入一个判断目标文件是否是文本的逻辑,如果是文本的话给特殊扩展名(不是 htmhtml 的)加上 html 后缀。

这样折腾完之后呢,两张图片的地址作为 GET 方法的参数 url 传入进去,返回 json 字符串提示服务器端下载成功了,然后我访问 json 中提示的地址,两张图片轻松到手。

不过这样怎么配叫做不折腾会死星人呢。这种下载方式每次都这么折腾,何不来个舒服点的,做成一个Chrome 扩展,遇到无法访问的资源,直接右击链接就能下载,这样岂不快哉。随后参考了N 多资料(我比较笨),主要是官方的文档,终于做好了。顺便说一下,Chrome扩展程序开发人员文档(非官方中文版)这个站点翻译得不错。

现在的效果就是,右击链接,选择 CrossGet this!,扩展会在后台发送 Ajax 请求,文件下载完成之后,会自动新建一个标签页打开,可以浏览或是下载啦。如果下载失败的话,有桌面通知提示。

最后记一下用到的一些代码神马的。

// 右键菜单。
var options = {"title": title, "contexts": contexts, "onclick": genericOnClick}; // genericOnClick 是回调函数。
var context = chrome.contextMenus.create(options);
// 桌面通知。
var notification = webkitNotifications.createNotification(
  'icon.png', 
  'Error!', 
  'Server returned an error.'
);
notification.show(); // 不调用show() 方法的话通知是不会显示的。
// Ajax 的GET 请求。
XmlHttp.open("GET", finalurl, true); // finalurl 中预先将要发送的GET 参数拼接好。
XmlHttp.send();
// 右键菜单的回调中如何获取链接的url。
var genericOnClick = function(info, tab){ // 不需要实际传入这两个参数。
  var link = info.linkUrl; //这样获取链接的url。
  console.log(link); // 可以输出到console 看一下。
}

因为这个用到了我的 kilu.de 免费空间,所以只是个人使用。

Ajax异步の基础

任何 JavaScript 书上都会教你这样创建 Ajax 请求。

var XmlHttp;
if(window.ActiveXObject){
  XmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
}else if(window.XMLHttpRequest){
  XmlHttp = new XMLHttpRequest();
}
XmlHttp.open("POST", "getlist.php", true);
XmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
XmlHttp.send("type=" + reqType);

但是我一直这样使用:

// ...
XmlHttp.open("POST", "getlist.php", false);
// ...
var response = XmlHttp.responseText;
// #actions...

这样是同步请求,就是说在等待的时候浏览器相当于冻住了,你无法执行其他他的操作。这就违背了 Ajax 异步的本意。我直到一个月前才理解了 Ajax 异步请求的基础。其实就是像下面这样。

// ...
XmlHttp.open("POST", "getlist.php", true);
// ...
XmlHttp.onreadystatechange = function(){
 if(XmlHttp.readyState == 4){
    // Actions here...
  }
}
// ...

VOA41Week小改进

虚拟机安装了XP ,IE 升级到IE 8了,顺手测试了一下VOA41Week ,发现列表根本就显示不出来。

在shownhide.jjs 中定义了Object 的show 和hide 方法,用于元素显示和隐藏的动画效果,但是在对元素调用这两个方法的时候,IE 提示"对象不支持此属性或方法"。找了很久找不到解决方法,在贴吧里问了一下,原来IE 中DOM 元素并不是继承自Object ,从http://msdn.microsoft.com/en-us/library/dd282900 来看,是继承自Element 。

然后改了下这两个方法,IE 、火狐和Chrome 测试都通过了。

ubuntu 12.04系统托盘不显示ibus输入法图标

在终端运行以下命令,然后注销,重新登录。

gconftool --type boolean -s /desktop/ibus/panel/show_icon_on_systray true
gconftool --type boolean -s /desktop/ibus/panel/show true
gsettings set com.canonical.Unity.Panel systray-whitelist "['all']"

PS,这个方法来自ubuntu 12.04系统托盘不显示ibus输入法图标的解决方法。我使用之后发现,不仅输入法图标出来了,原来一直没有图标的 Shutter 截图程序也能显示系统图标了。

学院网站の吐槽

由于时间久远,这篇文章吐槽的网站现在已经改版,读者请根据文章内容自行脑补。

话说我不得不吐槽一下学院的这个网站了。

这个“网站”。。。首先要吐槽的是端口,好端端地你用什么8088端口啊?!你服务器默认的80端口哪里去了啊?!其次你这个子域名也很蛋疼啊,www2是神马个意思啊!!!既然学校有自己的域名,搭一个cehui的子域名很难吗?!!!!还有你这个路径。。/ch/是神马???不知道的还以为你有多国语言支持啊!!找了一圈才发现只有中文啊!!只有中文你这是干毛啊!!!!

版面就更加令人发指了啊!!用的表格布局也就算了啊,你右上角那个导航是怎么回事啊!!!用图片做的链接,字体都能不一样啊!!!左上角那个logo下面的“Home | Site”是神马啊!!!导航下面那个一闪一闪亮晶晶的居然不是动画效果啊!!那就是一个gif动画啊!!!开始我还以为有链接可以进入不同的新闻啊!!!这个动画左边转呀转的flash是要表达什么啊!!!这货还把写着学院名字的图片挡住了啊!!!右边这个“推荐文章”的背景图错位了啊喂!!用表格布局都还能错位啊喂!!!!乃们把搜索按钮肿么了啊!!!它看起来好委屈啊!!!

用表格布局就用吧,可是每个板块的宽高都 不一样是怎么回事啊喂!!怎么有种感觉像是随手拖出来的啊!!左下角的友情链接没有内容啊喂!!!右边联系方式的图片看不清楚啊喂!!右下角的投票是个摆设啊我擦,有种被深深欺骗了的赶脚啊!!!

最下面的版权说明语义重复了好嘛。。。还有那个看起来崩坏了的版权图片是怎么回事???

吐槽完毕,接着工作。