发布于 2017-06-27 06:06:23 | 79 次阅读 | 评论: 0 | 来源: 网友投递
这里有新鲜出炉的Javascript教程,程序狗速度看过来!
JavaScript客户端脚本语言
Javascript 是一种由Netscape的LiveScript发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
例如下面这个模样的例子:
2011-04-12
负责调查切尔诺贝利核事故对人与环境造成影响的俄科学家亚布罗科夫博士指出,因福岛核电站使用的燃料较切尔诺贝利核电站多,且有反应堆使用了含有高毒性的钚的燃料,因此"福岛核电站事故可能会比切尔诺贝利带来更严重的后果"。
上面选中状态的那些文字就可以转换成Range对象
(下面会详细讲述)。通过Range对象
你可以找到Range
的起始点和结束点,如果你实在有心,还可以删除或是复制这些内容,或是用其他文字替换,甚至是简单的HTML。
上面的例子可以说是最简单的Range对象
的例子,因为其只包含了文字。而实际上,Range对象
也是可以包含HTML代码内容的,例如下面这个示例:
<time>2011-04-12</time>
<p>据日本广播协会电视台12日报道,日本经济产业省原子能安全保安院决定将福岛第一核电站核泄漏事故等级提高至7级。这使日本核泄漏事故等级与苏联切尔诺贝利核电站核泄漏事故等级相同。</p>
<p>负责调查切尔诺贝利核事故对人与环境造成影响的俄科学家亚布罗科夫博士指出,因福岛核电站使用的燃料较切尔诺贝利核电站多,且有反应堆使用了含有高毒性的钚的燃料,因此"福岛核电站事故可能会比切尔诺贝利带来更严重的后果"。</p>
同样的,Range对象
被创建,且包含HTML,现在的问题是选择的内容正好跨过了楚河和汉界(跨标签),如果就单纯的论选择的内容的话,应该如下:
泄漏事故等级与苏联切尔诺贝利核电站核泄漏事故等级相同。</p>
<p>负责调查切尔诺贝
显然,上面的HTML属于1级残废,基本无效。然而幸运的是,所有的浏览器都会自动调整HTML片段使其有效,就像变成下面这样:
<p>泄漏事故等级与苏联切尔诺贝利核电站核泄漏事故等级相同。</p>
<p>负责调查切尔诺贝</p>
可以看到,浏览器自动补全了一定数目的HTML来让Range
有效。如果你复制或是移动Range
,你所复制或移动的HTML内容一定是有效的。
在真正操刀JavaScript之前我们需要大致知道Range对象
的浏览器兼容性情况。实际上,问题是比较麻烦的,因为至少有3种类似Range对象
,且你有必要全部理解。先展示详细的兼容性情况表:
支持:不支持:部分支持:
Explorer 6/7 | Firefox 2 | Safari 1.3 | Opera 9 | |
---|---|---|---|---|
cloneContents() | ||||
cloneRange() | ||||
collapse() | tbd | tbd | tbd | tbd |
collapsed | ||||
commonAncestorContainer | ||||
compareBoundaryPoints() | ||||
comparePoint() – Mozilla 扩展 | ||||
createContextualFragment() – Mozilla 扩展 | ||||
deleteContents() | ||||
detach() | ||||
endContainer | ||||
endOffset | ||||
extractContents() | ||||
insertNode() | ||||
isPointInRange() – Mozilla 扩展 | ||||
selectNode() | ||||
selectNodeContents() | ||||
setEnd() | ||||
setEndAfter() | ||||
setEndBefore() | ||||
setStart() | ||||
setStartAfter() | ||||
setStartBefore() | ||||
startContainer | ||||
startOffset | ||||
surroundContents() |
说明:cloneContents()
的用法类似docFrag = rangeObject.cloneContents()
,Range对象
内容被克隆同时被添加到文档片段上,并返回自身。但是在Safari下有个问题,即如果选择范围是空,将会返回null
而不是空的文档片段。可以通过类似docFrag = rangeObject.cloneContents() || document.createDocumentFragment()
这样的代码修复。
deleteContents()
处,Range
内容会被永久删除,无返回值。
endContainer
指用户选择内容结尾处的容器节点。通常是文本节点。
extractContents()
用法docFrag = rangeObject.extractContents()
。从DOM树上剪切Range对象
并返回文档片段。该片段可以粘贴到页面上。
startContainer
指用户选择内容起始处的容器节点。通常是文本节点。
startOffset
在Opera浏览器下,在选择内容为空的时候返回0
。
Explorer 6/7 | Firefox 2 | Safari 1.3 | Opera 9 | |
---|---|---|---|---|
addRange() | ||||
anchorNode | ||||
anchorOffset | ||||
collapse() | tbd | tbd | tbd | tbd |
collapseToEnd() | ||||
collapseToStart() | ||||
containsNode() | ||||
deleteFromDocument() | ||||
extend() | ||||
focusNode | ||||
focusOffset | ||||
getRangeAt() | ||||
isCollapsed | ||||
rangeCount | ||||
removeAllRanges() | ||||
removeRange() | ||||
selectAllChildren() | ||||
selectionLanguageChange() |
说明:anchorNode
用法为userSelection.anchorNode
。指用户选择内容起始处的容器节点。通常是文本节点。
anchorNode
在Opera浏览器下,在选择内容为空的时候返回0
。
focusNode
用法为userSelection.focusNode
。指用户选择内容结尾处的容器节点。通常是文本节点。
focusOffset
在Opera浏览器下,在选择内容为空的时候返回0
。
getRangeAt()
用法为rangeObject = userSelection.getRangeAt(0),作用是将
Mozilla Selection
转换为W3C Range
。
Explorer 6/7 | Firefox 2 | Safari 1.3 | Opera 9 | |
---|---|---|---|---|
boundingHeight | ||||
boundingLeft | ||||
boundingTop | ||||
boundingWidth | ||||
collapse() | tbd | tbd | tbd | tbd |
compareEndPoints() | ||||
duplicate() | ||||
expand() | ||||
findText() | ||||
htmlText | ||||
move() | ||||
moveEnd() | ||||
moveStart() | ||||
moveToElementText() | ||||
moveToPoint() | ||||
offsetLeft | ||||
offsetTop | ||||
parentElement() | ||||
pasteHTML() | ||||
scrollIntoView() | ||||
select() | ||||
text |
说明:htmlText
用法为htmlString = userSelection.htmlText
。返回字符串,为TextRange
的HTML内容,相当于innerHTML
。只读。
pasteHTML()
,当粘贴HTML到一个文本节点时,该文本节点自动分隔。
text
用法为string = userSelection.text
。返回字符串,为TextRange
的文本内容,相当于innerText
。可读/写。
Explorer 6/7 | Firefox 2 | Safari 1.3 | Opera 9 | |
---|---|---|---|---|
W3C Range | ||||
Mozilla Selection | ||||
Microsoft Text Range |
说明:
W3C Range对象
是唯一官方指定。基本上其是将Range
作为包含DOM的文档片段。
Mozilla Selection对象
显得有些多余,其存在是为了向后兼容Netscape 4。其类似于W3C Range对象
,也是基于DOM树的。
Microsoft Text Range对象
跟上面两个就是郭德纲和玄彬的区别了,因为其是基于字符串的。事实上,Text Range
包含的字符串是很难一下子跳变成DOM节点的。 总的来说,Mozilla Selection对象
就是个打酱油的命,仅有的闪光点能够直接将用户选择任何内容变成完全Range对象
以及一些额外的方法或是属性可以向后兼容Netscape 4。但是不幸的是除了IE浏览器外的其他浏览器都支持此Selection对象
。
婆婆妈妈的解释就免了,直接看相关代码:
var userSelection;
if (window.getSelection) { //现代浏览器
userSelection = window.getSelection();
} else if (document.selection) { //IE浏览器 考虑到Opera,应该放在后面
userSelection = document.selection.createRange();
}
var selectedText = userSelection;
if (userSelection.text) {
selectedText = userSelection.text;
}
var getRangeObject = function(selectionObject) {
if (selectionObject.getRangeAt)
return selectionObject.getRangeAt(0);
else { // 较老版本Safari!
var range = document.createRange();
range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);
range.setEnd(selectionObject.focusNode,selectionObject.focusOffset);
return range;
}
}
var rangeObject = getRangeObject(userSelection);
var startP = [the p node];
var endLi = [the second li node];
range.setStart(startP, 8);
range.setEnd(endLi, 5);
var userSelection, rangeObject;
if (window.getSelection) {
//现代浏览器
userSelection = window.getSelection();
} else if (document.selection) {
//IE浏览器 考虑到Opera,应该放在后面
userSelection = document.selection.createRange();
}
//Range对象
rangeObject = userSelection;
if (userSelection.getRangeAt) {
//现代浏览器
rangeObject = userSelection.getRangeAt(0);
}
var sel = rangy.getSelection();
alert(sel.toString());
<script type="text/javascript" src="http://www.zhangxinxu.com/study/201104/rangy/rangy-core.js"></script>
<script type="text/javascript" src="http://www.zhangxinxu.com/study/201104/rangy/rangy-cssclassapplier.js"></script>
<script>
var cssApplier;
window.onload = function() {
rangy.init();
cssApplier = rangy.createCssClassApplier("selectClass", true);
document.body.onmouseup = function() {
cssApplier.toggleSelection();
};
};
</script>
源代码有些高度,为了节约篇幅,这里就不展示出来了,您可以在demo页面中看到完整的CSS/HTML/JS代码。不过JS部分半封装,您要是有兴趣可以在外面包裹一个函数使其插件化,我是懒得再去折腾了。
对于Range
相关的知识即使到现在都是半生不熟的,所以文章的内容更多的算是翻译性质的内容。自己并没有从深入理解的基础上很浅显地剖析相关知识点,文章很多地方会显得不怎么通俗易懂。
文中多展示的Range
等兼容性表格的数据都是N年前的,还是Safari 1.3时代的数据,老的牙都掉了,实用价值大打折扣,不过可以告知的是先前现代浏览器所不支持的个别属性现早就支持了。
跌跌撞撞,滚滚爬爬。文章难免有表述不准确的地方,欢迎指正。也欢迎提交相关的脚本的bug。
原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活