2010年10月30日星期六

用代码完美替换All in One SEO插件最新方法

很多网友向老七反映,wordpress博客中用了All in One SEO插件后网站速度明显变慢,百度收录也不太正常,比较勤一点的站长向老七征求通过修改代码的方式达到完美替换掉wordpress博客中All in One SEO插件的效果,甚至比All in One SEO插件效果更好,老七研究了两天,终于大功告成了,老 七在信心,通过代码修改的方式达到的效果比All in One SEO插件更好!现在老七网络推广博客也彻底抛弃了All in One SEO插件,现将方法详细解说:

首先通过百度搜索关于用代码替换All in One SEO插件的文章,发现很少,甚至可以说没有,因为那些方法已经不太适合现在2010年的SEO情况,老七自己钻研了一下All in One SEO插件的原理,再结合过滤等技巧,终于达到了非常理想的效果!

WordPress 主题提供的keywords和description这两个meta标签一般都做得很差,或者根本就不提供,这样不利于SEO。本文将指导你如何给主页、 分类、页面以及文章页添加单独的Description 和 Keywords。

很多人都在用All in One SEO插件解决这个问题,但是又有很多人说这个插件不好。老七可以直接肯定的告诉你:赶紧换成代码吧,如果想做实力技术型站长的话!

注意哦,精彩在最后面,关于自动截取文章描述作为 description的代码,其中还包含了过滤一些字符的代码!

All in One SEO 一度被认为是必备 Wordpress 插件,它的标准化 title 结构、自动用 tag 作为关键字(keywords)自动生成页面描述(description)和分类等页面的 noindex 功能几乎是大家的标准化设置。但是恰恰是这些,让你的 blog 在 SEO 上减分。

原因一:noindex 导致百度不收录内容
百度爬虫很傻的,看到 noindex 就 k 掉全部只留一个首页,或者最近的内容不收录。这就是坊间流传的所谓百度不收录 wordpress 的根源,其实罪在 All in One SEO。

原因二:自动描述导致丢失描述
老七一度的 google 搜索存档信息里除了标题就剩下文章信息(日期作者什么的),然后就是评论。原因是启用了 All in One SEO 的自动 description,但是英文还好,对于大部分页面它压根无法生成中文 description,而你有一个空白 description 在这里搜索引擎就不给你自动 description 了。

原因三:All in One SEO 很耗资源
这个有待验证。昨天我去掉它以后,很多人包括我自己在内都感觉到马上速度快了很多。

那么,去掉以后,如果保证必要的 SEO 措施

之一:title 结构
这个很重要,如果你一直用“标题 - 站名”这样的结构千万别改,否则可能被搜索引擎惩罚。保持原有结构我们在 header.php 里加了(或替换原有 title 部分)这么一句:
<title><?php if (is_home() ) { ?>老七 - digg digest<?php } else {?><?php wp_title(''); ?> - 老七<?php } ?></title>
意思很简单。blog 名和描述直接写的目的是尽量减少执行函数。

之二:关键字和站点描述
在 header.php 里,用下面这段代码来代替原来默认模板里的同类代码:
<?if (is_home()){
$description = "你的站点描述";
$keywords = "你的关键字";
} elseif (is_single()){
$description = $post->post_title ;
$keywords = "";
$tags = wp_get_post_tags($post->ID);
foreach ($tags as $tag ) {
$keywords = $keywords . $tag->name . ", ";
}
} elseif(is_category()){
$description = category_description();
}
?>
<meta name="keywords" content="<?=$keywords?>" />
<meta name="description" content="<?=$description?>" />

之三:文章描述
这个有两个办法,一是用截断文章前多少字(貌似有相应插件)的摘要作为描述,另一个就是利用 All in One SEO 的原理,利用自定义关键字(custom field)定义 description 然后调用,具体操作可参考这篇,代码是:
<?php if ( is_single() ) { ?>
<meta name="description" content="<?php $key="description"; echo get_post_meta($post->ID, $key, true); ?>" />
<?php } ?>

如果没用过 All in One SEO 插件的,可以先新建一个 description 关键字,下次就可以选择了。

之四:NoIndex
既然百度爬虫太傻逼,那就针对 Google 爬虫写,在 header.php 里加这么一句:
<?php if ( !(is_home()) and !(is_single()) ) { ?><meta name="Googlebot" content="noindex,follow" /><?php }?>
意思就是除了首页和文章,其它页面最好不要 index。另外据我个人的经验,这句话前面最好加个空行。

未完:也许很多人认为到这里就该结束了,老七刚开始 也是这么觉得的,但后来仔细分析了一下,这里对于description(文章描述)做的还不够好,因为代码是将title直接给了 description,也就是description=title(文章描述和标题一样),与其这样做,还不如将description空着,因为 description和title一样是SEO中要避免的问题,帮老七又另外对description进行了一翻修改,终于达到了理想的效果!

下面看看老七怎么自动截取文章描述,过滤相关字符的吧!

第一步:在模板文件里找到functions.php,将最前面<?php 改成:

