Javascript 获取文本选择中的元素

Javascript 获取文本选择中的元素,javascript,dom,range,Javascript,Dom,Range,我希望获得用户选择中包含的所有元素(如DOM 2 ranges/MS TextRanges) /**@return{Array.}*/ 函数getSelectedElements(){ var元素=[]; //以某种方式获取用户选择中的元素 返回元素; } 我试着通过跟随Tim Down的优秀作品,一些Moz和MS文档,以及一些PPK的东西来做到这一点 方法基本上是: 将SelectionLikeObject定义为DOM选择或IE选择 将RangeLikeObject定义为DOM范围或IE

我希望获得用户选择中包含的所有元素(如DOM 2 ranges/MS TextRanges)

/**@return{Array.}*/
函数getSelectedElements(){
var元素=[];
//以某种方式获取用户选择中的元素
返回元素;
}
我试着通过跟随Tim Down的优秀作品,一些Moz和MS文档,以及一些PPK的东西来做到这一点

方法基本上是:


  • 将SelectionLikeObject定义为DOM选择或IE选择

  • 将RangeLikeObject定义为DOM范围或IE文本范围

  • containerNode
    成为一个节点

  • containerElement
    成为一个元素

  • containedElements
    成为节点列表

  • elementRange
    成为RangeLike对象

  • selectedRange
    成为一个类似RangeObject的对象

  • selectedElements
    成为元素数组

  • 元素
    成为元素

  • selection
    成为selectionlike对象

  • 从用户的选择中设置
    选择

  • selectedElements
    设置为新数组

  • 对于
    选择中的每个
    选择范围

    • containerNode
      设置为
      selectedRange
      的公共祖先容器

    • containerElement
      设置为距离
      containerNode
      最近的元素祖先

    • containedelement
      设置为
      containedelement
      的后代列表

    • 对于
      包含元素中的每个
      元素

      • 元素
        设置
        元素范围

      • 如果
        elementRange
        的边界在
        所选范围的边界

        • 元素
          推到
          所选元素

DOM分支如下所示:

/** 
    @param {Document} doc
    @return {Array.<Element>} 
*/
getSelectedElements.fromIE = function (doc) {

  // Selection - http://msdn.microsoft.com/en-us/library/ie/dd347133(v=vs.85).aspx
  // TextRange - http://msdn.microsoft.com/en-us/library/dd347140(v=vs.85).aspx
  // ControlRange - http://msdn.microsoft.com/en-us/library/ie/ms537447(v=vs.85).aspx

  /** @type {TextRange|ControlRange} */
  var ieRange = doc.selection && doc.selection.createRange();

  /** @type {Array.<Element>} */
  var selectedElements = [];

  /** @type {TextRange} */
  var selectedRange;

  /** @type {Element} */
  var containerElement;

  /** @type {NodeList} */
  var containedElements;

  /** @type {TextRange} */
  var elementRange;

  /** @type {Element} */
  var element;

  /** @type {Selection} */
  var selection;

  /** @type {number} */
  var i = -1;


  if (ieRange.text === void 0) {

    return []; // FIXME: It's a ControlRange, give up.

  }

  selectedRange = /** @type {TextRange} */ ieRange;

  containerElement = selectedRange.parentElement();

  containedElements = containerElement.getElementsByTagName('*');

  elementRange = doc.body.createTextRange();

  while ((element = containedElements[++i])) {

      elementRange.moveToElementText(element);

      if (elementRange.compareEndPoints("StartToEnd", selectedRange) > -1 && 
          elementRange.compareEndPoints("EndToStart", selectedRange) < 1) {

        selectedElements.push(element);

      } 
  }

  return /** @type {Array.<Element>} */ selectedElements;

};
/**
@param{Document}doc
@返回{Array.}
*/
getSelectedElements.fromDOM=函数(doc){
/**@type{Range}*/
var选择范围;
/**@type{Array.}*/
var selectedElements=[];
/**@type{Node}*/
var containerNode;
/**@type{Element}*/
var集装箱运输;
/**@type{NodeList}*/
var包含元素;
/**@type{Range}*/
变量元素范围;
/**@type{Element}*/
var元素;
/**@type{Selection}*/
var selection=doc.defaultView.getSelection();
/**@type{number}*/
var rangeCount=selection.rangeCount;
/**@type{number}*/
var元素计数;
/**@type{number}*/
var i;
//没有getRangeAt的浏览器黑客攻击
//看http://www.quirksmode.org/dom/range_intro.html
如果(!selection.getRangeAt){
selection.getRangeAt=函数(i){
/**@type{Range}*/
var range=doc.createRange();
if(i | |!selection.anchorNode){
返回范围;
}
range.setStart(selection.anchorNode,selection.anchorOffset);
range.setEnd(selection.focusNode,selection.focusOffset);
返回范围;
};
selection.rangeCount=1;
}
elementRange=doc.createRange();
对于(i=0;i-1){
选择元素。推送(元素);
}
}
}
elementRange.detach();
返回所选元素;
};
IE分支如下所示:

