由clientWidth到document
引言
最近想用js写一些插件,其中一点就是要获取浏览器可视窗口的宽度或高度,以及相对于文档的偏移等等。我们知道用JQuery用起来很爽快,你可以通过
$(window).width() 获取宽度
$(window).height() 获取高度
$(ele).offset().top 相对于浏览器顶部的偏移
$(ele).offset().left 相对于浏览器左边的偏移
我们来看看jQuery源码:
offset: function(a) { if (arguments.length) return void 0 === a ? this : this.each(function(b) { m.offset.setOffset(this, a, b) }); var b, c, d = { top: 0, left: 0 }, e = this[0], f = e && e.ownerDocument; if (f) return b = f.documentElement, m.contains(b, e) ? (typeof e.getBoundingClientRect !== K && (d = e.getBoundingClientRect()), c = dd(f), { top: d.top + (c.pageYOffset || b.scrollTop) - (b.clientTop || 0), left: d.left + (c.pageXOffset || b.scrollLeft) - (b.clientLeft || 0) }) : d }, position: function() { if (this[0]) { var a, b, c = { top: 0, left: 0 }, d = this[0]; return "fixed" === m.css(d, "position") ? b = d.getBoundingClientRect() : (a = this.offsetParent(), b = this.offset(), m.nodeName(a[0], "html") || (c = a.offset()), c.top += m.css(a[0], "borderTopWidth", !0), c.left += m.css(a[0], "borderLeftWidth", !0)), { top: b.top - c.top - m.css(d, "marginTop", !0), left: b.left - c.left - m.css(d, "marginLeft", !0) } } }
ownerDocument 是个什么东西?我们随便写个div盒子,起个id为box,打印一下
> document.getElementById('box').ownerDocument.nodeName
> #document
嗦嘎,原来这样可以获取到document对象!出于好奇我继续打印下面的结果:
> document.getElementById('box').ownerDocument.documentElement.nodeName; > HTML > document.getElementById('box').ownerDocument.body.nodeName; > BODY
到这里,你可能对ownerDocument还不是太熟悉,但你一定经常看到过 document.documentElement.clientWidth 与 docuemnt.body.clientWidth这样的代码,没错,今天的问题就此而展开。
正文
为了写出兼容老版本浏览器的代码,我们需要通过document.compatMode判断当前浏览器处于什么模式。是quirksMode 还是 standradMode?standradMode也叫strict mode。
什么是怪异模式呢?
在早期W3C标准还没出来之前,一些浏览器比如netscape、Explorer 4 都按照浏览器自己的方式进行解析,他们各自为政,所以被称为怪异模式。标准模式则自然是W3C颁布的标准咯!
如何区分标准模式和怪异模式呢?
Ⅰ 区分标准模式和怪异模式与文档Doctype声明有关,对于没有该声明的,浏览器将采用quirks mode
Ⅱ 对于有Doctype声明的,没有使用DTD声明或者使用HTML4以下的DTD声明时,则采用quirks mode
Ⅲ 在我们现在开发网页中,一般都使用h5标准头<!Doctype html>,其采用的是标准模式strict mode
更多关于怪异模式和标准模式,可以去参考其他资料:http://hsivonen.iki.fi/doctype
现在我们知道了这两种模式之后,那么如何用代码判断呢?各浏览器对document提供了一个叫compatMode的属性,他有两个值:
1. BackCompat
2. CSS1Compat
当compatMode的值为CSS1Compat,我们使用document.documentElement
当compatMode的值为BackCompat,我们使用document.body,固有:
clientWidth = document.compatMode == 'CSS1Compat' ? document.documentElement.clientWidth : document.body.clientWidth;
clientHeight = document.compatMode == 'CSS1Compat' ? document.documentElement.clientHeight : document.body.clientHeight;