Thursday, May 29, 2008

用 AJAX 实现 Blogger 页内评论

之前服务器上有 Java 环境时,一直用一个自己写的 Servlet 作为中间代理来向 Blogger 的评论页面 POST 表单数据,实现页面内的评论操作,后来转挂在朋友的 IIS 服务器下,由于对 ASP 不熟,这一功能就一度取消了。现在购买了新的 Linux PHP 服务器,因此用 PHP 重新写了一个同样功能的中间代理来实现这一功能,并且实现成了 AJAX 的模式。评论内容的读取也一样通过 Blogger Feed 的 JSON 模式读取,因此提交评论后可以立即显示出来,而不用再等待 Blogger 重新生成 HTML 页面并通过 FTP 上传这一漫长的过程。(虽然实际上后台它还是不可避免的执行了这个过程。)

经过多次测试,应该可以用了。关于 Spam 的问题,以前的验证码是直接读取的 Blogger 页面的 Captcha 图片,现在 Google 改变了表单结构以至于程序已经无法自动做这个动作。所以我取消了 Blogger 自己的 Captcha 验证,自己写了个简单的加减法验证,虽然仍然不能完全杜绝 Spam,但已经比几天前测试时裸奔的情况好多了。当时夸张到一个下午一张帖子被贴了 50 多条 Spam 评论。毕竟传说 Google 的 Captcha 也已经被破解了么,同样不能完全杜绝 Spam。 ;-)