/** 
    @param {Document} doc
    @return {Array.<Element>} 
*/
getSelectedElements.fromIE = function (doc) {

  // Selection - http://msdn.microsoft.com/en-us/library/ie/dd347133(v=vs.85).aspx
  // TextRange - http://msdn.microsoft.com/en-us/library/dd347140(v=vs.85).aspx
  // ControlRange - http://msdn.microsoft.com/en-us/library/ie/ms537447(v=vs.85).aspx

  /** @type {TextRange|ControlRange} */
  var ieRange = doc.selection && doc.selection.createRange();

  /** @type {Array.<Element>} */
  var selectedElements = [];

  /** @type {TextRange} */
  var selectedRange;

  /** @type {Element} */
  var containerElement;

  /** @type {NodeList} */
  var containedElements;

  /** @type {TextRange} */
  var elementRange;

  /** @type {Element} */
  var element;

  /** @type {Selection} */
  var selection;

  /** @type {number} */
  var i = -1;


  if (ieRange.text === void 0) {

    return []; // FIXME: It's a ControlRange, give up.

  }

  selectedRange = /** @type {TextRange} */ ieRange;

  containerElement = selectedRange.parentElement();

  containedElements = containerElement.getElementsByTagName('*');

  elementRange = doc.body.createTextRange();

  while ((element = containedElements[++i])) {

      elementRange.moveToElementText(element);

      if (elementRange.compareEndPoints("StartToEnd", selectedRange) > -1 && 
          elementRange.compareEndPoints("EndToStart", selectedRange) < 1) {

        selectedElements.push(element);

      } 
  }

  return /** @type {Array.<Element>} */ selectedElements;

};
/**
@param{Document}doc
@返回{Array.}
*/
getSelectedElements.fromIE=函数(doc){
//选择-http://msdn.microsoft.com/en-us/library/ie/dd347133(v=vs.85).aspx
//文本范围-http://msdn.microsoft.com/en-us/library/dd347140(v=vs.85).aspx
//控制范围-http://msdn.microsoft.com/en-us/library/ie/ms537447(v=vs.85).aspx
/**@type{TextRange | ControlRange}*/
var ieRange=doc.selection&&doc.selection.createRange();
/**@type{Array.}*/
var selectedElements=[];
/**@type{TextRange}*/
var选择范围;
/**@type{Element}*/
var集装箱运输;
/**@type{NodeList}*/
var包含元素;
/**@type{TextRange}*/
变量元素范围;
/**@type{Element}*/
var元素;
/**@type{Selection}*/
var选择;
/**@type{number}*/
var i=-1;
如果(ieRange.text==无效0){
return[];//修复:这是一个控制范围,放弃。
}
selectedRange=/**@type{TextRange}*/ieRange;
containerElement=selectedRange.parentElement();
containedElements=containerElement.getElementsByTagName('*');
elementRange=doc.body.createTextRange();
而((元素=包含元素[++i])){
elementRange.moveToElementText(元素);
如果(elementRange.compareEndPoints(“StartToEnd”,selectedRange)>-1&&
元素范围。比较点(“EndToStart”,selectedRange)<1){
选择元素。推送(元素);
} 
}
返回/**@type{Array.}*/selectedElements;
};
现在,我想解决的问题是:如果只选择了元素中的部分文本,那么它将显示在返回的数组中,即使它是唯一的

我想添加一个可以更改的参数