以这段文字为例子。。
<p><b>法国国营铁路公司(SNCF)20日承认,</b>新订购的2000列火车因车体过宽,<strong>无法开进国内许多火车站的站台,从而不得不花大笔资金改造站台。</strong>法国国营铁路公司发言人克里斯托夫·皮耶诺埃尔告诉法国新闻电台:“我们发现问题晚了点。<b>我们承认这一失误并为此承担责任。”</b></p>
一个P标签包含了文字节点以及其他几个标签,标签中包含了文字节点。
selection 对象有一下几个属性:(以下都为chrome下单测的结果,firefox,IE另说)
- anchorNode:anchorNode为selection对象的起点Node,假如选中的文字为“新订购的2000列火”,那么anchorNode就为“ 新订购的2000列火车因车体过宽”, ”这个文字节点。anchorNode还有几个子属性,我选出有用的有这么几个:length:这个节点的文字个数、nextSibling:这个文字节点的下一个同级节点,这里为 Strong标签、previousSibling:这个文字节点的前一个标签,这里是 B标签、textContent:这个选中的文字节点的全部文字,全部文字就是“ 新订购的2000列火车因车体过宽, ”即便只选择了“ 新订购的2000列火 ”。以上只是选择了单个的文字,还没有跨标签进行选择,比如“ 列火车因车体过宽,<strong>无法开进国内 ”这样的选择。也不会属性对其造成影响。假如anchorNode起点为“ 司(SNCF)20日承认,</b>新订购的2000列火 ”这样的呢?anchorNode起点就为 B 标签里面的textNode,有部分属性就会产生变化。length:不变,都是textNode,nextSibling:变化了,B标签里面只有一个textnode,textnode的nextsibling就为null、previousSibling:和nextsibling 同理;textContent:不变;
- anchorOffset:基于anchorNode也就是起点节点的偏移量,选中“ 订购的2000列火车因车体过 ”这段话,起点节点为“ 新订购的2000列火车因车体过宽 “ 那么偏移量就为1;
- baseNode:和anchorNode 属性一致。但是选择的起点不同的话则完全不一样。 假如选择 ” 订购的2000列火车因车体过 “ 这段话,anchorNode和baseNode的属性完全一致。假如选择起点为0,即anchorOffset为0的话属性就完全不一样了。比如” 新订购的2000列火车因车体过宽, “这段话,baseNode的起点就是这个textNode的previousSibling: B标签。其属性length、nextsibling,previoussibling都为B标签的文字节点属性
- baseOffset:和anchorOffset的一致,如果像” 新订购的2000列火车因车体过宽, “这段话的话,那么值就为previousSibling的textNode的length。
- extentNode:selection选中文字的结束节点,假如选中的文字为“ 新订购的2000列火 ”,那么extentNode就为“ 新订购的2000列火车因车体过宽 ”,这个属性还有几个子属性,有用的几个和anchorNode和baseNode基本一致,length:这个节点的文字个数、nextSibling:这个文字节点的下一个同级节点,这里为 Strong标签、previousSibling:这个文字节点的前一个标签,这里是 B标签、textContent:这个选中的文字节点的全部文字,全部文字就是“ 新订购的2000列火车因车体过宽, ”即便只选择了“ 新订购的2000列火 ”。以上只是选择了单个的文字,还没有跨标签进行选择,比如“ 列火车因车体过宽,<strong>无法开进国内 ”这样的选择的话,看最后选中的文字所处的地方,“ 列火车因车体过宽,<strong>无法开进国内 ” 国内所处的标签是 Strong标签,那么extentNode就为Strong标签的 textNode,其length,nextSiblint,previousSibling,textContents都要做出相应的改变.
- extentOffset:选中文字最后所处的标签的偏移量。“ 列火车因车体过宽,<strong>无法开进国内 ” 这个内字在Strong标签内所处的位置就是extentOffset的值。
- focusNode:属性和定于与extentNode完全一致
- focusOffset:属性和定义与extentOffset完全一致
- getRangeAt:把选中的文字转化为range对象,可以进行操作。接受一个参数,一般填写为0,表示从selection对象的0开是进行转化;
以上的属性为chrome下console selection对象出来的与FF IE不一致,下面来说FF的selection对象属性,方法;
FF的selection 方法基本和chrome的一样,但是少了baseNode和extentNode以及extentOffset,baseOffset这4个属性,所以综上所述胃:起点节点用的属性为anchorNode,结束节点为focusNode的属性即可
IE下的的selection对象与上面又不相同为:
seletion对象属性和方法完全不同于W3C的selection之属性,方法;
RANGE对象
range对象也分为IE和W3C对象;range对象可以对选中的文字进行添加对象,删除,变粗,改变字体等适合用于网页富文本编辑等。在网上一搜一大片,我选几个目前能用到的属性来记录下。
W3C range:可以由selection对象创建也可以由document来创建。两者的区别为selection已经选好的range对象,通过selection.getRangeAt(0);来得到从selection 0开始的range对象;通过Document来创建就要稍微复杂一点,首先要确定range对象来自哪个元素,就拿上面的列子来讲;range对象来自P标签这个DOM对象;另外,range对象有4个基本属性:
- startContainer:要选中的range对象开始的父节点,比如range对象是“法国国营铁路公司” 那么startContainer就是这个段文字所在标签B的文字节点。这个对象是可以被制定为文字节点或则一般节点。
- startOffset:选中的range对象的起点,假如是文字节点,注释等,那么这个值就是这个range对象第一个字所在该文字节点的索引值;比如“国营铁路公司” 这个range对象第一个字是“国”,所在的text节点是“ 法国国营铁路公司(SNCF)20日承认, ” 那么国字在这段文字的第2个。所以startOffset的值就为2。。万一我们选择的startContainer为一般节点,那么该值就为子节点的索引值;就拿上面列子来说,选择range对象为“ 无法开进国内许多火车站的站台,从而不得不花大笔资金改造站台。 ”,startContainer为P标签的话。那么startOffset就为“ 1 ”;
- endOffset:选择规则和startOffset一致
- endContainer:range结束时文字的父对象所在节点;比如” 台:“我们发现问题晚了点。<b>我们承认这一 “ 那么endContainer就是B节点的文本节点;
- commonAncestorContainer:endContainer和startContainer的共同父节点在这个Document最深的一个(最近的一个);比如“法国国营铁路公司“ 这种range对象所在End和startContainer的共同祖先都是文本节点。如果是跨标签的话,比如” 20日承认,</b>新订购的 “ startContainer是B标签的文本节点,endContainer是P标签。那么他们的共同祖先就是P标签;
一般选择:使用range.SelectNode(Dom)连同startContainer和endContainer一同选中;包含标签;range.SelectNodeContents(Dom);选中除了start,endContainer之外的内容,只是内容,不包含标签;
复杂选择:可以指定选择某段文字从哪开始从哪结束;有2个方法,为setStart,setEnd;方法分别接受2个参数,第一个参数为这个range对象的container,第2个参数为索引值;start和end2个方法的参数分别对应为setStart(startContainer,startOffset);setEnd(endContainer,endOffset);
以上就是range对象的基本属性和选择方式,分为selection选择和自己输入参数创建;下面就是实际操作range对象,让其实现富文本编辑;
- insertNode:插入节点,创建一个节点,比如span标签,插入到这个range对象的开始处;用法:range.insertNode(span标签);
- surroundContent:环绕节点,创建一个节点,比如span标签,把range对象添加进这个span标签。用处:一般用来设置其CSS样式等比如设置背景色;用法:range.surroundContents(span标签);(注:这个方法只能用于startContaienr和endContainer都是文本节点并且range没有跨标签。比如” 台:“我们发现问题晚了点。<b>我们承认这一 “ 这种不行,要报错,解决方法是用extractContents方法提出来,添加进span,使用insetAdjacentHTML添加;
extractContents:提取并删除range对象,返回一个document.fragment对象;相当于我们的剪切功能;这方法和insertAdjacentHTML配合非常牛逼;例子:比如我们” 台:“我们发现问题晚了点。<b>我们承认这一 “ 这种range对象的话有一部分的B标签在里面,那么使用这个方法的话,剪切后,B标签会自动补全开始和闭合标签,内容为剪切剩下的内容。比如剪切上面的range后,B标签就变成了<b>失误并为此承担责任。”</b> range中含有B标签部分的文字也会自动闭合成一个完整的B标签例如:<b>我们承认这一</b>;
要使用insetAdjacentElement的话,必须知道调用insetAdjacentElement的节点为哪个。比如要把剪切出来的内容原原本本添加个背景色后还原,那么就必须知道确切的使用“insetAdjacentElement”的DOM节点。insetAdjacentElement可以添加在这个DOM节点的标签面前,内容开始前,内容结束后,标签结束后。分别为beforeBegin,beforeBegin,beforeEnd,afterEnd; 如何知道确切的调用这个方法的DOM节点呢?前面的selection对象的anchorNode和focusNode就派上用场了。我们分别得到这2个节点的父节点;总共有这么几种可能性:
1:假如起始节点的父节点不这个例子的根节点的话,那么说明range对象的anchroeNode是一个子节点而非文本节点,那么我们就把提取出来的range添加进span使用ahchorNode.insetAdjacentElement('afterEnd',span)来添到经过extractContents后自动闭合的起始节点的后面;
2:假如起始父节点为这个例子的根节点,但是结束父节点不是的话,那么就是FocusNode.insetAdjacentElement('beforeBegin',span)来添加到这个节点的前面;
3:假如起始父节点和结束父节点为相同的话,那么说明这个range的anchor和FocusNode都在子节点里面;使用surroundContents即可。
4:起始父节点为例子的根节点,结束父节点不是,那么就以结束父节点为起点,使用FocusNode.insetAdjacentElement('beforeBegin',span);
5:假如起始和结束父节点都是例子的话使用surroungContents即可。
但是有一点不同的是,在firefox下insetAdjacentElement不是一个有效的方法,firefox只支持insetAdjacentHTML。在chrome下HTML,TEXT,ELEMENT都支持。
目前在firefox下要使用怎么办呢?只支持insetAdjacentHTML的话我们就用span的innerHTML来拼接一个新的span就是了哇
如:FocusNode.insetAdjacentElement('beforeBegin',"<span style='background-color:red'>"+span.innerHTML+"</span>") problem solved~~
IE下实现range给背景添加颜色等操作
IE下的selection为document.selection;获取selection选中的range对象为document.selection.createRange();
由于IE的selection对象没有anchorNode等属性,所以添加背景色等操作就用不到insetAdjacentElement这样的函数,那么是怎么样进行操作的呢?
IE特有的execCommad来执行的,这个方法非常的强大,可以把range对象替换为其他的文本,input,img标签,还可以给range对象的文字进行样式设置;
获取range对象的方式和W3C一致,分别是通过selection 来获取,还有就是通过创建range对象;
selection创建:document.selection.createRange();
range对象创建:IE可以用不同标签来创建不同选择区域的range对象。比如用body创建range对象,那么range对象的选择区域就是整个页面了:获取整个body的range:document.body.createTextRange();目前IE range对象支持由body,input,button,textarea创建的range对象
简单的选择range对象:range.findText(”查找的文字“),返回一个bool值,true为找到值,false为没找到;例如上面的例子” 公司(SNCF) “ range.findText('公司(SNCF)'); 返回true,就可以使用execCommad操作对象了;注意:使用这个方法时候要注意range对象是由哪个标签创建的。比如Button创建的range对象要查找由textarea创建的range对象在textarea中的值,肯定是找不到的;
复杂的选择:IE range复杂的选择是通过moveStart,moveEnd来前后移动range选区;
这2个方法接受2个参数,第一个是移动的类型; 有4个类型:
character:按照字符进行移动,最小单位
word:按照单词进行移动;
sentence:按照句子进行移动;
textedit:直接移动到选区的结束位置,start传入这个参数无效,只有end方法传入才还效
第2个参数是数字,具体移动的个数,可以接受负值;start方法的数字是range开始起第几个开始计算;end方法的传入数字是这段range的结束位置起开始算,正数的话就是range的结束范围就是range本身的长度。负数的话那么就是range的长度减去负数值(绝对值);比如 一段完整的range文字,法国国营铁路公司(SNCF)20日承认, 我们要截取“铁路公司” 话看下面的例子:
这里用character来做例子;
range.moveStart('character',4);
range.moveEnd('character',-11);
那么range的范围就是创建这个range的元素的开始第4个到第8个之间的位置;
操作range对象
IE操作range对象全是通过execCommad来进行操作的
execCommad的参数有3个,
参数A,操作的类型比如设置range的css属性,剪切,复制,把range的文字转化成input、textarea标签等,
参数B,为bool值,在参数A为替换元素,添加链接的情况下才有用,目的为是否弹出框来确定这个操作,true为弹出,false为不弹出;
参数C,为参数A的具体属性,比如设置背景色的颜色,替换元素的ID属性,替换超链接的URL等;
参数A的部分参数为:
- 2D-Position 允许通过拖曳移动绝对定位的对象。
- AbsolutePosition 设定元素的 position 属性为“absolute”(绝对)。
- BackColor 设置或获取当前选中区的背景颜色。
- BlockDirLTR 目前尚未支持。
- BlockDirRTL 目前尚未支持。
- Bold 切换当前选中区的粗体显示与否。
- BrowseMode 目前尚未支持。
- Copy 将当前选中区复制到剪贴板。
- CreateBookmark 创建一个书签锚或获取当前选中区或插入点的书签锚的名称。
- CreateLink 在当前选中区上插入超级链接,或显示一个对话框允许用户指定要为当前选中区插入的超级链接的 URL。
- Cut 将当前选中区复制到剪贴板并删除之。
- Delete 删除当前选中区。
- DirLTR 目前尚未支持。
- DirRTL 目前尚未支持。
- EditMode 目前尚未支持。
- FontName 设置或获取当前选中区的字体。
- FontSize 设置或获取当前选中区的字体大小。
- ForeColor 设置或获取当前选中区的前景(文本)颜色。
- FormatBlock 设置当前块格式化标签。
- Indent 增加选中文本的缩进。
- InlineDirLTR 目前尚未支持。
- InlineDirRTL 目前尚未支持。
- InsertButton 用按钮控件覆盖当前选中区。
- InsertFieldset 用方框覆盖当前选中区。
- InsertHorizontalRule 用水平线覆盖当前选中区。
- InsertIFrame 用内嵌框架覆盖当前选中区。
- InsertImage 用图像覆盖当前选中区。
- InsertInputButton 用按钮控件覆盖当前选中区。
- InsertInputCheckbox 用复选框控件覆盖当前选中区。
- InsertInputFileUpload 用文件上载控件覆盖当前选中区。
- InsertInputHidden 插入隐藏控件覆盖当前选中区。
- InsertInputImage 用图像控件覆盖当前选中区。
- InsertInputPassword 用密码控件覆盖当前选中区。
- InsertInputRadio 用单选钮控件覆盖当前选中区。
- InsertInputReset 用重置控件覆盖当前选中区。
- InsertInputSubmit 用提交控件覆盖当前选中区。
- InsertInputText 用文本控件覆盖当前选中区。
- InsertMarquee 用空字幕覆盖当前选中区。
- InsertOrderedList 切换当前选中区是编号列表还是常规格式化块。
- InsertParagraph 用换行覆盖当前选中区。
- InsertSelectDropdown 用下拉框控件覆盖当前选中区。
- InsertSelectListbox 用列表框控件覆盖当前选中区。
- InsertTextArea 用多行文本输入控件覆盖当前选中区。
- InsertUnorderedList 切换当前选中区是项目符号列表还是常规格式化块。
- Italic 切换当前选中区斜体显示与否。
- JustifyCenter 将当前选中区在所在格式化块置中。
- JustifyFull 目前尚未支持。
- JustifyLeft 将当前选中区所在格式化块左对齐。
- JustifyNone 目前尚未支持。
- JustifyRight 将当前选中区所在格式化块右对齐。
- LiveResize 迫使 MSHTML 编辑器在缩放或移动过程中持续更新元素外观,而不是只在移动或缩放完成后更新。
- MultipleSelection 允许当用户按住 Shift 或 Ctrl 键时一次选中多于一个站点可选元素。
- Open 目前尚未支持。
- Outdent 减少选中区所在格式化块的缩进。
- OverWrite 切换文本状态的插入和覆盖。
- Paste 用剪贴板内容覆盖当前选中区。
- PlayImage 目前尚未支持。
- Print 打开打印对话框以便用户可以打印当前页。
- Redo 目前尚未支持。
- Refresh 刷新当前文档。
- RemoveFormat 从当前选中区中删除格式化标签。
- RemoveParaFormat 目前尚未支持。
- SaveAs 将当前 Web 页面保存为文件。
- SelectAll 选中整个文档。
- SizeToControl 目前尚未支持。
- SizeToControlHeight 目前尚未支持。
- SizeToControlWidth 目前尚未支持。
- Stop 目前尚未支持。
- StopImage 目前尚未支持。
- StrikeThrough 目前尚未支持。
- Subscript 目前尚未支持。
- Superscript 目前尚未支持。
- UnBookmark 从当前选中区中删除全部书签。
- Underline 切换当前选中区的下划线显示与否。
- Undo 目前尚未支持。
- Unlink 从当前选中区中删除全部超级链接。
- Unselect 清除当前选中区的选中状态。
列如我们要设置背景色就为ragne.execCommad('BackColor','true','red');背景色为红色,其他css属性一直;
替换元素成TextBox并且把textbox的值设置为替换前的值:
var text=range.text;
range.execCommad('InsertInputText','false','tba');