2017-10-17 12 views
1

J'ai un div avec un seul nœud interne:de TreeWalker et/ou document.createRange() ne pas décrocher un seul élément

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

et je suis en train d'obtenir son contenu avec document.createRange() et document.createTreeWalker() comme ci-dessous :

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

Mais quelque part le long du chemin, le nœud le plus à l'intérieur est perdu.

Comme vous pouvez le voir dans le code complet (inclus dans l'extrait), l'intervalle "test" reste à l'intérieur de la Source, alors qu'il devrait être déplacé vers Cloner.

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>

Répondre

1

Votre endOffset est désactivé. Dans findEndNodes Lorsque vous trouvez le noeud votre code actuel suppose que le nombre de décalage est un de moins que nécessaire, c'est parce que vous utilisez setEndBefore lorsque vous devez utiliser setEndAfter.

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>