日志更新

跨浏览器的本地存储(二):DOM:Storage

DOM Storage,是基于 Web Applications 1.0 specification 中介绍的 Structured client-side storage。相比 Cookies 来说,DOM Stroage 空间更大、更安全、更易于使用的。目前它只在基于Moziila的浏览器中可以使用,从 Firefox2 开始。

一、DOM:Storage: sessionStorage

浏览器支持:Firefox 2.0+

基本语法:

  • // 设置 key 值
    sessionStorage.key = value;
  • // 获取 key 值
    value = sessionStorage.key;

备注:

  1. 作为每个 window 对象的属性存在的全局对象,即:可以通过 sessionStorage 或者 window.sessionStorage 来访问它们。
  2. sessionStorage 含有一个在页面会话有效期内(只要页面没有关闭,一个页面会话就始终保持着,且当页面被重新载入或恢复时“复活”,而打开一个新的标签页或新窗口都会初始化新的会话)可用的存储区域。
  3. sessionStorage 持有那些应该保存的临时数据,一旦浏览器突然被刷新时,可恢复。
  4. sessionStorage 暂时还没有实现在浏览器崩溃后存储和恢复数据的功能( bug 339445 )。

更多信息:sessionStorage specification

样例:自动保存文本字段的内容,如果浏览器突然被刷新,就恢复字段内容,这样就不会丢失任何输入了。

// 获得我们要跟踪的那个文本字段
var field = document.getElementById("field");

// 看看我们是否有一个autosave的值
// (这将只会在页面被突然刷新时发生)
if ( sessionStorage.autosave ) {
    // 恢复文本字段中的内容
    field.value = sessionStorage.autosave;
}

// 每秒钟检查一次文本字段的内容
setInterval(function(){
    // 并把结果保存到会话存储对象中
    sessionStorage.autosave = field.value;
}, 1000);

二、DOM:Storage: globalStorage(重点)

浏览器支持:Firefox 2.0+

基本语法:

  • globalStorage['developer.mozilla.org'] —— 在developer.mozilla.org下面所有的子域都可以通过这个存储对象来进行读和写。
  • globalStorage['mozilla.org'] —— 在mozilla.org域名下面的所有网页都可以通过这个存储对象来进行读和写。
  • globalStorage['org'] —— 在.org域名下面的所有网页都可以通过这个存储对象来进行读和写。
  • globalStorage[''] —— 在任何域名下的任何网页都可以通过这个存储对象来进行读和写。

方法属性:

  • setItem(key, value) —— 设置或重置 key 值。
  • getItem(key) —— 获取 key 值。
  • removeItem(key) —— 删除 key 值。

或者:

  • // 设置 key 值
    window.globalStorage["planabc.net"].key = value;
  • // 获取 key 值
    value = window.globalStorage["planabc.net"].key;

备注:

  1. 作为每个 window 对象的属性存在的全局对象,即:可以通过 globalStorage 或者 window.globalStorage 来访问它们。
  2. Storage 空间:整个域名的默认 Storage 大小为 5MB (不过 Storage 区域的大小用户可以自定义),globalStorage['net'] 为 2MB,globalStorage['planabc.net'] 为 3MB,如果超过限制,则会报错。
  3. Firefox 支持 Storage 事件:document.addEventListener(”storage”, eventHandler, false);。
  4. Firefox 目前还没有实现 globalStorage[tld] 和 globalStorage[''] (会抛出一个安全错误),这是由于对于这些名字空间可以进行随意读写的话是有安全漏洞的。
  5. Firefox 2 允许访问比当前文档域名层次高的存储的对象,由于安全的因素 Firefox 3 中不再允许。

更多信息:globalStorage specification

样例:DOM Storage Test

// 跟踪一个用户在你的域名下所访问的所有页面的次数
globalStorage['mozilla.org'].visits =
    parseInt( globalStorage['mozilla.org'].visits || 0 ) + 1;

参考阅读:

position:relative 的使用限制

在 W3C 规范中 position 是可以使用在任何元素上的,但 position:relative 却有部分例外:

The effect of ‘position:relative’ on table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption elements is undefined.

经测试,在浏览器(IE 除外)中给 table 定义 position:relative 属性是无效的。如果的确需要在表格中使用该属性,建议在单元格中嵌套一个 div 元素,再在其上设置 position:relative 属性来模拟。

跨浏览器的本地存储(一):userData behavior

前言

