2017-10-17 4 views
1

私は、単一の内部ノードとのdiv要素があります。JS TreeWalkerのおよび/またはdocument.createRange()単一の要素を拾っていない

<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>

答えて

1

あなたendOffsetのがオフになっています。 In 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>

関連する問題