0

いくつかのブロック要素全体に広がるテキストを渡そうとすると、window.find メソッドは機能しません。

HTML :

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
</head>
<body>
  <p>search me</p><b> I could be the answer</b>
</body>
</html>

JavaScript :

window.find("meI could be");

または:

str = "me";
str+= "\n";
str+="I could be t";

window.find(str);

これは、<p>要素が検索語の間に存在する場合に発生します。
最終結果は、ページ内のテキストの GUI 選択である必要があります。存在する場合は検索したくありません。

Firefox(少なくとも)とインターネットエクスプローラーでこれを達成する方法を知りたいです。
注: dom を変更することはできません (たとえば、インラインで表示するように変更します)。

編集:
@Alexey Lebedevのコメントの後に試したことがありますが、スクリプトも見つかります(タグ[...]テキスト):

もっと簡単にできますか?(より良い)?

function nativeTreeWalker(startNode) {
    var walker = document.createTreeWalker(
        startNode, 
        NodeFilter.SHOW_TEXT, 
        null, 
        false
    );
    var node;
    var textNodesV = [];
    var textNodes = [];
    node = walker.nextNode();

    while(node ) {
      if(node.nodeValue.trim()){
        textNodes.push(node);
        textNodesV.push(node.nodeValue);
        //console.log(node.nodeValue);
      }
        node = walker.nextNode();
    }
  return [textNodes,textNodesV];
}

var result = nativeTreeWalker(document.body);
var textNodes = result[0];
var textNodesV = result[1];

var param = " Praragraph.Test 3 Praragr";
paramArr = param.split(/(?=[\S])(?!\s)(?=[\W])(?=[\S])/g);
//Fix split PARAM
for(i=0;i<paramArr.length-1;i++){
  paramArr[i]= paramArr[i]+paramArr[i+1].charAt(0);
  paramArr[i+1] = paramArr[i+1].substring(1,paramArr[i+1].length);
}
//Fix last element PARAM
if(paramArr[paramArr.length-1] === ""){
  paramArr.splice(paramArr.length-1,1);
}
//console.log(paramArr);
var startNode,startOffset,sFound=false,
    endNode,endOffset;
for(i=0;i<paramArr.length;i++){
  for(j=0;j<textNodesV.length;j++){
    //Fully Equal
    var pos = textNodesV[j].indexOf(paramArr[i]);
    if(pos != -1){
      if(!sFound){
        startNode = textNodes[j];
        startOffset = pos;
        sFound=true;
      }else{
        endNode = textNodes[j];
        endOffset = pos+paramArr[i].length;
        break;
      }
    }
  }
}
console.log(startNode);
console.log(startOffset);
console.log(endNode);
console.log(endOffset);

var range = document.createRange();
range.setStart(startNode,startOffset);
range.setEnd(endNode,endOffset);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

: jQuery はありません (Raw JS のみ)。

4

1 に答える 1

2

JS Binデモ: http: //jsbin.com/aqiciv/1/

これをIE<9で機能させたい場合は、MS固有の選択コード(悪夢)を追加するか、Rangy.js(かなり重い)を使用する必要があります。

function visibleTextNodes() {
    var walker = document.createTreeWalker(
        document.body,
        NodeFilter.SHOW_ALL,
        function(node) {
            if (node.nodeType == 3) {
                return NodeFilter.FILTER_ACCEPT;
            } else if (node.offsetWidth && node.offsetHeight && node.style.visibility != 'hidden') {
                return NodeFilter.FILTER_SKIP;
            } else {
                return NodeFilter.FILTER_REJECT;
            }
        },
        false
    );

    for (var nodes = []; walker.nextNode();) {
        nodes.push(walker.currentNode);
    }
    return nodes;
}

// Find the first match, select and scroll to it.
// Case- and whitespace- insensitive.
// For better scrolling to selection see https://gist.github.com/3744577
function highlight(needle) {
    needle = needle.replace(/\s/g, '').toLowerCase();

    var textNodes = visibleTextNodes();

    for (var i = 0, texts = []; i < textNodes.length; i++) {
        texts.push(textNodes[i].nodeValue.replace(/\s/g, '').toLowerCase());
    }

    var matchStart = texts.join('').indexOf(needle);
    if (matchStart < 0) {
        return false;
    }

    var nodeAndOffsetAtPosition = function(position) {
        for (var i = 0, consumed = 0; consumed + texts[i].length < position; i++) {
            consumed += texts[i].length;
        }
        var whitespacePrefix = textNodes[i].nodeValue.match(/^\s*/)[0];
        return [textNodes[i], position - consumed + whitespacePrefix.length];
    };

    var range = document.createRange();
    range.setStart.apply(range, nodeAndOffsetAtPosition(matchStart));
    range.setEnd.apply(  range, nodeAndOffsetAtPosition(matchStart + needle.length));
    window.getSelection().removeAllRanges();
    window.getSelection().addRange(range);
    range.startContainer.parentNode.scrollIntoView();
}

highlight('hello world');
于 2012-09-18T18:25:25.617 に答える