<?php
    function sub_str($str, $start = 0, $length = 0, $append = true , $appendstring = ‘…’)
{
 $str = trim($str);
 if ($length == 0)
 {
  return $str;
 }

 /*if (function_exists(‘mb_substr’))
 {
  $newstr = mb_substr($str, $start, $length, ‘UTF-8′);
 }
 else
 {*/
  $strlength = strlen($str);

  if ($length < 0)
  {
   $length = $strlength + $length;
  }
  elseif ($length >= $strlength)
  {
   return $str;
  }
  $newstr = preg_replace(‘#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,’ . $start .  ‘}((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,’ . $length . ‘}).*#s’, ‘$1′, $str);
 //}

 if ($append && $str != $newstr)
 {
  $newstr .= $appendstring;
 }

 return $newstr;
}

第二步:在header.php里面将定义文章页描述的内容修改为如下语句:

 elseif (is_single())
     {
$description  = strip_tags($post->post_content);
$description  = str_replace(“\r\n”, ” ,$description );
$description  = str_replace(“&nbsp” , ” ,$description ) ;
       $description = trim(sub_str($description , 0 , 120 , false));
       $keywords = “”;
       $tags = wp_get_post_tags($post->ID);
       foreach ($tags as $tag )
       { $keywords = $keywords . $tag->name . “, “;  }
     }

注解:

$description  = str_replace(“\r\n”, ” ,$description );
$description  = str_replace(“&nbsp” , ” ,$description ) ;

表示空格和回车过滤!

$description = trim(sub_str($description , 0 , 120 , false));
120表示描述字符数,wordpress编码的原因,写成120效果最好!

写到这里,差不多就完成了!不知不觉已经很晚了,希望对大家有用!

2010年10月27日星期三

[JS]javascript获取select的当前值(兼容 IE、Firefox,Opera, Chrome)

document.getElementById("select").options[document.getElementById("select").options.selectedIndex].value

例 子:
<script>
function check()
{
      var select = document.getElementById("select").options[document.getElementById("select").options.selectedIndex].value;
      alert(select);
}
</script>
 <select name="select" id="select">
<option value="test1" selected="selected">Test1</option>
<option value="test2">Test2</option>
</select>
<input type="button" value="我要试试" onclick="check()"/>

Dreamhost到Hawkhost搬家手记

前言

2009年4月,因为朋友GordianZ帮助的关系,购入一个777优惠 码的Dreamhost(简称DH)主机,之后的几个博客便都搭建在上面,总的来说,还是稳定可靠的,不过,今年4月到期的续费价格高达$119.40, 这对不从博客上获得收入的21来说还是一笔很大的开支,于是我便策划着搬家。

2009年12月,因为朋友老卫的非盈利性主机评论博客提到一家主 机商叫Hawkhost(简称HH),俗称老鹰主机,在12月份推出了一个高达50%的优惠码,基础方案$3.29/mo的费用打折后堪称亲 民,于是毫不犹豫就购入一个帐户(老卫把这种行为叫"不理智消费"),但是为什么没有一购入就搬家呢?

搬家前其实是基于两点考量:

  1. 稳定性未知。虽然官方声称能达到99.9% Uptime,但是我们都知道这个99.9%可以有很多种算法。
  2. 可靠性未知。我们知道有些小主机商实际上是骗人的,一两个月后就消失,需要观察。

所以,在设置了一个Uptime以后,就暂时闲置了,直到一月初在我的建议之下朋友Tomato也成为WP党的一员,于是应用方面的监测也开始了。 就到目前为止的情况来看,长达两个月时间的监测,Uptime非常不错,值得信赖 ── 除了前两个月电信的线路抽风外,所以我决定将DH上的几个博客都迁移过来。

首先说明,因为这是DH到HH的手记,具备一些部分主机可能不具备的特性,所以请酌情参考,有疑问请留言。
Dreamhost和Hawkhost同时具备一个条件:SSH,也就说,很多复杂或者麻烦的操作,我可以通过SSH直接在主机上操作,避免了FTP上传 下载需要花费的额外时间开销。这也是这篇手记与一般教程不同的地方。

Dreamhost 的备份

在DH上执行备份,有两种办法,我分别写出,因为过程混杂,实际上两种我都用到了。

    备份方法 一

    Dreamhost提供了一个备份的服务,在DH面板[1]左侧Sidebar的位 置,+DreamHost -> Backup Your Account,然后点一下唯一的按钮,DH会提交 你的备份请求到队列里面 ── 对,是要排队的,如果前面的人不多,应该马上就好,备份完成后你的DH帐户的注册邮箱会收到一封邮件,大概内容如下:

    [username 3158xxxx] Success! Your account (#526xxx) has been backed up!

    Ta da! Your ENTIRE DreamHost account has been backed up now here:

    http://backups.dreamhost.com/2010-01-05-GQ2SRxxxxxxxxx //备份服务 登录的链接。

    username: {backup login user} //登录的用户名,http验证的。
    password: {backup login passwd} //登录的密码。

    Your backup will only be available at this location for FIVE days.. so
    please hurry and download what you need right away!
    //意思是说,备份会保存5天,请尽快处理。

    Here are all the users/mailboxes we've backed up (as zipped homedirs):
    NOTE: Any users with more than 4GB of data have been skipped!
    {your dh account list here}
    //你的DH主帐户和子帐户都会备份(即使home目录不同),并且在这里列出一个清单。

    And here are all your mysql databases we've backed up (as gzipped dumps):
    NOTE: Any databases with more than 4GB of data have been skipped!
    {your dh mysql database list here}
    //你名下的所有数据库都会备份,并且在这里列出一个清单。

    Enjoy!
    The Happy DreamHost Account Backup Robot!

    这个办法会自动备份你所有的东西,非常方便,但是如果你想要更有挑战性呢?方法二。

    备份方法 二

    先说明,如果你使用备份方法一没有问题,请直接跳入下一章节。

    在这里我们需要登入DH的SSH,使用SSH对自己指定的文件进行打包存放,然后再转移,但是这个办法对独立home目录的子帐户无效。
    我个人推荐win用户使用putty客户端(Linux和Mac用户直接打开终端输入ssh username@host就 行),简单明了,登入以后,先输入pwd确认自己的位置,一般都是在用户自己的目录下的,比如我的用户名是delive,效果如下:

    1
    2
    3
    4
    5
      [avalanche]$ pwd
    /home/delive '如果不是 /home?/username 格式的,继续'
    [avalanche]$ cd ~
    [avalanche]$ pwd
    /home/delive

    OK,确认自己已经在自己帐户的目录下了,然后执行以下命令备份文件(不包括数据库):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    打包压缩需要备份的目录
    格式:tar zcf 目的文件名.tar.gz 需要打包压缩的目录(用空格隔开,可以多个)
    范例:
    [avalanche]$ ls
    目录1 目录2 目录3
    [avalanche]$ tar zcf bak.tar.gz ~/目录1/ ~/目录2/ ~/目录3/
    tar: Removing leading `/` from member names
    [avalanche]$ ls
    bak.tar.gz 目录1 目录2 目录3

    到这一步,我们已经把目录1/2/3打包为bak.tar.gz文件了,接下来是数据库

    1
    2
    3
    4
    5
    6
    7
    8
    备份数据库
    格式:mysqldump -h数据库主机 -u数据库用户名 -p 数据库名 > 1.sql
    范例:
    [avalanche]$ mysqldump -hmysql.21.com -ublog21 -p 21db > 21.sql
    Enter password: '提示这个的时候请输入数据库访问密码,没有回显的,输完回车就行'
    [avalanche]$ mysqldump -hmysql.21.com -ublog21 -p 22db > 22.sql
    Enter password:
    依此类推

    然后是打包数据库

    1
    2
    3
    4
    5
    6
    7
    8
      [avalanche]$ tar zcf mysql.tar.gz 21.sql 22.sql
    [avalanche]$ ls
    ./ ../ 21.sql 22.sql bak.tar.gz mysql.tar.gz 目录1 目录2 目录3
    [avalanche]$ tar zcf dh.tar.gz bak.tar.gz mysql.tar.gz
    [avalanche]$ ls
    ./ ../ 21.sql 22.sql bak.tar.gz dh.tar.gz mysql.tar.gz 目录1 目录2 目录3
    [avalanche]$ pwd
    /home/delive

    至此,这个繁琐又复杂的SSH备份总算搞定了。

实际上,方法二算是比较啰唆复杂的,并且在一些特殊情况下备份不完整(如果是一个人使用的DH倒是不存在这样的问题),但是为了学习嘛,不过大多数 情况下用方法一就行。
下一步就是把备份出来的数据弄到新主机上,这次就需要SSH了,虽然通过一些PHP脚本能搞定,但是我建议有SSH干嘛不用呢?本机也可以想办法下载一份 留存,这个留到最后的章节讲解。

数据的迁移

因为前一节提到了两种备份办法,所以这一节会对应之前两种方法的迁移方法,基本上来说,不算复杂,但是问题是,备份一的迁移方法要比备份二的迁移方 法麻烦一些,为什么呢?请看。

    迁移方法 一(对应备份一)

    先简述,因为之前备份一实际上备份文件是存放在DH的备份服务器上的,并且以网页的形式体现的,而除了http下载之外,我们似乎也没有其它办法获 取那些备份文件,如果子帐户多一点或者数据库多一点,那会变得比较麻烦。
    正常情况下,我们可以在网页右键选择"使用迅雷下载全部链接"来搞定这个问题,但是,本手记的目的是不通过本机的迁移,所以,我们将用SSH解决。

    登录HH的SSH,然后我们准备好之前DH备份完成的邮件,开始:

    1
    2
    3
    4
    5
    6
    7
    8
    21MBP:~ 21$ ssh user@example.com
    The authenticity of host 'example.com (174.37.xxx.xx)' can't be established.
    RSA key fingerprint is cc:bd:03:fc:f7:59:fe:96:90:82:44:xx:xx:xx:xx:xx.
    Are you sure you want to continue connecting (yes/no)? y
    Please type 'yes' or 'no': yes
    Warning: Permanently added 'example.com,174.37.xxx.xx' (RSA) to the list of known hosts.
    example@example.com's password:
    example@example.com [~]#

    这是在我苹果本子上登录的提示,一般初次登录,会提示你接受一个密钥用于双方的加密数据传输,这个时候输入yes就 行,输入y的话会提示错误,之后输入密码,如果正确无误的话,我们就登录进去了。接下来准备下载那些备份文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    example@example.com [~]# pwd  //确定当前位置
    /home/example
    example@example.com [~]# mkdir temp //创建一个temp目录备用
    example@example.com [~]# cd temp //切换到temp目录
    example@example.com [~/temp]# ls //列出目录
    ./ ../
    example@example.com [~/temp]# wget http://backups.dreamhost.com/2010-01-05-GQ2SRxxxxxxxxx -r --http-user={backup login user} --http-password={backup login password}
    '{此处省略暴多的乱七八糟的提示}'
    Downloaded: 42 files, 397M in 1m 5s (6.11 MB/s)
    example@example.com [~/temp]#

    这里用到的http://backups.dreamhost.com/2010-01-05- GQ2SRxxxxxxxxx、{backup login user}、{backup login password} 均出自 DH发给你提示备份成功的邮件。
    恩,我是通过wget抓取网页并且在本地重建的方式把备份服务器上的所有备份文件一次性下载下来的办法。通常在两个美国主机之间传输数据,基本上单位都是 以"M(兆)"来计算的,我300多M的数据一分钟多点就全部搞定了。

    1
    2
    3
    4
    5
    6
    7
    8
      example@example.com [~/temp]# ls
    ./ ../ backups.dreamhost.com index.html
    example@example.com [~/temp]# cd backups.dreamhost.com
    example@example.com [~/temp/backups.dreamhost.com]# ls
    ./ ../ 2010-01-05-GQ2SRxxxxxxxxx
    example@example.com [~/temp/backups.dreamhost.com]# cd 2010-01-05-GQ2SRxxxxxxxxx
    example@example.com [~/temp/backups.dreamhost.com/2010-01-05-GQ2SRxxxxxxxxx]# ls
    ./ ../ mysql users

    经过确认,我们下载下来的主要有两个目录,一个是「mysql」,里面存放你DH帐户的所有mysql数据库,一个是「users」,里面以ftp 用户名为目录的方式存放了你的web文件,都是打包好的。到此为止,方法一的文件就全部迁移到新的HH主机上了,如果没有任何问题,请直接进入下一节,我 们将讨论如何恢复这些迁移过来的数据。

    迁移方法 二(对应备份二)

    通过备份二那个繁琐的办法,我们搞定了自己的数据库和文件,并且打包为一个文件叫dh.tar.gz放在/home/delive目录下,那么,对 应的,这个步骤就要相对简单了。

    登录HH的SSH:

    1
    2
    3
    4
    5
    6
    7
    8
      21MBP:~ 21$ ssh user@example.com
    The authenticity of host 'example.com (174.37.xxx.xx)' can't be established.
    RSA key fingerprint is cc:bd:03:fc:f7:59:fe:96:90:82:44:xx:xx:xx:xx:xx.
    Are you sure you want to continue connecting (yes/no)? y
    Please type 'yes' or 'no': yes
    Warning: Permanently added 'example.com,174.37.xxx.xx' (RSA) to the list of known hosts.
    example@example.com's password:
    example@example.com [~]#

    登录进去以后,我们要新建一个目录用来存放我们的备份文件,这个同 迁移一 是一样的,

    1
    2
    3
    4
    5
    6
    example@example.com [~]# pwd  //确定当前位置
    /home/example
    example@example.com [~]# mkdir temp //创建一个temp目录备用
    example@example.com [~]# cd temp //切换到temp目录
    example@example.com [~/temp]# ls //列出目录
    ./ ../

    接下来我们就要把之前的备份文件弄过来了,这次简单了,直接在SSH里面通过ftp就搞定了,这里用到的用户名密码是你DH的用户名密码,不再是之 前的备份邮件里面提到的那个,请谨记

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    example@example.com [~/temp]# ftp your_dh_domain.com
    Connected to your_dh_domain.com.
    220 DreamHost FTP Server
    500 AUTH not understood
    500 AUTH not understood
    KERBEROS_V4 rejected as an authentication type
    Name (your_dh_domain.com:hh_user): your_dh_user '输入你的DH用户名'
    331 Password required for delive.
    Password: '输入你的DH密码'
    230 User delive logged in.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> get dh.tar.gz
    local: dh.tar.gz remote: dh.tar.gz
    227 Entering Passive Mode (67,205,61,244,208,60).
    150 Opening BINARY mode data connection for dh.tar.gz (xxxxxx bytes)
    226 Transfer complete.
    xxxxxxx bytes received in xx.xx seconds (xxxx Kbytes/s)
    ftp> by
    221 Goodbye.
    example@example.com [~/temp]# ls
    ./ ../ dh.tar.gz

    恩,文件在SSH里面通过FTP的方式从DH拉到HH了,接下来就是解压什么的,因为之前我们压缩过了,给个范例参考,根据自己的需要修改就成:
    example@example.com [~/temp]# tar zxf 文件名.tar.gz

总的来说,实际上在迁移这步,两种办法都差不多,只不过一个是通过wget下载,一个是用过ftp,而实际上后者这个ftp同样可以通过wget来 替代,稍微麻烦的是方法一的文件多了点,而方法二比较干脆,就一个压缩包搞定。下面,我们要搞定的部署我们的新主机HH。

[未完待续,余下部分便是数据恢复,还有目录整理。]

---------------------------------------
  1. http://panel.dreamhost.com 登录,这个简称为DH面板 []
http://mr21.in/2010-03/dreamhost-to-hawkhost-hosting-move-note.html

前端在线编辑测试工具整理

本文将要介绍的这些编辑器,都是与前端开发相关的,并不同于传统的富文本编辑器.其中一些是可以多人同时进行编写一份文档,一些是可以编辑完以后进 行多人共享,抑或是像一个IDE环境一样可以运行查看javascript和css运行效果.如果您知道我这里没有列出的优秀编辑测试工具,劳烦留个言.

编辑+运行+分享

编辑+分享

  • Code Dumper:编辑后的文本可以选择非常多语种的代码高 亮.
  • TitanPad:可以多人协助的同时编辑一份文档,不同的身份使用不 同的颜色区分,非常酷.
  • OkSoClap:与上一个一样,可以作为后备.
  • notepad
  • write.fm
  • Gist:应该不陌生了,依托于github.
  • Entri
  • peg.gd

其他

  • memorizenow.com:类似于便签,也可以作 为临时的脑图记录
  • darkcopy:一款纯黑背景的编辑器,没啥特别的,可以全屏,可以 下载.

背完这444句,你的口语应该是不成问题了

1. I see. 我明白了。

2. I quit! 我不干了!

3. Let go! 放手!

4. Me too. 我也是。

5. My god! 天哪!

6. No way! 不行!

7. Come on. 来吧(赶快)

8. Hold on. 等一等。

9. I agree。 我同意。

10. Not bad. 还不错。

11. Not yet. 还没。

12. See you. 再见。

13. Shut up! 闭嘴!

14. So long. 再见。

15. Why not? 好呀! (为什么不呢?)

16. Allow me. 让我来。

17. Be quiet! 安静点!

18. Cheer up! 振作起来!

19. Good job! 做得好!

20. Have fun! 玩得开心!

21. How much? 多少钱?

22. I'm full. 我饱了。

23. I'm home. 我回来了。

24. I'm lost. 我迷路了。

25. My treat. 我请客。

26. So do I. 我也一样。

27. This way。 这边请。

28. After you. 您先。

29. Bless you! 祝福你!

30. Follow me. 跟我来。

31. Forget it! 休想! (算了!)

32. Good luck! 祝好运!

33. I decline! 我拒绝!

34. I promise. 我保证。

35. Of course! 当然了!

36. Slow down! 慢点!

37. Take care! 保重!

38. They hurt. (伤口)疼。

39. Try again. 再试试。

40. Watch out! 当心。

41. What's up? 有什么事吗?

42. Be careful! 注意!

43. Bottoms up! 干杯(见底)!

44. Don't move! 不许动!

45. Guess what? 猜猜看?

46. I doubt it 我怀疑。

47. I think so. 我也这么想。

48. I'm single. 我是单身贵族。

49. Keep it up! 坚持下去!

50. Let me see.让我想想。

51. Never mind.不要紧。

52. No problem! 没问题!

53. That's all! 就这样!

54. Time is up. 时间快到了。

55. What's new? 有什么新鲜事吗?

56. Count me on 算上我。

57. Don't worry. 别担心。

58. Feel better? 好点了吗?

59. I love you! 我爱你!

60. I'm his fan。 我是他的影迷。

61. Is it yours? 这是你的吗?

62. That's neat. 这很好。

63. Are you sure? 你肯定吗?

64. Do l have to 非做不可吗?

65. He is my age. 他和我同岁。

66. Here you are. 给你。

67. No one knows . 没有人知道。

68. Take it easy. 别紧张。

69. What a pity! 太遗憾了!

70. Any thing else? 还要别的吗?

71. To be careful! 一定要小心!

72. Do me a favor? 帮个忙,好吗?

73. Help yourself. 别客气。

74. I'm on a diet. 我在节食。

75. Keep in Touch. 保持联络。

76. Time is money. 时间就是金钱。

77. Who's calling? 是哪一位?

78. You did right. 你做得对。

79. You set me up! 你出卖我!

80. Can I help you? 我能帮你吗?

81. Enjoy yourself! 祝你玩得开心!

82. Excuse me,Sir. 先生,对不起。

83. Give me a hand! 帮帮我!

84. How's it going? 怎么样?

85. I have no idea. 我没有头绪。

86. I just made it! 我做到了!

87. I'll see to it 我会留意的。

88. I'm in a hurry! 我在赶时间!

89. It's her field. 这是她的本行。

90. It's up to you. 由你决定。

91. Just wonderful! 简直太棒了!

92. What about you? 你呢?

93. You owe me one.你欠我一个人情。

94. You're welcome. 不客气。

95. Any day will do. 哪一天都行夕

96. Are you kidding? 你在开玩笑吧!

97. Congratulations! 祝贺你!

98. T can't help it. 我情不自禁。

99. I don't mean it. 我不是故意的。

100. I'll fix you Up. 我会帮你打点的

101. It sounds great!. 听起来很不错。

102. It's a fine day。 今天是个好天。

103. So far,So good. 目前还不错。

104. What time is it? 几点了?

105. You can make it! 你能做到!

106. Control yourself! 克制一下!

107. He came by train. 他乘火车来。

108. He is ill in bed. 他卧病在床。

109. He lacks courage. 他缺乏勇气。

110. How's everything? 一切还好吧?

111. I have no choice. 我别无选择。

112. I like ice-cream. 我喜欢吃冰淇淋。

113. I love this game. 我钟爱这项运动。

114. I'll try my best. 我尽力而为。

115. I'm On your side. 我全力支持你。

116. Long time no see! 好久不见!

117. No pain,no gain. 不劳无获。

118. Well,it depends 噢,这得看情况。

119. We're all for it. 我们全都同意。

120. What a good deal! 真便宜!

121. What should I do? 我该怎么办?

122. You asked for it! 你自讨苦吃!

123. You have my word. 我保证。

124. Believe it or not! 信不信由你!

125. Don't count on me.别指望我。

126. Don't fall for it! 别上当!

127. Don't let me down. 别让我失望。

128. Easy come easy go. 来得容易,去得快。

129. I beg your pardon. 请你原谅。

130. I beg your pardon? 请您再说一遍(我没有听清)。

131. I'll be back soon. 我马上回来。

132. I'll check it out. 我去查查看。

133. It's a long story. 说来话长。

134. It's Sunday today. 今天是星期天。

135. Just wait and see! 等着瞧!

136. Make up your mind. 做个决定吧。

137. That's all I need. 我就要这些。

138. The view is great. 景色多么漂亮!

139. The wall has ears. 隔墙有耳。

140. There comes a bus. 汽车来了。

141. What day is today? 今天星期几?

142. What do you think? 你怎么认为?

143. Who told you that? 谁告诉你的?

144. Who's kicking off? 现在是谁在开球?

145. Yes,I suppose So. 是的,我也这么认为。

146. You can't miss it 你一定能找到的。

147. Any messages for me? 有我的留言吗?

148. Don't be so modest. 别谦虚了。

149. Don't give me that! 少来这套!

150. He is a smart boy. 他是个小机灵鬼。

151. He is just a child. 他只是个孩子。

152. I can't follow you. 我不懂你说的。

153. I felt sort of ill. 我感觉有点不适。

154. I have a good idea! 我有一个好主意。

155. It is growing cool. 天气渐渐凉爽起来。

156. It seems all right. 看来这没问题。

157. It's going too far. 太离谱了。

158. May I use your pen? 我可以用你的笔吗?

159. She had a bad cold. 她患了重感冒。

160. That's a good idea. 这个主意真不错。

161. The answer is zero. 白忙了。

162. What does she like? 她喜欢什么?

163. As soon as possible! 越快越好!

164. He can hardly speak. 他几乎说不出话来。

165. He always talks big. 他总是吹牛。

166. He won an election. 他在选举中获胜。

167. I am a football fan. 我是个足球迷。

168. If only I could fly. 要是我能飞就好了。

169. I'll be right there. 我马上就到。

170. I'll see you at six. 我六点钟见你。

171. IS it true or false? 这是对的还是错的?

172. Just read it for me. 就读给我听好了。

173. Knowledge is power. 知识就是力量。

174. Move out of my way! 让开!

175. Time is running out. 没时间了。

176. We are good friends. 我们是好朋友。

177. What's your trouble? 你哪儿不舒服?

178. You did fairly well! 你干得相当不错1

179. Clothes make the man. 人要衣装。

180. Did you miss the bus? 你错过公共汽车了?

181. Don't lose your head。 不要惊慌失措。

182. He can't take a joke. 他开不得玩笑。

183. He owes my uncle $100.他欠我叔叔100美元。

184. How are things going? 事情进展得怎样?

185. How are you recently? 最近怎么样?

186. I know all about it. 我知道有关它的一切。

187. It really takes time. 这样太耽误时间了。

188. It's against the law. 这是违法的。

189. Love me,love my dog. (谚语)爱屋及乌。

190. My mouth is watering. 我要流口水了。

191. Speak louder,please. 说话请大声点儿。

192. This boy has no job. 这个男孩没有工作。

193. This house is my own. 这所房子是我自己的。

194. What happened to you? 你怎么了?

195. You are just in time. 你来得正是时候。

196. You need to workout. 你需要去运动锻炼一下。

197. Your hand feels cold. 你的手摸起来很冷。。

198. Don't be so childish. 别这么孩子气。

199. Don't trust to chance! 不要碰运气。

200. Fasten your seat belt. 系好你的安全带。

201. He has a large income. 他有很高的收入。

202. He looks very healthy. 他看来很健康。

203. He paused for a reply. 他停下来等着・回答。

204. He repaired his house. 他修理了他的房子。

205. He suggested a picnic. 他建议搞一次野餐。

206. Here's a gift for you. 这里有个礼物送给你。

207. How much does it cost? 多少钱?

208. I caught the last bus. 我赶上了最后一班车。

209. I could hardly speak. 我简直说不出话来。

210. I'll have to try that. 我得试试这么做。

211. I'm very proud of you. 我为你感到非常骄傲。

212. It doesn't make sense. 这没有意义(不合常理)。

213. Make yourself at home. 请不要拘礼。

214. My car needs washing. 我的车需要洗一洗。

215. None of your business! 与你无关!

216. Not a sound was heard. 一点声音也没有。

217. That's always the case. 习以为常了。

218. The road divides here. 这条路在这里分岔。

219. Those are watermelons. 那些是西瓜。

220. What a nice day it is! 今天天气真好!

221. What's wrong with you? 你哪里不对劲?

222. You are a chicken. 你是个胆小鬼。

223. A lovely day,isn't it? 好天气,是吗?

224. He is collecting money. 他在筹集资金。

225. He was born in New York. 他出生在纽约。

226. He was not a bit tired. 他一点也不累。

227. I will be more careful. 我会小心一些的,

228. I will never forget it. 我会记着的。

229. It is Just what I need. 这正是我所需要的。

230. It rather surprised me. 那事使我颇感惊讶。

231. Just around the comer. 就在附近。

232. Just for entertainment. 只是为了消遣一下。

233. Let bygones be bygones. 过去的,就让它过去吧。

234. Mother doesn't make up. 妈妈不化妆。

235. Oh,you are kidding me. 哦,你别拿我开玩笑了。

236. She has been to school. 她上学去了。

237. Skating is interesting. 滑冰很有趣。

238. Supper is ready at six. 晚餐六点钟就好了。

239. That's a terrific idea! 真是好主意!

240. What horrible weather! 这鬼天气!

241. Which would you prefer? 你要选哪个?

242. Does she like ice-cream? 她喜欢吃冰淇淋吗?

243. First come first served. 先到先得。

244. Great minds think alike. 英雄所见略同。

245. He has a sense of humor. 他有幽默感。

246. He is acting an old man. 他正扮演一个老人。

247. He is looking for a job. 他正在找工作。

248. He doesn't care about me. 他并不在乎我。

249. I develop films myself. 我自己冲洗照片。

250. I felt no regret for it. 对这件事我不觉得后悔。

251. I get up at six o'clock. 我六点起床。

252. I meet the boss himself. 我见到了老板本人。

253. I owe you for my dinner. 我欠你晚餐的钱。

254. I really enjoyed myself. 我玩得很开心。

255. I'm fed up with my work! 我对工作烦死了!

256. It's no use complaining. 发牢骚没什么用。

257. She's under the weather. 她心情・不好。

258. The child sobbed sadly. 小孩伤心地抽泣着。

259. The rumor had no basis. 那谣言没有・根据。

260. They praised him highly. 他们大大地表扬了他。

261. Winter is a cold season. 冬天是一个,寒冷的季节。

262. You can call me any time. 你可以随时打电话给我。

263. 15 divided by3 equals 5. 15除以3等于5。

264. All for one,one for all. 我为人人,人人为我。

265. East,west,home is best. 金窝,银窝,不如自己的草窝。

266. He grasped both my hands. 他紧握住我的双手。

267. He is physically mature. 他身体己发育成熟。

268. I am so sorry about this. 对此我非常抱歉(遗憾)。

269. I can't afford a new car. 我买不起一部新车。

270. I do want to see him now. 我现在确实很想去见他。

271. I have the right to know. 我有权知道。

272. I heard some one laughing. 我听见有人在笑。

273. I suppose you dance much. 我想你常常跳舞吧。

274. I walked across the park. 我穿过了公园。

275. I'll just play it by ear. 我到时随机应变。

276. I'm not sure I can do it. 恐怕这事我干不了。

277. I'm not used to drinking. 我不习惯喝酒。

278. Is the cut still painful? 伤口还在痛吗?

279. It's too good to be true! 好得难以置信。

280. Jean is a blue-eyed girl. 珍是个蓝眼睛的女孩。

281. Let's not waste our time. 咱们别浪费时间了。

282. May I ask some questions? 我可以问几个问题吗?

283. Money is not everything. 金钱不是一切。

284. Neither of the men spoke. 两个人都没说过话。

285. Stop making such a noise. 别吵了。

286. That makes no difference. 没什么区别。

287. The price is reasonable. 价格还算合理。

288. They crowned him king. 他们拥立他为国王。

289. They're in red and white. 他们穿着红白相间的衣服。

290. We all desire happiness. 我们都想要幸福。

291. We just caught the plane 我们刚好赶上了飞机。

292. What shall we do tonight? 我们今天晚上去干点儿什么呢?

293. What's your goal in life 你的人生目标是什么?

294. When was the house built? 这幢房子是什么时候建造的?

295. Why did you stay at home? 为什么呆在家里?

296. Would you like some help? 需要帮忙吗?

297. You mustn't aim too high 你不可好高骛远。

298. You're really killing me! 真是笑死我了!

299. You've got a point there. 你说得挺有道理的。

300. Being criticized is awful! 被人批评真是痛苦

301. Did you enter the contest? 你参加比赛了吗?

302. Do you accept credit cards? 你们收信用卡吗?

303. Don't cry over spilt milk. 不要做无益的后悔。

304. Don't let chances pass by. 不要让机遇从我们身边溜走。

305. He owned himself defeated. 他承认自己失败了。

306. He seems at little nervous. 他显得有点紧张。

307. He strolls about the town. 他在镇上四处遛达。

308. Her tooth ached all night. 她牙疼了一整夜。

309. How about a drink tonight? 今晚喝一杯怎样?

310. I can do nothing but that. 我只会做那件事。

311. I get hold of you at last. 我终于找到你了。

312. I have a surprise for you.我有一个意想不到的东西给你看。

313. I like all kinds of fruit. 我喜欢各种各样的水果。

314. I saw it with my own eyes. 我亲眼所见。

315. I will arrange everything. 我会安排一切的。

316. I wish I knew my neighbor. 我很想认识我的邻居。

317. I would like to check out. 我想结帐。

318. It has be come much cooler. 天气变得凉爽多了。

319. It's time you went to bed. 你早就该睡觉了。

320. No spitting on the street. 禁止在大街上吐痰。

321. She was totally exhausted. 她累垮了。

322. Show your tickets,please. 请出示你的票。

323. Thank you for your advice. 谢谢你的建议。

324. That's the latest fashion. 这是最流行的款式。

325. The train arrived on time. 火车准时到达。

326. There go the house lights. 剧院的灯光灭了。

327. They are paid by the hour. 他们按时取酬。

328. Things are getting better. 情况正在好转。

329. Wake me up at five thirty. 请在五点半叫醒我。

330. We are all busy with work. 我们都忙于工作。

331. Where do you want to meet? 你想在哪儿见面?

332. You can get what you want. 你能得到你想要的。

333. A barking dog doesn't bite! 吠犬不咬人。

334. Are you free this Saturday? 你这个星期六有空吗?

335. Be careful not to fall ill. 注意不要生病了。

336. Being a mother is not easy. 做一个母亲是不容易的。

337. Brevity is the soul of wit. 简洁是智慧的精华。

338. Cancer is a deadly disease. 癌症是一种致命的疾病。

339. Did you fight with others? 你又和别人打架了吗?

340. Don't dream away your time. 不要虚度光阴。

341. Don't keep me waiting long. 不要让我等得太久。

342. He has a remarkable memory. 他有惊人的记忆力。

343. He has completed the task. 他完成了这个任务。

344. He has quite a few friends. 他有不少的朋友。

345. He is capable of any crime.他什么样的坏事都能干得出来。

346. He walks with a quick pace. 他快步走路。

347. He was not a little tired. 他很累。

348. His looks are always funny. 他的样子总是滑稽可笑。

349. How about going to a movie? 去看场电影怎么样?

350. I think I've caught a cold.我想我得了感冒。

351. I was taking care of Sally. 我在照顾萨莉。

352. I wish I lived in NEWYORK. 我希望住在纽约。

353. I'm very glad to hear that. 很高兴听你这样说。

354. I'm your lucky fellow then. 我就是你的幸运舞伴啦!

355. It's none of your business! 这不关你的事儿!

356. No littering on the campus. 在校园内不准乱丢废物。

357. She is a good-looking girl. 她是一个漂亮女孩。

358. She mended the broken doll. 她修补了破了的洋娃娃。

359. So I just take what I want. 那么我只拿我所需要的东西。

360. Spring is a pretty season, 春天是一个好季节。

361. The figure seems all Right. 数目看起来是对的。

362. The stars are too far away. 星星太遥远了。

363. The whole world knows that. 全世界都知道。

364. Tomorrow will be a holiday. 明天放假。

365. We walk on the garden path. 我们走在花园小径上。

366. What you need is just rest. 你需要的就是休息。

367. What's your favorite steps? 你最喜欢跳什么舞?

368. You'd better let her alone.你们最好是让她一个人呆会儿。

369. A lost chance never returns. 错过的机会永不再来。

370. Don't let this get you down. 不要为此灰心丧气。

371. He shot the lion with a gun. 他用枪把狮子打死了。

372. I don't think you are right. 我认为你是不对的。

373. I have never seen the movie. 我从未看过那部电影。

374. I haven't seen you for ages. 我好久没见到你了。

375. I was alone,but not lonely.我独自一人,但并不觉得寂寞。

376. I went there three days ago. 我三天前去过那儿。

377. It's a friendly competition. 这是一场友谊赛。

378. It's very thoughtful of you. 你想得真周到。

379. May I speak to Lora,please? 我能和劳拉说话吗?

380. Mr.Wang is fixing his bike. 王先生在修他的自行车。

381. My brother is see king a job. 我弟弟正在找工作。

382. Nancy will retire next year. 南希明年就退休了。

383. Neither you nor he is wrong. 你没错,他也没错。

384. Opportunity knocks but once. 机不可失,时不再来。

385. She dressed herself hastily. 她匆忙穿上衣服。

386. She hired a car by the hour.她租了一辆按钟点计费的汽车。

387. Someone is ringing the bell. 有人在按门铃。

388. The Smiths are my neighbors. 史密斯一家是我的邻居。

389. These shoes don't fit right. 这双鞋不太合适。

390. This is only the first half. 这才是上半场呢。

391. This pen doesn't write well. 这钢笔不好写。

392. Would you like a cup of tea? 你想喝杯茶吗?

393. You really look sharp today. 你今天真漂亮。

394. Another cat came to my house. 又有一只猫来到我家了。

395. Check your answers with mine.把你的答案跟我的核对一下。

396. Don't keep the truth from me. 别瞒着我事实真相。

397. Everything has its beginning. 凡事都有开端。

398. He came to the point at once. 他一下子就说到了点子上。

399. He fell behind with his work. 他工作落后了。

400. He is the happiest man alive. 他是世界上最快乐的人。

401. He neither smokes nor drinks. 他既不抽烟也不喝酒。

402. He ran his horse up the hill. 他策马跑上小山。

403. He reminds me of his brother. 他使我想起了他的弟弟。

404. He was efficient in his work. 他工作效率高。

405. He will do anything but work.只要不是干活,他干什么都行。

406. His father runs a restaurant. 他的父亲经营一家餐馆。

407. I have something to tell you. 我有事要告诉你。

408. I smelled a smell of cooking. 我闻到了烧菜做饭的味道。

409. I want to see the film again. 我真想再看一遍。

410. I've got too much work to do. 我要做的工作太多了。

411. Let's go for a walk,shall we? 咱们出去走走,好吗?

412. Please let me check the bill. 请让我核对一下帐单。

413. Plenty of sleep is healthful. 充足的睡眠有益于健康。

414. The sun comes up in the east. 太阳从东方升起。

415. This is because we feel pain. 这是因为我们能感到疼痛。

416. What do you desire me to do? 你想要我做什么?

417. What you said was quite true. 你所说的完全符合事实。

418. You can either stay or leave. 你或者留下或者离开。

419. Your life is your own affair. 你的生活是你自己的事。

420. All that glitters is not gold. 发闪光的不全是黄金。

421. Are you going to have a party? 你要举行聚会吗?

422. Aren't you concerned about it? 难道你不担心吗?

423. Don't forget to keep in touch. 别忘了保持联系。

424. He broke his words once again. 他又一次违背了诺言。

425. He is in his everyday clothes. 他穿着平常的衣服。

426. He is taller than I by ahead. 他比我高一头。

427. He led them down the mountain. 他带他们下山。

428. He was trained to be a lawyer. 他被培养成一名律师。

429. I am afraid that l have to go. 我要走了。

430. I don't have any cash with me. 我身上没带现金。

431. I have been putting on weight. 我开始发胖了。

432. I have just finished the book. 我刚刚读完这本书。

433. I was late for work yesterday, 我昨天上班迟到了。

434. It appears to be a true story. 这故事似乎是真的。

435. I've got to start working out. 我必须开始做健身运动了。

436. Japan is to the east of China. 日本在中国的东部。

437. John asked Grace to marry him, 约翰向格雷斯求婚。

438. My watch is faster than yours. 我的表比你的表快。

439. New China was founded in l949. 1949年新中国成立。

440. Thanks for your flattering me. 多谢你的夸奖。

441. They charged the fault on him. 他们把过失归咎于他。

442. This car is in good condition. 这车性能很好。

443. This work itself is very easy. 这件工作本身很容易。

444. Truth is the daughter of time. 时间见真理。

CSS文字排版终极指南

在今天的设计中,排版常常被忽视,特别是被网页设计师忽视。这真是件遗憾的事情因为CSS可以做很多事情来控制我们的排版。也就是说,我们被局限于 某些"网络安全"排版,但是我们不应该限制我们自己的创造性。本文整理了一些用于在网页上排版的CSS技巧。

Font属性

CSS提供了font属性,它允许我们在我们的页面中调整文字。这是一系列的关于语法和如何使用CSS调整文字的概述。

Font-size

使用font-size可以修改你的文字的大小。

1
2
3
font-size: 1.2em;
font-size: 12px;
font-size: 10pt;
预览
  1. 文字大小为1.2em.
  2. 文字大小为12px.
  3. 文字大小为10pt.

PS:关于font-size,推荐一下码头写的《http://www.css88.com/archives/821

Font-weight

该属性用来改变你的文字的粗细(比如bold, bolder)

1
2
3
4
font-weight: normal;
font-weight: bold;
font-weight: bolder;
font-weight: lighter;
预览
  1. font-weight设置为normal
  2. font-weight设置为bold
  3. font-weight设置为bolder
  4. font-weight设置为lighter

font-weight属性还可以使用100,200,300,400,500,600,700,800,900等数字值,数字越大,文字越粗。 400等效于normal,700等效于bold。

Text-transform

text-transform属性允许你应用uppercase(大写), lowercase(小写), 以及capitalize(首字母大写)等效果到你的文字。当然,该属性不能用于中文。

1
2
3
4
text-transform: capitalize;
text-transform: uppercase;
text-transform: lowercase;
text-transform: inherit;
预览
  1. Capitalizes the first letter in every word
  2. Allows your html to be lower case the converts it all to uppercase characters
  3. ALLOWS YOUR HTML TO BE UPPERCASE THEN CONVERTS IT TO LOWERCASE, THIS WAS TYPED IN ALLCAPS
  4. inherits the text-transform property from its parent element

Text-decoration

text-transform属性允许你使用一些文字修饰,比如下划线(underline)、上划线(overline)、删除线(line- through)以及文字闪动(blink)。

1
2
3
4
5
text-decoration: normal;
text-decoration: underline;
text-decoration: overline;
text-decoration: line-through;
text-decoration: blink;
预览
  1. text-decoration设置为normal
  2. text-decoration设置为underline
  3. text-decoration设置为overline
  4. text-decoration设置为line- through
  5. text-decoration设置为blink (只有Firefox 和Opera 支持)

Font-Variant

font-variant属性允许你制作小型大写字母效果,也就是将小写字母变成大写并减小字体型号

1
2
3
font-variant: normal;
font-variant: small-caps;
font-variant: inherit;
预览
  1. Font Variant 设置为 normal
  2. Font Variant 设置为 small-caps
  3. Font variant 设置为 inherit

Letter-Spacing 和 word-spacing

这两个属性都用来添加他们对应的元素中的空白。letter-spacing添加字母之间的空白,而word-spacing添加每个单词之间的空 白。请注意,word-spacing对中文无效。

1
2
3
letter-spacing: normal;
letter-spacing: 2px;
letter-spacing: inherit;
预览
  1. Letter spacing 设置为 normal
  2. Letter spacing 设置为 2px
  3. Letter spacing设置为 inherit

font缩写

上面的font属性可以缩写,这样可以大大的提高你的css的效率。

1
font:font-style font-variant font-weight font-size[/line-height] font-family

请注意上面的缩写的书写顺序。另外,如果这里不设置line-height,元素的line-height将会被设置为默认的1,而不会从父级元素 或body元素继承。使用缩写的时候,font-size和font-family是必须的,其它几项可根据情况不写。

制作有吸引力的段落

对于更有吸引力的段落排版,可以采用Robert Bringhurst的方法,它约定:用你的文字大小乘以30就可以得到段落的宽度。

比如如果你的文字大小是12px,用30乘以它,也就是360px,这样每行大约可以呈现65个英文字符。

不正确的段落大小:

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

正确的段落大小

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

Line-height示例

行高用来限定每行文字之间的空白大小。一个经验之谈就是让行高比你的字体大6-7px。

比如,如果你的文字大小是12px,加上6px就是你的行高,也就是18px。

不正确的Line-Height

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

正确的Line-Height

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

PS:关于line-height的设置,推荐一下码头写的《line-height的继承 问题

清晰的强调文字

下划线应该只用于文字链接,而斜体是一个更清晰的可选方案.

不正确的例子

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

正确的例子

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

first-letter与first-line

顾名思义,first-letter就是第一个字母,first-line是第一行文字,它们是少有的被所有主流浏览器支持的CSS 2.1 伪元素,你可以为它们定义任意样式。

示例代码
1
2
3
#demo5{ width:400px;}
#demo5:first-letter{ font-size:32px;color:green}
#demo5:first-line{color:red;}
前端观察 Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

前瞻 � CSS3

已经有一部分很棒的CSS3特性可以用到你的设计中了。当然这些中的一部分新属性还不能用于IE,但是你或许了解这对IE来说是常事儿,所以你不妨 试试。

@Font-face

@font-face允许你上次一个字体文件到你的网站服务器并将其引入到你的外部CSS文件中,然后就可以将它应用到你的网站 的任何文字上。

这是处理文字的最大的功能,但是随之而来的是它的负面效果。由于版权问题,只有少数的字体"被允许"使用。这些字体也就是CSS3安全就在这里里面提到的。当然,对于中文字体来说,除了版权问题,还有网速的问题,一般中文字体动辄 几MB的大小,字体文件下载到浏览器就要几分钟,这对于用户来说是不划算的。

使用@font-face

在这个例子中我在我的网站的根目录下放了一个font文件夹,然后将需要用到的字体放入该文件夹。你首先需要声明@font- face 属性以导入你的字体文件,然后使用该字体名称来控制其它元素的字体。

1
2
3
4
5
6
7
/* 声明字体 */
@font-face {
src:(font/diavlo.otf)
}
/* 将改字体应用到一个元素 */
h1 {font-family: diavlo, Arial;
}

PS:关于页面的嵌入字体,推荐阅读《如何在网页设计中使用个性化字体

Text-Shadow

text-shadow属性赶走了用Photoshop为某些元素制作下拉阴影的需求,并给你提供动态的阴影控制。当然,该属性IE并不支持。

示例标题

1
2
3
4
5
6
p {
font-size: 2em;
font-weight: bold;
color: #777;
text-shadow: 1px 1px 1px #222;
}

示例标题2

1
p {text-shadow: 2px 2px 2px #222;}

示例标题3

1
p {text-shadow: 1px 1px 5px #FFF;}

PS:呃,其实前端观察的文章标题和章节的二级标题都用了text-shadow,而且还是用了更漂亮的RGBa颜色。关于CSS阴影,强烈推荐阅 读《CSS阴影详解

挑战

本文中提到的这些技术都只是一个入门指南。试着采用并实现你喜欢的技术到你的设计中。排版可能是一个网站中最重要的部分,请不要无视它。

PS:本文在原文的基础上,补充了少量内容,比如first-letter和first-line部分――神飞

关于原作者

Shane JeffersThree Styles的创办者 和作者。他对设计趋势和教程有独特的喜好。你可以通过这个联系页面和他联系到他或者在twitter上关注他 @ThreeStyles

译自:The Ultimate Guide to CSS Typography
中文:CSS文字排版终极指南

使用 Dojo 开发离线应用

Dojo 离线功能简介

所谓离线,指的是用户能够在没有网络的环境下也可以进行工作,并且当网络环境恢复后,之前的操作能够自动地同步到服务器上。目前,离线应用可以分为 两种,一种是桌面应用,其中以 IBM Lotus Notes 为代表。另外一种则是近来比较热门的 Web 离线应用,其中最具代表的为 Google 的离线应用,如 Google Docs, Gmail, Google Reader 等。而本文介绍的 Dojo 离线功能,则是目前最为流行的实现第二种离线应用的框架。


回页首

Dojo 离线原理

Dojo Offline 是一个免费的开放源代码的离线开发工具,它可以轻松地让 Web 开发人员开发离线应用。Dojo Offline 构建于 Google Gear 之上,它使得在 Google Gear 上开发离线应用变得更加简单。Dojo Offline 对 Google Gears 的 API 进行了封装,能够更方便地以 JavaScript 的方式访问数据;另外,Dojo Offline 还提供了如下功能:

  1. Offline Widget:开发人员只要添加几行代码,就能够将这个离线的 widget 嵌入自己的应用中,之后,就能够自动获得网络反馈 , 同步消息以及离线操作配置说明等。
  2. 同步框架:保存离线数据,并且在网络恢复后将这些操作和服务器进行同步。
  3. 自动的网络和应用程序状态监控机制:离线应用可以基于这些监控结果来决定采取什么样的操作。
  4. slurp() 方法:通过 slurp() 方法来自动扫描页面,找出需要缓存到本地的资源,包括图片,样式,脚本等。这使得 Web 开发人员能够集中精力地去开发业务逻辑和展示页面,而不需要考虑具体哪些资源需要缓存到本地。
  5. 提供两种本地存储实现方法:Dojo Storage 和 Dojo SQL。Dojo Storage 使用哈希表来存储离线数据,为开发人员屏蔽了重量级的 Google Gears 的 SQL 使用方法,我们可以通过 Dojo Storage 将数据保存到 Google Gears 里去。Dojo SQL 通过执行 SQL 命令,对一般的 JavaScript 对象进行存取。
  6. 加密和解密关键字 ENCRYPT() 和 DECRYPT():提供对下载后的离线数据加密和解密方法。
  7. Dojo 其他模块的集成:如果用户选择 Dojo Offline,毫无疑问,其应用可以受益于 Dojo 的其他功能,比如完善的事件处理机制,Ajax 框架等等。

回页首

Google Gears 简介

Google Gears 是 Google 开发的一个自由和开源软件,以 BSD 许可证发布。主要是为了能够让用户可以在离线时能够继续使用 Web 应用。这套软件透过 SQLite 数据库让本地端能够把资料暂存起来。所以网页是透过缓存取得的,而不是从实际的网络上取得。而且,Web 相关的程序可以周期性的透过 Gears 将本地缓存的资料与网络上的资料做同步。如果网络暂时无法使用,这个同步过程将会延后,直到网络恢复为止。Google Gears 通过以浏览器扩展的方式添加 JavaScript API,使得浏览器的脚本能够访问本地的缓存数据库。该扩展目前支持 Firefox,Internet Explorer 和 Safari,并需工作于 Windows、Mac OS X,或是 Linux 下。

Google Gears 有几个主要的组件:

  1. 一个本地服务器,用来存储和读取离线程序资源(包括 HTML 文件 , JavaScript 文件 , 图片等)。
  2. 一个小型数据库(基于 SQLite 轻量数据库),用来储存本地数据。
  3. 一个工作池,用来让开发者将本地数据与服务器端后台同步。
  4. 一个桌面模型,可使网络程序的操作贴近桌面程序。
  5. 一个地理定位模型,能够让网络程序侦测到目前用户的地理位置。

回页首

开发 Dojo 离线应用程序

一般来说开发一个离线应用有以下几个步骤:

  1. 应用加载时缓存所引用的资源。
  2. 应用加载之后设置必要的离线事件处理函数。如:与服务器进行同步操作时的下载事件、下载完成事件,重放事件等。
  3. 检查应用是否在线,读取应用所需的数据。如果离线则从本地读取数据;如果在线则与服务器数据进行同步:首先上传离线数据(如果有的话),然后从服 务器上下载最新数据。
  4. 初始化应用程序。

下面我们会先分别介绍如何保存离线资源,保存和使用应用离线数据以及如何与服务器的数据保持同步等相关技术,然后以一个具体的例子说明如何按上述步 骤开发一个离线应用。

保存离线资源

为了使页面能够在离线情况下操作,在页面加载时必须要保存页面所引用的 HTML 文件,JavaScript 文件,CSS 文件,图片文件等资源,这样在与服务器断开连接时,页面便能够从本地缓存中提取到页面及相关的资源。Dojo 提供了一个功能非常强大的函数 slurp 来实现这一功能。slurp 函数在页面加载之后会自动分析页面所引用的资源,并得到一个资源文件的 url 列表,然后抓取 url 的内容,保存到 Google Gears 中。slurp 函数能够缓存大部分的资源文件,包括引用 CSS 文件里的图片,但是对于使用内联方式指定的 CSS 图片以及用 JavaScript 动态产生的引用 slurp 则无法进行缓存。这种情况可以通过调用 dojox.off.files.cache () 方法来手动添加要缓存的资源,具体用法详见后文。

Dojo Offline 还提供了在调试时查看已缓存资源文件的方法,首先以 debug 方式加载 Dojo,然后在页面和 Dojo Offline 加载完之后调用 dojox.off.files.printURLs() 函数。这个函数会在控制台以调试的方式打印出已缓存的资源文件的 url。

保存和使用离线数据

一般来说,离线应用不仅要缓存页面所引用的 HTML 文件,JavaScript,CSS,图片等资源,还要缓存页面所使用的数据。Dojo 对 Google Gears 的访问接口进行了封装,提供了 Dojo Storage 和 Dojo SQL 两种方式操作离线数据。通过这两种方式,用户可以方便、灵活地保存和读取离线数据。

  • Dojo Storage

提供了一种类似哈希表的方式对数据进行操作,数据以键值对的方式存取。

保存:dojox.storage.put(key,value) — key 是字符串类型,value 可以是字符串和可序列化的 JavaScript 对象,但是浏览器对象(如 DOM 节点和 XMLHttpRequest 对象)是不能够保存的。

读取:var value = dojox.storage.get(key) —获取字符串 key 对应的值。
清单 1

var car = {type: "Nissan", color: "white", price: 20000, optional:
"air-conditioner, stereo"};
dojox.storage.put("complexKey", car);

var value = dojox.storage.get("someKey");
var car = dojox.storage.get("complexKey");
if(car)
alert(car.type);

上述代码先将一个对象 car 放置在 Dojox.Storage 里,然后又从中取出并展示。

  • Dojo SQL

通过 Dojo SQL 对 Google Gears 关系存储层的封装,能够以更适合 JavaScript 对象的访问方式对关系表进行操作。如下所示,我们对 Documents 表进行了创建,插入,查询操作:
清单 2

//create Documents table if not exist
dojox.sql("CREATE TABLE IF NOT EXISTS DOCUMENTS ("
+ "fileName TEXT NOT NULL PRIMARY KEY UNIQUE,"
+ "content TEXT NOT NULL) ");
//insert a record
dojox.sql("INSERT INTO DOCUMENTS (fileName, content) VALUES (?, ?)", fileName, contents);
//query
var results = dojox.sql("SELECT * FROM DOCUMENTS WHERE fileName = ?", someFileName);

Dojo 查询操作返回的是一个记录对象的数组,如访问第一条记录的 fileName 字段,可以使用 results[0].fileName,访问 content 字段则可以使用 results[0].content。

与服务器同步数据

离线操作所产生的新数据,在与服务器连接可用时需要上传到服务器;并且,在该用户离线期间,其他用户也可能已经更改过数据,因此重新连接服务器时需 要下载最新的数据。Dojo 的同步操作发生的时机有两个,一是在页面首次加载并且在线的时候,或是离线后又检测到连接恢复的时候,具体包括 3 个步骤:

  1. 下载并缓存最新的页面资源,包括由 slurp 函数以及用户手动缓存的资源。Dojo Offline Widget 会自动更新相应的状态,如下图所示:

    图 1. 下载状态
    下载状态

  2. 上传用户在离线期间所创建的数据。

    图 2. 上传状态
    上传状态

  3. 下载服务器最新数据进行展示。

    图 3. 同步成功
    同步成功

    如上所示,Dojo Offline 提供了一个 UI 控件来通知用户当前的状态,如下载,上传以及网络连接状态等。Dojo Offline Widget 处理了大部分的逻辑,开发人员可以直接在页面中使用该控件。使用 Offline Widget 很简单,只需在页面加入一个占位符即可。Offline Widget 也提供了扩展机制,以更改所使用的图片和样式来跟页面风格保持一致。

Dojo 离线应用示例

Dojo Offline 随附的开发包中提供了 3 个例子,下面以 hello world 为例说明如何构建一个简单的离线应用。hello world 程序模拟了用户与服务器简单的消息交互。用户界面包括一个输入框和一个发送按钮,在输入框里输入文本,点击发送按钮将消息发送到服务器。为了保持用例的简 单,实际上消息并没有真正被发送到服务器,而只是简单地将其弹出。在应用离线时,点击发送按钮则会先在本地保存该消息,当应用重新连接时再重新执行该操 作。

  1. 首先加载 Dojo 及离线所使用的 JavaScript 文件。

    清单 3

    <script type="text/javascript" src="../../../../dojo/dojo.js"
    djConfig="isDebug: true"></script>
    <script type="text/javascript" src="../../../../dojox/off/offline.js">
    </script>

    当然,我们也可以用 dojo.require 方法进行加载:

    清单 4

    <script type="text/javascript" src="../../../../dojo/dojo.js"
    djConfig="isDebug: true"></script>
    <script type="text/javascript" >
    dojo.require(“dojox.off.offline”);
    </script>
  2. 设置应用程序的名字,这个名字会显示在 Dojo Offline Widget 上。

    清单 5

    dojox.off.ui.appName = "Hello World";
  3. 缓存页面资源文件。要使离线功能正常工作,这个函数必须在 Dojo Offline 初始化之前调用,即 dojox.off.initialize 函数调用之前。

    清单 6

    dojox.off.files.slurp();
  4. 初始化应用程序,设置离线操作的一些事件响应函数。

    清单 7

    initialize: function(){
    console.debug("helloWorld.initialize");
    var self = this;
    dojo.connect(dojox.off.sync, "onSync", this, function(type){
    if(type == "download"){
    self._messages.push("Hi! This is fake downloaded data!");
    dojox.storage.put("messages", self._messages);
    dojox.off.sync.finishedDownloading();
    }else if(type == "finished"){
    this._messages = [];
    dojox.storage.remove("messages");
    }
    });
    dojo.connect(dojox.off.sync.actions, "onReplay", this,
    function(action, actionLog){
    if(action.name == "new hello world message"){
    var message = action.data;
    self.sendMessage(message);
    actionLog.continueReplay();
    }
    });
    if(!dojox.off.isOnline){
    this.loadOfflineData();
    }
    this.printMessages();
    }

    可以看到,此处最主要的两个操作是设置 dojox.off.sync 对象的 onSync 事件和 dojox.off.sync.actions 对象的 onReplay 事件。其中,onSync 用来处理与服务器的同步,download 事件发生在第一次加载页面或是网络重新连接的时候,在该事件中我们应该从服务器下载数据,并在下载完毕之后调用 dojox.off.sync.finishedDownloading() 方法,以便告诉 Dojo Offline Widget 更新当前状态。finished 事件则说明从服务器下载数据结束,可以更新应用程序了。

    Dojo Offline 使用 action log 来记录用户在离线时所执行的操作,并在重新获得网络连接时再次执行这些操作,将数据上传到服务器。

    一般来说,程序初始化时首先要判断应用是否在线,如果不在线则加载本地数据进行页面展示。值得注意的是,这些事件何时触发是由 Dojo Offline 的同步框架根据当前应用程序状态决定的,开发人员只需设置相应的事件处理函数即可。

  5. 保存离线数据,这是通过创建 action log 来实现的。在与服务器重新连接时 action log 会自动重新执行。

    清单 8

    saveOfflineSend: function(message){
    this._messages.push(message);
    dojox.storage.put("messages", this._messages);
    var action = {name: "new hello world message", data: message};
    dojox.off.sync.actions.add(action);
    alert("This message has been saved for sending when we go back online");
  6. Dojo 的离线功能要在页面加载完及 Dojo Offline 初始化之后才能工作,因此页面本身的代码要在 Dojo Offline 初始化完成之后执行。Dojo Offline 的初始化完成可以用 dojox.off.ui 的 onLoad 事件来标识。我们首先将页面的初始化函数绑定到 dojox.off.ui 的 onLoad 事件,然后调用 dojox.off.initialize 函数对 Dojo Offline 进行初始化。

    清单 9

    dojo.connect(dojox.off.ui, "onLoad", helloWorld, "initialize");
    dojox.off.initialize();
  7. 加载 Dojo Offline Widget。实际上任何 html 元素,只要 id 为“dot-widget”都可以作为 Offline Widget 的占位符。Dojo Offline 初始化的时候会对这个元素进行填充。

    清单 10

    <div id="dot-widget"></div>
  8. 为页面加入展示元素。

    清单 11

    <div id="helloMessage" style="margin: 1em;">
    <label for="helloInput" style="margin-right: 0.2em;">
    Enter Hello World Message:
    </label>
    <input name="helloInput" id="helloInput" style="margin-right: 0.2em;">
    <button id="sendMessage" onclick="helloWorld.send()" style="margin-right: 0.2em;">
    Send</button>
    </div>
    <p>Debug output:</p>
  9. 运行 hello world

    hello world 示例程序不涉及服务器端代码,因此并不一定需要部署才能执行。但是为了便于测试在线 / 离线操作,最好还是通过服务器访问。

    在 Dojo Offline 里随附的例子中,Moxie 编辑器是一个包括服务器和客户端的完整应用程序,它使用 Jetty 作为 Web 容器,使用 Derby 作为数据库。我们可以启动 Moxie 应用所在的 Jetty 容器来访问 hello world 应用。

    首先请安装 jdk1.5 或以上版本,在 dojox/off/demos/editor/server/ 目录下,运行:

    java -jar editor.jar

    在浏览器地址栏输入 http://localhost:8000/dojox/off/demos/helloworld/helloworld.html 即可访问 hello world 应用。可以通过关闭 / 打开 Jetty 来观察 hello world 和 Dojo Offline Widget 在离线、在线及同步时的行为。


回页首

高级议题

网页资源的手工缓存

尽管利用 slurp() 方法可以为我们完成很多自动化的工作,但一些出现在 JavaScript 中的动态加载的资源是 slurp() 所无法分析得到的。因此,在实际应用中作为补充,我们往往还需要将一些 slurp 过程中的“漏网之鱼”手工加入本地缓存中。而 Dojo Offline 也为我们提供了相应的功能以支持这一需求。

手工将网络资源加入本地缓存的方法十分简单,例如,假设我们要将一个名为 big_and_little_fish.jpg 的文件缓存起来,可以执行如下方法:
清单 12

dojox.off.files.cache("images/big_and_little_fish.jpg");

不仅如此,Dojo Offline 还提供了一次性指定多个文件的功能,调用方法如下所示:
清单 13

dojox.off.files.cache([
"images/fish1.png",
"images/fish2.png",
"scripts/some_dynamic_fish.js"
]);

我们可以多次调用 cache() 方法,假如调用过程中指定了多个同名文件,则最后一次被缓存的文件将会替换前面的同名文件。利用这一方法,再结合前述的 slurp() 方法,我们就可以很好的将离线所需的全部资源在本地缓存起来了。

数据的加密与解密

将数据下载到本地进行缓存是离线功能得以实现的重要步骤,但是假如这些数据中包含有敏感信息,例如身份证号码,而本地环境又不甚安全时,则对数据进 行加密处理是很有必要的。前面曾经提到,我们在利用 Dojo Offline 进行数据存储时可以选择使用 Dojo SQL。而 Dojo SQL 允许我们很方便的对数据的某些字段进行加密和解密。

假设我们以前面的 DOCUMENT 表为例,假定其中的“content”字段属于敏感信息。

Dojo SQL 提供了两个特殊的关键字,ENCRYPT() 和 DECRYPT(),分别用以实现加密和解密操作。以 content 为例,调用方式类似如下:
清单 14

var password = "password";
dojox.sql("INSERT INTO DOCUMENTS VALUES (?,ENCRYPT(?))", "helloworld.txt",
"sensitive content", password,
function(results, error, errorMsg){
if(error){ alert(errorMsg); return; }
});

在上述代码中,我们在后一个字段加上了 ENCRYPT 关键字,声明对其进行加密。除此以外,我们还提供了一个 password 参数,这是底层加密机制所必须的。当我们启用应用系统时,系统会提示输入这一密码。出于对本地数据安全性的考虑,请不要将其存于 Cookie,Dojo Storage,或是 Dojo SQL 中,否则他人就可以轻易利用这一密码解开存于本地的敏感数据。另外,上述代码里还定义了一个回调函数。该回调函数将会在加密过程结束之后被调用。如果加密 成功,results 对象中将会包含经过加密后的数据;如果加密失败,则 error 值将会为 true,并且 errorMsg 中会包含对错误原因的描述信息。

和加密一样,对数据进行解密的过程也十分简单。我们只需对需要解密的字段调用 DECRYPT 关键字即可。示例代码如下:
清单 15

var password = "password";
dojox.sql("SELECT fileName, DECRYPT(content) FROM DOCUMENTS",
password,
function(results, error, errorMsg){
if(error){ alert(errorMsg); return; }
// go through decrypted results
alert("First document info: "
+ results[0].fileName + " "
+ results[0].content);
});

在上述代码中,我们利用 alert 语句将加密后的第一条结果数据打印了出来。其中的 password 必须与加密时所使用的完全一致,否则解密将会失败,结果数据将仍然是加密后的样子。

假如我们要对多个字段进行加密,Dojo SQL 的 ENCRYPT 还有一种很方便的书写方法,即:ENCRYPT(?, ?);同样的,对于 DECRYPT 也存在类似的书写方式,已完成一次性对多个数据字段进行解密:DECRYPT(fileName, content)

定制 Offline Widget

虽然利用 Dojo Offline Widget 可以省去我们很多的功夫,但是在某些情况下,其默认行为并不一定能够很好的满足我们的需要,例如:默认的样式风格与我们的应用程序不一致,此时,我们就可 以对 Offline Widget 进行一定程度的定制。

事实上,我们在页面上所见到的 Offline Widget 有其对应的模板文件,该文件位于 dojox/off/resources/offline-widget.html,其中包含有一系列的 HTML 元素,这些元素都有相应的 ID,比如:dot-widget-network-indicator,Offline Widget 就是利用默认的 CSS 文件对其进行控制的,该 CSS 文件位于:dojox/off/resources/offline-widget.css。我们可以通过自定义 CSS 的方式来改变 HTML 元素的样式,从而改变 Offline Widget 在页面中的展现风格。

除了改变展现风格,有时我们可能还需要改变展现的内容,我们可以将 offline-widget.html 中的内容选择性的复制到我们自己的 HTML 页面中,这样我们就可以根据自己的需要随意设计 Offline Widget 的展现内容,而无需定义一个 ID 为 dot-widget 的特定 DIV 了。

此外,如果我们只是想修改 Offline Widget 所使用的默认图标的话,则还有更为简单的做法。那就是对如下几个 JavaScript 变量进行修改:

  • dojox.off.ui.onlineImagePath:表示在线状态的图标
  • dojox.off.ui.offlineImagePath:表示离线状态的图标
  • dojox.off.ui.rollerImagePath:表示同步正在进行的图标
  • dojox.off.ui.checkmarkImagePath:表示同步结束的图标

例如,如果我们想将表示在线状态的绿色小圆球状图标替换为自己设计的图标,则可以修改如下:

dojox.off.ui.onlineImagePath = “images/myonlineball.png”;

最后,假如我们对默认的“Learn How”页面不甚满意的话,则还可以对 dojox/off/resources/learnhow.html 进行修改,其对应的 CSS 样式也定义与 dojox/off/resources/offline-widget.css 中。

性能问题

Dojo Offline 每次在对数据进行同步时,始终都会刷新缓存于本地的资源,这一点有可能会对同步的性能构成较大的影响,因为毕竟并非每一次同步都需要刷新所有的本地数据。 为了提高同步的效率,Dojo Offline 提供了一种可选的方案,即由应用程序提供一个名为 version.js 的特殊文件,并将其置于应用程序的主路径下。假如该文件存在的话,则同步期间 Dojo Offline 会去读取该文件的内容,并判断其内容是否改变,以此来选择性的刷新本地缓存文件。

我们在 version.js 文件中所提供的内容其实非常简单,可以是一个字符串,也可以是一个数字,形式不限。例如:”03-15-2009.9″。只要能够让 Dojo Offline 判断出内容的变化即可。

除了同步时候的性能问题外,另一个可能会遇到的性能问题是数据的存储。当我们使用 Dojo SQL 来存储数据时,必须先将底层所依赖的 Google Gears 的存储数据库打开,而后才能进行数据的存储,而当数据存储完毕之后,还需将数据库关闭。通常情况下,我们并不需要关心这一点,因为 Dojo SQL 会自动为我们完成这一切,每次当我们执行一句 SQL 语句时,底层代码都会自动处理数据库的打开和关闭。

不过,假如我们是在批量的向本地缓存插入数据的话,比如在一个循环次数为上百次的 for 循环中执行数据插入操作,那么每执行一次 SQL 语句都要打开和关闭一次数据库或许是一种很低效做法。为了提高效率,我们可以在批量操作数据之前通过调用 dojox.sql.open() 手工将数据库打开,等所有操作完成之后后再通过调用 dojox.sql.close() 手工将其关闭。插入数据期间,Dojo SQL 会自动判断数据库的连接状态,并保持连接一直处于打开状态,直至手工关闭为止:
清单 16

var dataSet = getDataSet(); // get an array that has a bunch of data
//in it
dojox.sql.open();
for(var i = 0; i < dataSet.length; i++){
dojox.sql("INSERT INTO DOCUMENTS (fileName, content) VALUES (?, ?)",
dataSet[i].fileName, dataSet[i].content);
}
dojox.sql.close();

回页首

总结

本文介绍了 Dojo Offline 的强大功能。通过阅读本文,读者能够了解到 Dojo Offline 的基本工作原理和一定的高级定制功能,从而掌握如何使用 Dojo Offline 进行 Web 离线应用程序开发的技能。


学习