javascript - js TreeWalker 和/或 document.createRange() 没有拾取单个元素

标签 javascript html range

我有一个带有单个内部节点的 div:

<section id="Source" class="source">
  <div>
    test
  </div>
</section>

我正在尝试使用 document.createRange()document.createTreeWalker() 获取其内容,如下所示:

function findEndNode(source, maxHeight) {
  const range = document.createRange();
  range.selectNodeContents(source);

  var nodes = document.createTreeWalker(
    source,
    NodeFilter.SHOW_ELEMENT,
    null,
    null
  );

  while (node = nodes.nextNode()) {
    range.setEndBefore(nodes.currentNode);
    const {
      height
    } = range.getBoundingClientRect();
    const rangeHeight = height;

    if (maxHeight <= rangeHeight) {
      console.log('out of  bounds');
      const newNode = nodes.previousNode();
      range.setEndBefore(nodes.currentNode);
      break;
    } else {
      console.log('within bounds');
      continue;
    }
  }

  return range;
};

但是在途中的某个地方,最里面的节点丢失了。

正如您在完整代码(包含在代码段中)中看到的那样,“测试”跨度保留在源代码中,而应将其移至克隆。

const source = document.getElementById('Source');
const target = document.getElementById('Target');
const wrapper = document.getElementById('Wrapper');

wordWrap(source);
splitContent(source, target, wrapper);
//splitContent(source, target, wrapper);

function splitContent(source, target, wrapper) {
  const {
    height
  } = target.getBoundingClientRect();
  const maxHeight = height;

  const range = document.createRange();
  const endNode = findEndNode(source, maxHeight);
  
  range.setStart(source, 0);
  range.setEnd(endNode.endContainer, endNode.endOffset);

  const content = range.extractContents();
  const clone = target.cloneNode(false);
  clone.id = 'Clone';
  clone.appendChild(content);
  wrapper.appendChild(clone);

  const hasChildren = source.hasChildNodes();
};


function findEndNode(source, maxHeight) {
  const range = document.createRange();
  range.selectNodeContents(source);

  var nodes = document.createTreeWalker(
    source,
    NodeFilter.SHOW_ELEMENT,
    null,
    null
  );

  while (node = nodes.nextNode()) {
    range.setEndBefore(nodes.currentNode);
    const {
      height
    } = range.getBoundingClientRect();
    const rangeHeight = height;

    if (maxHeight <= rangeHeight) {
      console.log('out of  bounds');
      const newNode = nodes.previousNode();
      range.setEndBefore(nodes.currentNode);
      break;
    } else {
      console.log('within bounds');
      continue;
    }
  }

  return range;
};



function wordWrap(element) {
  var nodes = document.createTreeWalker(
    element,
    NodeFilter.SHOW_TEXT,
    null,
    null
  );
  var node;
  while (node = nodes.nextNode()) {
    var p = node.parentNode;
    var text = node.nodeValue;
    var m;
    while (m = text.match(/^(\s*)(\S+)/)) {
      text = text.slice(m[0].length);
      p.insertBefore(document.createTextNode(m[1]), node);
      var word = p.insertBefore(document.createElement('span'), node);
      word.appendChild(document.createTextNode(m[2]));
      word.className = 'word';
    }
    node.nodeValue = text;
  }
}
section {
  font-family: arial;
  font-size: 11pt;
}

.target {
  height: 400px;
  width: 400px;
  border: 2px dashed green;
  margin: 20px;
}

.source {
  border: 2px dashed blue;
  width: 400px;
  margin: 20px;
}
#Clone {
  border-color: red;
}
<section id="Source" class="source">
  <div>
    test
  </div>
</section>

<div id="Target" class="target">
</div>

<section id="Wrapper">
</section>

最佳答案

您的结束偏移已关闭。在 findEndNodes 中,当您找到节点时,您当前的代码假定偏移量比必要的少一个,这是因为您在应该使用 setEndAfter 时使用了 setEndBefore。

const source = document.getElementById('Source');
const target = document.getElementById('Target');
const wrapper = document.getElementById('Wrapper');

wordWrap(source);
splitContent(source, target, wrapper);
//splitContent(source, target, wrapper);

function splitContent(source, target, wrapper) {
  const {
    height
  } = target.getBoundingClientRect();
  const maxHeight = height;

  const range = document.createRange();
  const endNode = findEndNode(source, maxHeight);
  
  range.setStart(source, 0);
  range.setEnd(endNode.endContainer, endNode.endOffset);

  const content = range.extractContents();
  const clone = target.cloneNode(false);
  clone.id = 'Clone';
  clone.appendChild(content);
  wrapper.appendChild(clone);

  const hasChildren = source.hasChildNodes();
};


function findEndNode(source, maxHeight) {
  const range = document.createRange();
  range.selectNodeContents(source);

  var nodes = document.createTreeWalker(
    source,
    NodeFilter.SHOW_ELEMENT,
    null,
    null
  );

  while (node = nodes.nextNode()) {
    range.setEndAfter(nodes.currentNode);
    const {
      height
    } = range.getBoundingClientRect();
    const rangeHeight = height;

    if (maxHeight <= rangeHeight) {
      console.log('out of  bounds');
      const newNode = nodes.previousNode();
      range.setEndAfter(nodes.currentNode);
      break;
    } else {
      console.log('within bounds');
      continue;
    }
  }

  return range;
};



function wordWrap(element) {
  var nodes = document.createTreeWalker(
    element,
    NodeFilter.SHOW_TEXT,
    null,
    null
  );
  var node;
  while (node = nodes.nextNode()) {
    var p = node.parentNode;
    var text = node.nodeValue;
    var m;
    while (m = text.match(/^(\s*)(\S+)/)) {
      text = text.slice(m[0].length);
      p.insertBefore(document.createTextNode(m[1]), node);
      var word = p.insertBefore(document.createElement('span'), node);
      word.appendChild(document.createTextNode(m[2]));
      word.className = 'word';
    }
    node.nodeValue = text;
  }
}
section {
  font-family: arial;
  font-size: 11pt;
}

.target {
  height: 400px;
  width: 400px;
  border: 2px dashed green;
  margin: 20px;
}

.source {
  border: 2px dashed blue;
  width: 400px;
  margin: 20px;
}
#Clone {
  border-color: red;
}
<section id="Source" class="source">
  <div>
    test
  </div>
</section>

<div id="Target" class="target">
</div>

<section id="Wrapper">
</section>

关于javascript - js TreeWalker 和/或 document.createRange() 没有拾取单个元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46799735/

相关文章:

javascript - 无限循环显示随机数js

javascript - Typescript 数组求和而不是串联

java - 请解释一下这个 Java 程序输出

c# excel 如何在已用范围内查找第一个单元格。

javascript - 未捕获类型错误 : Object [object Object] has no method 'jqxmaskedinput'

javascript - 如何使用jquery交换多个图像的点击位置

html - HTML 覆盖 Div 后面的外部 Flash 电影

jquery - 在容器内重新排列 div 并保存新 View 的推荐方法

javascript - JS : Why this code isn´t changing when clicked on?

包含 NA 的字段上的范围