另外,Backlink 不显示的问题也修正了。不过,经过前端时间页面恶意代码事件的影响,目前似乎已经没什么 Backlink 了…… :-(

Labels: , , , , , , ,

(请点击这里阅读全文)

Friday, January 05, 2007

用 JSON 实现侧边栏的最新评论列表

上个月 21 号 Google 发出消息,声称 GData API 开始支持以 JSON (JavaScript Object Notation,中文介绍) 的形式提供数据,并且给出了对应的 API 文档,同时 Blogger Buzz 网站也告知广大用户,JSON 支持的 GData API 中同样也包括 Blogger。

在这之前,由于 JavaScript 先天的限制,我们不能通过 JavaScript 代码打开当前域以外的远程文件,这也就限制了我们通过传统的 AJAX 技术利用 GData API 的 Atom Feed 来实现 Blogger 页面上最新帖子、评论列表的即使更新,因为我们无法在某个 *.blogspot.com 域名下打开 www.blogger.com 下的 XML 文档。当然,新的 Blogger 支持在自己的域名下,也就是以 yourname.blogspot.com/feeds/ 的形式访问 Atom Feed 解决了这个问题,但是对于通过 FTP/sFTP 发布的非 blogspot 用户,还是无法绕过这个问题。

现在,Google GData API 除了可以在原来的地址后面加 alt=json 参数来以 JSON 的格式组织数据以外,还可以用 alt=json-in-script&callback=myFunction (其中 myFunction 是自己用来处理 JSON 数据的函数) 的方式使得 Feed 返回的 JS 代码内容直接是对 myFunction 函数的调用,这样就绕过了以上 JavaScript 不能远程调用本域以外资源的限制。

通过这个办法,我修改了自己 Blogger 侧边栏的最新评论列表。虽然原来有一个,不过只是根据 Blogger Help 上的这篇介绍开启的,原理还是利用 <Blogger> 标签的循环,只输出评论的部分,也就是说,原来的方法输出的只是当前页面最新评论列表,没有在首页列出的文章,其评论是不会出现的。而且,在默认情况下,评论的排序方式是先按帖子先后顺序,再按时间顺序。我自己另外写了一个 JavaScript 函数来对它们重新排序,并只保留最新的 10 条。

现在,通过 GData API 的 JSON 回调支持,我写了一个真正意义上的最新评论列表。看到这位网友提供了一个 blogspot 用户适用的办法,对于非 blogspot 发布,特别是 FTP/sFTP 发布的用户,可以用我的办法:

<div id="sidebar-recent-comments">
<p id="comment-loading">Loading Data...</p>
<dl id="comments-block">
<dt class="comment-data" name="comment-data">
<a href=""></a><span>, </span>
<span class="comment-poster">
<a href="" rel="nofollow"></a></span>
<span> said...</span></dt>
<dd class="comment-body" name="comment-body"><p></p></dd>
</dl></div>

<script type="text/javascript">

// Fetch the recent comments from Blogger Feed with JSON code and
// the callback func is "dispComments".
function getComments(blogId, counts) {

// Temporarily hide it
var dl = document.getElementById("comments-block");
dl.style.display = "none";

// Retrieve the JSON feed.
var script = document.createElement('script');
script.setAttribute('src', 'http://www2.blogger.com/feeds/' + blogId +
'/comments/default?alt=json-in-script&callback=' +
'dispComments&start-index=1&max-results=' + counts);
script.setAttribute('id', 'jsonScript-recent-comments');
script.setAttribute('type', 'text/javascript');
document.documentElement.firstChild.appendChild(script);
}

// Translate the date
function transDate(dateStr) {
dateStr = dateStr.substring(0, dateStr.indexOf("."));
dateStr = dateStr.replace("T", " ");
dateStr = dateStr.replace(/\-/g, "/");
return dateStr;
}

// Display the comment entries onto the web page.
function dispComments(json) {
var dl = document.getElementById("comments-block");

// get entry template
var dt = dl.getElementsByTagName("dt")[0];
var dd = dl.getElementsByTagName("dd")[0];

dl.removeChild(dt);
dl.removeChild(dd);

for (var i = 0; i < json.feed.entry.length; i++) {
var entry = json.feed.entry[i];
var curDt = dt.cloneNode(true);
var curDd = dd.cloneNode(true);

// Time
curDt.childNodes[0].href = entry.link[0].href;
curDt.childNodes[0].appendChild(
document.createTextNode(transDate(entry.published.$t)));

// Author
curDt.childNodes[2].childNodes[0].appendChild(
document.createTextNode(entry.author[0].name.$t));
if (entry.author[0].uri) {
curDt.childNodes[2].childNodes[0].href = entry.author[0].uri.$t;
}
else {
curDt.childNodes[2].childNodes[0].removeAttribute("href");
}
dl.appendChild(curDt);
dl.appendChild(curDd);

//Content
curDd.childNodes[0].appendChild(
document.createTextNode(entry.title.$t));
}

dl.style.display = "block";
var commentLoading = document.getElementById("comment-loading");
commentLoading.style.display = "none";
}

getComments('yourBlogId', entryCount);
</script>

注意最后一行调用的 getComments 函数的两个参数,yourBlogId 是你当前这个 Blog 的 blogId,每个 Blog 都是不同的。打开自己帖子的评论页面,从 URL 上就可以找到自己的 blogId。第二个参数 entryCount 是要显示的评论条数,例如 10。

另外,为了保持页面整洁,我只使用了评论的第一行,也就是 title 部分的内容。如果需要显示完整,将以上代码中蓝色的 title 改成 content 即可。

为了简洁起见,也可以把 getComments 和 dispComments 两个函数放到外部的 .js 文件中去定义,页面只用引入这个 .js 文件,然后调用 getComments 即可。

Labels: , , , ,

(请点击这里阅读全文)

Thursday, December 21, 2006

Blogger 不再 Beta

昨天 Blogger Buzz 更新消息说 Blogger 推出了正式版本,不再是 beta 状态了。

看了下更新列表,没什么特别的新东西。都是最近长期 beta 以来一步步更新的内容。只是发现新版本 Blogger 的域名从 beta.blogger.com 变成了 www2.blogger.com,不过这个并不影响原来 blog 的网页。访问任何 beta.blogger.com 下的页面,会直接跳转到 www2.blogger.com。

趁着这次更新发布,又修改了一下我的模版。主要是把 Calendar 部分换成了可以在一个页面上来回翻月份,而不会在翻动的时候跳动到对应的存档页,这样可以提高 Calendar 导航的效率。

另外,把树状 Archive 目录提前了一些,并在存档页和帖子页会自动展开对应的月份,这同样也是为了加强导航的作用。

之前发现在页内的评论表单上提交评论后,HTML 页面不会被 Blogger 重建,现在欣喜的发现,这个问题 Blogger 似乎已经在最近的某次更新中修正过了。目前直接在页内提交评论,页面会马上开始重建了。只不过由于新 Blogger 每次要更新的页面比较多(包含所有的 Label 页面),因此和以往老的 Blogger 页面重建相比,速度还是要稍慢点,通常 5 分钟之内应该是可以完成的。

接下来打算在有时间的时候把页面左栏的最新评论改成用 JSON 实现,这样就成了真正意义上的“最新评论列表”,而不是目前的“出现在引导页上的帖子相关评论列表”。本来是想把页面上所有可以由 Bogger 的 Feed 实现的数据都用 JSON 来提供,但是每次请求返回的内容多的时候高达 60 多 K,可能会导致页面变慢,而访问上,不会感觉到太大的改变,因此决定先放一放再说。目前还是通过一个 JS 文件来静态存储所有帖子的时间和标题等信息。只不过这个文件仍然可以写服务端程序通过调用 Blogger 的 GData API 来自动更新。

Labels: , , ,

(请点击这里阅读全文)

Saturday, November 11, 2006

Firefox 的 JavaScript 问题两则

今天发现页面上新加上的左列 Tag 在 Firefox 上显示不正确,在细察之下,发现 Firefox 在 JavaScript / CSS 上和 IE 不同之处:

问题 1. 类似 obj.style.height = imgObj.height 的语句无效。

即将一个 image 对象的高度值赋给另一个对象,用来修改其样式高度,这样做无效。

分析

要理解这个问题,首先要纠正思想上的一个误区。以上这个操作,其实并非是通常编程概念上的将一个 int 值赋给另一个 int 变量。这个语句的操作,实际上是把 imageObj.height 当作一个字符串,作为 obj 这个对象 CSS 中 height 的属性。

之前的一篇帖子说过,Firefox 对 CSS 的理解非常严格,任何表示大小的值,数字后面必须跟上单位,除非是 0。也就是说,height: 20 对于 Firefox 来讲不具有任何意义,必须写成 height: 20px 才会被接受。所以,在 JavaScript 中,为了让对 CSS 的 height 值的设置有效,所赋给的字符串也同样必须是数量加上单位。

解决

以上语句,应该写成:
obj.style.height = imgObj.height + 'px';


问题 2. Firefox 不支持 obj.innerText 属性。

如果把 obj.innerText alert() 出来,显示的值是 undefined

分析

Firefox 支持 innerHTML 属性却不支持 innerText,这一点实在是蹊跷。很多人建议用 innerHTML 来代替需要用 innerText 的场合,但是这显然并不总是适用。我们有时候只是要取得一个 Tag 中的文字信息而不需要 HTML 的标记。

解决

良好的替代办法是用 obj.textContent,这个属性的作用和 innerText 是相同的,名称不同而已。不过为了兼容性,我们还是需要在程序中区分一下当前环境支持哪种。以下方法可以帮助我们区分:
if (document.all) {
obj.innerText = "myText";
}
else {
obj.textContent = "myText";
}

以前我们讲过,Firefox 不支持 document.all 这个 Collection,我们需要用 getElementById() 方法来替代,所以通过判断是否有 document.all,就能区分当前环境。

Labels: , , , ,

(请点击这里阅读全文)

Tuesday, October 18, 2005

SSI 和 document.write()

这两天一直在考虑怎么给 Blogger 加上 Calendar 和分类的功能。原来是这么打算的:

首先,要让生成的 HTML 代码尽量符合 XHTML 规范,以便可以写程序用 XML 解析器来分析并从中提取数据。只要是合法的 XML,应该问题就不大,不一定要完全遵循 XHTML 的 DTD,反正 Dom4J 没有 DTD 照样能分析 XML,不过,这个还有待试验证实。

Blogger 的帖子数据里面,link 这个字段似乎没有什么用,可以利用它来存储分类。通过程序分析提取以后,套用 Blogger 的模板生成 HTML,并把出现过的分类列表写到一个单独的 HTML 中,由需要的页面通过 SSI include 进来。

同样利用分析出来的数据,生成日历的 HTML,每个月一个文件,供需要的页面调用。

不过,要让 Resin 支持 SSI 功能,可能性不太大,必须另外想办法。

昨天给 BlogBus 做模板,发现这个 Blog 的默认模板里头,所有侧边栏(日历,最近贴,存档,Tags 等)全部都是由 JavaScript 来 document.write() 的,而 JavaScript 代码本身,也貌似是发布的时候根据数据动态产生的,估计这个是为了达到这些数据块可以在需要的地方重复调用的目的。

于是,我想,是不是我也可以将 Blogger 里头需要的 Calendar 和分类数据也在发布时用 Servlet 写成 JavaScript,然后再在需要的地方用这些 JavaScript 来 document.write()

嗯,有空试验一下就知道了…… 理论上应该是可行的……

Updated on 11/13/2005:

经过试验,用 document.write() 方式输出是可行的,现在此 blog sidebar 上的日历就是用 document.write() 打印出来的,而数据是由 Servlet 分析生成的 HTML 文件后自动写的 JavaScript 代码。问题有两个,一是用 Dom4j 解析的时候,对实体 (entities) 的解析有点问题,要把除 &amp; 以外的所有实体全部清楚掉才能解析正确,应该有正确的识别方法,尚在研究中。另一个问题是,documents.write() 写出来的内容,无法被搜索引擎识别,但对网站本身功能影响不大。

Labels: , , , ,

(请点击这里阅读全文)

Monday, October 10, 2005

IE, Opera 和 Mozilla Firefox

为了验证 tableless layout 版面的浏览器兼容性,特地找来了时下流行的 Opera 8.5 和 Mozilla Firefox 1.0.7 与 微软的 Internet Explorer 6.0 一起测试,结果是倍受打击……

原来以为基本上不用改就能兼容,因为完全没有用 table 排版,结果在这两个非 IE 的浏览器上,页面虽然没有面目全非,但是也不如在 IE 上显示的完整,而且有些地方莫名奇妙的怎么都设置不正确。花了 4 个小时,经过反复的和 stopdesign 网站样式表的比对,最后发现原因有两点:

  • 没有用标准的 XHTML 头来声明页面的 DocType,经过测试,发现用传统的 HTML 4.0 声明,和 XHTML 声明,三种浏览器渲染出来的结果都不同;
  • Mozilla Firefox 浏览器对样式表的要求非常严格,所有的数字属性,除了 0 以外,都必须带上单位,否则一律忽略不计!为了这个我纳闷了很久——前两个浏览器都能正确的显示各种样式的 border,而 Firefox 上所有的 border 全部都被忽略了,汗哪…… 给 border-width 参数加上单位 px 后,就正确了。paddingmargin 具有同样的问题。

以上提到的 XHTML 需要如下声明:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://gmpg.org/xfn/1">

对于线条的样式,dotted 和 dashed,在 IE 上 width 为 1 时,都显示为 dashed;但这两个样式在 Opera 和 Firefox 上能够明显的区分出来。另外,原来几乎所有的 JavaScript 在 Mozilla Firefox 上都不能运行,它对 JavaScript 的语法要求也非常严格,必须完全符合 W3C 标准:
  • document.all['id-name'] 不合法,用 document.getElementById('id-name') 替代;
  • object.all.tags("DIV") 不合法,用 object.getElementsByTagName("DIV") 替代;
  • collObjs(i) 不合法,用 collObjs[i] 替代。

做完以上工作后,终于页面能够在三种浏览器上得到几乎相同的结果了。突然觉得自己做了 5 年的 WEB,完全被微软毒害了,已经养成了太多不好的习惯;看来以后要严格执行 W3C 的 XHTML、CSS 和 JavaScript 标准才是。

Labels: , , , ,

(请点击这里阅读全文)

Thursday, October 06, 2005

Throwing Tables Out the Window

这是一篇翻译自 blogger.com 的新版网站界面设计者 stop design 网站的文章,如果对原文感兴趣,可以访问 Douglas Bowman 的英文原著

如果您对本译文有任何疑问或者意见,请直接对本 blog 文章发表评论,或者给我发送电子邮件


文章摘要

很多网站已经对 CSS 这片海洋进行了深入充分的测试,现在我们从水底开始欢呼的时候到了,让我们奉劝并鼓励那些还没有跳下水来的人,赶紧加入我们的行列。现在已经没有任何理由继续用表格来排版,也没有理由为不同的浏览器维护同一个网站的多个版本。赶快把表格扔掉吧,相信我们,你不再需要它们了!(译文:巴西葡萄牙语丹麦语法语德语意大利语日语西班牙语土耳其语


Throwing Tables Out the Window

妈妈快看,没有表格哟!

那些参加了今年在西雅图的 Digital Design World 的朋友们可能看到我主持了一场题为“No More Tables, CSS Layout Techniques”的讨论。在讨论中,我们回顾了一下表格的正确用法,以及一些用 CSS 来达到同样目的的方法。然后我们转向无表格排版,列举了一些范例并概括出两种基本的途径:控制位置和悬浮(positioning and floats)。

讨论进行到一半的时候,我改换了风格,宣布我们将就现实中的实例,实现从表格和占位 GIF 图片的排版方式向纯 CSS 排版的转换。我原本可以设置一个虚拟的例子用在讨论中,但是这个看起来会显得非常做作。如果我设置了我自己的例子,它看起来可能会显得漂亮整洁,所有的一切都会被按照我想象的那样被渲染,会避开所有我已知的问题点。
虚拟的还不够好,我要向真实的案例挑战。所以我选择了一个为大部分听众所熟悉的西雅图本地的小公司:

Microsoft

OK,大概并不只有一部分听众熟悉这个并不那么小的公司。很多用户每天都要登录微软网站的官方网站,不管它是不是像搜索巨头 Google 以及 Yahoo! 那样出名或者被经常用到,勿庸置疑的是,每天有数以百万计的用户访问 microsoft.com ,它为我们的互联网带来了极大的流量。

遗憾的是微软并没有竭尽全力优化她的网站。用户下载着不必要的大型页面,服务器为了支持他们浪费着额外的带宽。对于 40KB 来讲,微软首页的 HTML 还算不上是洪水猛兽,但是它负担着无法访问的、七拼八凑的、基于表格并充斥着各种属性的标记,以及一些笨拙的 JavaScript。注意我并没有提到这些是不是有效的标记。尽管它采用了 XHTML 风格,但是微软在其页面上漏掉了 doctype 声明。

为什么是微软?

这是不是仅仅另外一次对微软的挑剔?

直率地,诚恳地说,不是!

我选择微软并不是为了跳上时尚的抨击讲坛,或者向业内人们喜欢讨厌的公司多扔些鸡蛋。(我从未放弃任何机会来置疑微软做出的某些决定,但是我总是避免指责。)

我承认我有意地选择并锁定了一个备受瞩目的公司,我天生喜欢追逐领头羊。不过,作为范例,大部分人都熟悉她。microsoft.com 曾经是(现在仍然是)完美的 CSS 标准改造候选者

以下是原因……

原因 #1
因为它低效率地用大量的表格和占位 GIF 来排版。当内容用表格进行排版后,页面的兼容性会更差,甚至无法访问。并不只有微软有这个问题。目前网络上绝大多数的网站仍然使用大量的表格用于页面排版,或者其它纯粹的视觉目的。我选择微软的网站,是因为它和很多其它网站有着同样的问题,而且它可以作为一个著名的范例(甚至最后成为模范)。

原因 #2
因为微软网站首页当前设计的基本结构和成千上万的网站的设计有着共同的模式:页眉 + 3 栏 + 页脚。进一步讲,页眉横跨整个页面上部,左栏主要包含导航系统,主栏放内容,右栏提供额外的资料,然后页脚在三栏下面同样横跨整个页宽。即使不是三栏式排版,很多网站也可能使用和这个结构类似的二栏式排版:一个边栏放在主栏的左边或者右边:

微软的主页,用三个不同的部分标识出其页面的结构,一个表示页眉+三栏+页脚,另外两个表示页眉+两栏+页脚

原因 #3
因为微软的网站对 CSS 的利用,仅限 FAC (字体和颜色)。我更希望看到这个曾经在应用环境下发明了样式表基础理论的公司,更偏重于 CSS,而非旧的方法。

原因 #4
因为目前微软根据浏览其网站的浏览器的不同,提供网站的不同版本。一个提供给 Windows 的 Internet Explorer (v5.5 及以上),另一个什么 dumbed-down 的版本提供给所有其它的浏览器(包括 IE 和 Mac),它省略了一些图片,以及所有的产品徽记。这个非 IE/Win 的版本去掉了一些功能(如弹出式菜单),并用不同的技术来渲染页面元素。如果您有 IE 5.5 或以上版本,以及另外一个浏览器,您可以自己查看。如果没有,以下是两种不同版本的屏幕截图,并用红色的圈标出了不同的地方:

微软提供的两种不同的首页截图。左侧的(提供给 IE 5.5 或更高版本)与右侧(提供给其它浏览器)的相比,显示了更多的图片,从体上样式更加饱满一些。

非 IE/Win 的版本和为 IE/Win 提供服务的版本相比,明显简陋得多。我们都知道它其实并不需要这样。这并不只是在某些浏览器上能够工作而在其它的浏览器上却不行的草率代码。微软故意做了一个 JavaScript 浏览器探测,当浏览器是 IE 5.5 或更高版本时,它会将浏览器重定向到另一个页面上。其实,微软可以只维护一个能够运行在所有浏览器上的版本。

微软还只是为非 IE/Win 的浏览器用户提供了其网站的另一个版本,有些开发者所做的可能远不止这些。一些网站放弃对其它浏览器提供支持,我们听到的最多的原因是 MSIE/Win 被绝大多数用户使用,同时为任何其它的浏览器提供正确的页面会花费太多时间。有些则抱怨说为 IE/Win 之外的浏览器开发太昂贵。其实,“太多时间”和“太昂贵”的说法并不成立。

很多开发者相信这些说法,因为他们是从为 IE 开发——并在 IE 中检查——开始的。当他们用另一种浏览器来查看的时候就会感到沮丧——他们看到各种各样他们认为必须去修正的 bug。

IE 和其它在近两年不断升级版本的浏览器(Mozilla、Firefox、Safari、Opera……)相比,对 CSS 的理解更加松散。从 IE 开始开发,意味着在开发早期发现的问题会更少一些。先在 IE 上开发,然后尝试更新支持其它浏览器,从长期来看这将增加时间和金钱的消耗。但是,我们有一个更好的办法能够更快更省钱的解决这个问题。

从更严格的浏览器开始开发,这些浏览器通常按照它们应该渲染页面的方式去渲染。先让页面在这些浏览器上运行正常,然后再回来为 IE 做一些“修补”。用这种方式,开发将快得多。虽然初期这样会让页面在您流量分析中出现得绝大多数浏览器上不太直观,但是如果您并不打算习惯——或者依赖——IE 松散的渲染行为的话,这个开发过程要流畅和有效率得多。从 IE 开始开发,您可能会花费更长的时间来修改开始的代码,以便适应更严格的浏览器。

走这条路,我们仍然有 IE 方面的问题需要关注。但是,当我们有了更多关于 IE 错误的 CSS 渲染行为的经验后,IE 方面的问题从一开始就降到最少,这是肯定的。

请说事实

在讨论的后半段,我们从头到尾地经历了将微软基于表格和占位 GIF 排版的页面,转换为更容易访问的、纯 CSS 驱动的版本,使其能在任何浏览器上运行。这并不新潮,以前已经有人对 microsoft.com 进行过重新编码。本站一些常来的读者从事无表格的设计到现在已经一年多了。尽管 CSS 海洋的水已经被公平的全面测试过,但是我们仍然没有看到更多的人跳下水。因此有了 Digital Design World 上的讨论,有了这片文章。

在接下来的讨论中,我们将每个环节分成容易操作的若干个小块。我指出了过程中的主要步骤,包括去掉表格,将它们转换成更容易理解的标记,以及用来忠实重现微软首页设计每一个环节的 CSS 技术。

在整个讨论过程中,我们每个环节都演示了很多形象的东西(图示、截屏、统计图表等)来帮助理解这些渲染技术。我也预先准备了在每个环节需要的文件代码。

撰写此篇文章的其中一个目的,是为了发布对 microsoft.com 进行改造的最终结果,看起来有点让人难忘:

 当前设计
(IE/Win)
当前设计
(其它)
改造后
使用表格40360
占位 GIF35760
总 <img> 标签431226
CSS 背景图片1111
浏览器支持2Most modernMost modern
HTML 文件大小40 KB39 KB15 KB
文件大小减少-3%62%


更多

当我们开始进行 Meyer/Davidson ESPN-style 评价和设计时,这些数字变得更加有趣了。在微软一篇公开的题为“Inside Microsoft”的网页上,微软公布了其流量统计:mocrosoft.com 在 2004 年 5 月获得了 12 亿次的 page view。在以上的讨论中,我显示了如何减少一个页面 62% 的标记,或者说 25 KB。我也同样预言了如果微软能够在整个网站上更加积极的应用 CSS,每页面 25KB 是一个公平的估计。如果乘以平均每天 3870 万次的 page view,每页面 25 KB 的减少每天可以为我们节省约 924 GB 的带宽,也就是每年 329 terabytes

光凭这些数据,就应该足以让一些人回头。

现在,回到现实中,我们改造的仅仅只是一个版本,但这种改造仍然支持微软更多“高级”的设计(就像现在在 IE/Win 中看到的那样),在很多其它流行的浏览器中仍然如此。

不管像微软这样的公司是不是需要只维护其主页的一个版本来支持所有的浏览器,来提高页面加载速促,来使其更容易被所有的用户和设备所访问,我觉得值得指出的是,现在非常容易的展示他们——或者任何公司—— 能够创建一个高级的版本,使用更干净的标记,能支持更多的浏览器,能更容易地被访问。所有的展示花费不过一两小时。

更多要点和警示

  • 如果您感到好奇,并且想更仔细一些,CSS 在改造过程中对原版本仅仅增加了 3KB / 5KB(分别对应 IE/Win 和非 IE/Win 版本)到 8KB。
  • IE/Win 版本左侧导航中两个选项所带有的弹出式菜单一样可以被重现。所有这些都由纯 CSS,简单、易懂且更容易访问的标记实现。当鼠标悬垂到列表父列表条目上时,改造版本用 :hover 伪类(pseudo-class)来开关一个内嵌的无序列表(子菜单)。考虑到 IE 在列表条目上不支持 :hover,所以为了在此浏览器上支持弹出式菜单,微软正在使用的 JavaScript 仍然是必要的。或者类似于 Suckerfish Dropdowns 的东西能够用来保持和改造版本所使用的同样易懂的内嵌列表标记。
  • 微软当前的非 IE/Win 版本上如此大的图片标签缩减主要是来源于占位 GIF 的滥用。另外,非 IE/Win 版本单独调用所有列表强调符图片,而不像其 IE/Win 版本以及改造版本那样,通过一条单独的 CSS 声明来调用。
  • 微软网站上能够找到的所有 JavaScript 标记都被移除了。链接元素上成百上千的属性标记显然是出于点击追踪目的。Microsoft would likely want to add some of this layer back in - though hopefully through a valid means of doing so.
  • 正如前面提到的,此文的目的是为了公布使用 CSS 和更简单的、易懂的标记来构建页面所带来的潜在结果和益处。我们仅仅用微软作为一个注明的范例。此文有意没有给出改造后的代码。我明白很多人能够从本次演讲讨论的成果中学到东西。即使没有参加演讲,也能够从对 HTML 和 CSS 代码的修改上获益。但是,我无意通过公开发表对源代码的修改来贬低任何人在微软的角色。我更倾向于有机会能够直接将它们展示给微软,与合适的团队成员讨论这些改变以及相关技术,如果他们愿意这么做的话。

Labels: , , , , ,

(请点击这里阅读全文)