Cssom-view
本规范为开发者提供了一些API,这些API是用来从视觉的角度审查或操作文档的,包括通过脚本获取元素盒模型布局的位置、获取视口的宽度、或滚动一个元素。
Contents
背景
本规范中定义的很多特性实际上都早已被众浏览器支持了。而本规范旨在让所有的浏览器将这些特性更好的互相配合。同时,本规范还包括了一些新的特性,希望对开发者们有用。(没用的点举报!)
一致性要求
该规范中的所有的图表、实例和注意事项都是非规范性的,同时这也是全部的非规范性内容。也就是说,除此之外的内容都是规范性的。
规范性内容中的关键字:“必须”、“禁止”、“要求的”、“应该”、“不应该”、“推荐的”、“可以”、“可选的”都是RFC2119中的描述性解释。为了保障阅读的流畅性,该规范中对这些关键字不会做格式上的强调。[RFC2119]
有算法要求的部分全部使用了“必须”、“应该”、“可以”等关键字进行描述。
算法和步骤方面的一致性要求可以通过任何方式进行实现,只要运行结果相同即可。(规范里的算法定义只是为了易于遵循,而非性能最优)
用户代理在实现上可以针对无约束的用户输入进行特殊限制。比如为了防御服务攻击、为了保护过多内存被占用、为了在有局限性的平台上工作等。
当一个方法或特性调用另一个方法或特性时,用户代理必须调用其内部的API。比如在ECMAScript中,开发者无法通过重写特性或方法来改变其原本的行为。
除非特殊声明,字符串的比较都是大小写敏感的。
具备一致性的用户代理会实现本规范中的所有需求。
Web IDL
本规范中的IDL片段一定是 Web IDL 规范下的描述性解释。[WEBIDL]
术语
本规范中的术语全部来自:DOM Core、DOM Range、CSSOM和HTML。[DOMCORE] [DOMRANGE] [CSSOM] [HTML]
MouseEvent
是定义于……HTML 中的 body
元素是 root
HTML 元素中的第一个 body
HTML 子元素。
内容边缘、内边距边缘、边框边缘和画布定义于CSS。
视口(viewport)和初始化包含块(initial containing block)是CSS 2.1定义的,除非这里有一个 http://www.w3.org/2000/svg 命名空间下的祖先 foreignObject
元素,且该元素被作为视口以及初始化包含块。
术语内容(content)指元素的内容区域的尺寸,这包括被溢出的内容。
术语文档内容(document content)指画布(canvas)渲染的区域,包括负坐标轴上的内容。
CSS 像素
本规范中API定义的所有坐标和尺寸都是以CSS中的像素为单位的。
matchMedia()
对 Window
接口的扩展
partial interface Window { MediaQueryList matchMedia(DOMString media_query_list); readonly attribute Screen screen; // viewport readonly attribute long innerWidth; readonly attribute long innerHeight; // viewport scrolling readonly attribute long scrollX; readonly attribute long pageXOffset; readonly attribute long scrollY; readonly attribute long pageYOffset; void scroll(long x, long y); void scrollTo(long x, long y); void scrollBy(long x, long y); // client readonly attribute long screenX; readonly attribute long screenY; readonly attribute long outerWidth; readonly attribute long outerHeight; };
当 matchMedia(media_query_list)
方法调用时,会执行如下步骤:
- 让 parsed_media_query_list 成为
media_query_list
的解析结果。 - 返回一个新的
MediaQueryList
对象,与Window
对象相关联,以 parsed_media_query_list 作为相关的媒体查询列表。
screen
特性必须返回与 Window
对象相关联的 Screen
对象。且每次返回的都是同一个对象。
在文档被导航之后,通过 WindowProxy
访问 screen
有可能得到不同的结果。
innerWidth
特性必须返回视口的宽度,如果存在滚动条的话,也包括滚动条的尺寸。
var viewportWidth = innerWidth
innerHeight
特性必须返回视口的高度,如果存在滚动条的话,也包括滚动条的尺寸。
scrollX
和 pageXOffset
特性必须返回相对于初始化包含块来源的从视口左侧计算出来的横坐标。
scrollY
和 pageYOffset
特性必须返回相对于初始化包含块来源的从视口左侧计算出来的纵坐标。
当 scroll(x,y)
方法被调用时,必须执行如下步骤:
- 如果
x
或y
是无穷大或非数字,则中断该运算。 - 如果文档内容已经溢出至右侧,则让
x
为 max(0, min(x, 内容宽度 - 内容边缘宽度));如果文档内容(在文字从右向左排版的情况下)已经溢出至左侧,则让x
为 min(0, max(x, 内容边缘宽度 - 内容宽度))。 - 让
y
为 max(0, min(y, 文档内容高度 - 如果存在滚动条的话也包括其高度在内的视口高度))。 - 将文档内容的横坐标
x
对齐到视口左侧,同时将文档内容的纵坐标y
对齐到视口顶端。 - 如果对齐操作触发内容移动,则创建一个队列任务,这个任务会触发名为
scroll
的事件,并冒泡到Document
对象——除非此时已经有一个同样的任务在队列中了。
当 scrollTo(x,y)
方法被调用的时候,用户代理必须用当前的参数执行 scroll()
方法。
当 scrollBy(x,y)
方法被调用的时候,用户代理必须用以下参数执行 scroll()
方法:把 x
加上 scrollX
作为第一个参数,同时把 y
加上 scrollY
作为第二个参数。
screenX
特性必须返回客户端窗口的最左端相对于输出设备的屏幕的横坐标。如果上述屏幕或客户端窗口不存在,则返回0。
screenY
特性必须返回客户端窗口的最顶端相对于输出设备的屏幕的纵坐标。如果上述屏幕或客户端窗口不存在,则返回0。
outerWidth
特性必须返回客户端窗口的宽度。如果该窗口不存在,则返回0。
outerHeight
特性必须返回客户端窗口的高度。如果该窗口不存在,则返回0。
MediaQueryList
接口
每个 MediaQueryList
对象在被创建时都有一个相关联的媒体查询列表集,以及一个空的媒体查询列表监听器集。
如果相关联的媒体查询列表在赋值时发生了变化,则媒体查询列表监听器集中的每一个监听器会按照添加的顺序依次创建队列任务,来调用这些监听器,其参数是 MediaQueryList
对象。
function handleOrientationChange(mql) { if(mql.matches) // landscape … else … } var mql = matchMedia("(orientation:landscape)") mql.addListener(handleOrientationChange)
interface MediaQueryList { readonly attribute DOMString media; readonly attribute boolean matches; void addListener(MediaQueryListListener listener); void removeListener(MediaQueryListListener listener); }; [Callback, NoInterfaceObject] interface MediaQueryListListener { void handleChange(MediaQueryList mql); };
media
必须返回序列化的相关联媒体查询列表。
如果相关联的媒体查询列表匹配渲染文档的状态,则 matches
必须返回 true,否则返回 false。
当 addListener(listener)
被调用时,必须将 listener
添加到媒体查询列表监听器集中,除非它已经在此列表中。
当 removeListener(listener)
被调用时,必须将 listener
移出媒体查询列表监听器集。
Screen
接口
如其名,Screen
接口用来展示屏幕输出设备的信息。
interface Screen { readonly attribute unsigned long availWidth; readonly attribute unsigned long availHeight; readonly attribute unsigned long width; readonly attribute unsigned long height; readonly attribute unsigned long colorDepth; readonly attribute unsigned long pixelDepth; };
availWidth
特性必须返回输出设备渲染表面的可用宽度。
availHeight
特性必须返回输出设备渲染表面的可用高度。
width
特性必须返回输出设备的宽度。
height
特性必须返回输出设备的高度。
colorDepth
和 pixelDepth
特性均必须返回分配给输出设备的颜色位数(比如,包括alpha通道)。如果输出设备并不支持显示颜色,则返回0。
对 Document
接口的扩展
partial interface Document { Element? elementFromPoint(float x, float y); CaretPosition? caretPositionFromPoint(float x, float y); };
elementFromPoint(x,y)
方法必须返回视口的坐标 x,y
上的元素。所返回的元素是通过点击测试决定的。如果任何参数是负数、或 x
大于视口宽度、或 y
大于视口高度(这里的视口宽度和高度应该包含可能存在的滚动条的宽或高),该方法必须返回 null
。如果给定位置上没有任何元素,则返回根元素,如果根元素也不存在,则返回 null
。
caretPositionFromPoint(x,y)
方法必须执行以下步骤并返回结果:
- 如果任何参数是负数、或
x
大于视口宽度、或y
大于视口高度(这里的视口宽度和高度应该包含可能存在的滚动条的宽或高),则返回null
。 - 如果在视口的坐标
x,y
上无法插入文本光标则返回null
。 - 如果在视口的坐标
x,y
上存在文本输入控件且可以插入文本光标,则返回一个具备如下属性的光标位置:- 光标结点:对应文本输入控件的结点。
- 光标位移:文本光标左侧距离的16位总数(The amount of 16-bit units to the left of where the text insertion point indicator would have inserted)。
- 光标范围:
null
- 否则,返回一个光标位置,该对象的光标范围是一个收起的范围对象,且处在文本光标的位置。其它的属性如下:
- 光标结点:包含光标范围起点的结点。
- 光标位移:光标范围的起点位移。
elementFromPoint()
和 caretPositionFromPoint()
的细节也同样如此。我们希望在未来的CSS或HTML版本中定义点击测试。CaretPosition
接口
光标位置交代了一个文本光标的位置。它始终关联着光标结点、光标位移和光标范围。并展现为一个 CaretPosition
对象。
interface CaretPosition { readonly attribute Node offsetNode; readonly attribute unsigned long offset; };
offsetNode
特性必须返回光标结点。
offset
特性必须返回光标位移。
对 Element
接口的扩展
partial interface Element { ClientRectList getClientRects(); ClientRect getBoundingClientRect(); // scrolling void scrollIntoView(optional boolean top); attribute long scrollTop; // scroll on setting attribute long scrollLeft; // scroll on setting readonly attribute long scrollWidth; readonly attribute long scrollHeight; readonly attribute long clientTop; readonly attribute long clientLeft; readonly attribute long clientWidth; readonly attribute long clientHeight; };
getClientRects()
和 getBoundingClientRect()
方法
这两个方法提供盒边框相对于视口的位置信息。通过这些方法获取到的对象是静态的,也就是说,文档随后发生的变化不会在这里体现出来。
getClientRects()
方法被调用时,必须遵循以下算法返回结果:
- 如果调用该方法的元素并没有相关联的CSS盒布局并且不在 http://www.w3.org/2000/svg 命名空间中,则返回一个空的
ClientRectList
对象且终止该运算。 - 如果该元素并没有相关联的CSS盒布局,但在 http://www.w3.org/2000/svg 命名空间中,则返回一个
ClientRectList
对象,它只有一个单独的描述其SVG规范中元素边界的ClientRect
对象。 [SVG] - 返回一个
ClientRectList
对象,该对象是包含一组ClientRect
的列表,它们遵循下列约束条件,按照内容顺序描述边框盒(包括那些宽或高为0的):- 如果调用该方法的元素的display属性计算值为table或inline-table,则包含此table盒和可能存在的caption盒,但不会包含匿名包裹盒。
- 将匿名盒替换为其子内容,并重复该操作,直到列表中不存在匿名盒为止。
getBoundingClientRect()
方法被调用时,必须遵循以下算法返回结果:
- 在该元素上调用
getClientRects()
方法并得到结果list
。 - 如果
list
是空的则返回一个ClientRect
对象,该对象的top
,right
,bottom
,left
都是0。 - 否则,返回一个
ClientRect
对象,描述包含list
中第一个矩形和其它长和宽非0的矩形的最小矩形。
var example = document.getElementsByTagName("div")[0].getBoundingClientRect(); var exampleWidth = example.width; var exampleHeight = example.height;
Element
的滚动成员
滚动一个元素到可视区域,并附带一个对齐到顶端的可选设置。这意味着,按照从最外层到最内层滚动盒的顺序,对每个已经建立滚动盒的祖先元素或视口,执行这些步骤:
- 如果文档中相关联的要滚动的元素和相关联的滚动盒元素或视口不属于相同的源,则终止运行。
- 如果具有对齐到顶端的设置,则把该元素边框盒的顶端和滚动盒的顶端对齐。
- 否则,如果对齐到顶端的选项并没有被设置,则把该元素边框盒的底边和滚动盒的顶端对齐。
- 把该元素边框盒的左端和滚动盒的左端对齐。
- 如果上述对齐操作并没有造成内容的移动则终止运行。
-
- 如果滚动盒关联着一个元素:则创建一个队列任务,该任务在相关联的元素上触发名为
scroll
的事件——除非队列中已经有了这个任务。 - 如果滚动盒关联着一个视口:则创建一个队列任务,该任务触发名为
scroll
的事件并冒泡到相关联的 Document
上——除非队列中已经有了这个任务。
- 如果滚动盒关联着一个元素:则创建一个队列任务,该任务在相关联的元素上触发名为
将元素滚动到 x,y 意味着:
- 如果
x
或y
是 无穷大或NaN
则终止运行。 -
- 如果元素有右侧的溢出,则让
x
为 max(0, min(x, 内容宽度 - 内容边缘宽度))。 - 如果元素有左侧的溢出(在从右到左排版的情况下),则让
x
为 min(0, max(x, 内容边缘宽度 - 内容宽度))
- 如果元素有右侧的溢出,则让
- 让
y
为 max(0, min(y, 内容高度 - 内容边缘高度))。 - 根据元素内容边缘的左侧对齐内容横坐标
x
,同时根据元素内容边缘的顶端对其内容纵坐标y
。 - 如果对其操作导致了内容的移动,则创建一个队列任务,该任务在该元素上触发名为
scroll
的事件——除非队列中已经有了这个任务。
scrollIntoView([top])
方法必须执行下面步骤:
- 如果元素并没有相关联的CSS布局盒,则终止运行。
- 滚动元素到可视区域,且如果
top
为真或被忽略,则顶端对齐。
scrollTop
特性必须通过以下步骤返回结果:
- 如果元素并没有相关联的CSS布局盒或在古怪模式下该元素是文档的根元素,则返回0并终止运行。
- 如果元素是根元素则返回
scrollY
的值。 - 如果该元素是 HTML body 元素,且文档在古怪模式下,该元素也没有溢出,则返回
scrollY
的值。 - 返回从元素内容边缘的顶端计算的内容的纵坐标。
当设置 scrollTop
特性时必须执行以下步骤:
- 让
y
为输入的值。 - 如果元素并没有相关联的CSS布局盒,或在古怪模式下该元素是文档的根元素,则终止运行。
- 如果该元素是根元素则调用
scroll()
方法,并以0为第一个参数,y
为第二个参数。 - 如果该元素是 HTML body 元素,且文档在古怪模式下,该元素也没有溢出,则调用
scroll()
方法,并以scrollX
为第一个参数,y
为第二个参数。 - 滚动元素到
scrollLeft,y
。
scrollLeft
特性必须通过以下步骤返回结果:
- 如果元素并没有相关联的CSS布局盒或在古怪模式下该元素是文档的根元素,则返回0并终止运行。
- 如果元素是根元素则返回
scrollX
的值。 - 如果该元素是 HTML body 元素,且文档在古怪模式下,该元素也没有溢出,则返回
scrollX
的值。 - 返回从元素内容左侧的顶端计算的内容的横坐标。
当设置 scrollLeft
特性时必须执行以下步骤:
- 让
x
为输入的值。 - 如果元素并没有相关联的CSS布局盒,或在古怪模式下该元素是文档的根元素,则终止运行。
- 如果该元素是根元素则调用
scroll()
方法,并以x
为第一个参数,0为第二个参数。 - 如果该元素是 HTML body 元素,且文档在古怪模式下,该元素也没有溢出,则调用
scroll()
方法,并以x
为第一个参数,scrollY
为第二个参数。 - 滚动元素到
x,scrollTop
。
scrollWidth
特性必须通过以下步骤返回结果:
- 如果元素并没有相关联的CSS布局盒或在古怪模式下该元素是文档的根元素,则返回0并终止运行。
- 如果元素是根元素则返回 max(文档内容宽度, innerWidth)。
- 如果该元素是 HTML body 元素,且文档在古怪模式下,则返回max(文档内容宽度, innerWidth)。
- 返回该元素实际的左内边距、右内边距和内容宽度之和。
scrollHeight
特性必须通过以下步骤返回结果:
- 如果元素并没有相关联的CSS布局盒或在古怪模式下该元素是文档的根元素,则返回0并终止运行。
- 如果元素是根元素则返回 max(文档内容高度, innerHeight)。
- 如果该元素是 HTML body 元素,且文档在古怪模式下,则返回max(文档内容高度, innerHeight)。
- 返回该元素实际的上内边距、下内边距和内容高度之和。
clientTop
、clientLeft
、clientWidth
、clientHeight
特性
如果元素并没有相关联的CSS布局盒,或CSS布局盒是inline的,则 clientTop
、clientLeft
、clientWidth
、clientHeight
特性必须返回0。否则,这些特性必须按照本章节剩余的定义来计算。
clientTop
特性必须返回实际的 border-top-width
属性值加上顶端内边距边缘和边框边缘之间出现的任何滚动条的宽度。
clientLeft
特性必须返回实际的 border-left-width
属性值加上左边内边距边缘和边框边缘之间出现的任何滚动条的宽度。
如果该元素是根元素,则 clientWidth
特性必须返回将可能存在的滚动条尺寸排除在外的视口宽度。否则返回排除内边距边缘和边框边缘之间可能存在的滚动条的宽度的内边距边缘宽度。
如果该元素是根元素,则 clientHeight
特性必须返回将可能存在的滚动条尺寸排除在外的视口高度。否则返回排除内边距边缘和边框边缘之间可能存在的滚动条的宽度的内边距边缘高度。
对 HTMLElement
接口的扩展
partial interface HTMLElement { readonly attribute Element offsetParent; readonly attribute long offsetTop; readonly attribute long offsetLeft; readonly attribute long offsetWidth; readonly attribute long offsetHeight; };
offsetParent
、offsetTop
、offsetLeft
、offsetWidth
和 offsetHeight
特性
offsetParent
特性必须通过以下步骤返回结果:
- 如果下列任何条件成立则返回
null
并终止运行。- 元素没有相关联的CSS布局盒。
- 元素是根元素。
- 元素是 HTML body 元素。
- 元素实际的
position
属性值是fixed
。
- 找到符合下列任何一个条件的离该元素最近的父元素,如果这个父元素存在,则返回该父元素且终止运行。
- 该父元素实际的
position
属性值不是static
。 - 该父元素是 HTML body 元素。
- 该父元素实际的
position
属性值是static
且是下列元素中的一种:td
、th
或table
。
- 该父元素实际的
- 返回
null
。
offsetTop
特性必须通过以下步骤返回结果:
- 如果元素是 HTML body 元素或并没有向关联的CSS布局盒则返回0并终止运行。
- 如果元素的
offsetParent
是null
,则返回该元素的第一个相关联CSS布局盒的顶端边框边缘的相对于初始化包含块源的纵坐标。 - 返回该元素第一个相关联的CSS布局盒的边框顶端的纵坐标,减去该元素的
offsetParent
的第一个相关联的CSS布局盒内边距顶端的纵坐标,得到的值。
offsetLeft
特性必须通过以下步骤返回结果:
- 如果元素是 HTML body 元素或并没有向关联的CSS布局盒则返回0并终止运行。
- 如果元素的
offsetParent
是null
,则返回该元素的第一个相关联CSS布局盒的左侧边框边缘的相对于初始化包含块源的横坐标。 - 返回该元素第一个相关联的CSS布局盒的边框左侧的纵坐标,减去该元素的
offsetParent
的第一个相关联的CSS布局盒内边距左侧的横坐标,得到的值。
offsetWidth
特性必须通过以下步骤返回结果:
- 如果元素并没有相关联的CSS布局盒,则返回0并终止运行。
- 返回该元素第一个相关联的CSS布局盒的边框边缘宽度。
offsetHeight
特性必须通过以下步骤返回结果:
- 如果元素并没有相关联的CSS布局盒,则返回0并终止运行。
- 返回该元素第一个相关联的CSS布局盒的边框边缘高度。
对 Range
接口的扩展
partial interface Range { ClientRectList getClientRects(); ClientRect getBoundingClientRect(); };
这些方法描述的以下对象均必须是静态的。
当调用 getClientRects()
方法时,如果该范围并不在文档中,则返回的 ClientRectList
对象必须为空,反之则返回的 ClientRectList
对象必须是遵循如下约束、按内容顺序排列的 ClientRect
列表:
- 为每个元素本身在选中范围内但其父元素不在选中范围内的元素调用
getClientRects()
方法,将其返回的边框盒包含在内。 - 为每个选中范围内或部分选中的文字结点(包括边界点重合的情况),包括一个
ClientRect
对象(仅选中的部分,并不是整个行盒)。这个ClientRect
对象的边界是通过字体矩阵计算出来的。因此,对于横向书写的情况,每个盒的纵向尺寸取决于其字体的大小,横向尺寸取决于文字的宽度。
当 getBoundingClientRect()
方法被调用时,必须通过以下步骤返回结果:
- 让
list
为相同范围内调用getClientRects()
的结果。 - 如果
list
为空,则返回一个top
、right
、bottom
、left
都为0的ClientRect
对象。 - 否则,返回一个
ClientRect
对象,该对象描述了能够同时包含list
中第一个矩形以及其它宽高非0的矩形的最小矩形。
对 MouseEvent
接口的扩展
partial interface MouseEvent { readonly attribute long screenX; readonly attribute long screenY; readonly attribute long pageX; readonly attribute long pageY; readonly attribute long clientX; readonly attribute long clientY; readonly attribute long x; readonly attribute long y; readonly attribute long offsetX; readonly attribute long offsetY; };
screenX
特性必须返回事件触发地相对于屏幕源的横坐标。
screenY
特性必须返回事件触发地相对于屏幕源的纵坐标。
pageX
特性必须返回事件触发地相对于初始化包含块源的横坐标。
pageY
特性必须返回事件触发地相对于初始化包含块源的纵坐标。
clientX
特性必须返回事件触发地相对于视口源的横坐标。
clientY
特性必须返回事件触发地相对于视口源的纵坐标。
x
特性必须返回 clientX
的值。
y
特性必须返回 clientY
的值。
offsetX
特性必须返回事件触发地相对于目标结点的内边距边缘的横坐标。
offsetY
特性必须返回事件触发地相对于目标结点的内边距边缘的纵坐标。
矩形
对 ClientRectList
接口的扩展
ClientRectList
对象由一组有序的 ClientRect
对象组成。
interface ClientRectList { readonly attribute unsigned long length; getter ClientRect item(unsigned long index); };
length
特性必须返回全部相关联的 ClientRect
对象的总数量。
当 item(index)
方法被调用时,如果 index
大于了 ClientRect
对象的数量,则必须抛出 INDEX_SIZE_ERR
异常。否则,返回该 index
对应的 ClientRect
对象。
对 ClientRect
接口的扩展
实现 ClientRect
接口的对象体现了一个矩形的盒。此类盒被一个返回 ClientRect
对象的方法所规范。
interface ClientRect { readonly attribute float top; readonly attribute float right; readonly attribute float bottom; readonly attribute float left; readonly attribute float width; readonly attribute float height; };
top
特性必须返回该矩形盒顶端相对于视口源的纵坐标。
right
特性必须返回该矩形盒右侧相对于视口源的横坐标。
bottom
特性必须返回该矩形盒底端相对于视口源的纵坐标。
left
特性必须返回该矩形盒左侧相对于视口源的横坐标。
width
特性必须返回该矩形盒的宽度。
right
减去 left
height
特性必须返回该矩形盒的宽度。
bottom
减去 top
引用
规范的引用
[CSSOM] CSSOM, A. van Kesteren. W3C.
[DOMCORE] DOM Core, A. van Kesteren and Ms2ger. W3C.
[DOMRANGE] DOM Range, Ms2ger. WHATWG.
[HTML] HTML, I. Hickson. WHATWG.
[RFC2119] Key words for use in RFCs to Indicate Requirement Levels, S. Bradner. IETF.
[SVG] Scalable Vector Graphics (SVG), O. Andersson, R. Berjon, E. Dahlström et al.. W3C.
[WEBIDL] Web IDL, C. McCormack. W3C.
致谢
The editor would like to thank Alexey Feldgendler, Björn Höhrmann, David Vest, Garrett Smith, Hallvord R. M. Steen, Leif Arne Storset, Luiz Agostini, Maciej Stachowiak, Michael Dyck, Mike Wilson, Morten Stenshorne, Peter-Paul Koch, Rachel Kmetz, Robert O'Callahan, Sam Weinig, Simon Pieters, Sylvain Galineau, Tarquin Wilton-Jones, Thomas Moore, and Xiaomei Ji for their contributions to this document.
Special thanks to the Microsoft employees who first implemented many of the features specified in this draft, which were first widely deployed by the Windows Internet Explorer browser.