现在最流行的本地存储莫过于 cookie 的应用,但浏览器对 cookie 有很多限制,最大的限制在于其对cookie 总大小,仅为 4K 左右(包括名(name)、值(value)和等号)。

对于复杂一点的应用和需求,仅有的 4K 大小还是有点相形见绌,其实很多浏览器(IE、Firefox、Safari)本身也提供了自己的本地存储的功能,或许在特定的环境下能满足我们。

一、userData behavior

浏览器支持:IE5.0 或以上

基本语法:

  • XML:<Prefix: CustomTag id=sID style=”behavior:url(’#default#userData’)” />
  • HTML:
    <ELEMENT style=”behavior:url(’#default#userData’)” id=sID>
    object.style.behavior = “url(’#default#userData’)”
  • Script: object.addBehavior (”#default#userData”)

属性:

  • expires —— 设置或者获取 userData behavior 保存数据的失效日期。
  • XMLDocument —— 获取 XML 的引用。

方法:

  • getAttribute() —— 获取指定的属性值。
  • load(object) —— 从 userData 存储区载入存储的对象数据。
  • removeAttribute() —— 移除对象的指定属性。
  • save(object) —— 将对象数据存储到一个 userData 存储区。
  • setAttribute() —— 设置指定的属性值。

备注:

1、从安全方面考虑,一个 userData 存储区只能用于同一目录和对同一协议进行存储。

2、如果使用 userData behavior 不正确可能会对你的应用造成危害,userData 存储区中的数据没有加密因而不安全的。任何可以访问 UserData 保存磁盘的应用都可以访问该数据,所以,推荐不要保存敏感的数据,比如信用卡号,详细:《Security Considerations: DHTML and Default Behaviors》

3、userData behavior 会跨 session 存储信息到存储区,这提供了动态的数据结构和比 cookie(一般 4KB) 更大的容量。userData 存储区的容量依赖于 domain 的安全域。下表显示的是 userData 存储最大容量,对单独文档和整个域名的所有文档都适用,但基于安全域。

Security Zone Document Limit (KB) Domain Limit (KB)
Local achine 128 1024
Intranet 512 10240
Trusted Sites 128 1024
Internet 128 1024
Restricted 64 640

4、如果设置 userData behavior 到 html、head、title 或者 style 对象上,当 save 和 load 方法被调用时会出错。如果必须设置到 style 中,可以设置内联或者文档头,例如:

<style>
    .storeuserData {behavior:url(#default#userData);}
</style>

5、对于 userData behavior 来说 ID 是可选的,但是如果有,则会改善执行性能。

6、userData 可以将数据以 XML 格式保存在客户端计算机上,一般保存在 C(WIN 系统盘):\Documents and Settings\XXX\UserData\ 文件夹下。

7、userData 数据一直存在,除非人为删除或者用脚本设置该数据的失效日期(expires)。

大部分翻译自:《userData Behavior》

XHTML1.1 Tags List

http://ore.to/htmllint/tagslist.cgi?HTMLVersion=XHTML11

Firefox 下 innerHTML 的一个 BUG

今天同事 明城 在项目中碰到一个 BUG,代码具体如下:

<!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>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>Firefox下innerHTML的一个BUG</title>
<style type="text/css">
    a { display: block; border: 1px solid red;}
    div { display: inline; border: 1px solid red;}
</style>
</head>
<body>
<a href="javascript:change();">change<div id="count">20</div>aaa</a>
<script type="text/javascript">
function change() {
    var count = document.getElementById('count');
    var c = count.innerHTML;
    var page = parseInt(c)+1;
    count.innerHTML = page;
    alert(page);
}
</script>
</body>
</html>

当你在 Firefox2.0+ 或 Firefox3.0+ 中点击链接后,会发现 innerHTML 插入的内容为<a>21</a>,而其他浏览器测试(IE6、IE7、Safari3.0+、Opera9.0+)都正常,插入内容均为文字 21。

估计是 Firefox 的一个 BUG,查找了官方网站的 BUG库,果真找到别人提交的该类问题——《Setting innerHTML on a block element inside an inline element creates extra copies of the inline element》(Bug 381808)。

我们可以参阅下8楼的 Boris Zbarsky 给出的个人解释:

There are two separate concepts of block vs inline. One in CSS and one in
HTML. They don’t match.

In any case, the point is that in HTML <b> is not allowed to contain <div> (so
the <b> needs to get closed), but the text needs to be bold for compat so we do
residual style handling. HTML5 is going to define a different method of doing
this anyway, so at that point we’ll need to revisit this bug.

虽然这是一个 BUG,但 BUG 的造成也却是人为的不良习惯造成的,在 WEB 标准中严格来说内联元素是不允许包含块级元素的(扩展阅读:《Allowed nesting of elements in HTML 4 Strict (and XHTML 1.0 Strict)》)。

Firebug Lite

Firebug Lite 源自 Firebug ,可使用在IE、Opera、Safari 浏览器上。最新版本为 Firebug Lite 1.2 ,不仅包含了旧版本的console.log 命令,还可查看 DOM 元素、跟踪 XHRs,操纵 HTML、 CSS 和 JavaScript 。

Firebug Lite 可以在页面中插入调试:

<script type='text/javascript' src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>

还可以创建 Firebug Lite 书签调试(推荐):

javascript:var firebug=document.createElement('script');firebug.setAttribute('src','http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js');document.body.appendChild(firebug);(function(){if(window.pi&&window.firebug){firebug.init();}else{setTimeout(arguments.callee);}})();void(firebug);

当然你也可以将文件下载到本地调试。

更多介绍请看:http://getfirebug.com/lite.html

line-height 属性的继承问题

淘宝商城的 detail 页面“产品详情”部分是商家自定义区块,曾出现这样一个问题:

<style type="text/css">
p {
    line-height:17px;
}
</style>

<div class="mdse-detail">
    <p>
        <strong style="font-size:30px">
            品牌:XZX<br />
            市场价:145元<br />
            颜色:黑色<br />
            面料:棉<br />
            尺码:S  M  L<br />
            衣长:S 89  M 90   L 91<br />
            肩宽:S 35  M 36   L 37<br />
            胸围:S 88  M 92   L 96<br />
            下摆:S 104 M 108  L 112<br />
            袖长:S 17  M 17.5 L18<br />
            由于测量方法不同,误差在2CM左右!
        </strong>
    </p>
</div>

你会发现上面例子的文字会重叠在一起!这是什么原因呢?

由于.detail-content 中的 p 元素继承了默认设置的全局样式 line-height:17px,而自定义区块又是由商家自定义,其内字体被设置为了 font-size:30px;(可能为任意值),根据 Inline formatting model,得知该文字的 line-box 高为 17px,多出的字体部分上下溢出,所以会出现字体重叠的现象。

那这个问题如何解决呢?

解决方案:我们给 .mdse-detail 下的 p 元素设定样式属性 line-height:1.4

为什么解决方案里的 1.4 不带单位?

元素的 line-height 属性值会继承父元素(或祖先元素)的 line-height 属性值,如果属性值有单位,则继承的值是换算后具体的 px 值而非原始的值(比如:em、%),而如果属性值没有单位,则浏览器会继承数值(无单位),然后根据该元素的 font-size 值重新解析得到新的 line-height 值。这个和 table 的 tr 设置 display 属性有一点点类似(tr.style.display = ”;,IE 显示 block,而 Firefox 等标准浏览器显示 table-row)。

还有另外一个相对低效的方法,但也不失为一个快捷的解决方案:

.mdse-detail p * {
    line-height:140%;
}

参考阅读:《Unitless line-heights》

如何给 legend 标签设定宽度

我们在做表单的时候经常会使用到这样的结构:

<fieldset>
    <legend>哪些浏览器legend标签设定的宽度有效</legend>
    <input type="checkbox" value="ie6" name="width" id="ie6" checked="checked" /><label for="ie6">IE6</label>
    <input type="checkbox" value="ie7" name="width" id="ie7"checked="checked" /><label for="firefox">IE7</label>
    <input type="checkbox" value="firefox2" name="width" id="firefox2" /><label for="firefox2">Firefox2</label>
    <input type="checkbox" value="firefox3" name="width" id="firefox3" /><label for="firefox3">Firefox3</label>
    <input type="checkbox" value="opera" name="width" id="opera" checked="checked" /><label for="opera">Opera9.0+</label>
    <input type="checkbox" value="safari" name="width" id="safari"checked="checked" /><label for="safari">Safari3.0+</label>
</fieldset> 

当我们使用 CSS 给 legend 标签设定固定宽度时:

legend {
    background:red;
    width:500px;
}

在 IE6、IE7、Opera9.0+、Safari3.0+ 都正能常显示,而在 Firefox2 和 Firefox3 中宽度却失效。

在这里我们不去深究为什么,只探讨解决的方法:

我们可以通过在 legend 标签内添加一个标签,并给标签设定所需要的宽度,此宽度的单位不可为百分比(%):

HTML 修改为:

<fieldset>
    <legend><span>哪些浏览器legend标签设定的宽度有效</span></legend>
    <input type="checkbox" value="ie6" name="width" id="ie6" checked="checked" /><label for="ie6">IE6</label>
    <input type="checkbox" value="ie7" name="width" id="ie7"checked="checked" /><label for="firefox">IE7</label>
    <input type="checkbox" value="firefox2" name="width" id="firefox2" /><label for="firefox2">Firefox2</label>
    <input type="checkbox" value="firefox3" name="width" id="firefox3" /><label for="firefox3">Firefox3</label>
    <input type="checkbox" value="opera" name="width" id="opera" checked="checked" /><label for="opera">Opera9.0+</label>
    <input type="checkbox" value="safari" name="width" id="safari"checked="checked" /><label for="safari">Safari3.0+</label>
</fieldset> 

CSS 修改为:

legend span {
    background:red;
    width:500px;
    display:block;
}

可参考:《how to set width of LEGEND tags in FF》

正淳 同时也提供了另外的一种解决方案,无需修改结构,仅修改样式即可:

legend {
    background:red;
    text-indent:-600px;
    padding-left:600px;

    /*IE下还原初始方式,只设定宽度*/
    *width:600px;
    *text-indent:0;
    *padding-left:0;
}

题外话:CSS 的兼容其实并不难,多尝试多实践就可以解决,最重要的是自己要去动手,只有动手了才会有更多的收获,才会有更深的印象。

iphone 浏览器缓存的几个注意点

  1. 正确设置 expires 或 cache-control 头才可缓存组件;
  2. 遵循“最少最近使用(least recently used (LRU))原则;
  3. 单个组件最大限制为 25KB,当大于 25KB,则不会被缓存;
  4. 最多可能缓存 19 个 25KB 的组件,缓存总限制为 475KB-500KB。
  5. gzipped 压缩对缓存文件不起作用,先解码后缓存。
  6. 重启后缓存不会被保留。

详细阅读:《Performance Research, Part 5: iPhone Cacheability - Making it Stick》(需要用代理才可以看到)

如何跨浏览器使用连续字符的换行

由于连续的字符(字母、符号、数字)在默认情况下是不换行的,可能会破坏整个界面布局。

那如何解决这个问题呢?

在 IE 和 Safari 1.3+ 下相对比较容易解决,使用 CSS 属性 word-wrap: break-word;。有朋友会问为什么不是使用 word-break:break-all; ,因为有一个特殊的情况,该属性无法解决换行——连续的英文标点符号。

注:word-break 主要使用在 CJK 文本,即:中文(Chinese)、日文(Japanese)、韩文(Korean)。

而 Firefox 和 Opera 浏览器,无法识别 word-wrap: break-word; 和 word-break:break-all; 属性。可以通过脚本给连续字符的每个字符之间插入 \ u8203 的字符(该字符在非 IE 浏览下不占据空间),使连续变为了不连续,达到了换行的效果。

breakWord = function(dEl){
    var dWalker = document.createTreeWalker(dEl, NodeFilter.SHOW_TEXT, null, false);
    var node,s,c = String.fromCharCode('8203');
    while (dWalker.nextNode()){
        node = dWalker.currentNode;
        s = trim( node.nodeValue ) .split('').join(c);
        node.nodeValue = s;
    }
    return true;
}

详细的脚本,可参看 Hedger Wang 整理的脚本《Cross Browser Word Breaker》

对于 Firefox ,你还可以通过 XBL bindings 来实现此效果:《Emulating CSS word-wrap for Mozilla/Firefox》

最新评论

  • 怿飞: Firefox只需装firebug即可...
  • www.ycsznet.com: 安装出错了。我的FIREFOX以前装过一个...
  • 怿飞: 知其然知其所以然也是有好处的,呵...
  • 怿飞: @八度社区 是在td中包含一个di...
  • 八度社区: 我一帮都会用jquery,兼容性比较好,能...
  • 八度社区: 你的意思是说在table里面外包围一个di...
  • 闲耘: 之前看过@谢飞提到的方法,很支持...
  • 闲耘: 觉得@old9的理解是正确的,标准也不...
  • 闲耘: @Lin.x IE有IE的实现,FF有FF的实现,而...
  • 大猫: IE ...frea...

管理登录