Today's the day

向软件大牛炫耀我会焊单片机,向硬件大牛炫耀我会写 Rails,向软硬件大牛炫耀我生物,向软硬件生物大牛炫耀我会折腾期货 -_-bbb

Javascript 相对时间

因为相对时间是随时变化的,所以如果在页面里面直接生成相对时间的文本,那么就没法缓存成静态文件,不过用 js 可以解决这个问题。

首先,在页面里面还是用 rails 生成一般的时间,这样即使关掉了 js,也可以显示正常的时间。并套个 span:

<span class="relative_time"><%= @post.created_at %></span>

然后就是 js 的事情了,找出这些 span,并且算出相对时间替换进去:

function show_relative_time(local){
    var times = $$('span.relative_time');
    var now = new Date();
    for(i=0;i<times.length;i++){
        var time = times[i];
        var t = new Date(time.innerHTML);
        var diff = now - t;
        time.innerHTML = relative_time_text(Math.floor(Math.abs(diff/1000/60)), local);
    }
}

其中的 relative_time_text 接收分钟为参数,返回相对时间的文本:

function relative_time_text(m, local){
    var text;
    if(!rtlang[local])
        local = 'en';

    if(m <= 1)
        text = rtlang[local]['less than a minute'];
    else if(m > 1 && m <= 45)
        text = m + rtlang[local][' minutes'];
    else if(m > 45 && m <= 90)
        text = rtlang[local]['about 1 hour'];
    else if(m > 90 && m <= 1440)
        text = Math.round(m/60) + rtlang[local][' hour'];
    else if(m > 1440 && m <= 2880)
        text = rtlang[local]['1 day'];
    else if(m > 2880 && m <= 43200)
        text = Math.round(m/1440)+ rtlang[local][' days'];
    else if(m > 43200 && m <= 86400)
        text = rtlang[local]['about 1 month'];
    else if(m > 86400 && m <= 525600)
        text = Math.round(m/43200) + rtlang[local][' months'];
    else if(m > 525600 && m <= 1051200)
        text = rtlang[local]['about 1 year'];
    else
        text = Math.round(m/525600) + rtlang[local][' years'];

    return text + rtlang[local][' ago'];
}

基本就是照着 rails 里那函数改的,rtlang 就是个 hash,保存多语言信息:

var rtlang = {'zh_CN':{}, 'en':{}};
rtlang['en']['less than a minute'] = 'less than a minute';
rtlang['en'][' minutes'] = ' minutes';
rtlang['en']['about 1 hour'] = 'about 1 hour';
rtlang['en'][' hour'] = ' hour';
rtlang['en']['1 day'] = '1 day';
rtlang['en'][' days'] = ' days';
rtlang['en']['about 1 month'] = 'about 1 month';
rtlang['en'][' months'] = ' months';
rtlang['en']['about 1 year'] = 'about 1 year';
rtlang['en'][' years'] = ' years';
rtlang['en'][' ago'] = ' ago';


rtlang['zh_CN']['less than a minute'] = '小于一分钟';
rtlang['zh_CN'][' minutes'] = ' 分钟';
rtlang['zh_CN']['about 1 hour'] = '大约 1 小时';
rtlang['zh_CN'][' hour'] = ' 小时';
rtlang['zh_CN']['1 day'] = '1 天';
rtlang['zh_CN'][' days'] = ' 天';
rtlang['zh_CN']['about 1 month'] = '大约 1 个月';
rtlang['zh_CN'][' months'] = ' 个月';
rtlang['zh_CN']['about 1 year'] = '大约 1 年';
rtlang['zh_CN'][' years'] = ' 年';
rtlang['zh_CN'][' ago'] = ' 前';

这样如果要显示中文的相对时间,那么只需在页面尾部加上:

<script type="text/javascript">
     show_relative_time("zh_CN");
</script>

就搞定了~

原来我的 Javascript 水平还不是最差的

早上洗好澡,坐在电脑前一边吃早饭一边上天涯逛,看了许久三 L 的相关帖子,心情很沉重。

随后跳到了国家质量监督总局的网站,习惯性的 Crtl+U 了一下,然后看到这么一句:

  1. if (3==2)    //把3==3改为3==2则弹出窗口不工作;改为3==3则工作。
  2. {
  3. popup = window.open('', 'popupnav', 'width=430, height=250, resizable=0, scrollbars=no');
  4. }

彻底被雷了一下……

Ruby 数组转换成 Javascript 参数

有的时候数据存储在 Ruby 的数组里,如果你想把这个数组当作 Javascript 的函数的参数,比如:

@names = ['Zhangsan','Lisi']

你想把他作为参数传给 Javascript 代码,达到这样的效果:

a_js_function(['Zhangsan','Lisi']);

需要把 @names 转换成字符串的表达形式,你可能想到迭代数组中的每项,拼出最终的字符串,其实简单的方法是 inspect:

a_js_function(<%= @name.inspect %>);

因为在 Ruby 和 Javascript 中数组的表达是基本一样的,所以这样刚好达到了要求。

不过如果数组中有不期望的数据,比如 nil 或者一个复杂的对象什么的,结果可能就不是你希望的了。那么可以试试 array_or_string_for_javascript:

a_js_function(<%= array_or_string_for_javascript(@names) %>);

不过,array_or_string_for_javascript 会把数组中所有的项目都转换成字符串,所以如果数组是 [100, 200, 300] 就会被转换成 ['100', '200', '300'] 如果你想传入数值的话就用前面的 inspect 了。

另外还有一个 options_for_javascript,把 Ruby 的 Hash 转成 Javascript 的格式:

<%= options_for_javascript(:a => 1, :b => 2, :c => 3) %>
=>  {a:1, b:2, c:3}

Rails 中的 Helper 也用这俩函数生成 Javascript 的参数。

inspect 只适合偷懒用,毕竟 inspect 的格式并不保证不会变,也许 Ruby 下一般换个更漂亮的方式显示 inspect 结果,这招就不灵了。

firefox扩展开发(五) : 驱动XUL界面

firefox扩展开发(五) : 驱动XUL界面

阅读全文